Add support code needed for gdb-darling

This commit is contained in:
Lubos Dolezel 2017-01-18 20:53:59 +01:00
parent 1c1d21ac91
commit 6f1c04770a
5 changed files with 94 additions and 2 deletions

View File

@ -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[]);

View File

@ -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
View 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
View 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

View File

@ -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: