├── .github ├── banner.png └── hero.png ├── .gitignore ├── .gitmodules ├── LICENSE ├── MachOExplorer-Bridging-Header.h ├── MachOExplorer.xcodeproj └── project.pbxproj ├── MachOExplorer ├── AppDelegate.swift ├── Details │ ├── MachODetailViewController.swift │ ├── MachODetailsViewController.swift │ ├── MachODetailsViewController.xib │ ├── MachOHexDetailViewController.swift │ └── MachOHexDetailViewController.xib ├── MachODocument.swift ├── MachODocumentDetailsViewController.swift ├── MachODocumentOutlineViewController.swift ├── MachODocumentOutlineViewController.xib ├── MachODocumentWindowContentViewController.swift ├── MachODocumentWindowController.swift ├── MachoDocumentWindow.xib ├── Model │ ├── DataModel.swift │ ├── DetailModel.swift │ ├── Field │ │ ├── FieldAdapter.swift │ │ └── SubFieldAdapter.swift │ ├── MKAddressedNode+Detail.swift │ ├── MKBackedNode+Data.swift │ ├── MKBackedNode+Detail.swift │ ├── MKNode+Adapter.swift │ ├── MKNode+Detail.swift │ ├── MKNode+Outline.swift │ ├── Model.swift │ ├── OutlineModel.swift │ ├── Overrides │ │ ├── FAT │ │ │ └── MKFatArch+Model.swift │ │ ├── MachO │ │ │ ├── MKExport+Model.swift │ │ │ ├── MKExportTrieBranch+Model.swift │ │ │ ├── MKFixup+Model.swift │ │ │ ├── MKFunctionStarts+Model.swift │ │ │ ├── MKPointerNode+Model.swift │ │ │ └── MKSection+Model.swift │ │ └── ObjC │ │ │ ├── MKObjCCategory+Model.swift │ │ │ ├── MKObjCClass+Model.swift │ │ │ └── MKObjCProtocol+Model.swift │ ├── Type │ │ ├── BitFieldTypeAdapter.swift │ │ ├── CollectionTypeAdapter.swift │ │ ├── ContainerTypeAdapter.swift │ │ ├── OptionSetTypeAdapter.swift │ │ └── TypeAdapter.swift │ └── Value │ │ ├── MKOptional+Model.swift │ │ ├── NSArray+Model.swift │ │ ├── NSDictionary+Model.swift │ │ └── NSObject+Model.swift └── Utility │ ├── NS+Initialize.h │ ├── NS+Initialize.m │ ├── NSValueTransformer+HexRepresentation.swift │ ├── NSValueTransformer+TakeFirst.swift │ ├── Utility.h │ └── Utility.m ├── ReadMe.md └── Resources ├── Assets.xcassets └── AppIcon.appiconset │ ├── AppIcon_512.png │ ├── AppIcon_512@2x.png │ └── Contents.json ├── MachOExplorer-Info.plist └── MainMenu.xib /.github/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeVaukz/MachO-Explorer/e82b6e6136f4312422c276762e837fe853030547/.github/banner.png -------------------------------------------------------------------------------- /.github/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeVaukz/MachO-Explorer/e82b6e6136f4312422c276762e837fe853030547/.github/hero.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS generated files # 2 | ###################### 3 | .DS_Store 4 | .DS_Store? 5 | ._* 6 | .Spotlight-V100 7 | .Trashes 8 | Icon? 9 | ehthumbs.db 10 | Thumbs.db 11 | 12 | # User specific Xcode files # 13 | ############################# 14 | *.xcworkspace 15 | *.xcuserdatad 16 | 17 | # Documentation # 18 | ################# 19 | html 20 | 21 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Configuration"] 2 | path = Configuration 3 | url = https://github.com/DeVaukz/xcconfigs.git 4 | [submodule "External/MachO-Kit"] 5 | path = External/MachO-Kit 6 | url = https://github.com/DeVaukz/MachO-Kit.git 7 | [submodule "External/WAYWindow"] 8 | path = External/WAYWindow 9 | url = https://github.com/weAreYeah/WAYWindow.git 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Devin Vaukz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /MachOExplorer-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import "Utility.h" 6 | #import "NS+Initialize.h" 7 | 8 | #import "WAYWindow.h" 9 | -------------------------------------------------------------------------------- /MachOExplorer/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file AppDelegate.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import Cocoa 29 | 30 | @NSApplicationMain 31 | class AppDelegate: NSObject, NSApplicationDelegate 32 | { 33 | 34 | } 35 | -------------------------------------------------------------------------------- /MachOExplorer/Details/MachODetailViewController.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MachODetailViewController.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import Cocoa 29 | import MachOKit 30 | 31 | class MachODetailViewController: NSViewController 32 | { 33 | @objc dynamic var wantsDisplay: Bool = false 34 | lazy var tabViewItem: NSTabViewItem = NSTabViewItem(viewController: self) 35 | 36 | // Model // 37 | @objc var model: Model? = nil 38 | fileprivate var modelBinding: ModelBinding? 39 | 40 | // UI // 41 | @objc var addressMode: MKNodeAddressType = .contextAddress 42 | fileprivate var addressModeBinding: AddressModeBinding? 43 | 44 | override var representedObject: Any? { 45 | willSet { 46 | self.unbind(MachODetailViewController.ModelBinding.Name) 47 | self.unbind(MachODetailViewController.AddressModeBinding.Name) 48 | } 49 | didSet { 50 | guard let representedObject = self.representedObject else { return } 51 | self.bind(MachODetailViewController.ModelBinding.Name, to: representedObject, withKeyPath: "selection", options: nil) 52 | self.bind(MachODetailViewController.AddressModeBinding.Name, to: representedObject, withKeyPath: "addressMode", options: nil) 53 | } 54 | } 55 | 56 | required init?(coder: NSCoder) { 57 | super.init(coder: coder) 58 | 59 | self.commonInit() 60 | } 61 | 62 | override init(nibName nibNameOrNil: NSNib.Name?, bundle nibBundleOrNil: Bundle?) { 63 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) 64 | 65 | self.commonInit() 66 | } 67 | 68 | func commonInit() { 69 | return 70 | } 71 | 72 | deinit { 73 | self.unbind(ModelBinding.Name) 74 | self.unbind(AddressModeBinding.Name) 75 | } 76 | } 77 | 78 | 79 | extension MachODetailViewController 80 | { 81 | @objc var tabViewToolTip: String { return NSStringFromClass(type(of: self)) } 82 | 83 | @objc func willAppear() { 84 | return 85 | } 86 | 87 | @objc func willDisappear() { 88 | return 89 | } 90 | } 91 | 92 | 93 | extension MachODetailViewController /* NSKeyValueBindingCreation */ 94 | { 95 | struct ModelBinding { 96 | static let Name = NSBindingName("model") 97 | let observedObject: NSObject 98 | let observedKeyPath: String 99 | } 100 | 101 | struct AddressModeBinding { 102 | static let Name = NSBindingName("addressMode") 103 | let observedObject: NSObject 104 | let observedKeyPath: String 105 | } 106 | 107 | override static func heySwiftSomePeopleStillNeedToOverrideInitialize() /* +initialize */ { 108 | exposeBinding(ModelBinding.Name) 109 | exposeBinding(AddressModeBinding.Name) 110 | } 111 | 112 | override func bind(_ binding: NSBindingName, to observable: Any, withKeyPath keyPath: String, options: [NSBindingOption : Any]? = nil) { 113 | if binding == ModelBinding.Name { 114 | guard let observable = observable as? NSObject else { return } 115 | self.unbind(binding) 116 | self.modelBinding = ModelBinding(observedObject: observable, observedKeyPath: keyPath) 117 | observable.addObserver(self, forKeyPath: keyPath, options: .initial, context: nil) 118 | 119 | } else if binding == AddressModeBinding.Name { 120 | guard let observable = observable as? NSObject else { return } 121 | self.unbind(binding) 122 | self.addressModeBinding = AddressModeBinding(observedObject: observable, observedKeyPath: keyPath) 123 | observable.addObserver(self, forKeyPath: keyPath, options: .initial, context: nil) 124 | 125 | } else { 126 | super.bind(binding, to: observable, withKeyPath: keyPath, options: options) 127 | } 128 | } 129 | 130 | override func unbind(_ binding: NSBindingName) { 131 | if binding == ModelBinding.Name { 132 | guard let binding = self.modelBinding else { return } 133 | binding.observedObject.removeObserver(self, forKeyPath: binding.observedKeyPath, context: nil) 134 | self.modelBinding = nil 135 | self.model = nil 136 | 137 | } else if binding == AddressModeBinding.Name { 138 | guard let binding = self.addressModeBinding else { return } 139 | binding.observedObject.removeObserver(self, forKeyPath: binding.observedKeyPath, context: nil) 140 | self.addressModeBinding = nil 141 | self.addressMode = .contextAddress 142 | 143 | } else { 144 | super.unbind(binding) 145 | } 146 | } 147 | 148 | override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 149 | if let object = object as? NSObject { 150 | 151 | if let binding = self.modelBinding, binding.observedObject == object && binding.observedKeyPath == keyPath { 152 | self.model = object.value(forKeyPath: binding.observedKeyPath) as! Model? 153 | return 154 | 155 | } else if let binding = self.addressModeBinding, binding.observedObject == object && binding.observedKeyPath == keyPath { 156 | self.addressMode = MKNodeAddressType(rawValue: (object.value(forKeyPath: binding.observedKeyPath) as! NSNumber).uintValue)! 157 | return 158 | } 159 | 160 | } 161 | 162 | super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /MachOExplorer/Details/MachODetailsViewController.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MachODetailsViewController.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import Cocoa 29 | import MachOKit 30 | 31 | class MachODetailsViewController: MachODetailViewController 32 | { 33 | @IBOutlet weak var tableView: NSTableView! 34 | @IBOutlet weak var addressColumn: NSTableColumn! 35 | @IBOutlet weak var dataColumn: NSTableColumn! 36 | @IBOutlet weak var descriptionColumn: NSTableColumn! 37 | @IBOutlet weak var valueColumn: NSTableColumn! 38 | 39 | override func commonInit() { 40 | self.title = "Details" 41 | } 42 | 43 | @IBOutlet var controller: NSArrayController! 44 | 45 | @objc dynamic var rowData: [Row] = [] 46 | 47 | override var model: Model? { 48 | didSet { 49 | guard self.model?.isEqual(oldValue) == false else { return } 50 | 51 | if let model = self.model as? DetailModel { 52 | self.rowData = MachODetailsViewController.makeRowData(for: model) ?? [] 53 | } else { 54 | self.rowData = [] 55 | } 56 | 57 | update() 58 | } 59 | } 60 | 61 | override var addressMode: MKNodeAddressType { 62 | didSet { 63 | update() 64 | } 65 | } 66 | 67 | func update() { 68 | self.tableView?.deselectAll(self) 69 | 70 | if self.rowData.count > 0 { 71 | self.wantsDisplay = true 72 | } else { 73 | self.wantsDisplay = false 74 | } 75 | 76 | let formatter = MKHexNumberFormatter(digits: 8) 77 | formatter.uppercase = true 78 | formatter.omitPrefix = true 79 | 80 | for row in rowData { 81 | switch self.addressMode { 82 | case .contextAddress: 83 | row.address = formatter.string(for: row.rawAddress != nil ? row.rawAddress! as NSNumber : nil) 84 | case .vmAddress: 85 | row.address = formatter.string(for: row.rvaAddress != nil ? row.rvaAddress! as NSNumber : nil) 86 | } 87 | } 88 | } 89 | } 90 | 91 | 92 | extension MachODetailsViewController 93 | { 94 | @objc(MachODetailsViewControllerRow) 95 | final class Row: NSObject { 96 | var rawAddress: mk_vm_address_t? 97 | var rvaAddress: mk_vm_address_t? 98 | 99 | @objc dynamic var address: String? 100 | @objc var data: String? 101 | @objc var name: String? 102 | @objc var value: String? 103 | 104 | var underline: Bool = false 105 | 106 | override var description: String { 107 | return self.name ?? "" 108 | } 109 | } 110 | 111 | static func makeRowData(for model: DetailModel) -> [Row]? { 112 | var previous: (UInt, Row)? 113 | 114 | return autoreleasepool { 115 | return model.detail_rows.map({ detailNode -> MachODetailsViewController.Row in 116 | let row = MachODetailsViewController.Row() 117 | 118 | if let contextAddress = detailNode.detail_address(mode: .contextAddress) { 119 | row.rawAddress = contextAddress as! mk_vm_address_t 120 | } 121 | if let vmAddress = detailNode.detail_address(mode: .vmAddress) { 122 | row.rvaAddress = vmAddress as! mk_vm_address_t 123 | } 124 | 125 | if var data = detailNode.detail_data { 126 | let transformer = HexRepresentationValueTransformer() 127 | 128 | // Cap the number of bytes we will format 129 | if data.count > 50 { 130 | data = data.subdata(in: 0..<50) 131 | } 132 | 133 | row.data = transformer.transformedValue(data) as? String; 134 | } 135 | 136 | row.name = detailNode.detail_description 137 | row.value = detailNode.detail_value 138 | 139 | let groupIdentifier: UInt 140 | if let detailNode = detailNode as? DetailRowDisplayModel { 141 | groupIdentifier = detailNode.detail_group_identifier 142 | } else { 143 | groupIdentifier = 0 144 | } 145 | 146 | if let (p, _) = previous, p != groupIdentifier { 147 | row.underline = true 148 | } 149 | previous = (groupIdentifier, row) 150 | 151 | return row 152 | }) 153 | } 154 | } 155 | } 156 | 157 | 158 | extension MachODetailsViewController: NSTableViewDelegate 159 | { 160 | class TableRow: NSTableRowView 161 | { 162 | var border: Bool = false 163 | 164 | override func drawBackground(in dirtyRect: NSRect) { 165 | super.drawBackground(in: dirtyRect) 166 | 167 | if self.border { 168 | if let tableView = self.superview as? NSTableView { 169 | tableView.gridColor.set() 170 | } else { 171 | NSColor.separatorColor.set() 172 | } 173 | 174 | // Hack - tableView.gridColor does not look correct in dark mode 175 | if (self.effectiveAppearance.name == NSAppearance.Name.darkAqua) { 176 | NSColor.lightGray.set() 177 | } 178 | 179 | NSBezierPath.strokeLine( 180 | from: NSPoint(x: self.bounds.origin.x, y: self.bounds.origin.y), 181 | to: NSPoint(x: self.bounds.origin.x + self.bounds.size.width, y: self.bounds.origin.y) 182 | ) 183 | } 184 | } 185 | } 186 | 187 | func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? { 188 | let rowView = TableRow() 189 | 190 | if self.rowData[row].underline { 191 | rowView.border = true 192 | } 193 | 194 | return rowView 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /MachOExplorer/Details/MachODetailsViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 218 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | -------------------------------------------------------------------------------- /MachOExplorer/Details/MachOHexDetailViewController.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MachOHexDetailViewController.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import Cocoa 29 | import MachOKit 30 | 31 | class MachOHexDetailViewController: MachODetailViewController 32 | { 33 | @IBOutlet weak var tableView: NSTableView! 34 | @IBOutlet weak var addressColumn: NSTableColumn! 35 | @IBOutlet weak var dataLoColumn: NSTableColumn! 36 | @IBOutlet weak var dataHiColumn: NSTableColumn! 37 | @IBOutlet weak var valueColumn: NSTableColumn! 38 | 39 | override func commonInit() { 40 | self.title = "Data" 41 | } 42 | 43 | var nodeAddress: mk_vm_address_t? 44 | var nodeData: Data? 45 | 46 | override var addressMode: MKNodeAddressType { 47 | didSet { 48 | if let model = self.model as? DataModel { 49 | self.nodeAddress = model.address(mode: self.addressMode) as! mk_vm_address_t? 50 | } 51 | 52 | update() 53 | } 54 | } 55 | 56 | override var model: Model? { 57 | didSet { 58 | guard self.model?.isEqual(oldValue) == false else { return } 59 | 60 | if let model = self.model as? DataModel { 61 | self.nodeAddress = model.address(mode: self.addressMode) as! mk_vm_address_t? 62 | self.nodeData = model.data 63 | } else { 64 | self.nodeAddress = nil 65 | self.nodeData = nil 66 | } 67 | 68 | update() 69 | } 70 | } 71 | 72 | func update() { 73 | if let tableView = self.tableView { 74 | tableView.reloadData() 75 | } 76 | 77 | if self.nodeData != nil { 78 | self.wantsDisplay = true 79 | } else { 80 | self.wantsDisplay = false 81 | } 82 | } 83 | } 84 | 85 | 86 | extension MachOHexDetailViewController: NSTableViewDataSource 87 | { 88 | func numberOfRows(in tableView: NSTableView) -> Int { 89 | guard let nodeData = self.nodeData else { return 0 } 90 | 91 | var numRows = nodeData.count / 16 92 | if nodeData.count % 16 != 0 { 93 | numRows += 1 94 | } 95 | 96 | return numRows 97 | } 98 | 99 | func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? { 100 | guard let nodeData = self.nodeData else { return nil } 101 | 102 | let offset = row * 16 103 | 104 | if tableColumn == self.addressColumn, let baseAddress = self.nodeAddress { 105 | let address = Int(baseAddress) + offset 106 | 107 | return NSString(format: "%.8lX", address) 108 | } 109 | 110 | let len = min(nodeData.count - offset, 16) 111 | let start = offset 112 | let end = start + len 113 | 114 | var buffer = Array(repeating: 0, count: 16) 115 | nodeData.copyBytes(to: &buffer, from: start.. UInt8 in 125 | if byte < 32 || byte > 126 { 126 | return 46 // '.' 127 | } else { 128 | return byte; 129 | } 130 | }) 131 | 132 | return NSString(bytes: &buffer, length: buffer.count, encoding: String.Encoding.ascii.rawValue) 133 | } 134 | 135 | return nil 136 | } 137 | } 138 | 139 | 140 | extension MachOHexDetailViewController: NSTableViewDelegate 141 | { 142 | class TableRow: NSTableRowView 143 | { 144 | override func drawSelection(in dirtyRect: NSRect) { 145 | super.drawSelection(in: dirtyRect) 146 | 147 | if self.interiorBackgroundStyle == .dark && self.isSelected && self.isEmphasized == false { 148 | NSColor(calibratedWhite: 78.0/255.0, alpha: 1.0).set() 149 | NSBezierPath.fill(self.bounds) 150 | } 151 | } 152 | } 153 | 154 | func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? { 155 | return TableRow() 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /MachOExplorer/Details/MachOHexDetailViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 191 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | -------------------------------------------------------------------------------- /MachOExplorer/MachODocument.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MachODocument.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import Cocoa 29 | import MachOKit 30 | 31 | class MachODocument: NSDocument 32 | { 33 | @objc var rootNode: MKNode! 34 | 35 | // UI State // 36 | @objc dynamic var addressMode: MKNodeAddressType = .contextAddress 37 | @objc dynamic var searchString: String? = nil 38 | @objc dynamic var selection: Model? = nil 39 | } 40 | 41 | 42 | extension MachODocument 43 | { 44 | override func read(from url: URL, ofType typeName: String) throws { 45 | let memoryMap = try MKMemoryMap.init(contentsOfFile: url) 46 | 47 | // Try initializing a dyld shared cache 48 | do { 49 | self.rootNode = try MKSharedCache(flags: .fromSourceFile, atAddress: 0, inMapping: memoryMap) 50 | return 51 | } catch let error as NSError { 52 | // If MK_EINVAL is returned, the file is not a shared cache. 53 | if mk_error_t(rawValue: UInt32(error.code)) != MK_EINVAL { 54 | throw error 55 | } 56 | } 57 | 58 | // Try initializing a FAT binary 59 | do { 60 | self.rootNode = try MKFatBinary(memoryMap: memoryMap) 61 | return 62 | } catch let error as NSError { 63 | // If MK_EINVAL is returned, the file is not a FAT binary. 64 | if mk_error_t(rawValue: UInt32(error.code)) != MK_EINVAL { 65 | throw error 66 | } 67 | } 68 | 69 | // Try initializing a Mach-O 70 | self.rootNode = try MKMachOImage(name: nil, flags: MKMachOImageFlags(rawValue: 0), atAddress: 0, inMapping: memoryMap) 71 | } 72 | } 73 | 74 | 75 | extension MachODocument 76 | { 77 | override func makeWindowControllers() { 78 | let windowController = MachODocumentWindowController(windowNibName: NSNib.Name("MachoDocumentWindow")) 79 | self.addWindowController(windowController) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /MachOExplorer/MachODocumentDetailsViewController.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MachODocumentDetailsViewController.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import Cocoa 29 | 30 | class MachODocumentDetailsViewController: NSTabViewController 31 | { 32 | let detailViewControllers: [MachODetailViewController] = [ 33 | MachODetailsViewController(), 34 | MachOHexDetailViewController() 35 | ] 36 | 37 | override var representedObject: Any? { 38 | didSet { 39 | for viewController in self.detailViewControllers { 40 | viewController.representedObject = self.representedObject 41 | } 42 | } 43 | } 44 | 45 | required init?(coder: NSCoder) { 46 | super.init(coder: coder) 47 | 48 | self.commonInit() 49 | } 50 | 51 | override init(nibName nibNameOrNil: NSNib.Name?, bundle nibBundleOrNil: Bundle?) { 52 | super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) 53 | 54 | self.commonInit() 55 | } 56 | 57 | func commonInit() { 58 | self.transitionOptions = TransitionOptions() 59 | self.tabStyle = .unspecified 60 | 61 | for viewController in self.detailViewControllers { 62 | viewController.addObserver(self, forKeyPath: "wantsDisplay", options: .initial, context: nil) 63 | } 64 | } 65 | 66 | deinit { 67 | for viewController in self.detailViewControllers { 68 | viewController.removeObserver(self, forKeyPath: "wantsDisplay", context: nil) 69 | } 70 | } 71 | } 72 | 73 | 74 | extension MachODocumentDetailsViewController 75 | { 76 | override func tabView(_ tabView: NSTabView, willSelect tabViewItem: NSTabViewItem?) { 77 | super.tabView(tabView, didSelect: tabViewItem) 78 | 79 | if self.tabViewItems.indices.contains(self.selectedTabViewItemIndex), 80 | let outgoingViewController = self.tabViewItems[self.selectedTabViewItemIndex].viewController as? MachODetailViewController 81 | { 82 | outgoingViewController.willDisappear() 83 | } 84 | 85 | if let tabViewItem = tabViewItem, 86 | let incomingViewController = tabViewItem.viewController as? MachODetailViewController 87 | { 88 | incomingViewController.willAppear() 89 | } 90 | } 91 | } 92 | 93 | 94 | extension MachODocumentDetailsViewController 95 | { 96 | @objc func updateVisibleViewControllers() { 97 | let newValue = self.detailViewControllers.filter({ viewController -> Bool in 98 | return viewController.wantsDisplay 99 | }).map({ viewController -> NSTabViewItem in 100 | return viewController.tabViewItem 101 | }) 102 | 103 | self.tabViewItems = newValue; 104 | } 105 | 106 | override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 107 | if keyPath == "wantsDisplay" 108 | { 109 | type(of: self).cancelPreviousPerformRequests(withTarget: self, selector: #selector(updateVisibleViewControllers), object: nil) 110 | self.perform(#selector(updateVisibleViewControllers), with: nil, afterDelay: 0) 111 | } 112 | else { 113 | super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /MachOExplorer/MachODocumentOutlineViewController.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MachODocumentOutlineViewController.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import Cocoa 29 | 30 | class MachODocumentOutlineViewController: NSViewController, NSOutlineViewDelegate 31 | { 32 | @IBOutlet var outlineController: NSTreeController! { 33 | didSet { 34 | oldValue?.removeObserver(self, forKeyPath: "selectedObjects") 35 | self.outlineController.addObserver(self, forKeyPath: "selectedObjects", options: NSKeyValueObservingOptions(), context: nil) 36 | } 37 | } 38 | 39 | deinit { 40 | self.outlineController.removeObserver(self, forKeyPath: "selectedObjects") 41 | } 42 | } 43 | 44 | 45 | extension MachODocumentOutlineViewController 46 | { 47 | override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 48 | if let object = object as? NSTreeController, 49 | object == self.outlineController && keyPath == "selectedObjects" 50 | { 51 | let document = self.representedObject as! MachODocument 52 | 53 | if let newValue = object.selectedObjects as? [Model] { 54 | document.selection = newValue.first 55 | } else { 56 | document.selection = nil 57 | } 58 | } 59 | else { 60 | super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /MachOExplorer/MachODocumentOutlineViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 86 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /MachOExplorer/MachODocumentWindowContentViewController.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MachODocumentWindowContentViewController.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import Cocoa 29 | 30 | class MachODocumentWindowContentViewController: NSSplitViewController 31 | { 32 | 33 | } 34 | -------------------------------------------------------------------------------- /MachOExplorer/MachODocumentWindowController.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MachODocumentWindowController.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import Cocoa 29 | 30 | class MachODocumentWindowController: NSWindowController 31 | { 32 | @IBOutlet var addressModeSelector: NSSegmentedControl! 33 | @IBOutlet var displayModeSelectorItem: NSToolbarItem! 34 | @IBOutlet var displayModeSelector: NSSegmentedControl! 35 | @IBOutlet var searchField: NSSearchField! 36 | @IBOutlet var panelVisibilitySelector: NSSegmentedControl! 37 | 38 | var previousDetailSelection: String? = nil 39 | 40 | override func windowDidLoad() { 41 | super.windowDidLoad() 42 | 43 | let splitViewController = MachODocumentWindowContentViewController() 44 | 45 | // Load the outline view controller (master) 46 | let outlineController = MachODocumentOutlineViewController(nibName: NSNib.Name("MachODocumentOutlineViewController"), bundle: nil) 47 | outlineController.representedObject = self.document 48 | let _ = outlineController.view // Force nib load 49 | 50 | // Load the detail view controller 51 | let detailController = MachODocumentDetailsViewController() 52 | detailController.representedObject = self.document 53 | detailController.addObserver(self, forKeyPath: "tabViewItems", options: [.initial, .new], context: nil) 54 | self.displayModeSelector.bind(NSBindingName("selectedIndex"), to: detailController, withKeyPath: "selectedTabViewItemIndex", options: nil) 55 | 56 | let masterSplitViewItem = NSSplitViewItem(viewController: outlineController) 57 | masterSplitViewItem.minimumThickness = 250 58 | splitViewController.addSplitViewItem(masterSplitViewItem) 59 | 60 | let detailSplitViewItem = NSSplitViewItem(viewController: detailController) 61 | detailSplitViewItem.minimumThickness = 600 62 | splitViewController.addSplitViewItem(detailSplitViewItem) 63 | 64 | self.contentViewController = splitViewController 65 | } 66 | } 67 | 68 | 69 | extension MachODocumentWindowController 70 | { 71 | @IBAction func displayModeChanged(_ sender: NSSegmentedControl?) { 72 | if let sender = sender, sender.selectedSegment >= 0 { 73 | self.previousDetailSelection = sender.label(forSegment: sender.selectedSegment) 74 | } else { 75 | self.previousDetailSelection = nil 76 | } 77 | } 78 | 79 | override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 80 | if keyPath == "tabViewItems" 81 | { 82 | let tabViewController = (object as! NSTabViewController) 83 | let newValue: [NSTabViewItem] = tabViewController.tabViewItems 84 | 85 | if newValue.count == 0 { 86 | self.displayModeSelector.isHidden = true 87 | } else { 88 | self.displayModeSelector.isHidden = false 89 | } 90 | 91 | self.displayModeSelector.segmentCount = newValue.count 92 | 93 | var i = 0 94 | for tab in newValue { 95 | self.displayModeSelector.setLabel(tab.label, forSegment: i) 96 | self.displayModeSelector.setWidth(0, forSegment: i) 97 | i = i + 1 98 | } 99 | 100 | if let previousSelection = self.previousDetailSelection { 101 | for i in 0.. 0 { 108 | self.displayModeSelector.selectedSegment = 0 109 | tabViewController.selectedTabViewItemIndex = 0 110 | } 111 | 112 | self.displayModeSelector.layoutSubtreeIfNeeded() 113 | self.displayModeSelector.sizeToFit() 114 | self.displayModeSelectorItem.maxSize = NSSize(width: self.displayModeSelector.frame.size.width, height: self.displayModeSelectorItem.maxSize.height) 115 | self.displayModeSelectorItem.minSize = NSSize(width: 50, height: self.displayModeSelectorItem.minSize.height) 116 | } 117 | else { 118 | super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /MachOExplorer/MachoDocumentWindow.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /MachOExplorer/Model/DataModel.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file DataModel.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import Cocoa 29 | import MachOKit 30 | 31 | @objc protocol DataModel 32 | { 33 | func address(mode addressMode: MKNodeAddressType) -> NSNumber? 34 | 35 | var data: Data? { get } 36 | } 37 | -------------------------------------------------------------------------------- /MachOExplorer/Model/DetailModel.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file DetailModel.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import Cocoa 29 | import MachOKit 30 | 31 | @objc protocol DetailModel: Model 32 | { 33 | var detail_rows: [DetailRowModel] { get } 34 | } 35 | 36 | @objc protocol DetailRowModel: Model 37 | { 38 | var detail_value: String? { get } 39 | 40 | var detail_description: String? { get } 41 | 42 | var detail_data: Data? { get } 43 | 44 | func detail_address(mode addressMode: MKNodeAddressType) -> NSNumber? 45 | } 46 | 47 | @objc protocol DetailRowDisplayModel: DetailRowModel 48 | { 49 | var detail_group_identifier: UInt { get } 50 | 51 | var detail_backgroundColor: NSColor? { get } 52 | } 53 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Field/FieldAdapter.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file FieldAdapter.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | class FieldAdapter: NSObject 31 | { 32 | let node: MKNode 33 | let field: MKNodeField 34 | 35 | var type: MKNodeFieldType? { 36 | return self.field.type 37 | } 38 | 39 | var value: NSObject! { 40 | let value = self.field.valueRecipe.value(for: self.field, of: self.node) 41 | return value.value as! NSObject? 42 | } 43 | 44 | var typeAdapter: TypeAdapter? { 45 | if let type = self.type { 46 | return TypeAdapter.For(value: self.value, ofType: type, inNode: self.node) 47 | } else { 48 | return nil 49 | } 50 | } 51 | 52 | var fieldIndex: UInt { 53 | let layout = self.node.layout 54 | var i: UInt = 0 55 | for field in layout.allFields { 56 | if field.name == self.field.name { 57 | break 58 | } else { 59 | i += 1 60 | } 61 | } 62 | return i 63 | } 64 | 65 | var alternateFieldAdapter: FieldAdapter? { 66 | if let alternateFieldName = self.field.alternateFieldName { 67 | if let field = self.node.layout.field(withName: alternateFieldName, searchAllFields: true) { 68 | return self.node.adapter(forField: field) 69 | } 70 | } 71 | 72 | return nil 73 | } 74 | 75 | init(field: MKNodeField, ofNode node: MKNode) { 76 | self.node = node 77 | self.field = field 78 | } 79 | } 80 | 81 | extension FieldAdapter /* OutlineModel */ 82 | { 83 | override var outline_nodes: [OutlineNodeModel] { 84 | guard self.field.options.contains(.hidden) == false else { return [] } 85 | guard self.field.options.contains(.displayAsChild) else { return [] } 86 | guard let value = self.value else { return [] } 87 | 88 | if field.options.contains(.mergeContainerContents) { 89 | if let collectionType = self.type as? MKNodeFieldCollectionType, 90 | let elementType = collectionType.elementType { 91 | return value.outline_nodes.reduce([], { $0 + TypeAdapter.For(value: $1 as! NSObject, ofType: elementType, inNode: self.node).outline_nodes }) 92 | } 93 | else if self.type is MKNodeFieldContainerType { 94 | return value.outline_nodes 95 | } 96 | else if self.type is MKNodeFieldPointerType, 97 | let pointer = value as? MKPointer { 98 | if let pointee = pointer.pointee.value(forKey: "value") { 99 | return (pointee as! NSObject).outline_nodes 100 | } else { 101 | return [] 102 | } 103 | } 104 | } 105 | 106 | // If the type is a pointer and there is no pointee, hide the field 107 | if self.type is MKNodeFieldPointerType, 108 | let pointer = value as? MKPointer, 109 | pointer.pointee.value == nil { 110 | return [] 111 | } 112 | 113 | // If the value is an MKNode then always merge the contents unless 114 | // the field options contains ignoreContainerContents. 115 | if value is MKNode && field.options.contains(.ignoreContainerContents) == false { 116 | return value.outline_nodes 117 | } 118 | 119 | return [self] 120 | } 121 | } 122 | 123 | extension FieldAdapter /* DetailModel */ 124 | { 125 | override var detail_rows: [DetailRowModel] { 126 | guard self.field.options.contains(.hidden) == false else { return [] } 127 | guard let value = self.value else { return [] } 128 | 129 | if field.options.contains(.displayAsDetail) || field.options.contains(.displayAsChild) == false 130 | { 131 | if field.options.contains(.mergeContainerContents) { 132 | if let collectionType = field.type as? MKNodeFieldCollectionType, 133 | let elementType = collectionType.elementType { 134 | let valueDetailRowModels = value.detail_rows 135 | 136 | var detailRowModels = Array() 137 | detailRowModels.reserveCapacity(valueDetailRowModels.count) 138 | for item in valueDetailRowModels { 139 | if item is FieldAdapter || item is SubFieldAdapter { 140 | detailRowModels.append(item) 141 | } else { 142 | detailRowModels += TypeAdapter.For(value: item as! NSObject, ofType: elementType, inNode: self.node).detail_rows 143 | } 144 | } 145 | 146 | return detailRowModels 147 | } 148 | else if self.field.type is MKNodeFieldContainerType { 149 | return value.detail_rows 150 | } 151 | } 152 | else if field.options.contains(.ignoreContainerContents) == false, 153 | let typeAdapter = self.typeAdapter, 154 | typeAdapter.providesSubFields { 155 | return [self] + typeAdapter.detail_rows.map({ detailRowModel -> SubFieldAdapter in 156 | return SubFieldAdapter(valueProvider: detailRowModel as! NSObject, inField: self) 157 | }) 158 | } 159 | 160 | return [self] 161 | } 162 | else if field.options.contains(.displayContainerContentsAsDetail) 163 | { 164 | if let collectionType = field.type as? MKNodeFieldCollectionType, 165 | let elementType = collectionType.elementType, 166 | elementType is MKNodeFieldTypeNode == false { 167 | return value.detail_rows.reduce([], { $0 + TypeAdapter.For(value: $1 as! NSObject, ofType: elementType, inNode: self.node).detail_rows }) 168 | } 169 | else if self.field.type is MKNodeFieldContainerType { 170 | return value.detail_rows 171 | } 172 | } 173 | 174 | // If the type is a pointer, then we always proxy the contents 175 | if self.type is MKNodeFieldPointerType, 176 | let pointer = value as? MKPointer { 177 | if let pointee = pointer.pointee.value(forKey: "value") { 178 | return (pointee as! NSObject).detail_rows 179 | } else { 180 | //return [] 181 | } 182 | } 183 | 184 | return [] 185 | } 186 | } 187 | 188 | extension FieldAdapter /* OutlineNodeModel */ 189 | { 190 | override var outline_isLeaf: Bool { 191 | return self.outline_childCount == 0 192 | } 193 | 194 | override var outline_childCount: Int { 195 | return self.outline_children.count 196 | } 197 | 198 | override var outline_children: [OutlineNodeModel] { 199 | if self.field.options.contains(.displayContainerContentsAsChild) 200 | { 201 | if let collectionType = field.type as? MKNodeFieldCollectionType { 202 | if let elementType = collectionType.elementType { 203 | return value.outline_nodes.reduce([], { $0 + TypeAdapter.For(value: $1 as! NSObject, ofType: elementType, inNode: self.node).outline_nodes }) 204 | } else { 205 | return value.outline_nodes 206 | } 207 | } 208 | } 209 | 210 | // If the type is a pointer, then we always proxy the contents 211 | if self.type is MKNodeFieldPointerType, 212 | let pointer = value as? MKPointer { 213 | if let pointee = pointer.pointee.value(forKey: "value") { 214 | return (pointee as! NSObject).outline_children 215 | } else { 216 | return [] 217 | } 218 | } 219 | 220 | return self.value.outline_children 221 | } 222 | 223 | override var outline_title: String { 224 | if let description = self.field.description { 225 | return description 226 | } else { 227 | return self.field.name 228 | } 229 | } 230 | } 231 | 232 | extension FieldAdapter /* DetailRowModel */ 233 | { 234 | override var detail_value: String? { 235 | let fieldValue: String? 236 | let alternateValue: String? = self.alternateFieldAdapter?.detail_value 237 | 238 | if let alternateValue = alternateValue, 239 | self.field.options.contains(.substituteAlternateFieldValue) { 240 | return alternateValue 241 | } 242 | 243 | if self.field.options.contains(.ignoreContainerContents) == false, 244 | let typeAdapter = self.typeAdapter, 245 | typeAdapter.providesSubFields { 246 | return alternateValue 247 | } 248 | 249 | if let formatter = self.field.valueFormatter, 250 | let formattedDescription = formatter.string(for: self.value) { 251 | fieldValue = formattedDescription 252 | } else { 253 | fieldValue = self.value?.detail_value 254 | } 255 | 256 | if let alternateValue = alternateValue, 257 | let fieldValue = fieldValue, 258 | self.field.options.contains(.hideAlternateFieldValue) == false { 259 | return fieldValue + " (" + alternateValue + ")" 260 | } else { 261 | return fieldValue 262 | } 263 | } 264 | 265 | override var detail_description: String? { 266 | let fieldDescription: String? 267 | let alternateDescription: String? = self.alternateFieldAdapter?.detail_description 268 | 269 | if let alternateDescription = alternateDescription, 270 | self.field.options.contains(.substituteAlternateFieldDescription) { 271 | return alternateDescription 272 | } 273 | 274 | 275 | if let fd = self.field.description { 276 | fieldDescription = fd 277 | } else { 278 | fieldDescription = self.field.name 279 | } 280 | 281 | if let alternateDescription = alternateDescription, 282 | let fieldDescription = fieldDescription, 283 | self.field.options.contains(.showAlternateFieldDescription) { 284 | return fieldDescription + " (" + alternateDescription + ")" 285 | } else { 286 | return fieldDescription 287 | } 288 | } 289 | 290 | override var detail_data: Data? { 291 | guard self.field.options.contains(.hideData) == false else { return nil } 292 | 293 | if let dataRecipe = self.field.dataRecipe, 294 | let node = self.node as? MKBackedNode { 295 | return dataRecipe.data(for: self.field, of: node) 296 | } else { 297 | return self.value.detail_data 298 | } 299 | } 300 | 301 | override func detail_address(mode addressMode: MKNodeAddressType) -> NSNumber? { 302 | guard self.field.options.contains(.hideAddress) == false else { return nil } 303 | 304 | if let dataRecipe = self.field.dataRecipe, 305 | let node = self.node as? MKBackedNode { 306 | var addr: NSNumber? 307 | 308 | ExceptionSafePerform { 309 | addr = dataRecipe.address(addressMode.rawValue, of: self.field, of: node) 310 | } 311 | 312 | return addr 313 | } 314 | else if let node = self.node as? MKAddressedNode, self.fieldIndex == 0 { 315 | return node.nodeAddress(addressMode) as NSNumber 316 | } 317 | else { 318 | return self.value.detail_address(mode: addressMode) 319 | } 320 | } 321 | } 322 | 323 | extension FieldAdapter: DetailRowDisplayModel 324 | { 325 | var detail_group_identifier: UInt { 326 | return self.node.detail_group_identifier 327 | } 328 | 329 | var detail_backgroundColor: NSColor? { 330 | return nil 331 | } 332 | } 333 | 334 | extension FieldAdapter: DataModel 335 | { 336 | func address(mode addressMode: MKNodeAddressType) -> NSNumber? { 337 | if let dataRecipe = self.field.dataRecipe, 338 | let node = self.node as? MKBackedNode { 339 | return dataRecipe.address(addressMode.rawValue, of: self.field, of: node) 340 | } else { 341 | return nil 342 | } 343 | } 344 | 345 | var data: Data? { 346 | if let dataRecipe = self.field.dataRecipe, 347 | let node = self.node as? MKBackedNode { 348 | return dataRecipe.data(for: self.field, of: node) 349 | } else { 350 | return nil 351 | } 352 | } 353 | } 354 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Field/SubFieldAdapter.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file SubFieldAdapter.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | class SubFieldAdapter: NSObject 31 | { 32 | unowned let field: FieldAdapter 33 | let valueProvider: NSObject 34 | 35 | init(valueProvider: NSObject, inField field: FieldAdapter) { 36 | self.field = field 37 | self.valueProvider = valueProvider 38 | } 39 | } 40 | 41 | extension SubFieldAdapter /* OutlineNodeModel */ 42 | { 43 | override var outline_title: String { 44 | return self.valueProvider.outline_title 45 | } 46 | } 47 | 48 | extension SubFieldAdapter /* DetailRowModel */ 49 | { 50 | override var detail_value: String? { 51 | return self.valueProvider.detail_value 52 | } 53 | 54 | override var detail_description: String? { 55 | return self.valueProvider.detail_description 56 | } 57 | } 58 | 59 | extension SubFieldAdapter: DetailRowDisplayModel 60 | { 61 | var detail_group_identifier: UInt { 62 | return self.field.detail_group_identifier 63 | } 64 | 65 | var detail_backgroundColor: NSColor? { 66 | return self.field.detail_backgroundColor 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /MachOExplorer/Model/MKAddressedNode+Detail.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MKAddressedNode+Detail.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension MKAddressedNode 31 | { 32 | override func detail_address(mode addressMode: MKNodeAddressType) -> NSNumber? { 33 | var addr: mk_vm_address_t? 34 | 35 | ExceptionSafePerform { 36 | addr = self.nodeAddress(addressMode) 37 | } 38 | 39 | return addr as NSNumber? 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /MachOExplorer/Model/MKBackedNode+Data.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MKBackedNode+Data.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension MKBackedNode: DataModel 31 | { 32 | func address(mode addressMode: MKNodeAddressType) -> NSNumber? { 33 | return self.nodeAddress(addressMode) as NSNumber 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /MachOExplorer/Model/MKBackedNode+Detail.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MKBackedNode+Detail.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension MKBackedNode 31 | { 32 | override var detail_data: Data? { 33 | return self.data 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /MachOExplorer/Model/MKNode+Adapter.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MKNode+Adapter.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension MKNode 31 | { 32 | @objc func adapter(forField field: MKNodeField) -> FieldAdapter? { 33 | return FieldAdapter(field: field, ofNode: self) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /MachOExplorer/Model/MKNode+Detail.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MKNode+Detail.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension MKNode /* DetailModel */ 31 | { 32 | override var detail_rows: [DetailRowModel] { 33 | var rows = Array() 34 | 35 | let nodeLayout = self.layout 36 | let nodeFields = nodeLayout.allFields 37 | 38 | for field in nodeFields { 39 | guard field.options.contains(.displayAsDetail) || field.options.contains(.displayAsChild) == false else { continue } 40 | 41 | if let fieldAdapter = self.adapter(forField: field) { 42 | rows += fieldAdapter.detail_rows 43 | } 44 | } 45 | 46 | return rows 47 | } 48 | } 49 | 50 | extension MKNode /* DetailRowModel */ 51 | { 52 | override var detail_value: String? { 53 | #if TRACE_DESCRIPTIONS_AND_VALUES 54 | return "[N]" + self.description 55 | #else 56 | return self.description 57 | #endif 58 | } 59 | 60 | override var detail_description: String? { 61 | #if TRACE_DESCRIPTIONS_AND_VALUES 62 | return "[N]" + type(of: self).description() 63 | #else 64 | return type(of: self).description() 65 | #endif 66 | } 67 | 68 | override var detail_data: Data? { 69 | return nil 70 | } 71 | 72 | override func detail_address(mode addressMode: MKNodeAddressType) -> NSNumber? { 73 | return nil 74 | } 75 | } 76 | 77 | extension MKNode: DetailRowDisplayModel 78 | { 79 | var detail_group_identifier: UInt { 80 | return unsafeBitCast(self, to: UInt.self) 81 | } 82 | 83 | var detail_backgroundColor: NSColor? { 84 | return nil 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /MachOExplorer/Model/MKNode+Outline.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MKNode+Outline.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension MKNode /* OutlineModel */ 31 | { 32 | } 33 | 34 | extension MKNode /* OutlineNodeModel */ 35 | { 36 | override var outline_isLeaf: Bool { 37 | return self.outline_children.count == 0 38 | } 39 | 40 | override var outline_childCount: Int { 41 | return self.outline_children.count 42 | } 43 | 44 | override var outline_children: [OutlineNodeModel] { 45 | if let cachedChildren = objc_getAssociatedObject(self, "outlineChildren") as? [OutlineNodeModel] { 46 | return cachedChildren 47 | } 48 | 49 | var children = Array() 50 | 51 | let nodeLayout = self.layout 52 | let nodeFields = nodeLayout.allFields 53 | 54 | for field in nodeFields { 55 | if let fieldAdapter = self.adapter(forField: field) { 56 | children += fieldAdapter.outline_nodes 57 | } 58 | } 59 | 60 | objc_setAssociatedObject(self, "outlineChildren", children, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) 61 | return children 62 | } 63 | 64 | override var outline_title: String { 65 | #if TRACE_DESCRIPTIONS_AND_VALUES 66 | return "[N]" + self.description 67 | #else 68 | return self.description 69 | #endif 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Model.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file Model.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import Cocoa 29 | import MachOKit 30 | 31 | @objc protocol Model: NSObjectProtocol { } 32 | -------------------------------------------------------------------------------- /MachOExplorer/Model/OutlineModel.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file OutlineModel.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import Cocoa 29 | import MachOKit 30 | 31 | @objc protocol OutlineModel: Model 32 | { 33 | var outline_nodes: [OutlineNodeModel] { get } 34 | } 35 | 36 | @objc protocol OutlineNodeModel: Model 37 | { 38 | var outline_isLeaf: Bool { get } 39 | 40 | var outline_childCount: Int { get } 41 | 42 | var outline_children: [OutlineNodeModel] { get } 43 | 44 | var outline_title: String { get } 45 | } 46 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Overrides/FAT/MKFatArch+Model.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MKFatArch+Model.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension MKFatArch /* OutlineModel */ 31 | { 32 | override var outline_children: [OutlineNodeModel] { 33 | var children = super.outline_children 34 | 35 | if let machoImage = try? MKMachOImage(name: nil, flags: .init(rawValue: 0), atAddress: mk_vm_address_t(self.offset), inMapping: self.memoryMap) { 36 | children += machoImage.outline_nodes 37 | } 38 | 39 | return children 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Overrides/MachO/MKExport+Model.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MKExport+Model.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension MKExport /* DetailModel */ 31 | { 32 | override var detail_rows: [DetailRowModel] { 33 | return [self] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Overrides/MachO/MKExportTrieBranch+Model.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MKExportTrieBranch+Model.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension MKExportTrieBranch 31 | { 32 | @objc var address: mk_vm_address_t { 33 | return (self.nearestAncestor(ofType: MKExportsInfo.self) as! MKExportsInfo).nodeVMAddress + self.offset 34 | } 35 | 36 | override func adapter(forField field: MKNodeField) -> FieldAdapter? { 37 | if field.name == "offset" { 38 | let modifiedValueRecipe = MKNodeFieldOperationReadKeyPath(keyPath: "address") 39 | let modifiedField = MKNodeField(name: field.name, description: "Next Node", type: field.type, value: modifiedValueRecipe, data: field.dataRecipe, formatter: Formatter.mk_hexCompact(), options: field.options) 40 | 41 | return FieldAdapter(field: modifiedField, ofNode: self) 42 | } else { 43 | return super.adapter(forField: field) 44 | } 45 | } 46 | } 47 | 48 | extension MKExportTrieBranch /* DetailRowDisplayModel */ 49 | { 50 | override var detail_group_identifier: UInt { 51 | return unsafeBitCast(self.parent, to: UInt.self) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Overrides/MachO/MKFixup+Model.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MKFixup+Model.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension MKFixup /* DetailModel */ 31 | { 32 | override var detail_rows: [DetailRowModel] { 33 | return [self] 34 | } 35 | } 36 | 37 | extension MKFixup /* DetailRowModel */ 38 | { 39 | override var detail_value: String? { 40 | let addressField = self.layout.field(withName: "address", searchAllFields: false)! 41 | let address = addressField.valueFormatter?.string(for: addressField.valueRecipe.value(for: addressField, of: self).value) 42 | 43 | let sectionField = self.layout.field(withName: "section", searchAllFields: false)! 44 | let section = sectionField.valueRecipe.value(for: sectionField, of: self).value?.description 45 | 46 | if let section = section { 47 | return "\(address!) (\(section))" 48 | } else { 49 | return "\(address!)" 50 | } 51 | } 52 | 53 | override var detail_description: String? { 54 | let typeField = self.layout.field(withName: "type", searchAllFields: false)! 55 | let type = typeField.valueFormatter?.string(for: typeField.valueRecipe.value(for: typeField, of: self).value) 56 | 57 | return type 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Overrides/MachO/MKFunctionStarts+Model.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MKFunctionStarts+Model.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension MKFunctionStarts /* OutlineNodeModel */ 31 | { 32 | override var outline_children: [OutlineNodeModel] { 33 | return [] 34 | } 35 | } 36 | 37 | extension MKFunctionStarts /* DetailModel */ 38 | { 39 | class Adapter: NSObject { 40 | var offset: MKFunctionOffset? 41 | var function: MKFunction? 42 | 43 | init(offset: MKFunctionOffset?, function: MKFunction?) { 44 | super.init() 45 | self.offset = offset 46 | self.function = function 47 | } 48 | 49 | override var detail_value: String? { 50 | return self.function?.detail_value 51 | } 52 | 53 | override var detail_description: String? { 54 | return self.offset?.detail_value 55 | } 56 | 57 | override var detail_data: Data? { 58 | return self.offset?.detail_data 59 | } 60 | 61 | override func detail_address(mode addressMode: MKNodeAddressType) -> NSNumber? { 62 | return self.offset?.detail_address(mode: addressMode) 63 | } 64 | } 65 | 66 | override var detail_rows: [DetailRowModel] { 67 | var rows = Array() 68 | 69 | let offsets = self.offsets 70 | let functions = self.functions 71 | 72 | var i = 0; 73 | let count = max(offsets.count, functions.count) 74 | while i < count { 75 | let offset = i < offsets.count ? offsets[i] : nil 76 | let function = i < functions.count ? functions[i] : nil 77 | 78 | rows.append(Adapter(offset: offset, function: function)) 79 | i = i + 1 80 | } 81 | 82 | return rows 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Overrides/MachO/MKPointerNode+Model.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MKPointerNode+Model.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension MKPointerNode /* OutlineModel */ 31 | { 32 | override var outline_nodes: [OutlineNodeModel] { 33 | // Use KVC to get the 'value' to work around a swift compiler crash 34 | if let pointee = self.pointee.value(forKey: "value") { 35 | return [(pointee as! NSObject)] 36 | } else { 37 | return super.outline_nodes 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Overrides/MachO/MKSection+Model.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MKSection+Model.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension MKSection 31 | { 32 | override func adapter(forField field: MKNodeField) -> FieldAdapter? { 33 | if field.name == "name" || 34 | field.name == "alignment" || 35 | field.name == "fileOffset" || 36 | field.name == "vmAddress" || 37 | field.name == "size" || 38 | field.name == "type" || 39 | field.name == "userAttributes" || 40 | field.name == "systemAttributes" { 41 | return nil 42 | } 43 | 44 | return super.adapter(forField: field) 45 | } 46 | } 47 | 48 | extension MKSection /* OutlineNodeModel */ 49 | { 50 | override var outline_title: String { 51 | return "Section (" + self.description + ")" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Overrides/ObjC/MKObjCCategory+Model.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MKObjCCategory+Model.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension MKObjCCategory 31 | { 32 | override open var description: String { 33 | if let name = self.name.pointee.value?.string { 34 | return name 35 | } else { 36 | return super.description 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Overrides/ObjC/MKObjCClass+Model.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MKObjCClass+Model.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension MKObjCClass 31 | { 32 | override open var description: String { 33 | if let className = self.classData.pointee.value?.name.pointee.value?.string { 34 | return className 35 | } else { 36 | return super.description 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Overrides/ObjC/MKObjCProtocol+Model.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MKObjCProtocol+Model.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension MKObjCProtocol 31 | { 32 | override open var description: String { 33 | if let name = self.mangledName.pointee.value?.string { 34 | return name 35 | } else { 36 | return super.description 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Type/BitFieldTypeAdapter.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file BitFieldTypeAdapter.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | class BitfieldTypeAdapter: TypeAdapter 31 | { 32 | required init(value: NSObject, ofType type: MKNodeFieldType, inNode node: MKNode) { 33 | assert(type is MKNodeFieldBitfieldType) 34 | super.init(value: value, ofType: type, inNode: node) 35 | } 36 | 37 | override var providesSubFields: Bool { 38 | let type = self.type as! MKNodeFieldBitfieldType 39 | 40 | if type.bits.count > 1 { 41 | return true 42 | } else { 43 | return false 44 | } 45 | } 46 | } 47 | 48 | extension BitfieldTypeAdapter /* DetailModel */ 49 | { 50 | override var detail_rows: [DetailRowModel] { 51 | guard let value = self.value as? NSNumber else { return super.detail_rows } 52 | 53 | let type = self.type as! MKNodeFieldBitfieldType 54 | var rows = Array() 55 | 56 | for mask in type.bits { 57 | let maskedValue = value.mk_mask(using: mask) 58 | let shiftedValue = maskedValue.mk_shift(type.shift(forMask: mask)) 59 | 60 | if let type = type.type(forMask: mask) { 61 | if type is MKNodeFieldEnumerationType { 62 | rows += BitfieldEnumerationTypeAdapter(value: shiftedValue, unshiftedValue: maskedValue, ofType: type, inContainerType: self.type, inNode: self.node).detail_rows 63 | } else { 64 | rows += TypeAdapter.For(value: shiftedValue, ofType: type, inNode: self.node).detail_rows 65 | } 66 | } else { 67 | // TODO - 68 | continue; 69 | } 70 | } 71 | 72 | return rows 73 | } 74 | } 75 | 76 | 77 | 78 | class BitfieldEnumerationTypeAdapter: TypeAdapter 79 | { 80 | let unshiftedValue: NSObject 81 | let containerType: MKNodeFieldType 82 | 83 | required init(value: NSObject, unshiftedValue: NSObject, ofType type: MKNodeFieldType, inContainerType containerType: MKNodeFieldType, inNode node: MKNode) { 84 | assert(type is MKNodeFieldEnumerationType) 85 | self.unshiftedValue = unshiftedValue 86 | self.containerType = containerType 87 | super.init(value: value, ofType: type, inNode: node) 88 | } 89 | 90 | required init(value: NSObject, ofType type: MKNodeFieldType, inNode node: MKNode) { 91 | assert(type is MKNodeFieldContainerType) 92 | self.unshiftedValue = value 93 | self.containerType = type 94 | super.init(value: value, ofType: type, inNode: node) 95 | } 96 | 97 | override var detail_description: String? { 98 | switch (self.containerType as! MKNodeFieldNumericType).size(for: self.node) { 99 | case 1: 100 | return Formatter.mk_hex8().string(for: self.unshiftedValue) 101 | case 2: 102 | return Formatter.mk_hex16().string(for: self.unshiftedValue) 103 | case 4: 104 | return Formatter.mk_hex32().string(for: self.unshiftedValue) 105 | case 8: 106 | return Formatter.mk_hex64().string(for: self.unshiftedValue) 107 | default: 108 | return Formatter.mk_hex().string(for: self.unshiftedValue) 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Type/CollectionTypeAdapter.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file CollectionTypeAdapter.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | class CollectionTypeAdapter: TypeAdapter 31 | { 32 | required init(value: NSObject, ofType type: MKNodeFieldType, inNode node: MKNode) { 33 | assert(type is MKNodeFieldCollectionType) 34 | super.init(value: value, ofType: type, inNode: node) 35 | } 36 | } 37 | 38 | extension CollectionTypeAdapter /* OutlineModel */ 39 | { 40 | override var outline_nodes: [OutlineNodeModel] { 41 | let collectionType = self.type as! MKNodeFieldCollectionType 42 | 43 | if let elementType = collectionType.elementType { 44 | return self.value.outline_nodes.reduce([], { $0 + TypeAdapter.For(value: $1 as! NSObject, ofType: elementType, inNode: self.node).outline_nodes }) 45 | } else { 46 | return self.value.outline_nodes 47 | } 48 | } 49 | } 50 | 51 | extension CollectionTypeAdapter /* DetailModel */ 52 | { 53 | override var detail_rows: [DetailRowModel] { 54 | let collectionType = self.type as! MKNodeFieldCollectionType 55 | 56 | if let elementType = collectionType.elementType { 57 | return self.value.detail_rows.reduce([], { $0 + TypeAdapter.For(value: $1 as! NSObject, ofType: elementType, inNode: self.node).detail_rows }) 58 | } else { 59 | return self.value.detail_rows 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Type/ContainerTypeAdapter.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file ContainerTypeAdapter.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | class ContainerTypeAdapter: TypeAdapter 31 | { 32 | required init(value: NSObject, ofType type: MKNodeFieldType, inNode node: MKNode) { 33 | assert(type is MKNodeFieldContainerType) 34 | super.init(value: value, ofType: type, inNode: node) 35 | } 36 | } 37 | 38 | extension ContainerTypeAdapter /* OutlineModel */ 39 | { 40 | override var outline_nodes: [OutlineNodeModel] { 41 | return self.value.outline_nodes 42 | } 43 | } 44 | 45 | extension ContainerTypeAdapter /* DetailModel */ 46 | { 47 | override var detail_rows: [DetailRowModel] { 48 | return self.value.detail_rows 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Type/OptionSetTypeAdapter.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file OptionSetTypeAdapter.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | class OptionSetTypeAdapter: TypeAdapter 31 | { 32 | required init(value: NSObject, ofType type: MKNodeFieldType, inNode node: MKNode) { 33 | assert(type is MKNodeFieldOptionSetType) 34 | super.init(value: value, ofType: type, inNode: node) 35 | } 36 | 37 | override var providesSubFields: Bool { return true } 38 | } 39 | 40 | extension OptionSetTypeAdapter /* DetailModel, DetailRowModel */ 41 | { 42 | class OptionDetailRowAdapter: NSObject 43 | { 44 | let value: NSNumber 45 | let name: String 46 | 47 | init(_ value: NSNumber, _ name: String) { 48 | self.value = value 49 | self.name = name 50 | } 51 | 52 | override var detail_value: String? { 53 | return self.name 54 | } 55 | 56 | override var detail_description: String? { 57 | return Formatter.mk_hex().string(for: self.value) 58 | } 59 | } 60 | 61 | override var detail_rows: [DetailRowModel] { 62 | guard let value = self.value as? NSNumber else { return [] } 63 | 64 | let v: UInt64 = value.mk_UnsignedValue(nil) 65 | guard v != 0 || (self.type as! MKNodeFieldOptionSetType).options[0] != nil else { 66 | return [] 67 | } 68 | 69 | var rows = Array() 70 | 71 | for (mask, name) in (self.type as! MKNodeFieldOptionSetType).options { 72 | let m: UInt64 = mask.mk_UnsignedValue(nil) 73 | 74 | if m == 0 && v != 0 { 75 | continue 76 | } 77 | 78 | if (v & m) == m { 79 | rows.append(OptionDetailRowAdapter(mask, name)) 80 | } else if (self.type as! MKNodeFieldOptionSetType).optionSetTraits.contains(.partialMatchingAllowed) { 81 | if (v & m) != 0 { 82 | rows.append(OptionDetailRowAdapter(mask, name)) 83 | } 84 | } 85 | } 86 | 87 | return rows 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Type/TypeAdapter.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file TypeAdapter.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | class TypeAdapter: NSObject 31 | { 32 | let value: NSObject 33 | let type: MKNodeFieldType 34 | let node: MKNode 35 | 36 | required init(value: NSObject, ofType type: MKNodeFieldType, inNode node: MKNode) { 37 | self.value = value 38 | self.type = type 39 | self.node = node; 40 | } 41 | 42 | static func For(value: NSObject, ofType type: MKNodeFieldType, inNode node: MKNode) -> TypeAdapter { 43 | if type is MKNodeFieldOptionSetType { 44 | return OptionSetTypeAdapter(value: value, ofType: type, inNode: node) 45 | } 46 | else if type is MKNodeFieldBitfieldType { 47 | return BitfieldTypeAdapter(value: value, ofType: type, inNode: node) 48 | } 49 | else if type is MKNodeFieldCollectionType { 50 | return CollectionTypeAdapter(value: value, ofType: type, inNode: node) 51 | } 52 | else if type is MKNodeFieldContainerType { 53 | return ContainerTypeAdapter(value: value, ofType: type, inNode: node) 54 | } 55 | else { 56 | return TypeAdapter(value: value, ofType: type, inNode: node) 57 | } 58 | } 59 | 60 | var providesSubFields: Bool { return false } 61 | } 62 | 63 | extension TypeAdapter /* OutlineModel */ 64 | { 65 | override var outline_nodes: [OutlineNodeModel] { 66 | return [self] 67 | } 68 | } 69 | 70 | extension TypeAdapter /* OutlineNodeModel */ 71 | { 72 | override var outline_isLeaf: Bool { 73 | return self.value.outline_isLeaf 74 | } 75 | 76 | override var outline_childCount: Int { 77 | return self.value.outline_childCount 78 | } 79 | 80 | override var outline_children: [OutlineNodeModel] { 81 | return self.value.outline_children 82 | } 83 | 84 | override var outline_title: String { 85 | if let formatter = self.type.formatter, 86 | let formattedDescription = formatter.string(for: self.value) { 87 | return formattedDescription 88 | } else { 89 | return self.value.outline_title 90 | } 91 | } 92 | } 93 | 94 | extension TypeAdapter /* DetailModel */ 95 | { 96 | override var detail_rows: [DetailRowModel] { 97 | return [self] 98 | } 99 | } 100 | 101 | extension TypeAdapter /* DetailRowModel */ 102 | { 103 | override var detail_value: String? { 104 | if let formatter = self.type.formatter, 105 | let formattedDescription = formatter.string(for: self.value) { 106 | return formattedDescription 107 | } else if let valueDescription = self.value.detail_value { 108 | return valueDescription 109 | } else { 110 | return nil 111 | } 112 | } 113 | 114 | override var detail_description: String? { 115 | return self.type.name 116 | } 117 | 118 | override var detail_data: Data? { 119 | return self.value.detail_data 120 | } 121 | 122 | override func detail_address(mode addressMode: MKNodeAddressType) -> NSNumber? { 123 | return self.value.detail_address(mode: addressMode) 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Value/MKOptional+Model.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file MKOptional+Model.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension MKOptional /* OutlineModel */ 31 | { 32 | override var outline_nodes: [OutlineNodeModel] { 33 | // Use KVC to get the 'value' to work around a swift compiler crash 34 | if let value = self.value(forKey: "value") as? OutlineModel { 35 | return value.outline_nodes 36 | } else { 37 | return [] 38 | } 39 | } 40 | } 41 | 42 | extension MKOptional /* DetailModel */ 43 | { 44 | override var detail_rows: [DetailRowModel] { 45 | // Use KVC to get the 'value' to work around a swift compiler crash 46 | if let value = self.value(forKey: "value") as? DetailModel { 47 | return value.detail_rows 48 | } else { 49 | return [] 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Value/NSArray+Model.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file NSArray+Model.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension NSArray /* OutlineModel */ 31 | { 32 | override var outline_nodes: [OutlineNodeModel] { 33 | return (self as! [NSObject]).reduce([], { $0 + $1.outline_nodes }) 34 | } 35 | } 36 | 37 | extension NSArray /* DetailModel */ 38 | { 39 | override var detail_rows: [DetailRowModel] { 40 | if self.count < 1 { 41 | return []; 42 | } 43 | 44 | var detailRowModels = Array() 45 | 46 | // Optimization - Ask the first item for its detail_rows, assume that 47 | // the detail_rows of every item will contain the same number of 48 | // DetailRowModel objects. 49 | let reserveCapacity = self.count * (self[0] as! NSObject).detail_rows.count; 50 | detailRowModels.reserveCapacity(reserveCapacity); 51 | 52 | for item in self { 53 | detailRowModels += (item as! NSObject).detail_rows; 54 | } 55 | 56 | return detailRowModels; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Value/NSDictionary+Model.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file NSDictionary+Model.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension NSDictionary /* OutlineModel */ 31 | { 32 | override var outline_nodes: [OutlineNodeModel] { 33 | return (self.allValues as! [NSObject]).reduce([], { $0 + $1.outline_nodes }) 34 | } 35 | } 36 | 37 | extension NSDictionary /* DetailModel */ 38 | { 39 | override var detail_rows: [DetailRowModel] { 40 | return (self.allValues as! [NSObject]).reduce([], { $0 + $1.detail_rows }) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /MachOExplorer/Model/Value/NSObject+Model.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file NSObject+Model.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import MachOKit 29 | 30 | extension NSObject: Model { } 31 | 32 | extension NSObject: OutlineModel 33 | { 34 | var outline_nodes: [OutlineNodeModel] { 35 | return [self] 36 | } 37 | } 38 | 39 | extension NSObject: OutlineNodeModel 40 | { 41 | var outline_isLeaf: Bool { 42 | return true 43 | } 44 | 45 | var outline_childCount: Int { 46 | return 0 47 | } 48 | 49 | var outline_children: [OutlineNodeModel] { 50 | return [] 51 | } 52 | 53 | var outline_title: String { 54 | return self.description 55 | } 56 | } 57 | 58 | extension NSObject: DetailModel 59 | { 60 | var detail_rows: [DetailRowModel] { 61 | return [self] 62 | } 63 | } 64 | 65 | extension NSObject: DetailRowModel 66 | { 67 | var detail_value: String? { 68 | return self.description 69 | } 70 | 71 | var detail_description: String? { 72 | return type(of: self).description() 73 | } 74 | 75 | var detail_data: Data? { 76 | return nil 77 | } 78 | 79 | func detail_address(mode addressMode: MKNodeAddressType) -> NSNumber? { 80 | return nil 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /MachOExplorer/Utility/NS+Initialize.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file NS+Initialize.h 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | @import Cocoa; 29 | 30 | @interface NSViewController (Initialize) 31 | + (void)heySwiftSomePeopleStillNeedToOverrideInitialize; 32 | @end 33 | -------------------------------------------------------------------------------- /MachOExplorer/Utility/NS+Initialize.m: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //| NS+Initialize.m 5 | //| 6 | //| D.V. 7 | //| Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | #import "NS+Initialize.h" 29 | #import 30 | 31 | @implementation NSViewController (Initialize) 32 | 33 | static void (*NSViewController_OriginalInitialize)(id, SEL) = NULL; 34 | 35 | static void NSViewController_Initialize(Class self, SEL _cmd) 36 | { 37 | if (NSViewController_OriginalInitialize) 38 | NSViewController_OriginalInitialize(self, _cmd); 39 | 40 | [self heySwiftSomePeopleStillNeedToOverrideInitialize]; 41 | } 42 | 43 | + (void)load 44 | { 45 | NSViewController_OriginalInitialize = (typeof(NSViewController_OriginalInitialize))class_replaceMethod(object_getClass(NSViewController.class), @selector(initialize), (IMP)&NSViewController_Initialize, "v16@0:8"); 46 | } 47 | 48 | + (void)heySwiftSomePeopleStillNeedToOverrideInitialize 49 | { 50 | /* For subclasses */ 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /MachOExplorer/Utility/NSValueTransformer+HexRepresentation.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file NSValueTransformer+HexRepresentation.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import Foundation 29 | 30 | class HexRepresentationValueTransformer: ValueTransformer 31 | { 32 | override static func allowsReverseTransformation() -> Bool { 33 | return false 34 | } 35 | 36 | override static func transformedValueClass() -> AnyClass { 37 | return NSString.self 38 | } 39 | 40 | override func transformedValue(_ value: Any?) -> Any? { 41 | guard let data = value as? Data else { return nil } 42 | 43 | let hexCodes: [UInt8] = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70] 44 | var characters = Array(repeating: 0, count: data.count * 2) 45 | 46 | data.enumerateBytes({ bytesPtr, index, stop in 47 | var i = 0 48 | 49 | for byte in bytesPtr { 50 | let hiByte = (byte & 0xF0) >> 4 51 | let loByte = (byte & 0x0F) >> 0 52 | 53 | characters[i] = hexCodes[Int(hiByte)] 54 | characters[i+1] = hexCodes[Int(loByte)] 55 | 56 | i = i + 2 57 | } 58 | }) 59 | 60 | return NSString(bytes: &characters, length: characters.count, encoding: String.Encoding.ascii.rawValue) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /MachOExplorer/Utility/NSValueTransformer+TakeFirst.swift: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file NSValueTransformer+TakeFirst.swift 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | import Foundation 29 | 30 | class TakeFirstValueTransformer: ValueTransformer 31 | { 32 | override static func allowsReverseTransformation() -> Bool { 33 | return true 34 | } 35 | 36 | override func transformedValue(_ value: Any?) -> Any? { 37 | guard let value = value else { return nil } 38 | 39 | return (value as! NSArray).firstObject 40 | } 41 | 42 | override func reverseTransformedValue(_ value: Any?) -> Any? { 43 | guard let value = value else { return nil } 44 | 45 | return [value]; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /MachOExplorer/Utility/Utility.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //! @file Utility.h 5 | //! 6 | //! @author D.V. 7 | //! @copyright Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | @import Foundation; 29 | 30 | NS_ASSUME_NONNULL_BEGIN 31 | 32 | NSException * _Nullable ExceptionSafePerform(NS_NOESCAPE dispatch_block_t block); 33 | 34 | NS_ASSUME_NONNULL_END 35 | -------------------------------------------------------------------------------- /MachOExplorer/Utility/Utility.m: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------// 2 | //| 3 | //| MachOExplorer - A Graphical Mach-O Viewer 4 | //| Utility.m 5 | //| 6 | //| D.V. 7 | //| Copyright (c) 2018 D.V. All rights reserved. 8 | //| 9 | //| Permission is hereby granted, free of charge, to any person obtaining a 10 | //| copy of this software and associated documentation files (the "Software"), 11 | //| to deal in the Software without restriction, including without limitation 12 | //| the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | //| and/or sell copies of the Software, and to permit persons to whom the 14 | //| Software is furnished to do so, subject to the following conditions: 15 | //| 16 | //| The above copyright notice and this permission notice shall be included 17 | //| in all copies or substantial portions of the Software. 18 | //| 19 | //| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | //| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | //| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | //| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | //| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | //| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | //| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | //----------------------------------------------------------------------------// 27 | 28 | #import "Utility.h" 29 | 30 | NSException* ExceptionSafePerform(dispatch_block_t block) 31 | { 32 | @try { 33 | block(); 34 | return nil; 35 | } @catch (NSException *exception) { 36 | return exception; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | Mach-O Explorer is a graphical Mach-O viewer for macOS. It aims to provide an interface and feature set that are similar to the venerable [MachOView](http://sourceforge.net/projects/machoview/) application. Parsing is handled by Mach-O Kit. Mach-O Explorer leverages Mach-O Kit's rich description system to present the parsed data using very little code. 6 | 7 | ![Screenshot](https://raw.githubusercontent.com/DeVaukz/MachO-Explorer/master/.github/hero.png) 8 | 9 | Mach-O Explorer should deploy back to OS X 10.11 (and possibly further) but is *currently* only being actively tested on macOS 10.14. 10 | 11 | ### Limitations 12 | 13 | * Mach-O Explorer does not include a disassembler. This may be added in the future. 14 | * Mach-O Explorer can not attach to a running process to analyze its headers. This may be added in the future once support in Mach-O Kit improves. 15 | * Mach-O Explorer does not support editing Mach-O files and there are no plans to add this feature. 16 | 17 | ## Getting Started 18 | 19 | ### Requirements 20 | 21 | * Xcode 11.0 or later to build 22 | 23 | ### Compiling 24 | 25 | ***Use a recursive git clone***. 26 | 27 | ``` 28 | git clone --recursive https://github.com/DeVaukz/MachO-Explorer 29 | ``` 30 | 31 | Open the `MachOExplorer.xcodeproj` file, select the `MachOExplorer` target and click Run. 32 | 33 | ## License 34 | 35 | Mach-O Explorer is released under the MIT license. See 36 | [LICENSE.md](https://github.com/DeVaukz/MachO-Explorer/blob/master/LICENSE). 37 | -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon.appiconset/AppIcon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeVaukz/MachO-Explorer/e82b6e6136f4312422c276762e837fe853030547/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon_512.png -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon.appiconset/AppIcon_512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DeVaukz/MachO-Explorer/e82b6e6136f4312422c276762e837fe853030547/Resources/Assets.xcassets/AppIcon.appiconset/AppIcon_512@2x.png -------------------------------------------------------------------------------- /Resources/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "size" : "512x512", 45 | "idiom" : "mac", 46 | "filename" : "AppIcon_512.png", 47 | "scale" : "1x" 48 | }, 49 | { 50 | "size" : "512x512", 51 | "idiom" : "mac", 52 | "filename" : "AppIcon_512@2x.png", 53 | "scale" : "2x" 54 | } 55 | ], 56 | "info" : { 57 | "version" : 1, 58 | "author" : "xcode" 59 | } 60 | } -------------------------------------------------------------------------------- /Resources/MachOExplorer-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDocumentTypes 8 | 9 | 10 | LSItemContentTypes 11 | 12 | com.apple.mach-o-dylib 13 | 14 | CFBundleTypeRole 15 | Viewer 16 | LSHandlerRank 17 | Alternate 18 | NSDocumentClass 19 | $(PRODUCT_MODULE_NAME).MachODocument 20 | 21 | 22 | LSItemContentTypes 23 | 24 | public.unix-executable 25 | 26 | CFBundleTypeRole 27 | Viewer 28 | LSHandlerRank 29 | Alternate 30 | NSDocumentClass 31 | $(PRODUCT_MODULE_NAME).MachODocument 32 | 33 | 34 | LSItemContentTypes 35 | 36 | public.data 37 | 38 | CFBundleTypeRole 39 | Viewer 40 | LSHandlerRank 41 | Alternate 42 | NSDocumentClass 43 | $(PRODUCT_MODULE_NAME).MachODocument 44 | 45 | 46 | CFBundleExecutable 47 | $(EXECUTABLE_NAME) 48 | CFBundleIconFile 49 | 50 | CFBundleIdentifier 51 | $(PRODUCT_BUNDLE_IDENTIFIER) 52 | CFBundleInfoDictionaryVersion 53 | 6.0 54 | CFBundleName 55 | $(PRODUCT_NAME) 56 | CFBundleDisplayName 57 | Mach-O Explorer 58 | CFBundlePackageType 59 | APPL 60 | CFBundleShortVersionString 61 | 1.0 62 | CFBundleSignature 63 | ???? 64 | CFBundleVersion 65 | 1 66 | LSApplicationCategoryType 67 | public.app-category.utilities 68 | LSMinimumSystemVersion 69 | $(MACOSX_DEPLOYMENT_TARGET) 70 | NSHumanReadableCopyright 71 | Copyright © 2018-2020 DeVaukz. All rights reserved. 72 | NSMainNibFile 73 | MainMenu 74 | NSPrincipalClass 75 | NSApplication 76 | 77 | 78 | --------------------------------------------------------------------------------