Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework darling-coredump To Avoid Hardcoding x86/x64 Logic #1461

Merged
merged 1 commit into from
Dec 14, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading