Skip to content

Commit

Permalink
Merge pull request #1461 from darlinghq/coredump_rework
Browse files Browse the repository at this point in the history
Rework `darling-coredump` To Avoid Hardcoding x86/x64 Logic
  • Loading branch information
CuriousTommy authored Dec 14, 2023
2 parents 3435165 + 4b8daad commit 1aa1d3c
Showing 1 changed file with 90 additions and 50 deletions.
140 changes: 90 additions & 50 deletions src/hosttools/src/coredump/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@

#include <linux/time_types.h>

#if __x86_64__
#include <coredump/x86_64.h>
#else
#error Not implemented
#endif

#include <darling-config.h>

Expand Down Expand Up @@ -238,6 +234,10 @@ static const union nt_file_entry* nt_file_get_entry(const struct coredump_params
return (const union nt_file_entry*)((const char*)header + nt_file_header_size(cprm) + (nt_file_entry_size(cprm) * index));
};

static uint16_t get_elf_machine_type(const struct coredump_params* cprm) {
return cprm->universal_header->e_machine;
}

// first tries to open the file directly, then tries to open the file in the lower layer of the overlay
// (because if we're outside the container, the overlay won't be mounted, but the core dump paths would refer to it)
static int open_file(struct coredump_params* cprm, const char* filename, size_t filename_length) {
Expand Down Expand Up @@ -342,7 +342,7 @@ int main(int argc, char** argv) {
return 1;
}

switch (cprm.universal_header->e_machine) {
switch (get_elf_machine_type(&cprm)) {
case EM_X86_64:
case EM_386:
cprm.input_header = cprm.input_corefile_mapping;
Expand Down Expand Up @@ -681,7 +681,7 @@ struct thread_flavor
};

static
void fill_thread_state32(x86_thread_state32_t* state, const struct thread_info* info)
void fill_x86_thread_state32(x86_thread_state32_t* state, const struct thread_info* info)
{
state->eax = info->prstatus->elf32.general_registers.i386.eax;
state->ebx = info->prstatus->elf32.general_registers.i386.ebx;
Expand All @@ -702,14 +702,14 @@ void fill_thread_state32(x86_thread_state32_t* state, const struct thread_info*
}

static
void fill_float_state32(x86_float_state32_t* state, const struct thread_info* info)
void fill_x86_float_state32(x86_float_state32_t* state, const struct thread_info* info)
{
// TODO
memset(state, 0, sizeof(*state));
}

static
void fill_thread_state64(x86_thread_state64_t* state, const struct thread_info* info)
void fill_x86_thread_state64(x86_thread_state64_t* state, const struct thread_info* info)
{
state->rax = info->prstatus->elf64.general_registers.x86_64.ax;
state->rbx = info->prstatus->elf64.general_registers.x86_64.bx;
Expand All @@ -735,7 +735,7 @@ void fill_thread_state64(x86_thread_state64_t* state, const struct thread_info*
}

static
void fill_float_state64(x86_float_state64_t* state, const struct thread_info* info)
void fill_x86_float_state64(x86_float_state64_t* state, const struct thread_info* info)
{
// TODO
memset(state, 0, sizeof(*state));
Expand All @@ -744,6 +744,8 @@ void fill_float_state64(x86_float_state64_t* state, const struct thread_info* in
static
bool macho_dump_headers32(struct coredump_params* cprm)
{
uint16_t machine_type = get_elf_machine_type(cprm);

// Count memory segments and threads
unsigned int segs = cprm->vm_area_count;
unsigned int threads = cprm->thread_info_count;
Expand All @@ -760,16 +762,25 @@ bool macho_dump_headers32(struct coredump_params* cprm)
}

mh.magic = MH_MAGIC;
#ifdef __x86_64__
mh.cputype = CPU_TYPE_X86;
mh.cpusubtype = CPU_SUBTYPE_X86_ALL;
#else
#warning Missing code for this arch
#endif
mh.filetype = MH_CORE;
mh.ncmds = segs + threads;

const int statesize = sizeof(x86_thread_state32_t) + (DUMP_FLOAT_STATE ? sizeof(x86_float_state32_t) : 0) + sizeof(struct thread_flavor) * (DUMP_FLOAT_STATE ? 2 : 1);
int statesize;
switch (machine_type)
{
case EM_386:
mh.cputype = CPU_TYPE_X86;
mh.cpusubtype = CPU_SUBTYPE_X86_ALL;

statesize = sizeof(struct thread_flavor) + sizeof(x86_thread_state32_t);
statesize += (DUMP_FLOAT_STATE ? sizeof(struct thread_flavor) + sizeof(x86_float_state32_t) : 0);
break;

default:
// Missing code for this arch
abort();
}

mh.sizeofcmds = segs * sizeof(struct segment_command) + threads * (sizeof(struct thread_command) + statesize);
mh.flags = 0;

Expand Down Expand Up @@ -837,25 +848,34 @@ bool macho_dump_headers32(struct coredump_params* cprm)
for (size_t i = 0; i < cprm->thread_info_count; ++i) {
const struct thread_info* thread_info = &cprm->thread_infos[i];
struct thread_command* tc = (struct thread_command*) buffer;
struct thread_flavor* tf = (struct thread_flavor*)(tc+1);
struct thread_flavor* tf;

tc->cmd = LC_THREAD;
tc->cmdsize = memsize;

// General registers
tf->flavor = x86_THREAD_STATE32;
tf->count = x86_THREAD_STATE32_COUNT;

fill_thread_state32((x86_thread_state32_t*)tf->state, thread_info);
switch (machine_type)
{
case EM_386:
// General registers
tf = (struct thread_flavor*)(tc+1);
tf->flavor = x86_THREAD_STATE32;
tf->count = x86_THREAD_STATE32_COUNT;
fill_x86_thread_state32((x86_thread_state32_t*)tf->state, thread_info);

// Float registers
if (DUMP_FLOAT_STATE) {
tf = (struct thread_flavor*) (tf->state + sizeof(x86_thread_state32_t));
tf->flavor = x86_FLOAT_STATE32;
tf->count = x86_FLOAT_STATE32_COUNT;
fill_x86_float_state32((x86_float_state32_t*)tf->state, thread_info);
}

#if DUMP_FLOAT_STATE
// Float registers
tf = (struct thread_flavor*) (tf->state + sizeof(x86_thread_state32_t));
tf->flavor = x86_FLOAT_STATE32;
tf->count = x86_FLOAT_STATE32_COUNT;
break;

fill_float_state32((x86_float_state32_t*)tf->state, thread_info);
#endif
default:
// Missing code for this arch
abort();
}

if (!dump_emit(cprm, buffer, memsize))
{
Expand All @@ -873,6 +893,8 @@ bool macho_dump_headers32(struct coredump_params* cprm)
static
bool macho_dump_headers64(struct coredump_params* cprm)
{
uint16_t machine_type = get_elf_machine_type(cprm);

// Count memory segments and threads
unsigned int segs = cprm->vm_area_count;
unsigned int threads = cprm->thread_info_count;
Expand All @@ -889,16 +911,25 @@ bool macho_dump_headers64(struct coredump_params* cprm)
}

mh.magic = MH_MAGIC_64;
#ifdef __x86_64__
mh.cputype = CPU_TYPE_X86_64;
mh.cpusubtype = CPU_SUBTYPE_X86_64_ALL;
#else
#warning Missing code for this arch
#endif
mh.filetype = MH_CORE;
mh.ncmds = segs + threads;

const int statesize = sizeof(x86_thread_state64_t) + (DUMP_FLOAT_STATE ? sizeof(x86_float_state64_t) : 0) + sizeof(struct thread_flavor) * (DUMP_FLOAT_STATE ? 2 : 1);
int statesize;
switch (machine_type)
{
case EM_X86_64:
mh.cputype = CPU_TYPE_X86_64;
mh.cpusubtype = CPU_SUBTYPE_X86_64_ALL;

statesize = sizeof(struct thread_flavor) + sizeof(x86_thread_state64_t);
statesize += (DUMP_FLOAT_STATE ? sizeof(struct thread_flavor) + sizeof(x86_float_state64_t) : 0);
break;

default:
// Missing code for this arch
abort();
}

mh.sizeofcmds = segs * sizeof(struct segment_command_64) + threads * (sizeof(struct thread_command) + statesize);
mh.flags = 0;
mh.reserved = 0;
Expand Down Expand Up @@ -965,25 +996,34 @@ bool macho_dump_headers64(struct coredump_params* cprm)
for (size_t i = 0; i < cprm->thread_info_count; ++i) {
const struct thread_info* thread_info = &cprm->thread_infos[i];
struct thread_command* tc = (struct thread_command*) buffer;
struct thread_flavor* tf = (struct thread_flavor*)(tc+1);
struct thread_flavor* tf;

tc->cmd = LC_THREAD;
tc->cmdsize = memsize;

// General registers
tf->flavor = x86_THREAD_STATE64;
tf->count = x86_THREAD_STATE64_COUNT;

fill_thread_state64((x86_thread_state64_t*)tf->state, thread_info);

#if DUMP_FLOAT_STATE
// Float registers
tf = (struct thread_flavor*) (tf->state + sizeof(x86_thread_state64_t));
tf->flavor = x86_FLOAT_STATE64;
tf->count = x86_FLOAT_STATE64_COUNT;
switch (machine_type)
{
case EM_X86_64:
// General registers
tf = (struct thread_flavor*)(tc+1);
tf->flavor = x86_THREAD_STATE64;
tf->count = x86_THREAD_STATE64_COUNT;
fill_x86_thread_state64((x86_thread_state64_t*)tf->state, thread_info);

// Float registers
if (DUMP_FLOAT_STATE) {
tf = (struct thread_flavor*) (tf->state + sizeof(x86_thread_state64_t));
tf->flavor = x86_FLOAT_STATE64;
tf->count = x86_FLOAT_STATE64_COUNT;
fill_x86_float_state64((x86_float_state64_t*)tf->state, thread_info);
}

fill_float_state64((x86_float_state64_t*)tf->state, thread_info);
#endif
break;

default:
// Missing code for this arch
abort();
}

if (!dump_emit(cprm, buffer, memsize))
{
Expand Down

0 comments on commit 1aa1d3c

Please sign in to comment.