this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

WIP work on 32-bit core dump support

`darling-coredump` can now process 32-bit core dumps, but it doesn't seem
to produce anything usable (LLDB says the code memory is missing in the
core dump).

+225 -117
+27 -1
src/hosttools/include/coredump/x86_64.h
··· 3 3 4 4 #include <stdint.h> 5 5 6 - struct nt_prstatus_registers { 6 + struct nt_prstatus_registers_i386 { 7 + uint32_t ebx; 8 + uint32_t ecx; 9 + uint32_t edx; 10 + uint32_t esi; 11 + uint32_t edi; 12 + uint32_t ebp; 13 + uint32_t eax; 14 + uint16_t ds; 15 + uint16_t ds_padding; 16 + uint16_t es; 17 + uint16_t es_padding; 18 + uint16_t fs; 19 + uint16_t fs_padding; 20 + uint16_t gs; 21 + uint16_t gs_padding; 22 + uint32_t orig_eax; 23 + uint32_t eip; 24 + uint16_t cs; 25 + uint16_t cs_padding; 26 + uint32_t eflags; 27 + uint32_t esp; 28 + uint16_t ss; 29 + uint16_t ss_padding; 30 + }; 31 + 32 + struct nt_prstatus_registers_x86_64 { 7 33 unsigned long r15; 8 34 unsigned long r14; 9 35 unsigned long r13;
+198 -116
src/hosttools/src/coredump/main.c
··· 39 39 uint64_t expected_offset; 40 40 }; 41 41 42 - struct nt_file_header { 42 + struct elf32_nt_file_header { 43 + uint32_t count; 44 + uint32_t page_size; 45 + }; 46 + 47 + struct elf64_nt_file_header { 43 48 uint64_t count; 44 49 uint64_t page_size; 45 50 }; 46 51 47 - struct nt_file_entry { 52 + union nt_file_header { 53 + struct elf32_nt_file_header elf32; 54 + struct elf64_nt_file_header elf64; 55 + }; 56 + 57 + struct elf32_nt_file_entry { 58 + uint32_t start; 59 + uint32_t end; 60 + uint32_t offset; 61 + }; 62 + 63 + struct elf64_nt_file_entry { 48 64 uint64_t start; 49 65 uint64_t end; 50 66 uint64_t offset; 51 67 }; 52 68 69 + union nt_file_entry { 70 + struct elf32_nt_file_entry elf32; 71 + struct elf64_nt_file_entry elf64; 72 + }; 73 + 74 + union nt_prstatus_registers { 75 + struct nt_prstatus_registers_i386 i386; 76 + struct nt_prstatus_registers_x86_64 x86_64; 77 + }; 78 + 53 79 struct nt_prstatus { 54 80 int signal_number; 55 81 int signal_code; ··· 65 91 struct __kernel_old_timeval system_time; 66 92 struct __kernel_old_timeval cumulative_user_time; 67 93 struct __kernel_old_timeval cumulative_system_time; 68 - struct nt_prstatus_registers general_registers; 94 + union nt_prstatus_registers general_registers; 69 95 }; 70 96 71 97 struct thread_info { ··· 82 108 uint32_t e_version; /* Object file version */ 83 109 }; 84 110 111 + union Elf_Ehdr { 112 + Elf32_Ehdr elf32; 113 + Elf64_Ehdr elf64; 114 + }; 115 + 116 + union Elf_Phdr { 117 + Elf32_Phdr elf32; 118 + Elf64_Phdr elf64; 119 + }; 120 + 121 + union Elf_Nhdr { 122 + Elf32_Nhdr elf32; 123 + Elf64_Nhdr elf64; 124 + }; 125 + 126 + #define cprm_elf(_is64, _expr, _member) ({ \ 127 + __typeof__((_expr)) tmp = _expr; \ 128 + /* cast to the bigger type (Elf64) */ \ 129 + _is64 ? tmp->elf64._member : (__typeof__(tmp->elf64._member))tmp->elf32._member; \ 130 + }) 131 + 85 132 struct coredump_params { 86 133 int input_corefile; 87 134 int output_corefile; 88 135 size_t input_corefile_size; 89 136 const void* input_corefile_mapping; 90 - struct elf_universal_header *universal_header; 91 - union { 92 - const Elf32_Ehdr* elf32; 93 - const Elf64_Ehdr* elf64; 94 - } input_header; 95 - union { 96 - const Elf32_Phdr* elf32; 97 - const Elf64_Phdr* elf64; 98 - } input_program_headers; 99 - union { 100 - const Elf32_Phdr* elf32; 101 - const Elf64_Phdr* elf64; 102 - } input_program_headers_end; 103 - union { 104 - const Elf32_Nhdr* elf32; 105 - const Elf64_Nhdr* elf64; 106 - } input_notes; 137 + const struct elf_universal_header *universal_header; 138 + const union Elf_Ehdr* input_header; 139 + const union Elf_Phdr* input_program_headers; 140 + const union Elf_Phdr* input_program_headers_end; 141 + const union Elf_Nhdr* input_notes; 107 142 size_t input_notes_size; 108 143 struct vm_area* vm_areas; 109 144 size_t vm_area_count; 110 - struct nt_file_header* nt_file; 145 + union nt_file_header* nt_file; 111 146 const char** nt_file_filenames; 112 147 struct thread_info* thread_infos; 113 148 size_t thread_info_count; ··· 116 151 size_t prefix_length; 117 152 const char* main_executable_path; 118 153 size_t main_executable_path_length; 154 + bool is_64_bit; 119 155 }; 120 156 121 157 static char default_output_name[4096]; ··· 129 165 return (number) & -multiple; 130 166 }; 131 167 132 - static const char* note_name(const Elf64_Nhdr* note) { 133 - return (const char*)note + sizeof(*note); 168 + static const char* note_name(const struct coredump_params* cprm, const union Elf_Nhdr* note) { 169 + return (const char*)note + (cprm->is_64_bit ? sizeof(note->elf64) : sizeof(note->elf64)); 170 + }; 171 + 172 + static const void* note_data(const struct coredump_params* cprm, const union Elf_Nhdr* note) { 173 + return note_name(cprm, note) + round_up_pow2(cprm_elf(cprm->is_64_bit, note, n_namesz), 4); 174 + }; 175 + 176 + static const union Elf_Nhdr* find_next_note(const struct coredump_params* cprm, const union Elf_Nhdr* note) { 177 + uint64_t length = sizeof(*note) + round_up_pow2(cprm_elf(cprm->is_64_bit, note, n_namesz), 4) + round_up_pow2(cprm_elf(cprm->is_64_bit, note, n_descsz), 4); 178 + return (const union Elf_Nhdr*)((char*)note + length); 179 + }; 180 + 181 + static size_t nt_file_entry_size(const struct coredump_params* cprm) { 182 + return cprm->is_64_bit ? sizeof(struct elf64_nt_file_entry) : sizeof(struct elf32_nt_file_entry); 134 183 }; 135 184 136 - static const void* note_data(const Elf64_Nhdr* note) { 137 - return note_name(note) + round_up_pow2(note->n_namesz, 4); 185 + static size_t nt_file_header_size(const struct coredump_params* cprm) { 186 + return cprm->is_64_bit ? sizeof(struct elf64_nt_file_header) : sizeof(struct elf32_nt_file_header); 138 187 }; 139 188 140 - static const Elf64_Nhdr* find_next_note(const Elf64_Nhdr* note) { 141 - uint64_t length = sizeof(*note) + round_up_pow2(note->n_namesz, 4) + round_up_pow2(note->n_descsz, 4); 142 - return (Elf64_Nhdr*)((char*)note + length); 189 + static const union nt_file_entry* nt_file_get_entry(const struct coredump_params* cprm, const union nt_file_header* header, size_t index) { 190 + return (const union nt_file_entry*)((const char*)header + nt_file_header_size(cprm) + (nt_file_entry_size(cprm) * index)); 143 191 }; 144 192 145 193 // first tries to open the file directly, then tries to open the file in the lower layer of the overlay ··· 229 277 cprm.universal_header->e_ident[EI_MAG1] != ELFMAG1 || 230 278 cprm.universal_header->e_ident[EI_MAG2] != ELFMAG2 || 231 279 cprm.universal_header->e_ident[EI_MAG3] != ELFMAG3 || 232 - cprm.universal_header->e_ident[EI_CLASS] != ELFCLASS64 || 233 280 cprm.universal_header->e_ident[EI_VERSION] != EV_CURRENT || 234 281 cprm.universal_header->e_version != EV_CURRENT || 235 282 cprm.universal_header->e_type != ET_CORE ··· 238 285 return 1; 239 286 } 240 287 241 - if (cprm.universal_header->e_machine == EM_X86_64) { 242 - cprm.input_header.elf64 = cprm.input_corefile_mapping; 288 + if (cprm.universal_header->e_ident[EI_CLASS] == ELFCLASS64) { 289 + cprm.is_64_bit = true; 290 + } else if (cprm.universal_header->e_ident[EI_CLASS] == ELFCLASS32) { 291 + cprm.is_64_bit = false; 243 292 } else { 244 - fprintf(stderr, "Unexpected e_machine (%d) detected, aborting.\n", cprm.universal_header->e_machine); 293 + fprintf(stderr, "Input file is not a valid corefile (invalid ELF class)\n"); 245 294 return 1; 246 295 } 247 296 248 - cprm.input_program_headers.elf64 = (const void*)((const char*)cprm.input_corefile_mapping + cprm.input_header.elf64->e_phoff); 249 - cprm.input_program_headers_end.elf64 = (const Elf64_Phdr*)((const char*)cprm.input_program_headers.elf64 + (cprm.input_header.elf64->e_phentsize * cprm.input_header.elf64->e_phnum)); 297 + switch (cprm.universal_header->e_machine) { 298 + case EM_X86_64: 299 + case EM_386: 300 + cprm.input_header = cprm.input_corefile_mapping; 301 + break; 302 + default: 303 + fprintf(stderr, "Unexpected e_machine (%d) detected, aborting.\n", cprm.universal_header->e_machine); 304 + return 1; 305 + } 306 + 307 + cprm.input_program_headers = (const void*)((const char*)cprm.input_corefile_mapping + cprm_elf(cprm.is_64_bit, cprm.input_header, e_phoff)); 308 + cprm.input_program_headers_end = (const void*)((const char*)cprm.input_program_headers + (cprm_elf(cprm.is_64_bit, cprm.input_header, e_phentsize) * cprm_elf(cprm.is_64_bit, cprm.input_header, e_phnum))); 250 309 251 310 // first, count how many VM areas we have 252 - for (const Elf64_Phdr* program_header = cprm.input_program_headers.elf64; program_header < cprm.input_program_headers_end.elf64; program_header = (const Elf64_Phdr*)((const char*)program_header + cprm.input_header.elf64->e_phentsize)) { 253 - if (program_header->p_type == PT_LOAD) { 311 + for (const union Elf_Phdr* program_header = cprm.input_program_headers; program_header < cprm.input_program_headers_end; program_header = (const void*)((const char*)program_header + cprm_elf(cprm.is_64_bit, cprm.input_header, e_phentsize))) { 312 + if (cprm_elf(cprm.is_64_bit, program_header, p_type) == PT_LOAD) { 254 313 ++cprm.vm_area_count; 255 - } else if (program_header->p_type == PT_NOTE) { 314 + } else if (cprm_elf(cprm.is_64_bit, program_header, p_type) == PT_NOTE) { 256 315 // while we're at it, also load the NOTE segment 257 316 258 317 // XXX: ignoring it is probably not the best choice 259 - if (cprm.input_notes.elf64) { 318 + if (cprm.input_notes) { 260 319 printf("warning: ignoring extra PT_NOTE segment\n"); 261 320 continue; 262 321 } 263 322 264 - cprm.input_notes.elf64 = (const void*)((const char*)cprm.input_corefile_mapping + program_header->p_offset); 265 - cprm.input_notes_size = program_header->p_filesz; 323 + cprm.input_notes = (const void*)((const char*)cprm.input_corefile_mapping + cprm_elf(cprm.is_64_bit, program_header, p_offset)); 324 + cprm.input_notes_size = cprm_elf(cprm.is_64_bit, program_header, p_filesz); 266 325 } 267 326 } 268 327 269 - if (!cprm.input_notes.elf64) { 328 + if (!cprm.input_notes) { 270 329 fprintf(stderr, "Input corefile does not contain PT_NOTE segment\n"); 271 330 return 1; 272 331 } 273 332 274 - for (const Elf64_Nhdr* note_header = cprm.input_notes.elf64; note_header < (const Elf64_Nhdr*)((const char*)cprm.input_notes.elf64 + cprm.input_notes_size); note_header = find_next_note(note_header)) { 275 - if (note_header->n_type == NT_FILE) { 333 + for (const union Elf_Nhdr* note_header = cprm.input_notes; note_header < (const union Elf_Nhdr*)((const char*)cprm.input_notes + cprm.input_notes_size); note_header = find_next_note(&cprm, note_header)) { 334 + if (cprm_elf(cprm.is_64_bit, note_header, n_type) == NT_FILE) { 276 335 // allocate a copy for alignment purposes 277 - cprm.nt_file = malloc(note_header->n_descsz); 336 + cprm.nt_file = malloc(cprm_elf(cprm.is_64_bit, note_header, n_descsz)); 278 337 if (!cprm.nt_file) { 279 338 perror("malloc"); 280 339 return 1; 281 340 } 282 - memcpy(cprm.nt_file, note_data(note_header), note_header->n_descsz); 341 + memcpy(cprm.nt_file, note_data(&cprm, note_header), cprm_elf(cprm.is_64_bit, note_header, n_descsz)); 283 342 284 - cprm.nt_file_filenames = malloc(cprm.nt_file->count * sizeof(const char*)); 343 + cprm.nt_file_filenames = malloc(cprm_elf(cprm.is_64_bit, cprm.nt_file, count) * sizeof(const char*)); 285 344 if (!cprm.nt_file_filenames) { 286 345 perror("malloc"); 287 346 return 1; 288 347 } 289 348 290 - const char* filenames = (const char*)cprm.nt_file + sizeof(struct nt_file_header) + (sizeof(struct nt_file_entry) * cprm.nt_file->count); 291 - for (size_t i = 0, offset = 0; i < cprm.nt_file->count; ++i) { 349 + const char* filenames = (const char*)nt_file_get_entry(&cprm, cprm.nt_file, cprm_elf(cprm.is_64_bit, cprm.nt_file, count)); 350 + for (size_t i = 0, offset = 0; i < cprm_elf(cprm.is_64_bit, cprm.nt_file, count); ++i) { 292 351 cprm.nt_file_filenames[i] = &filenames[offset]; 293 352 offset += strlen(&filenames[offset]) + 1; 294 353 } 295 - } else if (note_header->n_type == NT_PRSTATUS) { 354 + } else if (cprm_elf(cprm.is_64_bit, note_header, n_type) == NT_PRSTATUS) { 296 355 ++cprm.thread_info_count; 297 356 } else { 298 357 continue; ··· 311 370 } 312 371 313 372 size_t thread_info_index = 0; 314 - for (const Elf64_Nhdr* note_header = cprm.input_notes.elf64; note_header < (const Elf64_Nhdr*)((const char*)cprm.input_notes.elf64 + cprm.input_notes_size); note_header = find_next_note(note_header)) { 315 - if (note_header->n_type == NT_PRSTATUS) { 373 + for (const union Elf_Nhdr* note_header = cprm.input_notes; note_header < (const union Elf_Nhdr*)((const char*)cprm.input_notes + cprm.input_notes_size); note_header = find_next_note(&cprm, note_header)) { 374 + if (cprm_elf(cprm.is_64_bit, note_header, n_type) == NT_PRSTATUS) { 316 375 // allocate a copy for alignment purposes 317 - struct nt_prstatus* prstatus = malloc(note_header->n_descsz); 376 + struct nt_prstatus* prstatus = malloc(cprm_elf(cprm.is_64_bit, note_header, n_descsz)); 318 377 if (!prstatus) { 319 378 perror("malloc"); 320 379 return 1; 321 380 } 322 381 cprm.thread_infos[thread_info_index++].prstatus = prstatus; 323 - memcpy(prstatus, note_data(note_header), note_header->n_descsz); 382 + memcpy(prstatus, note_data(&cprm, note_header), cprm_elf(cprm.is_64_bit, note_header, n_descsz)); 324 383 } else { 325 384 continue; 326 385 } ··· 328 387 329 388 // determine if we have extra mappings in NT_FILE that aren't present in the program headers (gcore tends to do this) 330 389 // also try to determine which file is our main executable 331 - for (size_t i = 0; i < cprm.nt_file->count; ++i) { 332 - const struct nt_file_entry* entry = &((const struct nt_file_entry*)((const char*)cprm.nt_file + sizeof(struct nt_file_header)))[i]; 390 + for (size_t i = 0; i < cprm_elf(cprm.is_64_bit, cprm.nt_file, count); ++i) { 391 + const union nt_file_entry* entry = nt_file_get_entry(&cprm, cprm.nt_file, i); 333 392 const char* filename = cprm.nt_file_filenames[i]; 334 393 bool found = false; 335 394 ··· 354 413 } 355 414 } 356 415 357 - for (const Elf64_Phdr* program_header = cprm.input_program_headers.elf64; program_header < cprm.input_program_headers_end.elf64; program_header = (const Elf64_Phdr*)((const char*)program_header + cprm.input_header.elf64->e_phentsize)) { 358 - if (program_header->p_type != PT_LOAD) { 416 + for (const union Elf_Phdr* program_header = cprm.input_program_headers; program_header < cprm.input_program_headers_end; program_header = (const union Elf_Phdr*)((const char*)program_header + cprm_elf(cprm.is_64_bit, cprm.input_header, e_phentsize))) { 417 + if (cprm_elf(cprm.is_64_bit, program_header, p_type) != PT_LOAD) { 359 418 continue; 360 419 } 361 420 362 - if (entry->start == program_header->p_vaddr) { 421 + if (cprm_elf(cprm.is_64_bit, entry, start) == cprm_elf(cprm.is_64_bit, program_header, p_vaddr)) { 363 422 found = true; 364 423 break; 365 424 } ··· 385 444 386 445 // now load up the VM area array 387 446 size_t vm_area_index = 0; 388 - for (const Elf64_Phdr* program_header = cprm.input_program_headers.elf64; program_header < cprm.input_program_headers_end.elf64; program_header = (const Elf64_Phdr*)((const char*)program_header + cprm.input_header.elf64->e_phentsize)) { 389 - if (program_header->p_type == PT_LOAD) { 447 + for (const union Elf_Phdr* program_header = cprm.input_program_headers; program_header < cprm.input_program_headers_end; program_header = (const union Elf_Phdr*)((const char*)program_header + cprm_elf(cprm.is_64_bit, cprm.input_header, e_phentsize))) { 448 + if (cprm_elf(cprm.is_64_bit, program_header, p_type) == PT_LOAD) { 390 449 struct vm_area* vm_area = &cprm.vm_areas[vm_area_index++]; 391 450 392 451 vm_area->valid = true; 393 - vm_area->memory_address = program_header->p_vaddr; 394 - vm_area->memory_size = program_header->p_memsz; 395 - vm_area->file_offset = program_header->p_offset; 452 + vm_area->memory_address = cprm_elf(cprm.is_64_bit, program_header, p_vaddr); 453 + vm_area->memory_size = cprm_elf(cprm.is_64_bit, program_header, p_memsz); 454 + vm_area->file_offset = cprm_elf(cprm.is_64_bit, program_header, p_offset); 396 455 397 456 if (!cprm.main_executable_path && vm_area->memory_address == 0) { 398 457 // if this is PAGEZERO and we don't yet have a main executable registered, ··· 403 462 } 404 463 405 464 vm_area->protection = 0; 406 - if (program_header->p_flags & PF_R) { 465 + if (cprm_elf(cprm.is_64_bit, program_header, p_flags) & PF_R) { 407 466 vm_area->protection |= PROT_READ; 408 467 } 409 - if (program_header->p_flags & PF_W) { 468 + if (cprm_elf(cprm.is_64_bit, program_header, p_flags) & PF_W) { 410 469 vm_area->protection |= PROT_WRITE; 411 470 } 412 - if (program_header->p_flags & PF_X) { 471 + if (cprm_elf(cprm.is_64_bit, program_header, p_flags) & PF_X) { 413 472 vm_area->protection |= PROT_EXEC; 414 473 } 415 474 416 - if (program_header->p_filesz == 0) { 475 + if (cprm_elf(cprm.is_64_bit, program_header, p_filesz) == 0) { 417 476 // contents contained within original file 418 477 419 478 // in this case, the file size *should* be the same as the size in memory 420 479 vm_area->file_size = vm_area->memory_size; 421 480 422 481 // let's look for the NT_FILE entry 423 - const struct nt_file_entry* entries = (const struct nt_file_entry*)((const char*)cprm.nt_file + sizeof(struct nt_file_header)); 424 - for (size_t i = 0; i < cprm.nt_file->count; ++i) { 425 - const struct nt_file_entry* entry = &entries[i]; 482 + for (size_t i = 0; i < cprm_elf(cprm.is_64_bit, cprm.nt_file, count); ++i) { 483 + const union nt_file_entry* entry = nt_file_get_entry(&cprm, cprm.nt_file, i); 426 484 const char* filename = cprm.nt_file_filenames[i]; 427 485 428 - if (entry->start > vm_area->memory_address || entry->end < vm_area->memory_address + vm_area->memory_size) { 486 + if (cprm_elf(cprm.is_64_bit, entry, start) > vm_area->memory_address || cprm_elf(cprm.is_64_bit, entry, end) < vm_area->memory_address + vm_area->memory_size) { 429 487 continue; 430 488 } 431 489 432 490 vm_area->filename = filename; 433 491 vm_area->filename_length = strlen(vm_area->filename); 434 - vm_area->file_offset = (entry->offset * cprm.nt_file->page_size) + (vm_area->memory_address - entry->start); 435 - vm_area->file_size = entry->end - entry->start; 492 + vm_area->file_offset = (cprm_elf(cprm.is_64_bit, entry, offset) * cprm_elf(cprm.is_64_bit, cprm.nt_file, page_size)) + (vm_area->memory_address - cprm_elf(cprm.is_64_bit, entry, start)); 493 + vm_area->file_size = cprm_elf(cprm.is_64_bit, entry, end) - cprm_elf(cprm.is_64_bit, entry, start); 436 494 437 495 break; 438 496 } ··· 455 513 // contents contained within this corefile 456 514 vm_area->filename = NULL; 457 515 vm_area->filename_length = 0; 458 - vm_area->file_size = program_header->p_filesz; 516 + vm_area->file_size = cprm_elf(cprm.is_64_bit, program_header, p_filesz); 459 517 } 460 518 } 461 519 } 462 520 463 521 // load in extra mappings from NT_FILE 464 - for (size_t i = 0; i < cprm.nt_file->count; ++i) { 465 - const struct nt_file_entry* entry = &((const struct nt_file_entry*)((const char*)cprm.nt_file + sizeof(struct nt_file_header)))[i]; 522 + for (size_t i = 0; i < cprm_elf(cprm.is_64_bit, cprm.nt_file, count); ++i) { 523 + const union nt_file_entry* entry = nt_file_get_entry(&cprm, cprm.nt_file, i); 466 524 const char* filename = cprm.nt_file_filenames[i]; 467 525 bool found = false; 468 526 469 - for (const Elf64_Phdr* program_header = cprm.input_program_headers.elf64; program_header < cprm.input_program_headers_end.elf64; program_header = (const Elf64_Phdr*)((const char*)program_header + cprm.input_header.elf64->e_phentsize)) { 470 - if (program_header->p_type != PT_LOAD) { 527 + for (const union Elf_Phdr* program_header = cprm.input_program_headers; program_header < cprm.input_program_headers_end; program_header = (const union Elf_Phdr*)((const char*)program_header + cprm_elf(cprm.is_64_bit, cprm.input_header, e_phentsize))) { 528 + if (cprm_elf(cprm.is_64_bit, program_header, p_type) != PT_LOAD) { 471 529 continue; 472 530 } 473 531 474 - if (entry->start == program_header->p_vaddr) { 532 + if (cprm_elf(cprm.is_64_bit, entry, start) == cprm_elf(cprm.is_64_bit, program_header, p_vaddr)) { 475 533 found = true; 476 534 break; 477 535 } ··· 485 543 486 544 vm_area->filename = filename; 487 545 vm_area->filename_length = strlen(vm_area->filename); 488 - vm_area->memory_address = entry->start; 489 - vm_area->memory_size = entry->end - entry->start; 546 + vm_area->memory_address = cprm_elf(cprm.is_64_bit, entry, start); 547 + vm_area->memory_size = cprm_elf(cprm.is_64_bit, entry, end) - cprm_elf(cprm.is_64_bit, entry, start); 490 548 vm_area->file_size = vm_area->memory_size; 491 - vm_area->file_offset = entry->offset * cprm.nt_file->page_size; 549 + vm_area->file_offset = cprm_elf(cprm.is_64_bit, entry, offset) * cprm_elf(cprm.is_64_bit, cprm.nt_file, page_size); 492 550 vm_area->protection = VM_PROT_READ; 493 551 vm_area->valid = true; 494 552 ··· 553 611 static 554 612 void fill_thread_state32(x86_thread_state32_t* state, const struct thread_info* info) 555 613 { 556 - // TODO 557 - memset(state, 0, sizeof(*state)); 614 + state->eax = info->prstatus->general_registers.i386.eax; 615 + state->ebx = info->prstatus->general_registers.i386.ebx; 616 + state->ecx = info->prstatus->general_registers.i386.ecx; 617 + state->edx = info->prstatus->general_registers.i386.edx; 618 + state->edi = info->prstatus->general_registers.i386.edi; 619 + state->esi = info->prstatus->general_registers.i386.esi; 620 + state->ebp = info->prstatus->general_registers.i386.ebp; 621 + state->esp = info->prstatus->general_registers.i386.esp; 622 + state->ss = info->prstatus->general_registers.i386.ss; 623 + state->eflags = info->prstatus->general_registers.i386.eflags; 624 + state->eip = info->prstatus->general_registers.i386.eip; 625 + state->cs = info->prstatus->general_registers.i386.cs; 626 + state->ds = info->prstatus->general_registers.i386.ds; 627 + state->es = info->prstatus->general_registers.i386.es; 628 + state->fs = info->prstatus->general_registers.i386.fs; 629 + state->gs = info->prstatus->general_registers.i386.gs; 558 630 } 559 631 560 632 static ··· 567 639 static 568 640 void fill_thread_state64(x86_thread_state64_t* state, const struct thread_info* info) 569 641 { 570 - state->rax = info->prstatus->general_registers.ax; 571 - state->rbx = info->prstatus->general_registers.bx; 572 - state->rcx = info->prstatus->general_registers.cx; 573 - state->rdx = info->prstatus->general_registers.dx; 574 - state->rdi = info->prstatus->general_registers.di; 575 - state->rsi = info->prstatus->general_registers.si; 576 - state->rbp = info->prstatus->general_registers.bp; 577 - state->rsp = info->prstatus->general_registers.sp; 578 - state->r8 = info->prstatus->general_registers.r8; 579 - state->r9 = info->prstatus->general_registers.r9; 580 - state->r10 = info->prstatus->general_registers.r10; 581 - state->r11 = info->prstatus->general_registers.r11; 582 - state->r12 = info->prstatus->general_registers.r12; 583 - state->r13 = info->prstatus->general_registers.r13; 584 - state->r14 = info->prstatus->general_registers.r14; 585 - state->r15 = info->prstatus->general_registers.r15; 586 - state->rip = info->prstatus->general_registers.ip; 587 - state->rflags = info->prstatus->general_registers.flags; 588 - state->cs = info->prstatus->general_registers.cs; 589 - state->fs = info->prstatus->general_registers.fs; 590 - state->gs = info->prstatus->general_registers.gs; 642 + state->rax = info->prstatus->general_registers.x86_64.ax; 643 + state->rbx = info->prstatus->general_registers.x86_64.bx; 644 + state->rcx = info->prstatus->general_registers.x86_64.cx; 645 + state->rdx = info->prstatus->general_registers.x86_64.dx; 646 + state->rdi = info->prstatus->general_registers.x86_64.di; 647 + state->rsi = info->prstatus->general_registers.x86_64.si; 648 + state->rbp = info->prstatus->general_registers.x86_64.bp; 649 + state->rsp = info->prstatus->general_registers.x86_64.sp; 650 + state->r8 = info->prstatus->general_registers.x86_64.r8; 651 + state->r9 = info->prstatus->general_registers.x86_64.r9; 652 + state->r10 = info->prstatus->general_registers.x86_64.r10; 653 + state->r11 = info->prstatus->general_registers.x86_64.r11; 654 + state->r12 = info->prstatus->general_registers.x86_64.r12; 655 + state->r13 = info->prstatus->general_registers.x86_64.r13; 656 + state->r14 = info->prstatus->general_registers.x86_64.r14; 657 + state->r15 = info->prstatus->general_registers.x86_64.r15; 658 + state->rip = info->prstatus->general_registers.x86_64.ip; 659 + state->rflags = info->prstatus->general_registers.x86_64.flags; 660 + state->cs = info->prstatus->general_registers.x86_64.cs; 661 + state->fs = info->prstatus->general_registers.x86_64.fs; 662 + state->gs = info->prstatus->general_registers.x86_64.gs; 591 663 } 592 664 593 665 static ··· 603 675 // Count memory segments and threads 604 676 unsigned int segs = cprm->vm_area_count; 605 677 unsigned int threads = cprm->thread_info_count; 678 + struct mach_header mh; 606 679 607 680 for (size_t i = 0; i < cprm->vm_area_count; ++i) { 608 681 struct vm_area* vma = &cprm->vm_areas[i]; ··· 612 685 --segs; 613 686 } 614 687 } 615 - 616 - struct mach_header mh; 617 688 618 689 mh.magic = MH_MAGIC; 619 690 #ifdef __x86_64__ 620 691 mh.cputype = CPU_TYPE_X86; 621 692 mh.cpusubtype = CPU_SUBTYPE_X86_ALL; 622 693 #else 623 - #error Missing code for this arch 694 + #warning Missing code for this arch 624 695 #endif 625 696 mh.filetype = MH_CORE; 626 697 mh.ncmds = segs + threads; 627 698 628 699 const int statesize = sizeof(x86_thread_state32_t) + sizeof(x86_float_state32_t) + sizeof(struct thread_flavor) * 2; 700 + mh.sizeofcmds = segs * sizeof(struct segment_command) + threads * (sizeof(struct thread_command) + statesize); 701 + mh.flags = 0; 629 702 630 - mh.sizeofcmds = segs * sizeof(struct segment_command) + threads * (sizeof(struct thread_command) + statesize); 703 + if (cprm->main_executable_path) { 704 + int tmpfd = open_file(cprm, cprm->main_executable_path, cprm->main_executable_path_length); 705 + if (tmpfd >= 0) { 706 + struct mach_header that_mh; 707 + if (read(tmpfd, &that_mh, sizeof(that_mh)) == sizeof(that_mh)) { 708 + mh.flags = that_mh.flags; 709 + } 710 + close(tmpfd); 711 + } 712 + } else { 713 + fprintf(stderr, "No main executable detected?\n"); 714 + } 631 715 632 716 if (!dump_emit(cprm, &mh, sizeof(mh))) 633 717 goto fail; ··· 637 721 // TODO: maybe align the initial offset to 0x1000 638 722 639 723 for (size_t i = 0; i < cprm->vm_area_count; ++i) { 640 - const struct vm_area* vma = &cprm->vm_areas[i]; 724 + struct vm_area* vma = &cprm->vm_areas[i]; 641 725 struct segment_command sc; 642 726 643 727 if (!vma->valid) { ··· 654 738 sc.vmsize = vma->memory_size; 655 739 sc.fileoff = file_offset; 656 740 741 + vma->expected_offset = sc.fileoff; 742 + 657 743 sc.filesize = (vma->file_size == 0) ? vma->memory_size : vma->file_size; 658 744 sc.initprot = 0; 659 745 ··· 689 775 fill_thread_state32((x86_thread_state32_t*)tf->state, thread_info); 690 776 691 777 // Float registers 692 - tf = (struct thread_flavor*) (((char*) tf) + sizeof(x86_thread_state32_t)); 778 + tf = (struct thread_flavor*) (tf->state + sizeof(x86_thread_state32_t)); 693 779 tf->flavor = x86_FLOAT_STATE32; 694 780 tf->count = x86_FLOAT_STATE32_COUNT; 695 781 ··· 756 842 if (!dump_emit(cprm, &mh, sizeof(mh))) 757 843 goto fail; 758 844 759 - struct vm_area_struct* vma; 760 845 uint64_t file_offset = mh.sizeofcmds + sizeof(mh); 761 846 762 847 for (size_t i = 0; i < cprm->vm_area_count; ++i) { ··· 835 920 836 921 void macho_coredump(struct coredump_params* cprm) 837 922 { 838 - #warning TODO: 32-bit coredump support 839 - #if TODO 840 923 // Write the Mach-O header and loader commands 841 - if (!check_64bit_mode(current_pt_regs())) 924 + if (!cprm->is_64_bit) 842 925 { 843 926 // 32-bit executables 844 927 if (!macho_dump_headers32(cprm)) 845 928 exit(EXIT_FAILURE); 846 929 } 847 930 else 848 - #endif 849 931 { 850 932 // 64-bit executables 851 933 if (!macho_dump_headers64(cprm))