-
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a1067c8
commit 1ff3d64
Showing
10 changed files
with
491 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
#ifndef BinaryImage_h | ||
#define BinaryImage_h | ||
|
||
#define _Noescape __attribute__((noescape)) | ||
#define ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") | ||
#define ASSUME_NONNULL_END _Pragma("clang assume_nonnull end") | ||
|
||
#include <stdint.h> | ||
#include <stdbool.h> | ||
#include <mach-o/loader.h> | ||
|
||
#if __OBJC__ | ||
#import <Foundation/Foundation.h> | ||
#endif | ||
|
||
ASSUME_NONNULL_BEGIN | ||
|
||
typedef struct { | ||
uintptr_t address; | ||
intptr_t loadAddress; | ||
uintptr_t length; | ||
} MachODataRegion; | ||
|
||
typedef struct { | ||
const uint8_t* uuid; | ||
intptr_t slide; | ||
MachODataRegion ehFrameRegion; | ||
MachODataRegion unwindInfoRegion; | ||
uintptr_t loadAddress; | ||
uintptr_t textSize; | ||
const char* path; | ||
} MachOData; | ||
|
||
#if __LP64__ | ||
typedef struct mach_header_64 MachOHeader; | ||
typedef struct section_64 MachOSection; | ||
typedef struct segment_command_64 SegmentCommand; | ||
typedef struct section_64 Section; | ||
|
||
const static uint32_t LCSegment = LC_SEGMENT_64; | ||
#else | ||
typedef struct mach_header MachOHeader; | ||
typedef struct section MachOSection; | ||
typedef struct segment_command SegmentCommand; | ||
typedef struct section Section; | ||
|
||
const static uint32_t LCSegment = LC_SEGMENT; | ||
#endif | ||
|
||
typedef struct { | ||
const char* name; | ||
const MachOHeader* header; | ||
} BinaryImage; | ||
|
||
typedef void (^BinaryImageIterator)(BinaryImage image, bool* stop); | ||
|
||
void BinaryImageEnumerateLoadedImages(_Noescape BinaryImageIterator iterator); | ||
|
||
typedef void (^BinaryImageLoadCommandIterator)(const struct load_command* lcmd, uint32_t cmdCode, bool* stop); | ||
|
||
void BinaryImageEnumerateLoadCommands(const MachOHeader* header, _Noescape BinaryImageLoadCommandIterator iterator); | ||
|
||
uint8_t* _Nullable BinaryImageGetUUIDBytesFromLoadCommand(const struct load_command* lcmd, uint32_t cmdCode); | ||
|
||
#if __OBJC__ | ||
NSUUID* _Nullable BinaryuImageUUIDFromLoadCommand(const struct load_command* lcmd, uint32_t cmdCode); | ||
#endif | ||
|
||
ASSUME_NONNULL_END | ||
|
||
#endif /* BinaryImage_h */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
#import <Foundation/Foundation.h> | ||
|
||
#include "BinaryImage.h" | ||
#include <mach-o/dyld.h> | ||
|
||
void BinaryImageEnumerateLoadedImages(BinaryImageIterator iterator) { | ||
for (uint32_t i = 0; i < _dyld_image_count(); ++i) { | ||
BinaryImage image = {0}; | ||
|
||
image.name = _dyld_get_image_name(i); | ||
image.header = (MachOHeader*)_dyld_get_image_header(i); | ||
|
||
bool stop = false; | ||
|
||
iterator(image, &stop); | ||
|
||
if (stop) { | ||
break; | ||
} | ||
} | ||
} | ||
|
||
void BinaryImageEnumerateLoadCommands(const MachOHeader* header, BinaryImageLoadCommandIterator iterator) { | ||
if (header == NULL) { | ||
return; | ||
} | ||
|
||
const uint8_t *ptr = (uint8_t *)header + sizeof(MachOHeader); | ||
|
||
for (uint32_t i = 0; i < header->ncmds; ++i) { | ||
const struct load_command* const lcmd = (struct load_command*)ptr; | ||
const uint32_t cmdCode = lcmd->cmd & ~LC_REQ_DYLD; | ||
|
||
bool stop = false; | ||
|
||
iterator(lcmd, cmdCode, &stop); | ||
|
||
if (stop) { | ||
break; | ||
} | ||
|
||
ptr += lcmd->cmdsize; | ||
} | ||
} | ||
|
||
uint8_t* BinaryImageGetUUIDBytesFromLoadCommand(const struct load_command* lcmd, uint32_t cmdCode) { | ||
if (lcmd == NULL || cmdCode != LC_UUID) { | ||
return NULL; | ||
} | ||
|
||
return ((struct uuid_command*)lcmd)->uuid; | ||
} | ||
|
||
NSUUID* BinaryuImageUUIDFromLoadCommand(const struct load_command* lcmd, uint32_t cmdCode) { | ||
const uint8_t* bytes = BinaryImageGetUUIDBytesFromLoadCommand(lcmd, cmdCode); | ||
|
||
return [[NSUUID alloc] initWithUUIDBytes:bytes]; | ||
} | ||
|
||
bool ImpactBinaryImageGetData(const MachOHeader* header, const char* path, MachOData* data) { | ||
if (header == NULL || data == NULL) { | ||
return false; | ||
} | ||
|
||
const uint8_t *ptr = (uint8_t *)header + sizeof(MachOHeader); | ||
|
||
data->loadAddress = (uintptr_t)header; | ||
data->path = path; | ||
|
||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import Foundation | ||
import BinaryImage | ||
|
||
public class DlfcnSymbolicator { | ||
private var pathCache: [String : String] | ||
|
||
public init() { | ||
self.pathCache = [:] | ||
} | ||
|
||
private lazy var imageMap: [UUID: BinaryImage] = { | ||
var map: [UUID: BinaryImage] = [:] | ||
|
||
BinaryImageEnumerateLoadedImages { image, _ in | ||
BinaryImageEnumerateLoadCommands(image.header) { lcmd, code, stop in | ||
switch code { | ||
case UInt32(LC_UUID): | ||
if let uuid = BinaryuImageUUIDFromLoadCommand(lcmd, code) { | ||
map[uuid] = image | ||
} | ||
|
||
stop.pointee = true | ||
default: | ||
break | ||
} | ||
} | ||
} | ||
|
||
return map | ||
}() | ||
} | ||
|
||
extension DlfcnSymbolicator: Symbolicator { | ||
public func symbolicate(address: Int, in target: SymbolicationTarget) -> [SymbolInfo] { | ||
guard let loadedImage = imageMap[target.uuid] else { | ||
return [] | ||
} | ||
|
||
let loadAddress = Int(bitPattern: loadedImage.header) | ||
let relativeAddress = address - target.loadAddress | ||
let processAddress = loadAddress + relativeAddress | ||
let ptr = UnsafeRawPointer(bitPattern: processAddress) | ||
var info: Dl_info = Dl_info() | ||
|
||
guard dladdr(ptr, &info) != 0 else { | ||
return [] | ||
} | ||
|
||
let offset = processAddress - Int(bitPattern: info.dli_saddr) | ||
let name = String(cString: info.dli_sname) | ||
let symbolInfo = SymbolInfo(symbol: name, offset: offset) | ||
|
||
return [symbolInfo] | ||
} | ||
} |
Oops, something went wrong.