mirror of
https://github.com/darlinghq/darling.git
synced 2025-03-03 07:18:35 +00:00
Add support code needed for gdb-darling
This commit is contained in:
parent
1c1d21ac91
commit
6f1c04770a
@ -25,7 +25,11 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#ifndef MLDR_BUILD
|
||||
#include <mach/mach.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -73,10 +77,12 @@ struct dyld_image_info {
|
||||
/* then file has been modified since dyld loaded it */
|
||||
};
|
||||
|
||||
#ifndef MLDR_BUILD
|
||||
struct dyld_uuid_info {
|
||||
const struct mach_header* imageLoadAddress; /* base address image is mapped into */
|
||||
uuid_t imageUUID; /* UUID of image */
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef void (*dyld_image_notifier)(enum dyld_image_mode mode, uint32_t infoCount, const struct dyld_image_info info[]);
|
||||
|
||||
|
@ -9,8 +9,8 @@ endif(COMMAND cmake_policy)
|
||||
|
||||
enable_language(C ASM)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11")
|
||||
add_definitions(-DINSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}" -D_GNU_SOURCE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -ggdb")
|
||||
add_definitions(-DINSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}" -D_GNU_SOURCE -DMLDR_BUILD)
|
||||
|
||||
add_executable(darling darling.c)
|
||||
|
||||
@ -19,6 +19,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(mldr_sources
|
||||
mldr.c
|
||||
threads.c
|
||||
gdb.c
|
||||
)
|
||||
add_executable(mldr ${mldr_sources})
|
||||
target_link_libraries(mldr -lpthread -ldl)
|
||||
|
58
src/dyld/gdb.c
Normal file
58
src/dyld/gdb.c
Normal file
@ -0,0 +1,58 @@
|
||||
#include "gdb.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
__attribute__ ((noinline))
|
||||
static void gdb_notifier(enum dyld_image_mode mode, uint32_t infoCount, const struct dyld_image_info info[]);
|
||||
static void dyld_notification_wrapper(enum dyld_image_mode mode, uint32_t infoCount, const struct dyld_image_info info[]);
|
||||
|
||||
static struct dyld_all_image_infos* orig_dyld_all_image_infos;
|
||||
|
||||
// This is the symbol GDB looks for
|
||||
struct dyld_all_image_infos _dyld_all_image_infos = {
|
||||
.version = 15,
|
||||
.infoArrayCount = 0,
|
||||
.infoArray = NULL,
|
||||
.notification = &gdb_notifier,
|
||||
};
|
||||
|
||||
void gdb_notifier(enum dyld_image_mode mode, uint32_t infoCount, const struct dyld_image_info info[])
|
||||
{
|
||||
// GDB sets a breakpoint in this function
|
||||
}
|
||||
|
||||
struct jump
|
||||
{
|
||||
uint16_t mov;
|
||||
void* addr;
|
||||
uint16_t jump;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
void setup_gdb_notifications(uint64_t slide, uint64_t addr)
|
||||
{
|
||||
orig_dyld_all_image_infos = (struct dyld_all_image_infos*)(addr + slide);
|
||||
|
||||
// dyld will later rebase the address in notification,
|
||||
// but at this point we must add slide manually.
|
||||
struct jump* jump = (struct jump*)(((uint64_t)orig_dyld_all_image_infos->notification) + slide);
|
||||
|
||||
// Rewrite instructions in the notification function to redirect the call to us.
|
||||
#ifdef __x86_64__
|
||||
jump->mov = 0xb948; // movabs imm,%rcx
|
||||
jump->addr = (void*) &dyld_notification_wrapper; // immediate for preceding movabs
|
||||
jump->jump = 0xe1ff; // jmpq *%ecx
|
||||
#else
|
||||
# error TODO: Unsupported platform
|
||||
#endif
|
||||
}
|
||||
|
||||
void dyld_notification_wrapper(enum dyld_image_mode mode, uint32_t infoCount, const struct dyld_image_info info[])
|
||||
{
|
||||
// Copy over all data from dyld's copy of the structure to the one GDB can find (ours)
|
||||
memcpy(&_dyld_all_image_infos, orig_dyld_all_image_infos, sizeof(_dyld_all_image_infos));
|
||||
_dyld_all_image_infos.notification = &gdb_notifier;
|
||||
|
||||
printf("Got notification from dyld\n");
|
||||
gdb_notifier(mode, infoCount, info);
|
||||
}
|
||||
|
9
src/dyld/gdb.h
Normal file
9
src/dyld/gdb.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef _GDB_H_
|
||||
#define _GDB_H_
|
||||
#include <mach-o/dyld_images.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void setup_gdb_notifications(uint64_t slide, uint64_t addr);
|
||||
|
||||
#endif
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <dlfcn.h>
|
||||
#include "elfcalls.h"
|
||||
#include "threads.h"
|
||||
#include "gdb.h"
|
||||
|
||||
#ifndef PAGE_SIZE
|
||||
# define PAGE_SIZE 4096
|
||||
@ -233,6 +234,23 @@ void load64(int fd, uint64_t* entryPoint_out, uint64_t* mh_out)
|
||||
if (seg->fileoff == 0)
|
||||
mappedHeader = (struct mach_header_64*) (seg->vmaddr + slide);
|
||||
}
|
||||
|
||||
if (strcmp(SEG_DATA, seg->segname) == 0)
|
||||
{
|
||||
// Look for section named __all_image_info for GDB integration
|
||||
struct section_64* sect = (struct section_64*) (seg+1);
|
||||
struct section_64* end = (struct section_64*) (&cmds[p + lc->cmdsize]);
|
||||
|
||||
while (sect < end)
|
||||
{
|
||||
if (strncmp(sect->sectname, "__all_image_info", 16) == 0)
|
||||
{
|
||||
setup_gdb_notifications(slide, sect->addr);
|
||||
break;
|
||||
}
|
||||
sect++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LC_UNIXTHREAD:
|
||||
|
Loading…
x
Reference in New Issue
Block a user