diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:26:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:26:05 +0000 |
commit | 14f1b3e8826ce43b978db93a62d1166055db5394 (patch) | |
tree | 0a00ad8d3498783fe0193f3b656bca17c4c8697d /tools | |
parent | 4ee8c119c71a06dcad1e0fecc8c675e480e59337 (diff) | |
download | src-14f1b3e8826ce43b978db93a62d1166055db5394.tar.gz src-14f1b3e8826ce43b978db93a62d1166055db5394.zip |
Vendor import of lldb trunk r290819:vendor/lldb/lldb-trunk-r290819
Notes
Notes:
svn path=/vendor/lldb/dist/; revision=311128
svn path=/vendor/lldb/lldb-trunk-r290819/; revision=311129; tag=vendor/lldb/lldb-trunk-r290819
Diffstat (limited to 'tools')
311 files changed, 63008 insertions, 60320 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 49af928c3815..86b9621a198e 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -2,11 +2,9 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") add_subdirectory(darwin-debug) add_subdirectory(debugserver) endif() - add_subdirectory(argdumper) - add_subdirectory(driver) -if (NOT __ANDROID_NDK__) - add_subdirectory(lldb-mi) -endif() +add_subdirectory(argdumper) +add_subdirectory(driver) +add_subdirectory(lldb-mi) if (LLDB_CAN_USE_LLDB_SERVER) add_subdirectory(lldb-server) endif() diff --git a/tools/argdumper/CMakeLists.txt b/tools/argdumper/CMakeLists.txt index 69bc97c7e518..9bf956396b4f 100644 --- a/tools/argdumper/CMakeLists.txt +++ b/tools/argdumper/CMakeLists.txt @@ -1,8 +1,13 @@ -add_lldb_executable(lldb-argdumper +include(${LLDB_PROJECT_ROOT}/cmake/LLDBDependencies.cmake) + +add_lldb_tool(lldb-argdumper INCLUDE_IN_FRAMEWORK argdumper.cpp ) -target_link_libraries(lldb-argdumper liblldb) +if (LLDB_LINKER_SUPPORTS_GROUPS) + target_link_libraries(lldb-argdumper -Wl,--start-group ${LLDB_USED_LIBS} -Wl,--end-group) +else() + target_link_libraries(lldb-argdumper ${LLDB_USED_LIBS}) +endif() +llvm_config(lldb-argdumper ${LLVM_LINK_COMPONENTS}) -install(TARGETS lldb-argdumper - RUNTIME DESTINATION bin) diff --git a/tools/argdumper/argdumper.cpp b/tools/argdumper/argdumper.cpp index 381a9d2f4b22..01a070efb82c 100644 --- a/tools/argdumper/argdumper.cpp +++ b/tools/argdumper/argdumper.cpp @@ -1,4 +1,4 @@ -//===-- argdumper.cpp --------------------------------------------*- C++ -*-===// +//===-- argdumper.cpp --------------------------------------------*- C++-*-===// // // The LLVM Compiler Infrastructure // @@ -14,25 +14,20 @@ using namespace lldb_private; -int -main (int argc, char *argv[]) -{ - JSONArray::SP arguments(new JSONArray()); - for (int i = 1; - i < argc; - i++) - { - arguments->AppendObject(JSONString::SP(new JSONString(argv[i]))); - } - - JSONObject::SP object(new JSONObject()); - object->SetObject("arguments", arguments); - - StreamString ss; - - object->Write(ss); - - std::cout << ss.GetData() << std::endl; - - return 0; +int main(int argc, char *argv[]) { + JSONArray::SP arguments(new JSONArray()); + for (int i = 1; i < argc; i++) { + arguments->AppendObject(JSONString::SP(new JSONString(argv[i]))); + } + + JSONObject::SP object(new JSONObject()); + object->SetObject("arguments", arguments); + + StreamString ss; + + object->Write(ss); + + std::cout << ss.GetData() << std::endl; + + return 0; } diff --git a/tools/compact-unwind/compact-unwind-dumper.c b/tools/compact-unwind/compact-unwind-dumper.c index f70f602326bf..570c42981a24 100644 --- a/tools/compact-unwind/compact-unwind-dumper.c +++ b/tools/compact-unwind/compact-unwind-dumper.c @@ -1,66 +1,64 @@ -#include <stdint.h> -#include <mach-o/loader.h> +#include <fcntl.h> +#include <inttypes.h> #include <mach-o/compact_unwind_encoding.h> +#include <mach-o/loader.h> +#include <mach-o/nlist.h> #include <mach/machine.h> -#include <stdlib.h> #include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> #include <string.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/mman.h> #include <sys/errno.h> +#include <sys/mman.h> #include <sys/stat.h> -#include <inttypes.h> -#include <stdio.h> -#include <mach-o/nlist.h> - +#include <sys/types.h> enum { - UNWIND_ARM64_MODE_MASK = 0x0F000000, - UNWIND_ARM64_MODE_FRAMELESS = 0x02000000, - UNWIND_ARM64_MODE_DWARF = 0x03000000, - UNWIND_ARM64_MODE_FRAME = 0x04000000, - - UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001, - UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002, - UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004, - UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008, - UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010, - UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100, - UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200, - UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400, - UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800, - - UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000, - UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF, + UNWIND_ARM64_MODE_MASK = 0x0F000000, + UNWIND_ARM64_MODE_FRAMELESS = 0x02000000, + UNWIND_ARM64_MODE_DWARF = 0x03000000, + UNWIND_ARM64_MODE_FRAME = 0x04000000, + + UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001, + UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002, + UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004, + UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008, + UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010, + UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100, + UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200, + UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400, + UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800, + + UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000, + UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF, }; enum { - UNWIND_ARM_MODE_MASK = 0x0F000000, - UNWIND_ARM_MODE_FRAME = 0x01000000, - UNWIND_ARM_MODE_FRAME_D = 0x02000000, - UNWIND_ARM_MODE_DWARF = 0x04000000, + UNWIND_ARM_MODE_MASK = 0x0F000000, + UNWIND_ARM_MODE_FRAME = 0x01000000, + UNWIND_ARM_MODE_FRAME_D = 0x02000000, + UNWIND_ARM_MODE_DWARF = 0x04000000, - UNWIND_ARM_FRAME_STACK_ADJUST_MASK = 0x00C00000, + UNWIND_ARM_FRAME_STACK_ADJUST_MASK = 0x00C00000, - UNWIND_ARM_FRAME_FIRST_PUSH_R4 = 0x00000001, - UNWIND_ARM_FRAME_FIRST_PUSH_R5 = 0x00000002, - UNWIND_ARM_FRAME_FIRST_PUSH_R6 = 0x00000004, + UNWIND_ARM_FRAME_FIRST_PUSH_R4 = 0x00000001, + UNWIND_ARM_FRAME_FIRST_PUSH_R5 = 0x00000002, + UNWIND_ARM_FRAME_FIRST_PUSH_R6 = 0x00000004, - UNWIND_ARM_FRAME_SECOND_PUSH_R8 = 0x00000008, - UNWIND_ARM_FRAME_SECOND_PUSH_R9 = 0x00000010, - UNWIND_ARM_FRAME_SECOND_PUSH_R10 = 0x00000020, - UNWIND_ARM_FRAME_SECOND_PUSH_R11 = 0x00000040, - UNWIND_ARM_FRAME_SECOND_PUSH_R12 = 0x00000080, + UNWIND_ARM_FRAME_SECOND_PUSH_R8 = 0x00000008, + UNWIND_ARM_FRAME_SECOND_PUSH_R9 = 0x00000010, + UNWIND_ARM_FRAME_SECOND_PUSH_R10 = 0x00000020, + UNWIND_ARM_FRAME_SECOND_PUSH_R11 = 0x00000040, + UNWIND_ARM_FRAME_SECOND_PUSH_R12 = 0x00000080, - UNWIND_ARM_FRAME_D_REG_COUNT_MASK = 0x00000700, + UNWIND_ARM_FRAME_D_REG_COUNT_MASK = 0x00000700, - UNWIND_ARM_DWARF_SECTION_OFFSET = 0x00FFFFFF, + UNWIND_ARM_DWARF_SECTION_OFFSET = 0x00FFFFFF, }; -#define EXTRACT_BITS(value, mask) \ - ( (value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask)))-1) ) - +#define EXTRACT_BITS(value, mask) \ + ((value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask))) - 1)) // A quick sketch of a program which can parse the compact unwind info // used on Darwin systems for exception handling. The output of @@ -68,1534 +66,1450 @@ enum { // can dump at least the UNWIND_X86_64_MODE_RBP_FRAME format entries // correctly. -struct symbol -{ - uint64_t file_address; - const char *name; +struct symbol { + uint64_t file_address; + const char *name; }; -int -symbol_compare (const void *a, const void *b) -{ - return (int) ((struct symbol *)a)->file_address - ((struct symbol *)b)->file_address; +int symbol_compare(const void *a, const void *b) { + return (int)((struct symbol *)a)->file_address - + ((struct symbol *)b)->file_address; } -struct baton -{ - cpu_type_t cputype; +struct baton { + cpu_type_t cputype; - uint8_t *mach_header_start; // pointer into this program's address space - uint8_t *compact_unwind_start; // pointer into this program's address space + uint8_t *mach_header_start; // pointer into this program's address space + uint8_t *compact_unwind_start; // pointer into this program's address space - int addr_size; // 4 or 8 bytes, the size of addresses in this file + int addr_size; // 4 or 8 bytes, the size of addresses in this file - uint64_t text_segment_vmaddr; // __TEXT segment vmaddr - uint64_t text_segment_file_offset; + uint64_t text_segment_vmaddr; // __TEXT segment vmaddr + uint64_t text_segment_file_offset; - uint64_t text_section_vmaddr; // __TEXT,__text section vmaddr - uint64_t text_section_file_offset; + uint64_t text_section_vmaddr; // __TEXT,__text section vmaddr + uint64_t text_section_file_offset; - uint64_t eh_section_file_address; // the file address of the __TEXT,__eh_frame section + uint64_t eh_section_file_address; // the file address of the __TEXT,__eh_frame + // section - uint8_t *lsda_array_start; // for the currently-being-processed first-level index - uint8_t *lsda_array_end; // the lsda_array_start for the NEXT first-level index + uint8_t + *lsda_array_start; // for the currently-being-processed first-level index + uint8_t + *lsda_array_end; // the lsda_array_start for the NEXT first-level index - struct symbol *symbols; - int symbols_count; + struct symbol *symbols; + int symbols_count; - uint64_t *function_start_addresses; - int function_start_addresses_count; + uint64_t *function_start_addresses; + int function_start_addresses_count; - int current_index_table_number; + int current_index_table_number; - struct unwind_info_section_header unwind_header; - struct unwind_info_section_header_index_entry first_level_index_entry; - struct unwind_info_compressed_second_level_page_header compressed_second_level_page_header; - struct unwind_info_regular_second_level_page_header regular_second_level_page_header; + struct unwind_info_section_header unwind_header; + struct unwind_info_section_header_index_entry first_level_index_entry; + struct unwind_info_compressed_second_level_page_header + compressed_second_level_page_header; + struct unwind_info_regular_second_level_page_header + regular_second_level_page_header; }; - -uint64_t -read_leb128 (uint8_t **offset) -{ - uint64_t result = 0; - int shift = 0; - while (1) - { - uint8_t byte = **offset; - *offset = *offset + 1; - result |= (byte & 0x7f) << shift; - if ((byte & 0x80) == 0) - break; - shift += 7; - } - - return result; +uint64_t read_leb128(uint8_t **offset) { + uint64_t result = 0; + int shift = 0; + while (1) { + uint8_t byte = **offset; + *offset = *offset + 1; + result |= (byte & 0x7f) << shift; + if ((byte & 0x80) == 0) + break; + shift += 7; + } + + return result; } // step through the load commands in a thin mach-o binary, // find the cputype and the start of the __TEXT,__unwind_info // section, return a pointer to that section or NULL if not found. -static void -scan_macho_load_commands (struct baton *baton) -{ - struct symtab_command symtab_cmd; - uint64_t linkedit_segment_vmaddr; - uint64_t linkedit_segment_file_offset; - - baton->compact_unwind_start = 0; - - uint32_t *magic = (uint32_t *) baton->mach_header_start; - - if (*magic != MH_MAGIC && *magic != MH_MAGIC_64) - { - printf ("Unexpected magic number 0x%x in header, exiting.", *magic); - exit (1); - } - - bool is_64bit = false; - if (*magic == MH_MAGIC_64) - is_64bit = true; - - uint8_t *offset = baton->mach_header_start; - - struct mach_header mh; - memcpy (&mh, offset, sizeof (struct mach_header)); - if (is_64bit) - offset += sizeof (struct mach_header_64); - else - offset += sizeof (struct mach_header); - - if (is_64bit) - baton->addr_size = 8; - else - baton->addr_size = 4; - - baton->cputype = mh.cputype; - - uint8_t *start_of_load_commands = offset; - - uint32_t cur_cmd = 0; - while (cur_cmd < mh.ncmds && (offset - start_of_load_commands) < mh.sizeofcmds) - { - struct load_command lc; - uint32_t *lc_cmd = (uint32_t *) offset; - uint32_t *lc_cmdsize = (uint32_t *) offset + 1; - uint8_t *start_of_this_load_cmd = offset; - - if (*lc_cmd == LC_SEGMENT || *lc_cmd == LC_SEGMENT_64) - { - char segment_name[17]; - segment_name[0] = '\0'; - uint32_t nsects = 0; - uint64_t segment_offset = 0; - uint64_t segment_vmaddr = 0; - - if (*lc_cmd == LC_SEGMENT_64) - { - struct segment_command_64 seg; - memcpy (&seg, offset, sizeof (struct segment_command_64)); - memcpy (&segment_name, &seg.segname, 16); - segment_name[16] = '\0'; - nsects = seg.nsects; - segment_offset = seg.fileoff; - segment_vmaddr = seg.vmaddr; - offset += sizeof (struct segment_command_64); - if ((seg.flags & SG_PROTECTED_VERSION_1) == SG_PROTECTED_VERSION_1) - { - printf ("Segment '%s' is encrypted.\n", segment_name); - } +static void scan_macho_load_commands(struct baton *baton) { + struct symtab_command symtab_cmd; + uint64_t linkedit_segment_vmaddr; + uint64_t linkedit_segment_file_offset; + + baton->compact_unwind_start = 0; + + uint32_t *magic = (uint32_t *)baton->mach_header_start; + + if (*magic != MH_MAGIC && *magic != MH_MAGIC_64) { + printf("Unexpected magic number 0x%x in header, exiting.", *magic); + exit(1); + } + + bool is_64bit = false; + if (*magic == MH_MAGIC_64) + is_64bit = true; + + uint8_t *offset = baton->mach_header_start; + + struct mach_header mh; + memcpy(&mh, offset, sizeof(struct mach_header)); + if (is_64bit) + offset += sizeof(struct mach_header_64); + else + offset += sizeof(struct mach_header); + + if (is_64bit) + baton->addr_size = 8; + else + baton->addr_size = 4; + + baton->cputype = mh.cputype; + + uint8_t *start_of_load_commands = offset; + + uint32_t cur_cmd = 0; + while (cur_cmd < mh.ncmds && + (offset - start_of_load_commands) < mh.sizeofcmds) { + struct load_command lc; + uint32_t *lc_cmd = (uint32_t *)offset; + uint32_t *lc_cmdsize = (uint32_t *)offset + 1; + uint8_t *start_of_this_load_cmd = offset; + + if (*lc_cmd == LC_SEGMENT || *lc_cmd == LC_SEGMENT_64) { + char segment_name[17]; + segment_name[0] = '\0'; + uint32_t nsects = 0; + uint64_t segment_offset = 0; + uint64_t segment_vmaddr = 0; + + if (*lc_cmd == LC_SEGMENT_64) { + struct segment_command_64 seg; + memcpy(&seg, offset, sizeof(struct segment_command_64)); + memcpy(&segment_name, &seg.segname, 16); + segment_name[16] = '\0'; + nsects = seg.nsects; + segment_offset = seg.fileoff; + segment_vmaddr = seg.vmaddr; + offset += sizeof(struct segment_command_64); + if ((seg.flags & SG_PROTECTED_VERSION_1) == SG_PROTECTED_VERSION_1) { + printf("Segment '%s' is encrypted.\n", segment_name); + } + } + + if (*lc_cmd == LC_SEGMENT) { + struct segment_command seg; + memcpy(&seg, offset, sizeof(struct segment_command)); + memcpy(&segment_name, &seg.segname, 16); + segment_name[16] = '\0'; + nsects = seg.nsects; + segment_offset = seg.fileoff; + segment_vmaddr = seg.vmaddr; + offset += sizeof(struct segment_command); + if ((seg.flags & SG_PROTECTED_VERSION_1) == SG_PROTECTED_VERSION_1) { + printf("Segment '%s' is encrypted.\n", segment_name); + } + } + + if (nsects != 0 && strcmp(segment_name, "__TEXT") == 0) { + baton->text_segment_vmaddr = segment_vmaddr; + baton->text_segment_file_offset = segment_offset; + + uint32_t current_sect = 0; + while (current_sect < nsects && + (offset - start_of_this_load_cmd) < *lc_cmdsize) { + char sect_name[17]; + memcpy(§_name, offset, 16); + sect_name[16] = '\0'; + if (strcmp(sect_name, "__unwind_info") == 0) { + if (is_64bit) { + struct section_64 sect; + memset(§, 0, sizeof(struct section_64)); + memcpy(§, offset, sizeof(struct section_64)); + baton->compact_unwind_start = + baton->mach_header_start + sect.offset; + } else { + struct section sect; + memset(§, 0, sizeof(struct section)); + memcpy(§, offset, sizeof(struct section)); + baton->compact_unwind_start = + baton->mach_header_start + sect.offset; } - - if (*lc_cmd == LC_SEGMENT) - { - struct segment_command seg; - memcpy (&seg, offset, sizeof (struct segment_command)); - memcpy (&segment_name, &seg.segname, 16); - segment_name[16] = '\0'; - nsects = seg.nsects; - segment_offset = seg.fileoff; - segment_vmaddr = seg.vmaddr; - offset += sizeof (struct segment_command); - if ((seg.flags & SG_PROTECTED_VERSION_1) == SG_PROTECTED_VERSION_1) - { - printf ("Segment '%s' is encrypted.\n", segment_name); - } + } + if (strcmp(sect_name, "__eh_frame") == 0) { + if (is_64bit) { + struct section_64 sect; + memset(§, 0, sizeof(struct section_64)); + memcpy(§, offset, sizeof(struct section_64)); + baton->eh_section_file_address = sect.addr; + } else { + struct section sect; + memset(§, 0, sizeof(struct section)); + memcpy(§, offset, sizeof(struct section)); + baton->eh_section_file_address = sect.addr; } - - if (nsects != 0 && strcmp (segment_name, "__TEXT") == 0) - { - baton->text_segment_vmaddr = segment_vmaddr; - baton->text_segment_file_offset = segment_offset; - - uint32_t current_sect = 0; - while (current_sect < nsects && (offset - start_of_this_load_cmd) < *lc_cmdsize) - { - char sect_name[17]; - memcpy (§_name, offset, 16); - sect_name[16] = '\0'; - if (strcmp (sect_name, "__unwind_info") == 0) - { - if (is_64bit) - { - struct section_64 sect; - memset (§, 0, sizeof (struct section_64)); - memcpy (§, offset, sizeof (struct section_64)); - baton->compact_unwind_start = baton->mach_header_start + sect.offset; - } - else - { - struct section sect; - memset (§, 0, sizeof (struct section)); - memcpy (§, offset, sizeof (struct section)); - baton->compact_unwind_start = baton->mach_header_start + sect.offset; - } - } - if (strcmp (sect_name, "__eh_frame") == 0) - { - if (is_64bit) - { - struct section_64 sect; - memset (§, 0, sizeof (struct section_64)); - memcpy (§, offset, sizeof (struct section_64)); - baton->eh_section_file_address = sect.addr; - } - else - { - struct section sect; - memset (§, 0, sizeof (struct section)); - memcpy (§, offset, sizeof (struct section)); - baton->eh_section_file_address = sect.addr; - } - } - if (strcmp (sect_name, "__text") == 0) - { - if (is_64bit) - { - struct section_64 sect; - memset (§, 0, sizeof (struct section_64)); - memcpy (§, offset, sizeof (struct section_64)); - baton->text_section_vmaddr = sect.addr; - baton->text_section_file_offset = sect.offset; - } - else - { - struct section sect; - memset (§, 0, sizeof (struct section)); - memcpy (§, offset, sizeof (struct section)); - baton->text_section_vmaddr = sect.addr; - } - } - if (is_64bit) - { - offset += sizeof (struct section_64); - } - else - { - offset += sizeof (struct section); - } - } + } + if (strcmp(sect_name, "__text") == 0) { + if (is_64bit) { + struct section_64 sect; + memset(§, 0, sizeof(struct section_64)); + memcpy(§, offset, sizeof(struct section_64)); + baton->text_section_vmaddr = sect.addr; + baton->text_section_file_offset = sect.offset; + } else { + struct section sect; + memset(§, 0, sizeof(struct section)); + memcpy(§, offset, sizeof(struct section)); + baton->text_section_vmaddr = sect.addr; } - - if (strcmp (segment_name, "__LINKEDIT") == 0) - { - linkedit_segment_vmaddr = segment_vmaddr; - linkedit_segment_file_offset = segment_offset; - } - } - - if (*lc_cmd == LC_SYMTAB) - { - memcpy (&symtab_cmd, offset, sizeof (struct symtab_command)); + } + if (is_64bit) { + offset += sizeof(struct section_64); + } else { + offset += sizeof(struct section); + } } + } - if (*lc_cmd == LC_DYSYMTAB) - { - struct dysymtab_command dysymtab_cmd; - memcpy (&dysymtab_cmd, offset, sizeof (struct dysymtab_command)); - - int nlist_size = 12; - if (is_64bit) - nlist_size = 16; - - char *string_table = (char *) (baton->mach_header_start + symtab_cmd.stroff); - uint8_t *local_syms = baton->mach_header_start + symtab_cmd.symoff + (dysymtab_cmd.ilocalsym * nlist_size); - int local_syms_count = dysymtab_cmd.nlocalsym; - uint8_t *exported_syms = baton->mach_header_start + symtab_cmd.symoff + (dysymtab_cmd.iextdefsym * nlist_size); - int exported_syms_count = dysymtab_cmd.nextdefsym; - - // We're only going to create records for a small number of these symbols but to - // simplify the memory management I'll allocate enough space to store all of them. - baton->symbols = (struct symbol *) malloc (sizeof (struct symbol) * (local_syms_count + exported_syms_count)); - baton->symbols_count = 0; - - for (int i = 0; i < local_syms_count; i++) - { - struct nlist_64 nlist; - memset (&nlist, 0, sizeof (struct nlist_64)); - if (is_64bit) - { - memcpy (&nlist, local_syms + (i * nlist_size), sizeof (struct nlist_64)); - } - else - { - struct nlist nlist_32; - memset (&nlist_32, 0, sizeof (struct nlist)); - memcpy (&nlist_32, local_syms + (i * nlist_size), sizeof (struct nlist)); - nlist.n_un.n_strx = nlist_32.n_un.n_strx; - nlist.n_type = nlist_32.n_type; - nlist.n_sect = nlist_32.n_sect; - nlist.n_desc = nlist_32.n_desc; - nlist.n_value = nlist_32.n_value; - } - if ((nlist.n_type & N_STAB) == 0 - && ((nlist.n_type & N_EXT) == 1 || - ((nlist.n_type & N_TYPE) == N_TYPE && nlist.n_sect != NO_SECT)) - && nlist.n_value != 0 - && nlist.n_value != baton->text_segment_vmaddr) - { - baton->symbols[baton->symbols_count].file_address = nlist.n_value; - if (baton->cputype == CPU_TYPE_ARM) - baton->symbols[baton->symbols_count].file_address = baton->symbols[baton->symbols_count].file_address & ~1; - baton->symbols[baton->symbols_count].name = string_table + nlist.n_un.n_strx; - baton->symbols_count++; - } - } + if (strcmp(segment_name, "__LINKEDIT") == 0) { + linkedit_segment_vmaddr = segment_vmaddr; + linkedit_segment_file_offset = segment_offset; + } + } - for (int i = 0; i < exported_syms_count; i++) - { - struct nlist_64 nlist; - memset (&nlist, 0, sizeof (struct nlist_64)); - if (is_64bit) - { - memcpy (&nlist, exported_syms + (i * nlist_size), sizeof (struct nlist_64)); - } - else - { - struct nlist nlist_32; - memcpy (&nlist_32, exported_syms + (i * nlist_size), sizeof (struct nlist)); - nlist.n_un.n_strx = nlist_32.n_un.n_strx; - nlist.n_type = nlist_32.n_type; - nlist.n_sect = nlist_32.n_sect; - nlist.n_desc = nlist_32.n_desc; - nlist.n_value = nlist_32.n_value; - } - if ((nlist.n_type & N_STAB) == 0 - && ((nlist.n_type & N_EXT) == 1 || - ((nlist.n_type & N_TYPE) == N_TYPE && nlist.n_sect != NO_SECT)) - && nlist.n_value != 0 - && nlist.n_value != baton->text_segment_vmaddr) - { - baton->symbols[baton->symbols_count].file_address = nlist.n_value; - if (baton->cputype == CPU_TYPE_ARM) - baton->symbols[baton->symbols_count].file_address = baton->symbols[baton->symbols_count].file_address & ~1; - baton->symbols[baton->symbols_count].name = string_table + nlist.n_un.n_strx; - baton->symbols_count++; - } - } + if (*lc_cmd == LC_SYMTAB) { + memcpy(&symtab_cmd, offset, sizeof(struct symtab_command)); + } - qsort (baton->symbols, baton->symbols_count, sizeof (struct symbol), symbol_compare); + if (*lc_cmd == LC_DYSYMTAB) { + struct dysymtab_command dysymtab_cmd; + memcpy(&dysymtab_cmd, offset, sizeof(struct dysymtab_command)); + + int nlist_size = 12; + if (is_64bit) + nlist_size = 16; + + char *string_table = + (char *)(baton->mach_header_start + symtab_cmd.stroff); + uint8_t *local_syms = baton->mach_header_start + symtab_cmd.symoff + + (dysymtab_cmd.ilocalsym * nlist_size); + int local_syms_count = dysymtab_cmd.nlocalsym; + uint8_t *exported_syms = baton->mach_header_start + symtab_cmd.symoff + + (dysymtab_cmd.iextdefsym * nlist_size); + int exported_syms_count = dysymtab_cmd.nextdefsym; + + // We're only going to create records for a small number of these symbols + // but to + // simplify the memory management I'll allocate enough space to store all + // of them. + baton->symbols = (struct symbol *)malloc( + sizeof(struct symbol) * (local_syms_count + exported_syms_count)); + baton->symbols_count = 0; + + for (int i = 0; i < local_syms_count; i++) { + struct nlist_64 nlist; + memset(&nlist, 0, sizeof(struct nlist_64)); + if (is_64bit) { + memcpy(&nlist, local_syms + (i * nlist_size), + sizeof(struct nlist_64)); + } else { + struct nlist nlist_32; + memset(&nlist_32, 0, sizeof(struct nlist)); + memcpy(&nlist_32, local_syms + (i * nlist_size), + sizeof(struct nlist)); + nlist.n_un.n_strx = nlist_32.n_un.n_strx; + nlist.n_type = nlist_32.n_type; + nlist.n_sect = nlist_32.n_sect; + nlist.n_desc = nlist_32.n_desc; + nlist.n_value = nlist_32.n_value; } - - if (*lc_cmd == LC_FUNCTION_STARTS) - { - struct linkedit_data_command function_starts_cmd; - memcpy (&function_starts_cmd, offset, sizeof (struct linkedit_data_command)); - - uint8_t *funcstarts_offset = baton->mach_header_start + function_starts_cmd.dataoff; - uint8_t *function_end = funcstarts_offset + function_starts_cmd.datasize; - int count = 0; - - while (funcstarts_offset < function_end) - { - if (read_leb128 (&funcstarts_offset) != 0) - { - count++; - } - } - - baton->function_start_addresses = (uint64_t *) malloc (sizeof (uint64_t) * count); - baton->function_start_addresses_count = count; - - funcstarts_offset = baton->mach_header_start + function_starts_cmd.dataoff; - uint64_t current_pc = baton->text_segment_vmaddr; - int i = 0; - while (funcstarts_offset < function_end) - { - uint64_t func_start = read_leb128 (&funcstarts_offset); - if (func_start != 0) - { - current_pc += func_start; - baton->function_start_addresses[i++] = current_pc; - } - } + if ((nlist.n_type & N_STAB) == 0 && + ((nlist.n_type & N_EXT) == 1 || + ((nlist.n_type & N_TYPE) == N_TYPE && nlist.n_sect != NO_SECT)) && + nlist.n_value != 0 && nlist.n_value != baton->text_segment_vmaddr) { + baton->symbols[baton->symbols_count].file_address = nlist.n_value; + if (baton->cputype == CPU_TYPE_ARM) + baton->symbols[baton->symbols_count].file_address = + baton->symbols[baton->symbols_count].file_address & ~1; + baton->symbols[baton->symbols_count].name = + string_table + nlist.n_un.n_strx; + baton->symbols_count++; + } + } + + for (int i = 0; i < exported_syms_count; i++) { + struct nlist_64 nlist; + memset(&nlist, 0, sizeof(struct nlist_64)); + if (is_64bit) { + memcpy(&nlist, exported_syms + (i * nlist_size), + sizeof(struct nlist_64)); + } else { + struct nlist nlist_32; + memcpy(&nlist_32, exported_syms + (i * nlist_size), + sizeof(struct nlist)); + nlist.n_un.n_strx = nlist_32.n_un.n_strx; + nlist.n_type = nlist_32.n_type; + nlist.n_sect = nlist_32.n_sect; + nlist.n_desc = nlist_32.n_desc; + nlist.n_value = nlist_32.n_value; + } + if ((nlist.n_type & N_STAB) == 0 && + ((nlist.n_type & N_EXT) == 1 || + ((nlist.n_type & N_TYPE) == N_TYPE && nlist.n_sect != NO_SECT)) && + nlist.n_value != 0 && nlist.n_value != baton->text_segment_vmaddr) { + baton->symbols[baton->symbols_count].file_address = nlist.n_value; + if (baton->cputype == CPU_TYPE_ARM) + baton->symbols[baton->symbols_count].file_address = + baton->symbols[baton->symbols_count].file_address & ~1; + baton->symbols[baton->symbols_count].name = + string_table + nlist.n_un.n_strx; + baton->symbols_count++; } + } - offset = start_of_this_load_cmd + *lc_cmdsize; - cur_cmd++; + qsort(baton->symbols, baton->symbols_count, sizeof(struct symbol), + symbol_compare); } + if (*lc_cmd == LC_FUNCTION_STARTS) { + struct linkedit_data_command function_starts_cmd; + memcpy(&function_starts_cmd, offset, + sizeof(struct linkedit_data_command)); - // Augment the symbol table with the function starts table -- adding symbol entries - // for functions that were stripped. + uint8_t *funcstarts_offset = + baton->mach_header_start + function_starts_cmd.dataoff; + uint8_t *function_end = funcstarts_offset + function_starts_cmd.datasize; + int count = 0; - int unnamed_functions_to_add = 0; - for (int i = 0; i < baton->function_start_addresses_count; i++) - { - struct symbol search_key; - search_key.file_address = baton->function_start_addresses[i]; - if (baton->cputype == CPU_TYPE_ARM) - search_key.file_address = search_key.file_address & ~1; - struct symbol *sym = bsearch (&search_key, baton->symbols, baton->symbols_count, sizeof (struct symbol), symbol_compare); - if (sym == NULL) - unnamed_functions_to_add++; - } - - baton->symbols = (struct symbol *) realloc (baton->symbols, sizeof (struct symbol) * (baton->symbols_count + unnamed_functions_to_add)); - - int current_unnamed_symbol = 1; - int number_symbols_added = 0; - for (int i = 0; i < baton->function_start_addresses_count; i++) - { - struct symbol search_key; - search_key.file_address = baton->function_start_addresses[i]; - if (baton->cputype == CPU_TYPE_ARM) - search_key.file_address = search_key.file_address & ~1; - struct symbol *sym = bsearch (&search_key, baton->symbols, baton->symbols_count, sizeof (struct symbol), symbol_compare); - if (sym == NULL) - { - char *name; - asprintf (&name, "unnamed function #%d", current_unnamed_symbol++); - baton->symbols[baton->symbols_count + number_symbols_added].file_address = baton->function_start_addresses[i]; - baton->symbols[baton->symbols_count + number_symbols_added].name = name; - number_symbols_added++; + while (funcstarts_offset < function_end) { + if (read_leb128(&funcstarts_offset) != 0) { + count++; + } + } + + baton->function_start_addresses = + (uint64_t *)malloc(sizeof(uint64_t) * count); + baton->function_start_addresses_count = count; + + funcstarts_offset = + baton->mach_header_start + function_starts_cmd.dataoff; + uint64_t current_pc = baton->text_segment_vmaddr; + int i = 0; + while (funcstarts_offset < function_end) { + uint64_t func_start = read_leb128(&funcstarts_offset); + if (func_start != 0) { + current_pc += func_start; + baton->function_start_addresses[i++] = current_pc; } + } } - baton->symbols_count += number_symbols_added; - qsort (baton->symbols, baton->symbols_count, sizeof (struct symbol), symbol_compare); + offset = start_of_this_load_cmd + *lc_cmdsize; + cur_cmd++; + } + + // Augment the symbol table with the function starts table -- adding symbol + // entries + // for functions that were stripped. + + int unnamed_functions_to_add = 0; + for (int i = 0; i < baton->function_start_addresses_count; i++) { + struct symbol search_key; + search_key.file_address = baton->function_start_addresses[i]; + if (baton->cputype == CPU_TYPE_ARM) + search_key.file_address = search_key.file_address & ~1; + struct symbol *sym = + bsearch(&search_key, baton->symbols, baton->symbols_count, + sizeof(struct symbol), symbol_compare); + if (sym == NULL) + unnamed_functions_to_add++; + } + + baton->symbols = (struct symbol *)realloc( + baton->symbols, sizeof(struct symbol) * + (baton->symbols_count + unnamed_functions_to_add)); + + int current_unnamed_symbol = 1; + int number_symbols_added = 0; + for (int i = 0; i < baton->function_start_addresses_count; i++) { + struct symbol search_key; + search_key.file_address = baton->function_start_addresses[i]; + if (baton->cputype == CPU_TYPE_ARM) + search_key.file_address = search_key.file_address & ~1; + struct symbol *sym = + bsearch(&search_key, baton->symbols, baton->symbols_count, + sizeof(struct symbol), symbol_compare); + if (sym == NULL) { + char *name; + asprintf(&name, "unnamed function #%d", current_unnamed_symbol++); + baton->symbols[baton->symbols_count + number_symbols_added].file_address = + baton->function_start_addresses[i]; + baton->symbols[baton->symbols_count + number_symbols_added].name = name; + number_symbols_added++; + } + } + baton->symbols_count += number_symbols_added; + qsort(baton->symbols, baton->symbols_count, sizeof(struct symbol), + symbol_compare); + + // printf ("function start addresses\n"); + // for (int i = 0; i < baton->function_start_addresses_count; i++) + // { + // printf ("0x%012llx\n", baton->function_start_addresses[i]); + // } + + // printf ("symbol table names & addresses\n"); + // for (int i = 0; i < baton->symbols_count; i++) + // { + // printf ("0x%012llx %s\n", baton->symbols[i].file_address, + // baton->symbols[i].name); + // } +} -// printf ("function start addresses\n"); -// for (int i = 0; i < baton->function_start_addresses_count; i++) -// { -// printf ("0x%012llx\n", baton->function_start_addresses[i]); -// } +void print_encoding_x86_64(struct baton baton, uint8_t *function_start, + uint32_t encoding) { + int mode = encoding & UNWIND_X86_64_MODE_MASK; + switch (mode) { + case UNWIND_X86_64_MODE_RBP_FRAME: { + printf("frame func: CFA is rbp+%d ", 16); + printf(" rip=[CFA-8] rbp=[CFA-16]"); + uint32_t saved_registers_offset = + EXTRACT_BITS(encoding, UNWIND_X86_64_RBP_FRAME_OFFSET); -// printf ("symbol table names & addresses\n"); -// for (int i = 0; i < baton->symbols_count; i++) -// { -// printf ("0x%012llx %s\n", baton->symbols[i].file_address, baton->symbols[i].name); -// } + uint32_t saved_registers_locations = + EXTRACT_BITS(encoding, UNWIND_X86_64_RBP_FRAME_REGISTERS); -} + saved_registers_offset += 2; -void -print_encoding_x86_64 (struct baton baton, uint8_t *function_start, uint32_t encoding) -{ - int mode = encoding & UNWIND_X86_64_MODE_MASK; - switch (mode) - { - case UNWIND_X86_64_MODE_RBP_FRAME: - { - printf ("frame func: CFA is rbp+%d ", 16); - printf (" rip=[CFA-8] rbp=[CFA-16]"); - uint32_t saved_registers_offset = EXTRACT_BITS (encoding, UNWIND_X86_64_RBP_FRAME_OFFSET); - - uint32_t saved_registers_locations = EXTRACT_BITS (encoding, UNWIND_X86_64_RBP_FRAME_REGISTERS); - - - saved_registers_offset += 2; - - for (int i = 0; i < 5; i++) - { - switch (saved_registers_locations & 0x7) - { - case UNWIND_X86_64_REG_NONE: - break; - case UNWIND_X86_64_REG_RBX: - printf (" rbx=[CFA-%d]", saved_registers_offset * 8); - break; - case UNWIND_X86_64_REG_R12: - printf (" r12=[CFA-%d]", saved_registers_offset * 8); - break; - case UNWIND_X86_64_REG_R13: - printf (" r13=[CFA-%d]", saved_registers_offset * 8); - break; - case UNWIND_X86_64_REG_R14: - printf (" r14=[CFA-%d]", saved_registers_offset * 8); - break; - case UNWIND_X86_64_REG_R15: - printf (" r15=[CFA-%d]", saved_registers_offset * 8); - break; - } - saved_registers_offset--; - saved_registers_locations >>= 3; - } - } + for (int i = 0; i < 5; i++) { + switch (saved_registers_locations & 0x7) { + case UNWIND_X86_64_REG_NONE: break; + case UNWIND_X86_64_REG_RBX: + printf(" rbx=[CFA-%d]", saved_registers_offset * 8); + break; + case UNWIND_X86_64_REG_R12: + printf(" r12=[CFA-%d]", saved_registers_offset * 8); + break; + case UNWIND_X86_64_REG_R13: + printf(" r13=[CFA-%d]", saved_registers_offset * 8); + break; + case UNWIND_X86_64_REG_R14: + printf(" r14=[CFA-%d]", saved_registers_offset * 8); + break; + case UNWIND_X86_64_REG_R15: + printf(" r15=[CFA-%d]", saved_registers_offset * 8); + break; + } + saved_registers_offset--; + saved_registers_locations >>= 3; + } + } break; - case UNWIND_X86_64_MODE_STACK_IND: - case UNWIND_X86_64_MODE_STACK_IMMD: - { - uint32_t stack_size = EXTRACT_BITS (encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); - uint32_t register_count = EXTRACT_BITS (encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT); - uint32_t permutation = EXTRACT_BITS (encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION); - - if (mode == UNWIND_X86_64_MODE_STACK_IND && function_start) - { - uint32_t stack_adjust = EXTRACT_BITS (encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST); + case UNWIND_X86_64_MODE_STACK_IND: + case UNWIND_X86_64_MODE_STACK_IMMD: { + uint32_t stack_size = + EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); + uint32_t register_count = + EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT); + uint32_t permutation = + EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION); - // offset into the function instructions; 0 == beginning of first instruction - uint32_t offset_to_subl_insn = EXTRACT_BITS (encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); + if (mode == UNWIND_X86_64_MODE_STACK_IND && function_start) { + uint32_t stack_adjust = + EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST); - stack_size = *((uint32_t*) (function_start + offset_to_subl_insn)); + // offset into the function instructions; 0 == beginning of first + // instruction + uint32_t offset_to_subl_insn = + EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); - stack_size += stack_adjust * 8; + stack_size = *((uint32_t *)(function_start + offset_to_subl_insn)); - printf ("large stack "); - } - - if (mode == UNWIND_X86_64_MODE_STACK_IND) - { - printf ("frameless function: stack size %d, register count %d ", stack_size * 8, register_count); - } - else - { - printf ("frameless function: stack size %d, register count %d ", stack_size, register_count); - } + stack_size += stack_adjust * 8; - if (register_count == 0) - { - printf (" no registers saved"); - } - else - { - - // We need to include (up to) 6 registers in 10 bits. - // That would be 18 bits if we just used 3 bits per reg to indicate - // the order they're saved on the stack. - // - // This is done with Lehmer code permutation, e.g. see - // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms - int permunreg[6]; - - // This decodes the variable-base number in the 10 bits - // and gives us the Lehmer code sequence which can then - // be decoded. - - switch (register_count) - { - case 6: - permunreg[0] = permutation/120; // 120 == 5! - permutation -= (permunreg[0]*120); - permunreg[1] = permutation/24; // 24 == 4! - permutation -= (permunreg[1]*24); - permunreg[2] = permutation/6; // 6 == 3! - permutation -= (permunreg[2]*6); - permunreg[3] = permutation/2; // 2 == 2! - permutation -= (permunreg[3]*2); - permunreg[4] = permutation; // 1 == 1! - permunreg[5] = 0; - break; - case 5: - permunreg[0] = permutation/120; - permutation -= (permunreg[0]*120); - permunreg[1] = permutation/24; - permutation -= (permunreg[1]*24); - permunreg[2] = permutation/6; - permutation -= (permunreg[2]*6); - permunreg[3] = permutation/2; - permutation -= (permunreg[3]*2); - permunreg[4] = permutation; - break; - case 4: - permunreg[0] = permutation/60; - permutation -= (permunreg[0]*60); - permunreg[1] = permutation/12; - permutation -= (permunreg[1]*12); - permunreg[2] = permutation/3; - permutation -= (permunreg[2]*3); - permunreg[3] = permutation; - break; - case 3: - permunreg[0] = permutation/20; - permutation -= (permunreg[0]*20); - permunreg[1] = permutation/4; - permutation -= (permunreg[1]*4); - permunreg[2] = permutation; - break; - case 2: - permunreg[0] = permutation/5; - permutation -= (permunreg[0]*5); - permunreg[1] = permutation; - break; - case 1: - permunreg[0] = permutation; - break; - } - - // Decode the Lehmer code for this permutation of - // the registers v. http://en.wikipedia.org/wiki/Lehmer_code - - int registers[6]; - bool used[7] = { false, false, false, false, false, false, false }; - for (int i = 0; i < register_count; i++) - { - int renum = 0; - for (int j = 1; j < 7; j++) - { - if (used[j] == false) - { - if (renum == permunreg[i]) - { - registers[i] = j; - used[j] = true; - break; - } - renum++; - } - } - } - - - if (mode == UNWIND_X86_64_MODE_STACK_IND) - { - printf (" CFA is rsp+%d ", stack_size); - } - else - { - printf (" CFA is rsp+%d ", stack_size * 8); - } - - uint32_t saved_registers_offset = 1; - printf (" rip=[CFA-%d]", saved_registers_offset * 8); - saved_registers_offset++; - - for (int i = (sizeof (registers) / sizeof (int)) - 1; i >= 0; i--) - { - switch (registers[i]) - { - case UNWIND_X86_64_REG_NONE: - break; - case UNWIND_X86_64_REG_RBX: - printf (" rbx=[CFA-%d]", saved_registers_offset * 8); - saved_registers_offset++; - break; - case UNWIND_X86_64_REG_R12: - printf (" r12=[CFA-%d]", saved_registers_offset * 8); - saved_registers_offset++; - break; - case UNWIND_X86_64_REG_R13: - printf (" r13=[CFA-%d]", saved_registers_offset * 8); - saved_registers_offset++; - break; - case UNWIND_X86_64_REG_R14: - printf (" r14=[CFA-%d]", saved_registers_offset * 8); - saved_registers_offset++; - break; - case UNWIND_X86_64_REG_R15: - printf (" r15=[CFA-%d]", saved_registers_offset * 8); - saved_registers_offset++; - break; - case UNWIND_X86_64_REG_RBP: - printf (" rbp=[CFA-%d]", saved_registers_offset * 8); - saved_registers_offset++; - break; - } - } + printf("large stack "); + } - } + if (mode == UNWIND_X86_64_MODE_STACK_IND) { + printf("frameless function: stack size %d, register count %d ", + stack_size * 8, register_count); + } else { + printf("frameless function: stack size %d, register count %d ", + stack_size, register_count); + } - } + if (register_count == 0) { + printf(" no registers saved"); + } else { + + // We need to include (up to) 6 registers in 10 bits. + // That would be 18 bits if we just used 3 bits per reg to indicate + // the order they're saved on the stack. + // + // This is done with Lehmer code permutation, e.g. see + // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms + int permunreg[6]; + + // This decodes the variable-base number in the 10 bits + // and gives us the Lehmer code sequence which can then + // be decoded. + + switch (register_count) { + case 6: + permunreg[0] = permutation / 120; // 120 == 5! + permutation -= (permunreg[0] * 120); + permunreg[1] = permutation / 24; // 24 == 4! + permutation -= (permunreg[1] * 24); + permunreg[2] = permutation / 6; // 6 == 3! + permutation -= (permunreg[2] * 6); + permunreg[3] = permutation / 2; // 2 == 2! + permutation -= (permunreg[3] * 2); + permunreg[4] = permutation; // 1 == 1! + permunreg[5] = 0; break; - - case UNWIND_X86_64_MODE_DWARF: - { - uint32_t dwarf_offset = encoding & UNWIND_X86_DWARF_SECTION_OFFSET; - printf ("DWARF unwind instructions: FDE at offset %d (file address 0x%" PRIx64 ")", - dwarf_offset, dwarf_offset + baton.eh_section_file_address); - } + case 5: + permunreg[0] = permutation / 120; + permutation -= (permunreg[0] * 120); + permunreg[1] = permutation / 24; + permutation -= (permunreg[1] * 24); + permunreg[2] = permutation / 6; + permutation -= (permunreg[2] * 6); + permunreg[3] = permutation / 2; + permutation -= (permunreg[3] * 2); + permunreg[4] = permutation; break; - - case 0: - { - printf (" no unwind information"); - } + case 4: + permunreg[0] = permutation / 60; + permutation -= (permunreg[0] * 60); + permunreg[1] = permutation / 12; + permutation -= (permunreg[1] * 12); + permunreg[2] = permutation / 3; + permutation -= (permunreg[2] * 3); + permunreg[3] = permutation; break; - } -} - -void -print_encoding_i386 (struct baton baton, uint8_t *function_start, uint32_t encoding) -{ - int mode = encoding & UNWIND_X86_MODE_MASK; - switch (mode) - { - case UNWIND_X86_MODE_EBP_FRAME: - { - printf ("frame func: CFA is ebp+%d ", 8); - printf (" eip=[CFA-4] ebp=[CFA-8]"); - uint32_t saved_registers_offset = EXTRACT_BITS (encoding, UNWIND_X86_EBP_FRAME_OFFSET); - - uint32_t saved_registers_locations = EXTRACT_BITS (encoding, UNWIND_X86_EBP_FRAME_REGISTERS); - - - saved_registers_offset += 2; - - for (int i = 0; i < 5; i++) - { - switch (saved_registers_locations & 0x7) - { - case UNWIND_X86_REG_NONE: - break; - case UNWIND_X86_REG_EBX: - printf (" ebx=[CFA-%d]", saved_registers_offset * 4); - break; - case UNWIND_X86_REG_ECX: - printf (" ecx=[CFA-%d]", saved_registers_offset * 4); - break; - case UNWIND_X86_REG_EDX: - printf (" edx=[CFA-%d]", saved_registers_offset * 4); - break; - case UNWIND_X86_REG_EDI: - printf (" edi=[CFA-%d]", saved_registers_offset * 4); - break; - case UNWIND_X86_REG_ESI: - printf (" esi=[CFA-%d]", saved_registers_offset * 4); - break; - } - saved_registers_offset--; - saved_registers_locations >>= 3; + case 3: + permunreg[0] = permutation / 20; + permutation -= (permunreg[0] * 20); + permunreg[1] = permutation / 4; + permutation -= (permunreg[1] * 4); + permunreg[2] = permutation; + break; + case 2: + permunreg[0] = permutation / 5; + permutation -= (permunreg[0] * 5); + permunreg[1] = permutation; + break; + case 1: + permunreg[0] = permutation; + break; + } + + // Decode the Lehmer code for this permutation of + // the registers v. http://en.wikipedia.org/wiki/Lehmer_code + + int registers[6]; + bool used[7] = {false, false, false, false, false, false, false}; + for (int i = 0; i < register_count; i++) { + int renum = 0; + for (int j = 1; j < 7; j++) { + if (used[j] == false) { + if (renum == permunreg[i]) { + registers[i] = j; + used[j] = true; + break; } + renum++; + } } - break; + } + + if (mode == UNWIND_X86_64_MODE_STACK_IND) { + printf(" CFA is rsp+%d ", stack_size); + } else { + printf(" CFA is rsp+%d ", stack_size * 8); + } + + uint32_t saved_registers_offset = 1; + printf(" rip=[CFA-%d]", saved_registers_offset * 8); + saved_registers_offset++; + + for (int i = (sizeof(registers) / sizeof(int)) - 1; i >= 0; i--) { + switch (registers[i]) { + case UNWIND_X86_64_REG_NONE: + break; + case UNWIND_X86_64_REG_RBX: + printf(" rbx=[CFA-%d]", saved_registers_offset * 8); + saved_registers_offset++; + break; + case UNWIND_X86_64_REG_R12: + printf(" r12=[CFA-%d]", saved_registers_offset * 8); + saved_registers_offset++; + break; + case UNWIND_X86_64_REG_R13: + printf(" r13=[CFA-%d]", saved_registers_offset * 8); + saved_registers_offset++; + break; + case UNWIND_X86_64_REG_R14: + printf(" r14=[CFA-%d]", saved_registers_offset * 8); + saved_registers_offset++; + break; + case UNWIND_X86_64_REG_R15: + printf(" r15=[CFA-%d]", saved_registers_offset * 8); + saved_registers_offset++; + break; + case UNWIND_X86_64_REG_RBP: + printf(" rbp=[CFA-%d]", saved_registers_offset * 8); + saved_registers_offset++; + break; + } + } + } - case UNWIND_X86_MODE_STACK_IND: - case UNWIND_X86_MODE_STACK_IMMD: - { - uint32_t stack_size = EXTRACT_BITS (encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); - uint32_t register_count = EXTRACT_BITS (encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT); - uint32_t permutation = EXTRACT_BITS (encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION); + } break; - if (mode == UNWIND_X86_MODE_STACK_IND && function_start) - { - uint32_t stack_adjust = EXTRACT_BITS (encoding, UNWIND_X86_FRAMELESS_STACK_ADJUST); + case UNWIND_X86_64_MODE_DWARF: { + uint32_t dwarf_offset = encoding & UNWIND_X86_DWARF_SECTION_OFFSET; + printf( + "DWARF unwind instructions: FDE at offset %d (file address 0x%" PRIx64 + ")", + dwarf_offset, dwarf_offset + baton.eh_section_file_address); + } break; - // offset into the function instructions; 0 == beginning of first instruction - uint32_t offset_to_subl_insn = EXTRACT_BITS (encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); + case 0: { + printf(" no unwind information"); + } break; + } +} - stack_size = *((uint32_t*) (function_start + offset_to_subl_insn)); +void print_encoding_i386(struct baton baton, uint8_t *function_start, + uint32_t encoding) { + int mode = encoding & UNWIND_X86_MODE_MASK; + switch (mode) { + case UNWIND_X86_MODE_EBP_FRAME: { + printf("frame func: CFA is ebp+%d ", 8); + printf(" eip=[CFA-4] ebp=[CFA-8]"); + uint32_t saved_registers_offset = + EXTRACT_BITS(encoding, UNWIND_X86_EBP_FRAME_OFFSET); - stack_size += stack_adjust * 4; + uint32_t saved_registers_locations = + EXTRACT_BITS(encoding, UNWIND_X86_EBP_FRAME_REGISTERS); - printf ("large stack "); - } - - if (mode == UNWIND_X86_MODE_STACK_IND) - { - printf ("frameless function: stack size %d, register count %d ", stack_size, register_count); - } - else - { - printf ("frameless function: stack size %d, register count %d ", stack_size * 4, register_count); - } - - if (register_count == 0) - { - printf (" no registers saved"); - } - else - { - - // We need to include (up to) 6 registers in 10 bits. - // That would be 18 bits if we just used 3 bits per reg to indicate - // the order they're saved on the stack. - // - // This is done with Lehmer code permutation, e.g. see - // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms - int permunreg[6]; - - // This decodes the variable-base number in the 10 bits - // and gives us the Lehmer code sequence which can then - // be decoded. - - switch (register_count) - { - case 6: - permunreg[0] = permutation/120; // 120 == 5! - permutation -= (permunreg[0]*120); - permunreg[1] = permutation/24; // 24 == 4! - permutation -= (permunreg[1]*24); - permunreg[2] = permutation/6; // 6 == 3! - permutation -= (permunreg[2]*6); - permunreg[3] = permutation/2; // 2 == 2! - permutation -= (permunreg[3]*2); - permunreg[4] = permutation; // 1 == 1! - permunreg[5] = 0; - break; - case 5: - permunreg[0] = permutation/120; - permutation -= (permunreg[0]*120); - permunreg[1] = permutation/24; - permutation -= (permunreg[1]*24); - permunreg[2] = permutation/6; - permutation -= (permunreg[2]*6); - permunreg[3] = permutation/2; - permutation -= (permunreg[3]*2); - permunreg[4] = permutation; - break; - case 4: - permunreg[0] = permutation/60; - permutation -= (permunreg[0]*60); - permunreg[1] = permutation/12; - permutation -= (permunreg[1]*12); - permunreg[2] = permutation/3; - permutation -= (permunreg[2]*3); - permunreg[3] = permutation; - break; - case 3: - permunreg[0] = permutation/20; - permutation -= (permunreg[0]*20); - permunreg[1] = permutation/4; - permutation -= (permunreg[1]*4); - permunreg[2] = permutation; - break; - case 2: - permunreg[0] = permutation/5; - permutation -= (permunreg[0]*5); - permunreg[1] = permutation; - break; - case 1: - permunreg[0] = permutation; - break; - } - - // Decode the Lehmer code for this permutation of - // the registers v. http://en.wikipedia.org/wiki/Lehmer_code - - int registers[6]; - bool used[7] = { false, false, false, false, false, false, false }; - for (int i = 0; i < register_count; i++) - { - int renum = 0; - for (int j = 1; j < 7; j++) - { - if (used[j] == false) - { - if (renum == permunreg[i]) - { - registers[i] = j; - used[j] = true; - break; - } - renum++; - } - } - } - - - if (mode == UNWIND_X86_MODE_STACK_IND) - { - printf (" CFA is esp+%d ", stack_size); - } - else - { - printf (" CFA is esp+%d ", stack_size * 4); - } - - uint32_t saved_registers_offset = 1; - printf (" eip=[CFA-%d]", saved_registers_offset * 4); - saved_registers_offset++; - - for (int i = (sizeof (registers) / sizeof (int)) - 1; i >= 0; i--) - { - switch (registers[i]) - { - case UNWIND_X86_REG_NONE: - break; - case UNWIND_X86_REG_EBX: - printf (" ebx=[CFA-%d]", saved_registers_offset * 4); - saved_registers_offset++; - break; - case UNWIND_X86_REG_ECX: - printf (" ecx=[CFA-%d]", saved_registers_offset * 4); - saved_registers_offset++; - break; - case UNWIND_X86_REG_EDX: - printf (" edx=[CFA-%d]", saved_registers_offset * 4); - saved_registers_offset++; - break; - case UNWIND_X86_REG_EDI: - printf (" edi=[CFA-%d]", saved_registers_offset * 4); - saved_registers_offset++; - break; - case UNWIND_X86_REG_ESI: - printf (" esi=[CFA-%d]", saved_registers_offset * 4); - saved_registers_offset++; - break; - case UNWIND_X86_REG_EBP: - printf (" ebp=[CFA-%d]", saved_registers_offset * 4); - saved_registers_offset++; - break; - } - } + saved_registers_offset += 2; - } - - } + for (int i = 0; i < 5; i++) { + switch (saved_registers_locations & 0x7) { + case UNWIND_X86_REG_NONE: break; - - case UNWIND_X86_MODE_DWARF: - { - uint32_t dwarf_offset = encoding & UNWIND_X86_DWARF_SECTION_OFFSET; - printf ("DWARF unwind instructions: FDE at offset %d (file address 0x%" PRIx64 ")", - dwarf_offset, dwarf_offset + baton.eh_section_file_address); - } + case UNWIND_X86_REG_EBX: + printf(" ebx=[CFA-%d]", saved_registers_offset * 4); break; - - case 0: - { - printf (" no unwind information"); - } + case UNWIND_X86_REG_ECX: + printf(" ecx=[CFA-%d]", saved_registers_offset * 4); + break; + case UNWIND_X86_REG_EDX: + printf(" edx=[CFA-%d]", saved_registers_offset * 4); + break; + case UNWIND_X86_REG_EDI: + printf(" edi=[CFA-%d]", saved_registers_offset * 4); + break; + case UNWIND_X86_REG_ESI: + printf(" esi=[CFA-%d]", saved_registers_offset * 4); break; + } + saved_registers_offset--; + saved_registers_locations >>= 3; } -} + } break; -void -print_encoding_arm64 (struct baton baton, uint8_t *function_start, uint32_t encoding) -{ - const int wordsize = 8; - int mode = encoding & UNWIND_ARM64_MODE_MASK; - switch (mode) - { - case UNWIND_ARM64_MODE_FRAME: - { - printf ("frame func: CFA is fp+%d ", 16); - printf (" pc=[CFA-8] fp=[CFA-16]"); - int reg_pairs_saved_count = 1; - uint32_t saved_register_bits = encoding & 0xfff; - if (saved_register_bits & UNWIND_ARM64_FRAME_X19_X20_PAIR) - { - int cfa_offset = reg_pairs_saved_count * -2 * wordsize; - cfa_offset -= wordsize; - printf (" x19=[CFA%d]", cfa_offset); - cfa_offset -= wordsize; - printf (" x20=[CFA%d]", cfa_offset); - reg_pairs_saved_count++; - } - if (saved_register_bits & UNWIND_ARM64_FRAME_X21_X22_PAIR) - { - int cfa_offset = reg_pairs_saved_count * -2 * wordsize; - cfa_offset -= wordsize; - printf (" x21=[CFA%d]", cfa_offset); - cfa_offset -= wordsize; - printf (" x22=[CFA%d]", cfa_offset); - reg_pairs_saved_count++; - } - if (saved_register_bits & UNWIND_ARM64_FRAME_X23_X24_PAIR) - { - int cfa_offset = reg_pairs_saved_count * -2 * wordsize; - cfa_offset -= wordsize; - printf (" x23=[CFA%d]", cfa_offset); - cfa_offset -= wordsize; - printf (" x24=[CFA%d]", cfa_offset); - reg_pairs_saved_count++; - } - if (saved_register_bits & UNWIND_ARM64_FRAME_X25_X26_PAIR) - { - int cfa_offset = reg_pairs_saved_count * -2 * wordsize; - cfa_offset -= wordsize; - printf (" x25=[CFA%d]", cfa_offset); - cfa_offset -= wordsize; - printf (" x26=[CFA%d]", cfa_offset); - reg_pairs_saved_count++; - } - if (saved_register_bits & UNWIND_ARM64_FRAME_X27_X28_PAIR) - { - int cfa_offset = reg_pairs_saved_count * -2 * wordsize; - cfa_offset -= wordsize; - printf (" x27=[CFA%d]", cfa_offset); - cfa_offset -= wordsize; - printf (" x28=[CFA%d]", cfa_offset); - reg_pairs_saved_count++; - } - if (saved_register_bits & UNWIND_ARM64_FRAME_D8_D9_PAIR) - { - int cfa_offset = reg_pairs_saved_count * -2 * wordsize; - cfa_offset -= wordsize; - printf (" d8=[CFA%d]", cfa_offset); - cfa_offset -= wordsize; - printf (" d9=[CFA%d]", cfa_offset); - reg_pairs_saved_count++; - } - if (saved_register_bits & UNWIND_ARM64_FRAME_D10_D11_PAIR) - { - int cfa_offset = reg_pairs_saved_count * -2 * wordsize; - cfa_offset -= wordsize; - printf (" d10=[CFA%d]", cfa_offset); - cfa_offset -= wordsize; - printf (" d11=[CFA%d]", cfa_offset); - reg_pairs_saved_count++; - } - if (saved_register_bits & UNWIND_ARM64_FRAME_D12_D13_PAIR) - { - int cfa_offset = reg_pairs_saved_count * -2 * wordsize; - cfa_offset -= wordsize; - printf (" d12=[CFA%d]", cfa_offset); - cfa_offset -= wordsize; - printf (" d13=[CFA%d]", cfa_offset); - reg_pairs_saved_count++; - } - if (saved_register_bits & UNWIND_ARM64_FRAME_D14_D15_PAIR) - { - int cfa_offset = reg_pairs_saved_count * -2 * wordsize; - cfa_offset -= wordsize; - printf (" d14=[CFA%d]", cfa_offset); - cfa_offset -= wordsize; - printf (" d15=[CFA%d]", cfa_offset); - reg_pairs_saved_count++; - } + case UNWIND_X86_MODE_STACK_IND: + case UNWIND_X86_MODE_STACK_IMMD: { + uint32_t stack_size = + EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); + uint32_t register_count = + EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT); + uint32_t permutation = + EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION); - } - break; + if (mode == UNWIND_X86_MODE_STACK_IND && function_start) { + uint32_t stack_adjust = + EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_ADJUST); - case UNWIND_ARM64_MODE_FRAMELESS: - { - uint32_t stack_size = encoding & UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK; - printf ("frameless function: stack size %d ", stack_size * 16); + // offset into the function instructions; 0 == beginning of first + // instruction + uint32_t offset_to_subl_insn = + EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); - } - break; + stack_size = *((uint32_t *)(function_start + offset_to_subl_insn)); - case UNWIND_ARM64_MODE_DWARF: - { - uint32_t dwarf_offset = encoding & UNWIND_ARM64_DWARF_SECTION_OFFSET; - printf ("DWARF unwind instructions: FDE at offset %d (file address 0x%" PRIx64 ")", - dwarf_offset, dwarf_offset + baton.eh_section_file_address); - } - break; + stack_size += stack_adjust * 4; - case 0: - { - printf (" no unwind information"); - } - break; + printf("large stack "); } -} -void -print_encoding_armv7 (struct baton baton, uint8_t *function_start, uint32_t encoding) -{ - const int wordsize = 4; - int mode = encoding & UNWIND_ARM_MODE_MASK; - switch (mode) - { - case UNWIND_ARM_MODE_FRAME_D: - case UNWIND_ARM_MODE_FRAME: - { - int stack_adjust = EXTRACT_BITS (encoding, UNWIND_ARM_FRAME_STACK_ADJUST_MASK) * wordsize; - - printf ("frame func: CFA is fp+%d ", (2 * wordsize) + stack_adjust); - int cfa_offset = -stack_adjust; - - cfa_offset -= wordsize; - printf (" pc=[CFA%d]", cfa_offset); - cfa_offset -= wordsize; - printf (" fp=[CFA%d]", cfa_offset); - - uint32_t saved_register_bits = encoding & 0xff; - if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R6) - { - cfa_offset -= wordsize; - printf (" r6=[CFA%d]", cfa_offset); - } - if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R5) - { - cfa_offset -= wordsize; - printf (" r5=[CFA%d]", cfa_offset); - } - if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R4) - { - cfa_offset -= wordsize; - printf (" r4=[CFA%d]", cfa_offset); - } - if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R12) - { - cfa_offset -= wordsize; - printf (" r12=[CFA%d]", cfa_offset); - } - if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R11) - { - cfa_offset -= wordsize; - printf (" r11=[CFA%d]", cfa_offset); - } - if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R10) - { - cfa_offset -= wordsize; - printf (" r10=[CFA%d]", cfa_offset); - } - if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R9) - { - cfa_offset -= wordsize; - printf (" r9=[CFA%d]", cfa_offset); - } - if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R8) - { - cfa_offset -= wordsize; - printf (" r8=[CFA%d]", cfa_offset); - } + if (mode == UNWIND_X86_MODE_STACK_IND) { + printf("frameless function: stack size %d, register count %d ", + stack_size, register_count); + } else { + printf("frameless function: stack size %d, register count %d ", + stack_size * 4, register_count); + } - if (mode == UNWIND_ARM_MODE_FRAME_D) - { - uint32_t d_reg_bits = EXTRACT_BITS (encoding, UNWIND_ARM_FRAME_D_REG_COUNT_MASK); - switch (d_reg_bits) - { - case 0: - // vpush {d8} - cfa_offset -= 8; - printf (" d8=[CFA%d]", cfa_offset); - break; - case 1: - // vpush {d10} - // vpush {d8} - cfa_offset -= 8; - printf (" d10=[CFA%d]", cfa_offset); - cfa_offset -= 8; - printf (" d8=[CFA%d]", cfa_offset); - break; - case 2: - // vpush {d12} - // vpush {d10} - // vpush {d8} - cfa_offset -= 8; - printf (" d12=[CFA%d]", cfa_offset); - cfa_offset -= 8; - printf (" d10=[CFA%d]", cfa_offset); - cfa_offset -= 8; - printf (" d8=[CFA%d]", cfa_offset); - break; - case 3: - // vpush {d14} - // vpush {d12} - // vpush {d10} - // vpush {d8} - cfa_offset -= 8; - printf (" d14=[CFA%d]", cfa_offset); - cfa_offset -= 8; - printf (" d12=[CFA%d]", cfa_offset); - cfa_offset -= 8; - printf (" d10=[CFA%d]", cfa_offset); - cfa_offset -= 8; - printf (" d8=[CFA%d]", cfa_offset); - break; - case 4: - // vpush {d14} - // vpush {d12} - // sp = (sp - 24) & (-16); - // vst {d8, d9, d10} - printf (" d14, d12, d10, d9, d8"); - break; - case 5: - // vpush {d14} - // sp = (sp - 40) & (-16); - // vst {d8, d9, d10, d11} - // vst {d12} - printf (" d14, d11, d10, d9, d8, d12"); - break; - case 6: - // sp = (sp - 56) & (-16); - // vst {d8, d9, d10, d11} - // vst {d12, d13, d14} - printf (" d11, d10, d9, d8, d14, d13, d12"); - break; - case 7: - // sp = (sp - 64) & (-16); - // vst {d8, d9, d10, d11} - // vst {d12, d13, d14, d15} - printf (" d11, d10, d9, d8, d15, d14, d13, d12"); - break; - } - } - } + if (register_count == 0) { + printf(" no registers saved"); + } else { + + // We need to include (up to) 6 registers in 10 bits. + // That would be 18 bits if we just used 3 bits per reg to indicate + // the order they're saved on the stack. + // + // This is done with Lehmer code permutation, e.g. see + // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms + int permunreg[6]; + + // This decodes the variable-base number in the 10 bits + // and gives us the Lehmer code sequence which can then + // be decoded. + + switch (register_count) { + case 6: + permunreg[0] = permutation / 120; // 120 == 5! + permutation -= (permunreg[0] * 120); + permunreg[1] = permutation / 24; // 24 == 4! + permutation -= (permunreg[1] * 24); + permunreg[2] = permutation / 6; // 6 == 3! + permutation -= (permunreg[2] * 6); + permunreg[3] = permutation / 2; // 2 == 2! + permutation -= (permunreg[3] * 2); + permunreg[4] = permutation; // 1 == 1! + permunreg[5] = 0; break; - - case UNWIND_ARM_MODE_DWARF: - { - uint32_t dwarf_offset = encoding & UNWIND_ARM_DWARF_SECTION_OFFSET; - printf ("DWARF unwind instructions: FDE at offset %d (file address 0x%" PRIx64 ")", - dwarf_offset, dwarf_offset + baton.eh_section_file_address); - } + case 5: + permunreg[0] = permutation / 120; + permutation -= (permunreg[0] * 120); + permunreg[1] = permutation / 24; + permutation -= (permunreg[1] * 24); + permunreg[2] = permutation / 6; + permutation -= (permunreg[2] * 6); + permunreg[3] = permutation / 2; + permutation -= (permunreg[3] * 2); + permunreg[4] = permutation; break; - - case 0: - { - printf (" no unwind information"); - } + case 4: + permunreg[0] = permutation / 60; + permutation -= (permunreg[0] * 60); + permunreg[1] = permutation / 12; + permutation -= (permunreg[1] * 12); + permunreg[2] = permutation / 3; + permutation -= (permunreg[2] * 3); + permunreg[3] = permutation; + break; + case 3: + permunreg[0] = permutation / 20; + permutation -= (permunreg[0] * 20); + permunreg[1] = permutation / 4; + permutation -= (permunreg[1] * 4); + permunreg[2] = permutation; + break; + case 2: + permunreg[0] = permutation / 5; + permutation -= (permunreg[0] * 5); + permunreg[1] = permutation; break; + case 1: + permunreg[0] = permutation; + break; + } + + // Decode the Lehmer code for this permutation of + // the registers v. http://en.wikipedia.org/wiki/Lehmer_code + + int registers[6]; + bool used[7] = {false, false, false, false, false, false, false}; + for (int i = 0; i < register_count; i++) { + int renum = 0; + for (int j = 1; j < 7; j++) { + if (used[j] == false) { + if (renum == permunreg[i]) { + registers[i] = j; + used[j] = true; + break; + } + renum++; + } + } + } + + if (mode == UNWIND_X86_MODE_STACK_IND) { + printf(" CFA is esp+%d ", stack_size); + } else { + printf(" CFA is esp+%d ", stack_size * 4); + } + + uint32_t saved_registers_offset = 1; + printf(" eip=[CFA-%d]", saved_registers_offset * 4); + saved_registers_offset++; + + for (int i = (sizeof(registers) / sizeof(int)) - 1; i >= 0; i--) { + switch (registers[i]) { + case UNWIND_X86_REG_NONE: + break; + case UNWIND_X86_REG_EBX: + printf(" ebx=[CFA-%d]", saved_registers_offset * 4); + saved_registers_offset++; + break; + case UNWIND_X86_REG_ECX: + printf(" ecx=[CFA-%d]", saved_registers_offset * 4); + saved_registers_offset++; + break; + case UNWIND_X86_REG_EDX: + printf(" edx=[CFA-%d]", saved_registers_offset * 4); + saved_registers_offset++; + break; + case UNWIND_X86_REG_EDI: + printf(" edi=[CFA-%d]", saved_registers_offset * 4); + saved_registers_offset++; + break; + case UNWIND_X86_REG_ESI: + printf(" esi=[CFA-%d]", saved_registers_offset * 4); + saved_registers_offset++; + break; + case UNWIND_X86_REG_EBP: + printf(" ebp=[CFA-%d]", saved_registers_offset * 4); + saved_registers_offset++; + break; + } + } } -} - + } break; + case UNWIND_X86_MODE_DWARF: { + uint32_t dwarf_offset = encoding & UNWIND_X86_DWARF_SECTION_OFFSET; + printf( + "DWARF unwind instructions: FDE at offset %d (file address 0x%" PRIx64 + ")", + dwarf_offset, dwarf_offset + baton.eh_section_file_address); + } break; -void print_encoding (struct baton baton, uint8_t *function_start, uint32_t encoding) -{ + case 0: { + printf(" no unwind information"); + } break; + } +} - if (baton.cputype == CPU_TYPE_X86_64) - { - print_encoding_x86_64 (baton, function_start, encoding); +void print_encoding_arm64(struct baton baton, uint8_t *function_start, + uint32_t encoding) { + const int wordsize = 8; + int mode = encoding & UNWIND_ARM64_MODE_MASK; + switch (mode) { + case UNWIND_ARM64_MODE_FRAME: { + printf("frame func: CFA is fp+%d ", 16); + printf(" pc=[CFA-8] fp=[CFA-16]"); + int reg_pairs_saved_count = 1; + uint32_t saved_register_bits = encoding & 0xfff; + if (saved_register_bits & UNWIND_ARM64_FRAME_X19_X20_PAIR) { + int cfa_offset = reg_pairs_saved_count * -2 * wordsize; + cfa_offset -= wordsize; + printf(" x19=[CFA%d]", cfa_offset); + cfa_offset -= wordsize; + printf(" x20=[CFA%d]", cfa_offset); + reg_pairs_saved_count++; } - else if (baton.cputype == CPU_TYPE_I386) - { - print_encoding_i386 (baton, function_start, encoding); + if (saved_register_bits & UNWIND_ARM64_FRAME_X21_X22_PAIR) { + int cfa_offset = reg_pairs_saved_count * -2 * wordsize; + cfa_offset -= wordsize; + printf(" x21=[CFA%d]", cfa_offset); + cfa_offset -= wordsize; + printf(" x22=[CFA%d]", cfa_offset); + reg_pairs_saved_count++; } - else if (baton.cputype == CPU_TYPE_ARM64) - { - print_encoding_arm64 (baton, function_start, encoding); + if (saved_register_bits & UNWIND_ARM64_FRAME_X23_X24_PAIR) { + int cfa_offset = reg_pairs_saved_count * -2 * wordsize; + cfa_offset -= wordsize; + printf(" x23=[CFA%d]", cfa_offset); + cfa_offset -= wordsize; + printf(" x24=[CFA%d]", cfa_offset); + reg_pairs_saved_count++; } - else if (baton.cputype == CPU_TYPE_ARM) - { - print_encoding_armv7 (baton, function_start, encoding); + if (saved_register_bits & UNWIND_ARM64_FRAME_X25_X26_PAIR) { + int cfa_offset = reg_pairs_saved_count * -2 * wordsize; + cfa_offset -= wordsize; + printf(" x25=[CFA%d]", cfa_offset); + cfa_offset -= wordsize; + printf(" x26=[CFA%d]", cfa_offset); + reg_pairs_saved_count++; } - else - { - printf (" -- unsupported encoding arch -- "); + if (saved_register_bits & UNWIND_ARM64_FRAME_X27_X28_PAIR) { + int cfa_offset = reg_pairs_saved_count * -2 * wordsize; + cfa_offset -= wordsize; + printf(" x27=[CFA%d]", cfa_offset); + cfa_offset -= wordsize; + printf(" x28=[CFA%d]", cfa_offset); + reg_pairs_saved_count++; } -} - -void -print_function_encoding (struct baton baton, uint32_t idx, uint32_t encoding, uint32_t entry_encoding_index, uint32_t entry_func_offset) -{ - - char *entry_encoding_index_str = ""; - if (entry_encoding_index != (uint32_t) -1) - { - asprintf (&entry_encoding_index_str, ", encoding #%d", entry_encoding_index); + if (saved_register_bits & UNWIND_ARM64_FRAME_D8_D9_PAIR) { + int cfa_offset = reg_pairs_saved_count * -2 * wordsize; + cfa_offset -= wordsize; + printf(" d8=[CFA%d]", cfa_offset); + cfa_offset -= wordsize; + printf(" d9=[CFA%d]", cfa_offset); + reg_pairs_saved_count++; } - else - { - asprintf (&entry_encoding_index_str, ""); + if (saved_register_bits & UNWIND_ARM64_FRAME_D10_D11_PAIR) { + int cfa_offset = reg_pairs_saved_count * -2 * wordsize; + cfa_offset -= wordsize; + printf(" d10=[CFA%d]", cfa_offset); + cfa_offset -= wordsize; + printf(" d11=[CFA%d]", cfa_offset); + reg_pairs_saved_count++; } - - uint64_t file_address = baton.first_level_index_entry.functionOffset + entry_func_offset + baton.text_segment_vmaddr; - - if (baton.cputype == CPU_TYPE_ARM) - file_address = file_address & ~1; - - printf (" func [%d] offset %d (file addr 0x%" PRIx64 ")%s, encoding is 0x%x", - idx, entry_func_offset, - file_address, - entry_encoding_index_str, - encoding); - - struct symbol *symbol = NULL; - for (int i = 0; i < baton.symbols_count; i++) - { - if (i == baton.symbols_count - 1 && baton.symbols[i].file_address <= file_address) - { - symbol = &(baton.symbols[i]); - break; - } - else - { - if (baton.symbols[i].file_address <= file_address && baton.symbols[i + 1].file_address > file_address) - { - symbol = &(baton.symbols[i]); - break; - } - } + if (saved_register_bits & UNWIND_ARM64_FRAME_D12_D13_PAIR) { + int cfa_offset = reg_pairs_saved_count * -2 * wordsize; + cfa_offset -= wordsize; + printf(" d12=[CFA%d]", cfa_offset); + cfa_offset -= wordsize; + printf(" d13=[CFA%d]", cfa_offset); + reg_pairs_saved_count++; } - - printf ("\n "); - if (symbol) - { - int offset = file_address - symbol->file_address; - - // FIXME this is a poor heuristic - if we're greater than 16 bytes past the - // start of the function, this is the unwind info for a stripped function. - // In reality the compact unwind entry may not line up exactly with the - // function bounds. - if (offset >= 0) - { - printf ("name: %s", symbol->name); - if (offset > 0) - { - printf (" + %d", offset); - } - } - printf ("\n "); + if (saved_register_bits & UNWIND_ARM64_FRAME_D14_D15_PAIR) { + int cfa_offset = reg_pairs_saved_count * -2 * wordsize; + cfa_offset -= wordsize; + printf(" d14=[CFA%d]", cfa_offset); + cfa_offset -= wordsize; + printf(" d15=[CFA%d]", cfa_offset); + reg_pairs_saved_count++; } - print_encoding (baton, baton.mach_header_start + baton.first_level_index_entry.functionOffset + baton.text_section_file_offset + entry_func_offset, encoding); - - bool has_lsda = encoding & UNWIND_HAS_LSDA; - - if (has_lsda) - { - uint32_t func_offset = entry_func_offset + baton.first_level_index_entry.functionOffset; + } break; - int lsda_entry_number = -1; + case UNWIND_ARM64_MODE_FRAMELESS: { + uint32_t stack_size = encoding & UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK; + printf("frameless function: stack size %d ", stack_size * 16); - uint32_t low = 0; - uint32_t high = (baton.lsda_array_end - baton.lsda_array_start) / sizeof (struct unwind_info_section_header_lsda_index_entry); + } break; - while (low < high) - { - uint32_t mid = (low + high) / 2; + case UNWIND_ARM64_MODE_DWARF: { + uint32_t dwarf_offset = encoding & UNWIND_ARM64_DWARF_SECTION_OFFSET; + printf( + "DWARF unwind instructions: FDE at offset %d (file address 0x%" PRIx64 + ")", + dwarf_offset, dwarf_offset + baton.eh_section_file_address); + } break; - uint8_t *mid_lsda_entry_addr = (baton.lsda_array_start + (mid * sizeof (struct unwind_info_section_header_lsda_index_entry))); - struct unwind_info_section_header_lsda_index_entry mid_lsda_entry; - memcpy (&mid_lsda_entry, mid_lsda_entry_addr, sizeof (struct unwind_info_section_header_lsda_index_entry)); - if (mid_lsda_entry.functionOffset == func_offset) - { - lsda_entry_number = (mid_lsda_entry_addr - baton.lsda_array_start) / sizeof (struct unwind_info_section_header_lsda_index_entry); - break; - } - else if (mid_lsda_entry.functionOffset < func_offset) - { - low = mid + 1; - } - else - { - high = mid; - } - } + case 0: { + printf(" no unwind information"); + } break; + } +} - if (lsda_entry_number != -1) - { - printf (", LSDA entry #%d", lsda_entry_number); - } - else - { - printf (", LSDA entry not found"); - } +void print_encoding_armv7(struct baton baton, uint8_t *function_start, + uint32_t encoding) { + const int wordsize = 4; + int mode = encoding & UNWIND_ARM_MODE_MASK; + switch (mode) { + case UNWIND_ARM_MODE_FRAME_D: + case UNWIND_ARM_MODE_FRAME: { + int stack_adjust = + EXTRACT_BITS(encoding, UNWIND_ARM_FRAME_STACK_ADJUST_MASK) * wordsize; + + printf("frame func: CFA is fp+%d ", (2 * wordsize) + stack_adjust); + int cfa_offset = -stack_adjust; + + cfa_offset -= wordsize; + printf(" pc=[CFA%d]", cfa_offset); + cfa_offset -= wordsize; + printf(" fp=[CFA%d]", cfa_offset); + + uint32_t saved_register_bits = encoding & 0xff; + if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R6) { + cfa_offset -= wordsize; + printf(" r6=[CFA%d]", cfa_offset); } - - uint32_t pers_idx = EXTRACT_BITS (encoding, UNWIND_PERSONALITY_MASK); - if (pers_idx != 0) - { - pers_idx--; // Change 1-based to 0-based index - printf (", personality entry #%d", pers_idx); + if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R5) { + cfa_offset -= wordsize; + printf(" r5=[CFA%d]", cfa_offset); } - - printf ("\n"); -} - -void -print_second_level_index_regular (struct baton baton) -{ - uint8_t *page_entries = baton.compact_unwind_start + baton.first_level_index_entry.secondLevelPagesSectionOffset + baton.regular_second_level_page_header.entryPageOffset; - uint32_t entries_count = baton.regular_second_level_page_header.entryCount; - - uint8_t *offset = page_entries; - - uint32_t idx = 0; - while (idx < entries_count) - { - uint32_t func_offset = *((uint32_t *) (offset)); - uint32_t encoding = *((uint32_t *) (offset + 4)); - - // UNWIND_SECOND_LEVEL_REGULAR entries have a funcOffset which includes the - // functionOffset from the containing index table already. UNWIND_SECOND_LEVEL_COMPRESSED - // entries only have the offset from the containing index table functionOffset. - // So strip off the containing index table functionOffset value here so they can - // be treated the same at the lower layers. - - print_function_encoding (baton, idx, encoding, (uint32_t) -1, func_offset - baton.first_level_index_entry.functionOffset); - idx++; - offset += 8; + if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R4) { + cfa_offset -= wordsize; + printf(" r4=[CFA%d]", cfa_offset); } -} - -void -print_second_level_index_compressed (struct baton baton) -{ - uint8_t *this_index = baton.compact_unwind_start + baton.first_level_index_entry.secondLevelPagesSectionOffset; - uint8_t *start_of_entries = this_index + baton.compressed_second_level_page_header.entryPageOffset; - uint8_t *offset = start_of_entries; - for (uint16_t idx = 0; idx < baton.compressed_second_level_page_header.entryCount; idx++) - { - uint32_t entry = *((uint32_t*) offset); - offset += 4; - uint32_t encoding; - - uint32_t entry_encoding_index = UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX (entry); - uint32_t entry_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET (entry); - - if (entry_encoding_index < baton.unwind_header.commonEncodingsArrayCount) - { - // encoding is in common table in section header - encoding = *((uint32_t*) (baton.compact_unwind_start + baton.unwind_header.commonEncodingsArraySectionOffset + (entry_encoding_index * sizeof (uint32_t)))); - } - else - { - // encoding is in page specific table - uint32_t page_encoding_index = entry_encoding_index - baton.unwind_header.commonEncodingsArrayCount; - encoding = *((uint32_t*) (this_index + baton.compressed_second_level_page_header.encodingsPageOffset + (page_encoding_index * sizeof (uint32_t)))); - } - - - print_function_encoding (baton, idx, encoding, entry_encoding_index, entry_func_offset); + if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R12) { + cfa_offset -= wordsize; + printf(" r12=[CFA%d]", cfa_offset); } -} - -void -print_second_level_index (struct baton baton) -{ - uint8_t *index_start = baton.compact_unwind_start + baton.first_level_index_entry.secondLevelPagesSectionOffset; - - if ((*(uint32_t*) index_start) == UNWIND_SECOND_LEVEL_REGULAR) - { - struct unwind_info_regular_second_level_page_header header; - memcpy (&header, index_start, sizeof (struct unwind_info_regular_second_level_page_header)); - printf (" UNWIND_SECOND_LEVEL_REGULAR #%d entryPageOffset %d, entryCount %d\n", baton.current_index_table_number, header.entryPageOffset, header.entryCount); - baton.regular_second_level_page_header = header; - print_second_level_index_regular (baton); + if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R11) { + cfa_offset -= wordsize; + printf(" r11=[CFA%d]", cfa_offset); + } + if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R10) { + cfa_offset -= wordsize; + printf(" r10=[CFA%d]", cfa_offset); + } + if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R9) { + cfa_offset -= wordsize; + printf(" r9=[CFA%d]", cfa_offset); + } + if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R8) { + cfa_offset -= wordsize; + printf(" r8=[CFA%d]", cfa_offset); } - if ((*(uint32_t*) index_start) == UNWIND_SECOND_LEVEL_COMPRESSED) - { - struct unwind_info_compressed_second_level_page_header header; - memcpy (&header, index_start, sizeof (struct unwind_info_compressed_second_level_page_header)); - printf (" UNWIND_SECOND_LEVEL_COMPRESSED #%d entryPageOffset %d, entryCount %d, encodingsPageOffset %d, encodingsCount %d\n", baton.current_index_table_number, header.entryPageOffset, header.entryCount, header.encodingsPageOffset, header.encodingsCount); - baton.compressed_second_level_page_header = header; - print_second_level_index_compressed (baton); + if (mode == UNWIND_ARM_MODE_FRAME_D) { + uint32_t d_reg_bits = + EXTRACT_BITS(encoding, UNWIND_ARM_FRAME_D_REG_COUNT_MASK); + switch (d_reg_bits) { + case 0: + // vpush {d8} + cfa_offset -= 8; + printf(" d8=[CFA%d]", cfa_offset); + break; + case 1: + // vpush {d10} + // vpush {d8} + cfa_offset -= 8; + printf(" d10=[CFA%d]", cfa_offset); + cfa_offset -= 8; + printf(" d8=[CFA%d]", cfa_offset); + break; + case 2: + // vpush {d12} + // vpush {d10} + // vpush {d8} + cfa_offset -= 8; + printf(" d12=[CFA%d]", cfa_offset); + cfa_offset -= 8; + printf(" d10=[CFA%d]", cfa_offset); + cfa_offset -= 8; + printf(" d8=[CFA%d]", cfa_offset); + break; + case 3: + // vpush {d14} + // vpush {d12} + // vpush {d10} + // vpush {d8} + cfa_offset -= 8; + printf(" d14=[CFA%d]", cfa_offset); + cfa_offset -= 8; + printf(" d12=[CFA%d]", cfa_offset); + cfa_offset -= 8; + printf(" d10=[CFA%d]", cfa_offset); + cfa_offset -= 8; + printf(" d8=[CFA%d]", cfa_offset); + break; + case 4: + // vpush {d14} + // vpush {d12} + // sp = (sp - 24) & (-16); + // vst {d8, d9, d10} + printf(" d14, d12, d10, d9, d8"); + break; + case 5: + // vpush {d14} + // sp = (sp - 40) & (-16); + // vst {d8, d9, d10, d11} + // vst {d12} + printf(" d14, d11, d10, d9, d8, d12"); + break; + case 6: + // sp = (sp - 56) & (-16); + // vst {d8, d9, d10, d11} + // vst {d12, d13, d14} + printf(" d11, d10, d9, d8, d14, d13, d12"); + break; + case 7: + // sp = (sp - 64) & (-16); + // vst {d8, d9, d10, d11} + // vst {d12, d13, d14, d15} + printf(" d11, d10, d9, d8, d15, d14, d13, d12"); + break; + } } + } break; + + case UNWIND_ARM_MODE_DWARF: { + uint32_t dwarf_offset = encoding & UNWIND_ARM_DWARF_SECTION_OFFSET; + printf( + "DWARF unwind instructions: FDE at offset %d (file address 0x%" PRIx64 + ")", + dwarf_offset, dwarf_offset + baton.eh_section_file_address); + } break; + + case 0: { + printf(" no unwind information"); + } break; + } } - -void -print_index_sections (struct baton baton) -{ - uint8_t *index_section_offset = baton.compact_unwind_start + baton.unwind_header.indexSectionOffset; - uint32_t index_count = baton.unwind_header.indexCount; - - uint32_t cur_idx = 0; - - uint8_t *offset = index_section_offset; - while (cur_idx < index_count) - { - baton.current_index_table_number = cur_idx; - struct unwind_info_section_header_index_entry index_entry; - memcpy (&index_entry, offset, sizeof (struct unwind_info_section_header_index_entry)); - printf ("index section #%d: functionOffset %d, secondLevelPagesSectionOffset %d, lsdaIndexArraySectionOffset %d\n", cur_idx, index_entry.functionOffset, index_entry.secondLevelPagesSectionOffset, index_entry.lsdaIndexArraySectionOffset); - - // secondLevelPagesSectionOffset == 0 means this is a sentinel entry - if (index_entry.secondLevelPagesSectionOffset != 0) - { - struct unwind_info_section_header_index_entry next_index_entry; - memcpy (&next_index_entry, offset + sizeof (struct unwind_info_section_header_index_entry), sizeof (struct unwind_info_section_header_index_entry)); - - baton.lsda_array_start = baton.compact_unwind_start + index_entry.lsdaIndexArraySectionOffset; - baton.lsda_array_end = baton.compact_unwind_start + next_index_entry.lsdaIndexArraySectionOffset; - - uint8_t *lsda_entry_offset = baton.lsda_array_start; - uint32_t lsda_count = 0; - while (lsda_entry_offset < baton.lsda_array_end) - { - struct unwind_info_section_header_lsda_index_entry lsda_entry; - memcpy (&lsda_entry, lsda_entry_offset, sizeof (struct unwind_info_section_header_lsda_index_entry)); - uint64_t function_file_address = baton.first_level_index_entry.functionOffset + lsda_entry.functionOffset + baton.text_segment_vmaddr; - uint64_t lsda_file_address = lsda_entry.lsdaOffset + baton.text_segment_vmaddr; - printf (" LSDA [%d] functionOffset %d (%d) (file address 0x%" PRIx64 "), lsdaOffset %d (file address 0x%" PRIx64 ")\n", - lsda_count, lsda_entry.functionOffset, - lsda_entry.functionOffset - index_entry.functionOffset, - function_file_address, - lsda_entry.lsdaOffset, lsda_file_address); - lsda_count++; - lsda_entry_offset += sizeof (struct unwind_info_section_header_lsda_index_entry); - } - - printf ("\n"); - - baton.first_level_index_entry = index_entry; - print_second_level_index (baton); - } - - printf ("\n"); - - cur_idx++; - offset += sizeof (struct unwind_info_section_header_index_entry); - } +void print_encoding(struct baton baton, uint8_t *function_start, + uint32_t encoding) { + + if (baton.cputype == CPU_TYPE_X86_64) { + print_encoding_x86_64(baton, function_start, encoding); + } else if (baton.cputype == CPU_TYPE_I386) { + print_encoding_i386(baton, function_start, encoding); + } else if (baton.cputype == CPU_TYPE_ARM64) { + print_encoding_arm64(baton, function_start, encoding); + } else if (baton.cputype == CPU_TYPE_ARM) { + print_encoding_armv7(baton, function_start, encoding); + } else { + printf(" -- unsupported encoding arch -- "); + } } -int main (int argc, char **argv) -{ - struct stat st; - char *file = argv[0]; - if (argc > 1) - file = argv[1]; - int fd = open (file, O_RDONLY); - if (fd == -1) - { - printf ("Failed to open '%s'\n", file); - exit (1); +void print_function_encoding(struct baton baton, uint32_t idx, + uint32_t encoding, uint32_t entry_encoding_index, + uint32_t entry_func_offset) { + + char *entry_encoding_index_str = ""; + if (entry_encoding_index != (uint32_t)-1) { + asprintf(&entry_encoding_index_str, ", encoding #%d", entry_encoding_index); + } else { + asprintf(&entry_encoding_index_str, ""); + } + + uint64_t file_address = baton.first_level_index_entry.functionOffset + + entry_func_offset + baton.text_segment_vmaddr; + + if (baton.cputype == CPU_TYPE_ARM) + file_address = file_address & ~1; + + printf( + " func [%d] offset %d (file addr 0x%" PRIx64 ")%s, encoding is 0x%x", + idx, entry_func_offset, file_address, entry_encoding_index_str, encoding); + + struct symbol *symbol = NULL; + for (int i = 0; i < baton.symbols_count; i++) { + if (i == baton.symbols_count - 1 && + baton.symbols[i].file_address <= file_address) { + symbol = &(baton.symbols[i]); + break; + } else { + if (baton.symbols[i].file_address <= file_address && + baton.symbols[i + 1].file_address > file_address) { + symbol = &(baton.symbols[i]); + break; + } } - fstat (fd, &st); - uint8_t *file_mem = (uint8_t*) mmap (0, st.st_size, PROT_READ, MAP_PRIVATE | MAP_FILE, fd, 0); - if (file_mem == MAP_FAILED) - { - printf ("Failed to mmap() '%s'\n", file); + } + + printf("\n "); + if (symbol) { + int offset = file_address - symbol->file_address; + + // FIXME this is a poor heuristic - if we're greater than 16 bytes past the + // start of the function, this is the unwind info for a stripped function. + // In reality the compact unwind entry may not line up exactly with the + // function bounds. + if (offset >= 0) { + printf("name: %s", symbol->name); + if (offset > 0) { + printf(" + %d", offset); + } + } + printf("\n "); + } + + print_encoding(baton, baton.mach_header_start + + baton.first_level_index_entry.functionOffset + + baton.text_section_file_offset + entry_func_offset, + encoding); + + bool has_lsda = encoding & UNWIND_HAS_LSDA; + + if (has_lsda) { + uint32_t func_offset = + entry_func_offset + baton.first_level_index_entry.functionOffset; + + int lsda_entry_number = -1; + + uint32_t low = 0; + uint32_t high = (baton.lsda_array_end - baton.lsda_array_start) / + sizeof(struct unwind_info_section_header_lsda_index_entry); + + while (low < high) { + uint32_t mid = (low + high) / 2; + + uint8_t *mid_lsda_entry_addr = + (baton.lsda_array_start + + (mid * sizeof(struct unwind_info_section_header_lsda_index_entry))); + struct unwind_info_section_header_lsda_index_entry mid_lsda_entry; + memcpy(&mid_lsda_entry, mid_lsda_entry_addr, + sizeof(struct unwind_info_section_header_lsda_index_entry)); + if (mid_lsda_entry.functionOffset == func_offset) { + lsda_entry_number = + (mid_lsda_entry_addr - baton.lsda_array_start) / + sizeof(struct unwind_info_section_header_lsda_index_entry); + break; + } else if (mid_lsda_entry.functionOffset < func_offset) { + low = mid + 1; + } else { + high = mid; + } } - FILE *f = fopen ("a.out", "r"); - - struct baton baton; - baton.mach_header_start = file_mem; - baton.symbols = NULL; - baton.symbols_count = 0; - baton.function_start_addresses = NULL; - baton.function_start_addresses_count = 0; + if (lsda_entry_number != -1) { + printf(", LSDA entry #%d", lsda_entry_number); + } else { + printf(", LSDA entry not found"); + } + } - scan_macho_load_commands (&baton); + uint32_t pers_idx = EXTRACT_BITS(encoding, UNWIND_PERSONALITY_MASK); + if (pers_idx != 0) { + pers_idx--; // Change 1-based to 0-based index + printf(", personality entry #%d", pers_idx); + } - if (baton.compact_unwind_start == NULL) - { - printf ("could not find __TEXT,__unwind_info section\n"); - exit (1); - } + printf("\n"); +} +void print_second_level_index_regular(struct baton baton) { + uint8_t *page_entries = + baton.compact_unwind_start + + baton.first_level_index_entry.secondLevelPagesSectionOffset + + baton.regular_second_level_page_header.entryPageOffset; + uint32_t entries_count = baton.regular_second_level_page_header.entryCount; + + uint8_t *offset = page_entries; + + uint32_t idx = 0; + while (idx < entries_count) { + uint32_t func_offset = *((uint32_t *)(offset)); + uint32_t encoding = *((uint32_t *)(offset + 4)); + + // UNWIND_SECOND_LEVEL_REGULAR entries have a funcOffset which includes the + // functionOffset from the containing index table already. + // UNWIND_SECOND_LEVEL_COMPRESSED + // entries only have the offset from the containing index table + // functionOffset. + // So strip off the containing index table functionOffset value here so they + // can + // be treated the same at the lower layers. + + print_function_encoding(baton, idx, encoding, (uint32_t)-1, + func_offset - + baton.first_level_index_entry.functionOffset); + idx++; + offset += 8; + } +} - struct unwind_info_section_header header; - memcpy (&header, baton.compact_unwind_start, sizeof (struct unwind_info_section_header)); - printf ("Header:\n"); - printf (" version %u\n", header.version); - printf (" commonEncodingsArraySectionOffset is %d\n", header.commonEncodingsArraySectionOffset); - printf (" commonEncodingsArrayCount is %d\n", header.commonEncodingsArrayCount); - printf (" personalityArraySectionOffset is %d\n", header.personalityArraySectionOffset); - printf (" personalityArrayCount is %d\n", header.personalityArrayCount); - printf (" indexSectionOffset is %d\n", header.indexSectionOffset); - printf (" indexCount is %d\n", header.indexCount); - - uint8_t *common_encodings = baton.compact_unwind_start + header.commonEncodingsArraySectionOffset; - uint32_t encoding_idx = 0; - while (encoding_idx < header.commonEncodingsArrayCount) - { - uint32_t encoding = *((uint32_t*) common_encodings); - printf (" Common Encoding [%d]: 0x%x ", encoding_idx, encoding); - print_encoding (baton, NULL, encoding); - printf ("\n"); - common_encodings += sizeof (uint32_t); - encoding_idx++; +void print_second_level_index_compressed(struct baton baton) { + uint8_t *this_index = + baton.compact_unwind_start + + baton.first_level_index_entry.secondLevelPagesSectionOffset; + uint8_t *start_of_entries = + this_index + baton.compressed_second_level_page_header.entryPageOffset; + uint8_t *offset = start_of_entries; + for (uint16_t idx = 0; + idx < baton.compressed_second_level_page_header.entryCount; idx++) { + uint32_t entry = *((uint32_t *)offset); + offset += 4; + uint32_t encoding; + + uint32_t entry_encoding_index = + UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry); + uint32_t entry_func_offset = + UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry); + + if (entry_encoding_index < baton.unwind_header.commonEncodingsArrayCount) { + // encoding is in common table in section header + encoding = + *((uint32_t *)(baton.compact_unwind_start + + baton.unwind_header.commonEncodingsArraySectionOffset + + (entry_encoding_index * sizeof(uint32_t)))); + } else { + // encoding is in page specific table + uint32_t page_encoding_index = + entry_encoding_index - baton.unwind_header.commonEncodingsArrayCount; + encoding = *((uint32_t *)(this_index + + baton.compressed_second_level_page_header + .encodingsPageOffset + + (page_encoding_index * sizeof(uint32_t)))); } - uint8_t *pers_arr = baton.compact_unwind_start + header.personalityArraySectionOffset; - uint32_t pers_idx = 0; - while (pers_idx < header.personalityArrayCount) - { - int32_t pers_delta = *((int32_t*) (baton.compact_unwind_start + header.personalityArraySectionOffset + (pers_idx * sizeof (uint32_t)))); - printf (" Personality [%d]: personality function ptr @ offset %d (file address 0x%" PRIx64 ")\n", pers_idx, pers_delta, baton.text_segment_vmaddr + pers_delta); - pers_idx++; - pers_arr += sizeof (uint32_t); - } + print_function_encoding(baton, idx, encoding, entry_encoding_index, + entry_func_offset); + } +} - printf ("\n"); +void print_second_level_index(struct baton baton) { + uint8_t *index_start = + baton.compact_unwind_start + + baton.first_level_index_entry.secondLevelPagesSectionOffset; + + if ((*(uint32_t *)index_start) == UNWIND_SECOND_LEVEL_REGULAR) { + struct unwind_info_regular_second_level_page_header header; + memcpy(&header, index_start, + sizeof(struct unwind_info_regular_second_level_page_header)); + printf( + " UNWIND_SECOND_LEVEL_REGULAR #%d entryPageOffset %d, entryCount %d\n", + baton.current_index_table_number, header.entryPageOffset, + header.entryCount); + baton.regular_second_level_page_header = header; + print_second_level_index_regular(baton); + } + + if ((*(uint32_t *)index_start) == UNWIND_SECOND_LEVEL_COMPRESSED) { + struct unwind_info_compressed_second_level_page_header header; + memcpy(&header, index_start, + sizeof(struct unwind_info_compressed_second_level_page_header)); + printf(" UNWIND_SECOND_LEVEL_COMPRESSED #%d entryPageOffset %d, " + "entryCount %d, encodingsPageOffset %d, encodingsCount %d\n", + baton.current_index_table_number, header.entryPageOffset, + header.entryCount, header.encodingsPageOffset, + header.encodingsCount); + baton.compressed_second_level_page_header = header; + print_second_level_index_compressed(baton); + } +} - baton.unwind_header = header; +void print_index_sections(struct baton baton) { + uint8_t *index_section_offset = + baton.compact_unwind_start + baton.unwind_header.indexSectionOffset; + uint32_t index_count = baton.unwind_header.indexCount; + + uint32_t cur_idx = 0; + + uint8_t *offset = index_section_offset; + while (cur_idx < index_count) { + baton.current_index_table_number = cur_idx; + struct unwind_info_section_header_index_entry index_entry; + memcpy(&index_entry, offset, + sizeof(struct unwind_info_section_header_index_entry)); + printf("index section #%d: functionOffset %d, " + "secondLevelPagesSectionOffset %d, lsdaIndexArraySectionOffset %d\n", + cur_idx, index_entry.functionOffset, + index_entry.secondLevelPagesSectionOffset, + index_entry.lsdaIndexArraySectionOffset); + + // secondLevelPagesSectionOffset == 0 means this is a sentinel entry + if (index_entry.secondLevelPagesSectionOffset != 0) { + struct unwind_info_section_header_index_entry next_index_entry; + memcpy(&next_index_entry, + offset + sizeof(struct unwind_info_section_header_index_entry), + sizeof(struct unwind_info_section_header_index_entry)); + + baton.lsda_array_start = + baton.compact_unwind_start + index_entry.lsdaIndexArraySectionOffset; + baton.lsda_array_end = baton.compact_unwind_start + + next_index_entry.lsdaIndexArraySectionOffset; + + uint8_t *lsda_entry_offset = baton.lsda_array_start; + uint32_t lsda_count = 0; + while (lsda_entry_offset < baton.lsda_array_end) { + struct unwind_info_section_header_lsda_index_entry lsda_entry; + memcpy(&lsda_entry, lsda_entry_offset, + sizeof(struct unwind_info_section_header_lsda_index_entry)); + uint64_t function_file_address = + baton.first_level_index_entry.functionOffset + + lsda_entry.functionOffset + baton.text_segment_vmaddr; + uint64_t lsda_file_address = + lsda_entry.lsdaOffset + baton.text_segment_vmaddr; + printf(" LSDA [%d] functionOffset %d (%d) (file address 0x%" PRIx64 + "), lsdaOffset %d (file address 0x%" PRIx64 ")\n", + lsda_count, lsda_entry.functionOffset, + lsda_entry.functionOffset - index_entry.functionOffset, + function_file_address, lsda_entry.lsdaOffset, lsda_file_address); + lsda_count++; + lsda_entry_offset += + sizeof(struct unwind_info_section_header_lsda_index_entry); + } + + printf("\n"); + + baton.first_level_index_entry = index_entry; + print_second_level_index(baton); + } - print_index_sections (baton); + printf("\n"); + cur_idx++; + offset += sizeof(struct unwind_info_section_header_index_entry); + } +} - return 0; +int main(int argc, char **argv) { + struct stat st; + char *file = argv[0]; + if (argc > 1) + file = argv[1]; + int fd = open(file, O_RDONLY); + if (fd == -1) { + printf("Failed to open '%s'\n", file); + exit(1); + } + fstat(fd, &st); + uint8_t *file_mem = + (uint8_t *)mmap(0, st.st_size, PROT_READ, MAP_PRIVATE | MAP_FILE, fd, 0); + if (file_mem == MAP_FAILED) { + printf("Failed to mmap() '%s'\n", file); + } + + FILE *f = fopen("a.out", "r"); + + struct baton baton; + baton.mach_header_start = file_mem; + baton.symbols = NULL; + baton.symbols_count = 0; + baton.function_start_addresses = NULL; + baton.function_start_addresses_count = 0; + + scan_macho_load_commands(&baton); + + if (baton.compact_unwind_start == NULL) { + printf("could not find __TEXT,__unwind_info section\n"); + exit(1); + } + + struct unwind_info_section_header header; + memcpy(&header, baton.compact_unwind_start, + sizeof(struct unwind_info_section_header)); + printf("Header:\n"); + printf(" version %u\n", header.version); + printf(" commonEncodingsArraySectionOffset is %d\n", + header.commonEncodingsArraySectionOffset); + printf(" commonEncodingsArrayCount is %d\n", + header.commonEncodingsArrayCount); + printf(" personalityArraySectionOffset is %d\n", + header.personalityArraySectionOffset); + printf(" personalityArrayCount is %d\n", header.personalityArrayCount); + printf(" indexSectionOffset is %d\n", header.indexSectionOffset); + printf(" indexCount is %d\n", header.indexCount); + + uint8_t *common_encodings = + baton.compact_unwind_start + header.commonEncodingsArraySectionOffset; + uint32_t encoding_idx = 0; + while (encoding_idx < header.commonEncodingsArrayCount) { + uint32_t encoding = *((uint32_t *)common_encodings); + printf(" Common Encoding [%d]: 0x%x ", encoding_idx, encoding); + print_encoding(baton, NULL, encoding); + printf("\n"); + common_encodings += sizeof(uint32_t); + encoding_idx++; + } + + uint8_t *pers_arr = + baton.compact_unwind_start + header.personalityArraySectionOffset; + uint32_t pers_idx = 0; + while (pers_idx < header.personalityArrayCount) { + int32_t pers_delta = *((int32_t *)(baton.compact_unwind_start + + header.personalityArraySectionOffset + + (pers_idx * sizeof(uint32_t)))); + printf(" Personality [%d]: personality function ptr @ offset %d (file " + "address 0x%" PRIx64 ")\n", + pers_idx, pers_delta, baton.text_segment_vmaddr + pers_delta); + pers_idx++; + pers_arr += sizeof(uint32_t); + } + + printf("\n"); + + baton.unwind_header = header; + + print_index_sections(baton); + + return 0; } diff --git a/tools/darwin-debug/CMakeLists.txt b/tools/darwin-debug/CMakeLists.txt index 352a573e25e1..2f28eab3a58f 100644 --- a/tools/darwin-debug/CMakeLists.txt +++ b/tools/darwin-debug/CMakeLists.txt @@ -1,6 +1,3 @@ -add_lldb_executable(lldb-launcher +add_lldb_tool(darwin-debug INCLUDE_IN_FRAMEWORK darwin-debug.cpp ) - -install(TARGETS lldb-launcher - RUNTIME DESTINATION bin) diff --git a/tools/darwin-debug/darwin-debug.cpp b/tools/darwin-debug/darwin-debug.cpp index ca0a8d48328b..e754ded474c4 100644 --- a/tools/darwin-debug/darwin-debug.cpp +++ b/tools/darwin-debug/darwin-debug.cpp @@ -18,11 +18,11 @@ // attribute flags to accomplish its task. It uses an "exec only" flag // which avoids forking this process, and it uses a "stop at entry" // flag to stop the program at the entry point. -// +// // Since it uses darwin specific flags this code should not be compiled // on other systems. //---------------------------------------------------------------------- -#if defined (__APPLE__) +#if defined(__APPLE__) #include <crt_externs.h> // for _NSGetEnviron() #include <getopt.h> @@ -41,314 +41,297 @@ #include <string> #ifndef _POSIX_SPAWN_DISABLE_ASLR -#define _POSIX_SPAWN_DISABLE_ASLR 0x0100 +#define _POSIX_SPAWN_DISABLE_ASLR 0x0100 #endif -#define streq(a,b) strcmp(a,b) == 0 - -static struct option g_long_options[] = -{ - { "arch", required_argument, NULL, 'a' }, - { "disable-aslr", no_argument, NULL, 'd' }, - { "no-env", no_argument, NULL, 'e' }, - { "help", no_argument, NULL, 'h' }, - { "setsid", no_argument, NULL, 's' }, - { "unix-socket", required_argument, NULL, 'u' }, - { "working-dir", required_argument, NULL, 'w' }, - { "env", required_argument, NULL, 'E' }, - { NULL, 0, NULL, 0 } -}; - -static void -usage() -{ - puts ( -"NAME\n" -" darwin-debug -- posix spawn a process that is stopped at the entry point\n" -" for debugging.\n" -"\n" -"SYNOPSIS\n" -" darwin-debug --unix-socket=<SOCKET> [--arch=<ARCH>] [--working-dir=<PATH>] [--disable-aslr] [--no-env] [--setsid] [--help] -- <PROGRAM> [<PROGRAM-ARG> <PROGRAM-ARG> ....]\n" -"\n" -"DESCRIPTION\n" -" darwin-debug will exec itself into a child process <PROGRAM> that is\n" -" halted for debugging. It does this by using posix_spawn() along with\n" -" darwin specific posix_spawn flags that allows exec only (no fork), and\n" -" stop at the program entry point. Any program arguments <PROGRAM-ARG> are\n" -" passed on to the exec as the arguments for the new process. The current\n" -" environment will be passed to the new process unless the \"--no-env\"\n" -" option is used. A unix socket must be supplied using the\n" -" --unix-socket=<SOCKET> option so the calling program can handshake with\n" -" this process and get its process id.\n" -"\n" -"EXAMPLE\n" -" darwin-debug --arch=i386 -- /bin/ls -al /tmp\n" -); - exit (1); +#define streq(a, b) strcmp(a, b) == 0 + +static struct option g_long_options[] = { + {"arch", required_argument, NULL, 'a'}, + {"disable-aslr", no_argument, NULL, 'd'}, + {"no-env", no_argument, NULL, 'e'}, + {"help", no_argument, NULL, 'h'}, + {"setsid", no_argument, NULL, 's'}, + {"unix-socket", required_argument, NULL, 'u'}, + {"working-dir", required_argument, NULL, 'w'}, + {"env", required_argument, NULL, 'E'}, + {NULL, 0, NULL, 0}}; + +static void usage() { + puts("NAME\n" + " darwin-debug -- posix spawn a process that is stopped at the entry " + "point\n" + " for debugging.\n" + "\n" + "SYNOPSIS\n" + " darwin-debug --unix-socket=<SOCKET> [--arch=<ARCH>] " + "[--working-dir=<PATH>] [--disable-aslr] [--no-env] [--setsid] [--help] " + "-- <PROGRAM> [<PROGRAM-ARG> <PROGRAM-ARG> ....]\n" + "\n" + "DESCRIPTION\n" + " darwin-debug will exec itself into a child process <PROGRAM> that " + "is\n" + " halted for debugging. It does this by using posix_spawn() along " + "with\n" + " darwin specific posix_spawn flags that allows exec only (no fork), " + "and\n" + " stop at the program entry point. Any program arguments " + "<PROGRAM-ARG> are\n" + " passed on to the exec as the arguments for the new process. The " + "current\n" + " environment will be passed to the new process unless the " + "\"--no-env\"\n" + " option is used. A unix socket must be supplied using the\n" + " --unix-socket=<SOCKET> option so the calling program can handshake " + "with\n" + " this process and get its process id.\n" + "\n" + "EXAMPLE\n" + " darwin-debug --arch=i386 -- /bin/ls -al /tmp\n"); + exit(1); } -static void -exit_with_errno (int err, const char *prefix) -{ - if (err) - { - fprintf (stderr, - "%s%s", - prefix ? prefix : "", - strerror(err)); - exit (err); - } +static void exit_with_errno(int err, const char *prefix) { + if (err) { + fprintf(stderr, "%s%s", prefix ? prefix : "", strerror(err)); + exit(err); + } } -pid_t -posix_spawn_for_debug -( - char *const *argv, - char *const *envp, - const char *working_dir, - cpu_type_t cpu_type, - int disable_aslr) -{ - pid_t pid = 0; - - const char *path = argv[0]; - - posix_spawnattr_t attr; - - exit_with_errno (::posix_spawnattr_init (&attr), "::posix_spawnattr_init (&attr) error: "); - - // Here we are using a darwin specific feature that allows us to exec only - // since we want this program to turn into the program we want to debug, - // and also have the new program start suspended (right at __dyld_start) - // so we can debug it - short flags = POSIX_SPAWN_START_SUSPENDED | POSIX_SPAWN_SETEXEC | POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; - - // Disable ASLR if we were asked to - if (disable_aslr) - flags |= _POSIX_SPAWN_DISABLE_ASLR; - - sigset_t no_signals; - sigset_t all_signals; - sigemptyset (&no_signals); - sigfillset (&all_signals); - ::posix_spawnattr_setsigmask(&attr, &no_signals); - ::posix_spawnattr_setsigdefault(&attr, &all_signals); - - // Set the flags we just made into our posix spawn attributes - exit_with_errno (::posix_spawnattr_setflags (&attr, flags), "::posix_spawnattr_setflags (&attr, flags) error: "); - - - // Another darwin specific thing here where we can select the architecture - // of the binary we want to re-exec as. - if (cpu_type != 0) - { - size_t ocount = 0; - exit_with_errno (::posix_spawnattr_setbinpref_np (&attr, 1, &cpu_type, &ocount), "posix_spawnattr_setbinpref_np () error: "); - } - - // I wish there was a posix_spawn flag to change the working directory of - // the inferior process we will spawn, but there currently isn't. If there - // ever is a better way to do this, we should use it. I would rather not - // manually fork, chdir in the child process, and then posix_spawn with exec - // as the whole reason for doing posix_spawn is to not hose anything up - // after the fork and prior to the exec... - if (working_dir) - ::chdir (working_dir); - - exit_with_errno (::posix_spawnp (&pid, path, NULL, &attr, (char * const*)argv, (char * const*)envp), "posix_spawn() error: "); - - // This code will only be reached if the posix_spawn exec failed... - ::posix_spawnattr_destroy (&attr); - - return pid; +pid_t posix_spawn_for_debug(char *const *argv, char *const *envp, + const char *working_dir, cpu_type_t cpu_type, + int disable_aslr) { + pid_t pid = 0; + + const char *path = argv[0]; + + posix_spawnattr_t attr; + + exit_with_errno(::posix_spawnattr_init(&attr), + "::posix_spawnattr_init (&attr) error: "); + + // Here we are using a darwin specific feature that allows us to exec only + // since we want this program to turn into the program we want to debug, + // and also have the new program start suspended (right at __dyld_start) + // so we can debug it + short flags = POSIX_SPAWN_START_SUSPENDED | POSIX_SPAWN_SETEXEC | + POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; + + // Disable ASLR if we were asked to + if (disable_aslr) + flags |= _POSIX_SPAWN_DISABLE_ASLR; + + sigset_t no_signals; + sigset_t all_signals; + sigemptyset(&no_signals); + sigfillset(&all_signals); + ::posix_spawnattr_setsigmask(&attr, &no_signals); + ::posix_spawnattr_setsigdefault(&attr, &all_signals); + + // Set the flags we just made into our posix spawn attributes + exit_with_errno(::posix_spawnattr_setflags(&attr, flags), + "::posix_spawnattr_setflags (&attr, flags) error: "); + + // Another darwin specific thing here where we can select the architecture + // of the binary we want to re-exec as. + if (cpu_type != 0) { + size_t ocount = 0; + exit_with_errno( + ::posix_spawnattr_setbinpref_np(&attr, 1, &cpu_type, &ocount), + "posix_spawnattr_setbinpref_np () error: "); + } + + // I wish there was a posix_spawn flag to change the working directory of + // the inferior process we will spawn, but there currently isn't. If there + // ever is a better way to do this, we should use it. I would rather not + // manually fork, chdir in the child process, and then posix_spawn with exec + // as the whole reason for doing posix_spawn is to not hose anything up + // after the fork and prior to the exec... + if (working_dir) + ::chdir(working_dir); + + exit_with_errno(::posix_spawnp(&pid, path, NULL, &attr, (char *const *)argv, + (char *const *)envp), + "posix_spawn() error: "); + + // This code will only be reached if the posix_spawn exec failed... + ::posix_spawnattr_destroy(&attr); + + return pid; } +int main(int argc, char *const *argv, char *const *envp, const char **apple) { +#if defined(DEBUG_LLDB_LAUNCHER) + const char *program_name = strrchr(apple[0], '/'); + + if (program_name) + program_name++; // Skip the last slash.. + else + program_name = apple[0]; -int main (int argc, char *const *argv, char *const *envp, const char **apple) -{ -#if defined (DEBUG_LLDB_LAUNCHER) - const char *program_name = strrchr(apple[0], '/'); - - if (program_name) - program_name++; // Skip the last slash.. - else - program_name = apple[0]; - - printf("%s called with:\n", program_name); - for (int i=0; i<argc; ++i) - printf("argv[%u] = '%s'\n", i, argv[i]); + printf("%s called with:\n", program_name); + for (int i = 0; i < argc; ++i) + printf("argv[%u] = '%s'\n", i, argv[i]); #endif - cpu_type_t cpu_type = 0; - bool show_usage = false; - int ch; - int disable_aslr = 0; // By default we disable ASLR - bool pass_env = true; - std::string unix_socket_name; - std::string working_dir; - + cpu_type_t cpu_type = 0; + bool show_usage = false; + int ch; + int disable_aslr = 0; // By default we disable ASLR + bool pass_env = true; + std::string unix_socket_name; + std::string working_dir; + #if __GLIBC__ - optind = 0; + optind = 0; #else - optreset = 1; - optind = 1; -#endif - - while ((ch = getopt_long_only(argc, argv, "a:deE:hsu:?", g_long_options, NULL)) != -1) - { - switch (ch) - { - case 0: - break; - - case 'a': // "-a i386" or "--arch=i386" - if (optarg) - { - if (streq (optarg, "i386")) - cpu_type = CPU_TYPE_I386; - else if (streq (optarg, "x86_64")) - cpu_type = CPU_TYPE_X86_64; - else if (streq (optarg, "x86_64h")) - cpu_type = 0; // Don't set CPU type when we have x86_64h - else if (strstr (optarg, "arm") == optarg) - cpu_type = CPU_TYPE_ARM; - else - { - ::fprintf (stderr, "error: unsupported cpu type '%s'\n", optarg); - ::exit (1); - } - } - break; - - case 'd': - disable_aslr = 1; - break; - - case 'e': - pass_env = false; - break; - - case 'E': - { - // Since we will exec this program into our new program, we can just set environment - // variables in this process and they will make it into the child process. - std::string name; - std::string value; - const char *equal_pos = strchr (optarg, '='); - if (equal_pos) - { - name.assign (optarg, equal_pos - optarg); - value.assign (equal_pos + 1); - } - else - { - name = optarg; - } - ::setenv (name.c_str(), value.c_str(), 1); - } - break; - - case 's': - // Create a new session to avoid having control-C presses kill our current - // terminal session when this program is launched from a .command file - ::setsid(); - break; - - case 'u': - unix_socket_name.assign (optarg); - break; - - case 'w': - { - struct stat working_dir_stat; - if (stat (optarg, &working_dir_stat) == 0) - working_dir.assign (optarg); - else - ::fprintf(stderr, "warning: working directory doesn't exist: '%s'\n", optarg); - } - break; - - case 'h': - case '?': - default: - show_usage = true; - break; - } - } - argc -= optind; - argv += optind; - - if (show_usage || argc <= 0 || unix_socket_name.empty()) - usage(); - -#if defined (DEBUG_LLDB_LAUNCHER) - printf ("\n%s post options:\n", program_name); - for (int i=0; i<argc; ++i) - printf ("argv[%u] = '%s'\n", i, argv[i]); + optreset = 1; + optind = 1; #endif - // Open the socket that was passed in as an option - struct sockaddr_un saddr_un; - int s = ::socket (AF_UNIX, SOCK_STREAM, 0); - if (s < 0) - { - perror("error: socket (AF_UNIX, SOCK_STREAM, 0)"); - exit(1); + while ((ch = getopt_long_only(argc, argv, "a:deE:hsu:?", g_long_options, + NULL)) != -1) { + switch (ch) { + case 0: + break; + + case 'a': // "-a i386" or "--arch=i386" + if (optarg) { + if (streq(optarg, "i386")) + cpu_type = CPU_TYPE_I386; + else if (streq(optarg, "x86_64")) + cpu_type = CPU_TYPE_X86_64; + else if (streq(optarg, "x86_64h")) + cpu_type = 0; // Don't set CPU type when we have x86_64h + else if (strstr(optarg, "arm") == optarg) + cpu_type = CPU_TYPE_ARM; + else { + ::fprintf(stderr, "error: unsupported cpu type '%s'\n", optarg); + ::exit(1); + } + } + break; + + case 'd': + disable_aslr = 1; + break; + + case 'e': + pass_env = false; + break; + + case 'E': { + // Since we will exec this program into our new program, we can just set + // environment + // variables in this process and they will make it into the child process. + std::string name; + std::string value; + const char *equal_pos = strchr(optarg, '='); + if (equal_pos) { + name.assign(optarg, equal_pos - optarg); + value.assign(equal_pos + 1); + } else { + name = optarg; + } + ::setenv(name.c_str(), value.c_str(), 1); + } break; + + case 's': + // Create a new session to avoid having control-C presses kill our current + // terminal session when this program is launched from a .command file + ::setsid(); + break; + + case 'u': + unix_socket_name.assign(optarg); + break; + + case 'w': { + struct stat working_dir_stat; + if (stat(optarg, &working_dir_stat) == 0) + working_dir.assign(optarg); + else + ::fprintf(stderr, "warning: working directory doesn't exist: '%s'\n", + optarg); + } break; + + case 'h': + case '?': + default: + show_usage = true; + break; } + } + argc -= optind; + argv += optind; - saddr_un.sun_family = AF_UNIX; - ::strncpy(saddr_un.sun_path, unix_socket_name.c_str(), sizeof(saddr_un.sun_path) - 1); - saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0'; - saddr_un.sun_len = SUN_LEN (&saddr_un); + if (show_usage || argc <= 0 || unix_socket_name.empty()) + usage(); - if (::connect (s, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0) - { - perror("error: connect (socket, &saddr_un, saddr_un_len)"); - exit(1); - } - - // We were able to connect to the socket, now write our PID so whomever - // launched us will know this process's ID - char pid_str[64]; - const int pid_str_len = ::snprintf (pid_str, sizeof(pid_str), "%i", ::getpid()); - const int bytes_sent = ::send (s, pid_str, pid_str_len, 0); - - if (pid_str_len != bytes_sent) - { - perror("error: send (s, pid_str, pid_str_len, 0)"); - exit (1); - } - - // We are done with the socket - close (s); +#if defined(DEBUG_LLDB_LAUNCHER) + printf("\n%s post options:\n", program_name); + for (int i = 0; i < argc; ++i) + printf("argv[%u] = '%s'\n", i, argv[i]); +#endif - system("clear"); - printf ("Launching: '%s'\n", argv[0]); - if (working_dir.empty()) - { - char cwd[PATH_MAX]; - const char *cwd_ptr = getcwd(cwd, sizeof(cwd)); - printf ("Working directory: '%s'\n", cwd_ptr); - } - else - { - printf ("Working directory: '%s'\n", working_dir.c_str()); - } - printf ("%i arguments:\n", argc); - - for (int i=0; i<argc; ++i) - printf ("argv[%u] = '%s'\n", i, argv[i]); - - // Now we posix spawn to exec this process into the inferior that we want - // to debug. - posix_spawn_for_debug (argv, - pass_env ? *_NSGetEnviron() : NULL, // Pass current environment as we may have modified it if "--env" options was used, do NOT pass "envp" here - working_dir.empty() ? NULL : working_dir.c_str(), - cpu_type, - disable_aslr); - - return 0; + // Open the socket that was passed in as an option + struct sockaddr_un saddr_un; + int s = ::socket(AF_UNIX, SOCK_STREAM, 0); + if (s < 0) { + perror("error: socket (AF_UNIX, SOCK_STREAM, 0)"); + exit(1); + } + + saddr_un.sun_family = AF_UNIX; + ::strncpy(saddr_un.sun_path, unix_socket_name.c_str(), + sizeof(saddr_un.sun_path) - 1); + saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0'; + saddr_un.sun_len = SUN_LEN(&saddr_un); + + if (::connect(s, (struct sockaddr *)&saddr_un, SUN_LEN(&saddr_un)) < 0) { + perror("error: connect (socket, &saddr_un, saddr_un_len)"); + exit(1); + } + + // We were able to connect to the socket, now write our PID so whomever + // launched us will know this process's ID + char pid_str[64]; + const int pid_str_len = + ::snprintf(pid_str, sizeof(pid_str), "%i", ::getpid()); + const int bytes_sent = ::send(s, pid_str, pid_str_len, 0); + + if (pid_str_len != bytes_sent) { + perror("error: send (s, pid_str, pid_str_len, 0)"); + exit(1); + } + + // We are done with the socket + close(s); + + system("clear"); + printf("Launching: '%s'\n", argv[0]); + if (working_dir.empty()) { + char cwd[PATH_MAX]; + const char *cwd_ptr = getcwd(cwd, sizeof(cwd)); + printf("Working directory: '%s'\n", cwd_ptr); + } else { + printf("Working directory: '%s'\n", working_dir.c_str()); + } + printf("%i arguments:\n", argc); + + for (int i = 0; i < argc; ++i) + printf("argv[%u] = '%s'\n", i, argv[i]); + + // Now we posix spawn to exec this process into the inferior that we want + // to debug. + posix_spawn_for_debug( + argv, + pass_env ? *_NSGetEnviron() : NULL, // Pass current environment as we may + // have modified it if "--env" options + // was used, do NOT pass "envp" here + working_dir.empty() ? NULL : working_dir.c_str(), cpu_type, disable_aslr); + + return 0; } #endif // #if defined (__APPLE__) - diff --git a/tools/darwin-threads/examine-threads.c b/tools/darwin-threads/examine-threads.c index 07212e999f99..5d965140cf8b 100644 --- a/tools/darwin-threads/examine-threads.c +++ b/tools/darwin-threads/examine-threads.c @@ -1,291 +1,266 @@ +#include <ctype.h> +#include <dispatch/dispatch.h> +#include <errno.h> +#include <libproc.h> +#include <mach/mach.h> +#include <mach/task_info.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <mach/mach.h> -#include <mach/task_info.h> -#include <time.h> #include <sys/sysctl.h> -#include <ctype.h> -#include <libproc.h> -#include <errno.h> -#include <dispatch/dispatch.h> +#include <time.h> // from System.framework/Versions/B/PrivateHeaders/sys/codesign.h -#define CS_OPS_STATUS 0 /* return status */ -#define CS_RESTRICT 0x0000800 /* tell dyld to treat restricted */ -int csops(pid_t pid, unsigned int ops, void * useraddr, size_t usersize); +#define CS_OPS_STATUS 0 /* return status */ +#define CS_RESTRICT 0x0000800 /* tell dyld to treat restricted */ +int csops(pid_t pid, unsigned int ops, void *useraddr, size_t usersize); /* Step through the process table, find a matching process name, return the pid of that matched process. If there are multiple processes with that name, issue a warning on stdout and return the highest numbered process. The proc_pidpath() call is used which gets the full process name including - directories to the executable and the full (longer than 16 character) + directories to the executable and the full (longer than 16 character) executable name. */ -pid_t -get_pid_for_process_name (const char *procname) -{ - int process_count = proc_listpids (PROC_ALL_PIDS, 0, NULL, 0) / sizeof (pid_t); - if (process_count < 1) - { - printf ("Only found %d processes running!\n", process_count); - exit (1); - } +pid_t get_pid_for_process_name(const char *procname) { + int process_count = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0) / sizeof(pid_t); + if (process_count < 1) { + printf("Only found %d processes running!\n", process_count); + exit(1); + } // Allocate a few extra slots in case new processes are spawned - int all_pids_size = sizeof (pid_t) * (process_count + 3); - pid_t *all_pids = (pid_t *) malloc (all_pids_size); + int all_pids_size = sizeof(pid_t) * (process_count + 3); + pid_t *all_pids = (pid_t *)malloc(all_pids_size); - // re-set process_count in case the number of processes changed (got smaller; we won't do bigger) - process_count = proc_listpids (PROC_ALL_PIDS, 0, all_pids, all_pids_size) / sizeof (pid_t); + // re-set process_count in case the number of processes changed (got smaller; + // we won't do bigger) + process_count = + proc_listpids(PROC_ALL_PIDS, 0, all_pids, all_pids_size) / sizeof(pid_t); int i; pid_t highest_pid = 0; int match_count = 0; - for (i = 1; i < process_count; i++) - { - char pidpath[PATH_MAX]; - int pidpath_len = proc_pidpath (all_pids[i], pidpath, sizeof (pidpath)); - if (pidpath_len == 0) - continue; - char *j = strrchr (pidpath, '/'); - if ((j == NULL && strcmp (procname, pidpath) == 0) - || (j != NULL && strcmp (j + 1, procname) == 0)) - { - match_count++; - if (all_pids[i] > highest_pid) - highest_pid = all_pids[i]; - } + for (i = 1; i < process_count; i++) { + char pidpath[PATH_MAX]; + int pidpath_len = proc_pidpath(all_pids[i], pidpath, sizeof(pidpath)); + if (pidpath_len == 0) + continue; + char *j = strrchr(pidpath, '/'); + if ((j == NULL && strcmp(procname, pidpath) == 0) || + (j != NULL && strcmp(j + 1, procname) == 0)) { + match_count++; + if (all_pids[i] > highest_pid) + highest_pid = all_pids[i]; } - free (all_pids); + } + free(all_pids); - if (match_count == 0) - { - printf ("Did not find process '%s'.\n", procname); - exit (1); - } - if (match_count > 1) - { - printf ("Warning: More than one process '%s'!\n", procname); - printf (" defaulting to the highest-pid one, %d\n", highest_pid); - } + if (match_count == 0) { + printf("Did not find process '%s'.\n", procname); + exit(1); + } + if (match_count > 1) { + printf("Warning: More than one process '%s'!\n", procname); + printf(" defaulting to the highest-pid one, %d\n", highest_pid); + } return highest_pid; } -/* Given a pid, get the full executable name (including directory +/* Given a pid, get the full executable name (including directory paths and the longer-than-16-chars executable name) and return the basename of that (i.e. do not include the directory components). This function mallocs the memory for the string it returns; the caller must free this memory. */ -const char * -get_process_name_for_pid (pid_t pid) -{ +const char *get_process_name_for_pid(pid_t pid) { char tmp_name[PATH_MAX]; - if (proc_pidpath (pid, tmp_name, sizeof (tmp_name)) == 0) - { - printf ("Could not find process with pid of %d\n", (int) pid); - exit (1); - } - if (strrchr (tmp_name, '/')) - return strdup (strrchr (tmp_name, '/') + 1); + if (proc_pidpath(pid, tmp_name, sizeof(tmp_name)) == 0) { + printf("Could not find process with pid of %d\n", (int)pid); + exit(1); + } + if (strrchr(tmp_name, '/')) + return strdup(strrchr(tmp_name, '/') + 1); else - return strdup (tmp_name); + return strdup(tmp_name); } /* Get a struct kinfo_proc structure for a given pid. Process name is required for error printing. - Gives you the current state of the process and whether it is being debugged by anyone. + Gives you the current state of the process and whether it is being debugged + by anyone. memory is malloc()'ed for the returned struct kinfo_proc and must be freed by the caller. */ -struct kinfo_proc * -get_kinfo_proc_for_pid (pid_t pid, const char *process_name) -{ - struct kinfo_proc *kinfo = (struct kinfo_proc *) malloc (sizeof (struct kinfo_proc)); - int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid }; - size_t len = sizeof (struct kinfo_proc); - if (sysctl (mib, sizeof (mib) / sizeof (mib[0]), kinfo, &len, NULL, 0) != 0) - { - free ((void *) kinfo); - printf ("Could not get kinfo_proc for pid %d\n", (int) pid); - exit (1); - } +struct kinfo_proc *get_kinfo_proc_for_pid(pid_t pid, const char *process_name) { + struct kinfo_proc *kinfo = + (struct kinfo_proc *)malloc(sizeof(struct kinfo_proc)); + int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; + size_t len = sizeof(struct kinfo_proc); + if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), kinfo, &len, NULL, 0) != 0) { + free((void *)kinfo); + printf("Could not get kinfo_proc for pid %d\n", (int)pid); + exit(1); + } return kinfo; } /* Get the basic information (thread_basic_info_t) about a given - thread. - Gives you the suspend count; thread state; user time; system time; sleep time; etc. + thread. + Gives you the suspend count; thread state; user time; system time; sleep + time; etc. The return value is a pointer to malloc'ed memory - it is the caller's responsibility to free it. */ -thread_basic_info_t -get_thread_basic_info (thread_t thread) -{ +thread_basic_info_t get_thread_basic_info(thread_t thread) { kern_return_t kr; - integer_t *thinfo = (integer_t *) malloc (sizeof (integer_t) * THREAD_INFO_MAX); + integer_t *thinfo = (integer_t *)malloc(sizeof(integer_t) * THREAD_INFO_MAX); mach_msg_type_number_t thread_info_count = THREAD_INFO_MAX; - kr = thread_info (thread, THREAD_BASIC_INFO, - (thread_info_t) thinfo, &thread_info_count); - if (kr != KERN_SUCCESS) - { - printf ("Error - unable to get basic thread info for a thread\n"); - exit (1); - } - return (thread_basic_info_t) thinfo; + kr = thread_info(thread, THREAD_BASIC_INFO, (thread_info_t)thinfo, + &thread_info_count); + if (kr != KERN_SUCCESS) { + printf("Error - unable to get basic thread info for a thread\n"); + exit(1); + } + return (thread_basic_info_t)thinfo; } -/* Get the thread identifier info (thread_identifier_info_data_t) - about a given thread. - Gives you the system-wide unique thread number; the pthread identifier number +/* Get the thread identifier info (thread_identifier_info_data_t) + about a given thread. + Gives you the system-wide unique thread number; the pthread identifier number */ -thread_identifier_info_data_t -get_thread_identifier_info (thread_t thread) -{ +thread_identifier_info_data_t get_thread_identifier_info(thread_t thread) { kern_return_t kr; thread_identifier_info_data_t tident; mach_msg_type_number_t tident_count = THREAD_IDENTIFIER_INFO_COUNT; - kr = thread_info (thread, THREAD_IDENTIFIER_INFO, - (thread_info_t) &tident, &tident_count); - if (kr != KERN_SUCCESS) - { - printf ("Error - unable to get thread ident for a thread\n"); - exit (1); - } + kr = thread_info(thread, THREAD_IDENTIFIER_INFO, (thread_info_t)&tident, + &tident_count); + if (kr != KERN_SUCCESS) { + printf("Error - unable to get thread ident for a thread\n"); + exit(1); + } return tident; } - -/* Given a mach port # (in the examine-threads mach port namespace) for a thread, - find the mach port # in the inferior program's port namespace. +/* Given a mach port # (in the examine-threads mach port namespace) for a + thread, + find the mach port # in the inferior program's port namespace. Sets inferior_port if successful. Returns true if successful, false if unable to find the port number. */ -bool -inferior_namespace_mach_port_num (task_t task, thread_t examine_threads_port, thread_t *inferior_port) -{ - kern_return_t retval; - mach_port_name_array_t names; - mach_msg_type_number_t nameslen; - mach_port_type_array_t types; - mach_msg_type_number_t typeslen; - - if (inferior_port == NULL) - return false; - - retval = mach_port_names (task, &names, &nameslen, &types, &typeslen); - if (retval != KERN_SUCCESS) - { - printf ("Error - unable to get mach port names for inferior.\n"); - return false; - } - int i = 0; - for (i = 0; i < nameslen; i++) - { - mach_port_t local_name; - mach_msg_type_name_t local_type; - retval = mach_port_extract_right (task, names[i], MACH_MSG_TYPE_COPY_SEND, &local_name, &local_type); - if (retval == KERN_SUCCESS) - { - mach_port_deallocate (mach_task_self(), local_name); - if (local_name == examine_threads_port) - { - *inferior_port = names[i]; - vm_deallocate (mach_task_self (), (vm_address_t) names, nameslen * sizeof (mach_port_t)); - vm_deallocate (mach_task_self (), (vm_address_t) types, typeslen * sizeof (mach_port_t)); - return true; - } - } - } - vm_deallocate (mach_task_self (), (vm_address_t) names, nameslen * sizeof (mach_port_t)); - vm_deallocate (mach_task_self (), (vm_address_t) types, typeslen * sizeof (mach_port_t)); +bool inferior_namespace_mach_port_num(task_t task, + thread_t examine_threads_port, + thread_t *inferior_port) { + kern_return_t retval; + mach_port_name_array_t names; + mach_msg_type_number_t nameslen; + mach_port_type_array_t types; + mach_msg_type_number_t typeslen; + + if (inferior_port == NULL) + return false; + + retval = mach_port_names(task, &names, &nameslen, &types, &typeslen); + if (retval != KERN_SUCCESS) { + printf("Error - unable to get mach port names for inferior.\n"); return false; + } + int i = 0; + for (i = 0; i < nameslen; i++) { + mach_port_t local_name; + mach_msg_type_name_t local_type; + retval = mach_port_extract_right(task, names[i], MACH_MSG_TYPE_COPY_SEND, + &local_name, &local_type); + if (retval == KERN_SUCCESS) { + mach_port_deallocate(mach_task_self(), local_name); + if (local_name == examine_threads_port) { + *inferior_port = names[i]; + vm_deallocate(mach_task_self(), (vm_address_t)names, + nameslen * sizeof(mach_port_t)); + vm_deallocate(mach_task_self(), (vm_address_t)types, + typeslen * sizeof(mach_port_t)); + return true; + } + } + } + vm_deallocate(mach_task_self(), (vm_address_t)names, + nameslen * sizeof(mach_port_t)); + vm_deallocate(mach_task_self(), (vm_address_t)types, + typeslen * sizeof(mach_port_t)); + return false; } /* Get the current pc value for a given thread. */ -uint64_t -get_current_pc (thread_t thread, int *wordsize) -{ - kern_return_t kr ; +uint64_t get_current_pc(thread_t thread, int *wordsize) { + kern_return_t kr; -#if defined (__x86_64__) || defined (__i386__) +#if defined(__x86_64__) || defined(__i386__) x86_thread_state_t gp_regs; mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT; - kr = thread_get_state (thread, x86_THREAD_STATE, - (thread_state_t) &gp_regs, &gp_count); - if (kr != KERN_SUCCESS) - { - printf ("Error - unable to get registers for a thread\n"); - exit (1); - } + kr = thread_get_state(thread, x86_THREAD_STATE, (thread_state_t)&gp_regs, + &gp_count); + if (kr != KERN_SUCCESS) { + printf("Error - unable to get registers for a thread\n"); + exit(1); + } - if (gp_regs.tsh.flavor == x86_THREAD_STATE64) - { - *wordsize = 8; - return gp_regs.uts.ts64.__rip; - } - else - { - *wordsize = 4; - return gp_regs.uts.ts32.__eip; - } + if (gp_regs.tsh.flavor == x86_THREAD_STATE64) { + *wordsize = 8; + return gp_regs.uts.ts64.__rip; + } else { + *wordsize = 4; + return gp_regs.uts.ts32.__eip; + } #endif -#if defined (__arm__) +#if defined(__arm__) arm_thread_state_t gp_regs; mach_msg_type_number_t gp_count = ARM_THREAD_STATE_COUNT; - kr = thread_get_state (thread, ARM_THREAD_STATE, - (thread_state_t) &gp_regs, &gp_count); - if (kr != KERN_SUCCESS) - { - printf ("Error - unable to get registers for a thread\n"); - exit (1); - } + kr = thread_get_state(thread, ARM_THREAD_STATE, (thread_state_t)&gp_regs, + &gp_count); + if (kr != KERN_SUCCESS) { + printf("Error - unable to get registers for a thread\n"); + exit(1); + } *wordsize = 4; return gp_regs.__pc; #endif -#if defined (__arm64__) +#if defined(__arm64__) arm_thread_state64_t gp_regs; mach_msg_type_number_t gp_count = ARM_THREAD_STATE64_COUNT; - kr = thread_get_state (thread, ARM_THREAD_STATE64, - (thread_state_t) &gp_regs, &gp_count); - if (kr != KERN_SUCCESS) - { - printf ("Error - unable to get registers for a thread\n"); - exit (1); - } + kr = thread_get_state(thread, ARM_THREAD_STATE64, (thread_state_t)&gp_regs, + &gp_count); + if (kr != KERN_SUCCESS) { + printf("Error - unable to get registers for a thread\n"); + exit(1); + } *wordsize = 8; return gp_regs.__pc; #endif - } /* Get the proc_threadinfo for a given thread. - Gives you the thread name, if set; current and max priorities. + Gives you the thread name, if set; current and max priorities. Returns 1 if successful Returns 0 if proc_pidinfo() failed */ -int -get_proc_threadinfo (pid_t pid, uint64_t thread_handle, struct proc_threadinfo *pth) -{ +int get_proc_threadinfo(pid_t pid, uint64_t thread_handle, + struct proc_threadinfo *pth) { pth->pth_name[0] = '\0'; - int ret = proc_pidinfo (pid, PROC_PIDTHREADINFO, thread_handle, - pth, sizeof (struct proc_threadinfo)); + int ret = proc_pidinfo(pid, PROC_PIDTHREADINFO, thread_handle, pth, + sizeof(struct proc_threadinfo)); if (ret != 0) return 1; else return 0; } -int -main (int argc, char **argv) -{ +int main(int argc, char **argv) { kern_return_t kr; task_t task; pid_t pid = 0; @@ -294,221 +269,239 @@ main (int argc, char **argv) int do_loop = 0; int verbose = 0; int resume_when_done = 0; - mach_port_t mytask = mach_task_self (); + mach_port_t mytask = mach_task_self(); - if (argc != 2 && argc != 3 && argc != 4 && argc != 5) - { - printf ("Usage: tdump [-l] [-v] [-r] pid/procname\n"); - exit (1); - } - - if (argc == 3 || argc == 4) - { - int i = 1; - while (i < argc - 1) - { - if (strcmp (argv[i], "-l") == 0) - do_loop = 1; - if (strcmp (argv[i], "-v") == 0) - verbose = 1; - if (strcmp (argv[i], "-r") == 0) - resume_when_done++; - i++; - } + if (argc != 2 && argc != 3 && argc != 4 && argc != 5) { + printf("Usage: tdump [-l] [-v] [-r] pid/procname\n"); + exit(1); + } + + if (argc == 3 || argc == 4) { + int i = 1; + while (i < argc - 1) { + if (strcmp(argv[i], "-l") == 0) + do_loop = 1; + if (strcmp(argv[i], "-v") == 0) + verbose = 1; + if (strcmp(argv[i], "-r") == 0) + resume_when_done++; + i++; } + } char *c = argv[argc - 1]; - if (*c == '\0') - { - printf ("Usage: tdump [-l] [-v] pid/procname\n"); - exit (1); - } - while (*c != '\0') - { - if (!isdigit (*c)) - { - arg_is_procname = 1; - procname = argv[argc - 1]; - break; - } - c++; + if (*c == '\0') { + printf("Usage: tdump [-l] [-v] pid/procname\n"); + exit(1); + } + while (*c != '\0') { + if (!isdigit(*c)) { + arg_is_procname = 1; + procname = argv[argc - 1]; + break; } + c++; + } - if (arg_is_procname && procname) - { - pid = get_pid_for_process_name (procname); - } - else - { - errno = 0; - pid = (pid_t) strtol (argv[argc - 1], NULL, 10); - if (pid == 0 && errno == EINVAL) - { - printf ("Usage: tdump [-l] [-v] pid/procname\n"); - exit (1); - } + if (arg_is_procname && procname) { + pid = get_pid_for_process_name(procname); + } else { + errno = 0; + pid = (pid_t)strtol(argv[argc - 1], NULL, 10); + if (pid == 0 && errno == EINVAL) { + printf("Usage: tdump [-l] [-v] pid/procname\n"); + exit(1); } + } - const char *process_name = get_process_name_for_pid (pid); + const char *process_name = get_process_name_for_pid(pid); - // At this point "pid" is the process id and "process_name" is the process name - // Now we have to get the process list from the kernel (which only has the truncated + // At this point "pid" is the process id and "process_name" is the process + // name + // Now we have to get the process list from the kernel (which only has the + // truncated // 16 char names) - struct kinfo_proc *kinfo = get_kinfo_proc_for_pid (pid, process_name); + struct kinfo_proc *kinfo = get_kinfo_proc_for_pid(pid, process_name); - printf ("pid %d (%s) is currently ", pid, process_name); + printf("pid %d (%s) is currently ", pid, process_name); switch (kinfo->kp_proc.p_stat) { - case SIDL: printf ("being created by fork"); break; - case SRUN: printf ("runnable"); break; - case SSLEEP: printf ("sleeping on an address"); break; - case SSTOP: printf ("suspended"); break; - case SZOMB: printf ("zombie state - awaiting collection by parent"); break; - default: printf ("unknown"); + case SIDL: + printf("being created by fork"); + break; + case SRUN: + printf("runnable"); + break; + case SSLEEP: + printf("sleeping on an address"); + break; + case SSTOP: + printf("suspended"); + break; + case SZOMB: + printf("zombie state - awaiting collection by parent"); + break; + default: + printf("unknown"); } if (kinfo->kp_proc.p_flag & P_TRACED) - printf (" and is being debugged."); - free ((void *) kinfo); + printf(" and is being debugged."); + free((void *)kinfo); - printf ("\n"); + printf("\n"); int csops_flags = 0; - if (csops (pid, CS_OPS_STATUS, &csops_flags, sizeof (csops_flags)) != -1 - && (csops_flags & CS_RESTRICT)) - { - printf ("pid %d (%s) is restricted so nothing can attach to it.\n", pid, process_name); + if (csops(pid, CS_OPS_STATUS, &csops_flags, sizeof(csops_flags)) != -1 && + (csops_flags & CS_RESTRICT)) { + printf("pid %d (%s) is restricted so nothing can attach to it.\n", pid, + process_name); } - kr = task_for_pid (mach_task_self (), pid, &task); - if (kr != KERN_SUCCESS) - { - printf ("Error - unable to task_for_pid()\n"); - exit (1); - } + kr = task_for_pid(mach_task_self(), pid, &task); + if (kr != KERN_SUCCESS) { + printf("Error - unable to task_for_pid()\n"); + exit(1); + } struct task_basic_info info; unsigned int info_count = TASK_BASIC_INFO_COUNT; - kr = task_info (task, TASK_BASIC_INFO, (task_info_t) &info, &info_count); - if (kr != KERN_SUCCESS) - { - printf ("Error - unable to call task_info.\n"); - exit (1); - } - printf ("Task suspend count: %d.\n", info.suspend_count); + kr = task_info(task, TASK_BASIC_INFO, (task_info_t)&info, &info_count); + if (kr != KERN_SUCCESS) { + printf("Error - unable to call task_info.\n"); + exit(1); + } + printf("Task suspend count: %d.\n", info.suspend_count); - struct timespec *rqtp = (struct timespec *) malloc (sizeof (struct timespec)); + struct timespec *rqtp = (struct timespec *)malloc(sizeof(struct timespec)); rqtp->tv_sec = 0; rqtp->tv_nsec = 150000000; int loop_cnt = 1; - do - { - int i; - if (do_loop) - printf ("Iteration %d:\n", loop_cnt++); - thread_array_t thread_list; - mach_msg_type_number_t thread_count; - - kr = task_threads (task, &thread_list, &thread_count); - if (kr != KERN_SUCCESS) - { - printf ("Error - unable to get thread list\n"); - exit (1); + do { + int i; + if (do_loop) + printf("Iteration %d:\n", loop_cnt++); + thread_array_t thread_list; + mach_msg_type_number_t thread_count; + + kr = task_threads(task, &thread_list, &thread_count); + if (kr != KERN_SUCCESS) { + printf("Error - unable to get thread list\n"); + exit(1); + } + printf("pid %d has %d threads\n", pid, thread_count); + if (verbose) + printf("\n"); + + for (i = 0; i < thread_count; i++) { + thread_basic_info_t basic_info = get_thread_basic_info(thread_list[i]); + + thread_identifier_info_data_t identifier_info = + get_thread_identifier_info(thread_list[i]); + + int wordsize; + uint64_t pc = get_current_pc(thread_list[i], &wordsize); + + printf("thread #%d, system-wide-unique-tid %lld, suspend count is %d, ", + i, identifier_info.thread_id, basic_info->suspend_count); + if (wordsize == 8) + printf("pc 0x%016llx, ", pc); + else + printf("pc 0x%08llx, ", pc); + printf("run state is "); + switch (basic_info->run_state) { + case TH_STATE_RUNNING: + puts("running"); + break; + case TH_STATE_STOPPED: + puts("stopped"); + break; + case TH_STATE_WAITING: + puts("waiting"); + break; + case TH_STATE_UNINTERRUPTIBLE: + puts("uninterruptible"); + break; + case TH_STATE_HALTED: + puts("halted"); + break; + default: + puts(""); + } + + printf(" pthread handle id 0x%llx (not the same value as " + "pthread_self() returns)\n", + (uint64_t)identifier_info.thread_handle); + + struct proc_threadinfo pth; + int proc_threadinfo_succeeded = + get_proc_threadinfo(pid, identifier_info.thread_handle, &pth); + + if (proc_threadinfo_succeeded && pth.pth_name[0] != '\0') + printf(" thread name '%s'\n", pth.pth_name); + + printf(" libdispatch qaddr 0x%llx (not the same as the " + "dispatch_queue_t token)\n", + (uint64_t)identifier_info.dispatch_qaddr); + + if (verbose) { + printf( + " (examine-threads port namespace) mach port # 0x%4.4x\n", + (int)thread_list[i]); + thread_t mach_port_inferior_namespace; + if (inferior_namespace_mach_port_num(task, thread_list[i], + &mach_port_inferior_namespace)) + printf(" (inferior port namepsace) mach port # 0x%4.4x\n", + (int)mach_port_inferior_namespace); + printf(" user %d.%06ds, system %d.%06ds", + basic_info->user_time.seconds, + basic_info->user_time.microseconds, + basic_info->system_time.seconds, + basic_info->system_time.microseconds); + if (basic_info->cpu_usage > 0) { + float cpu_percentage = basic_info->cpu_usage / 10.0; + printf(", using %.1f%% cpu currently", cpu_percentage); } - printf ("pid %d has %d threads\n", pid, thread_count); - if (verbose) - printf ("\n"); - - for (i = 0; i < thread_count; i++) - { - thread_basic_info_t basic_info = get_thread_basic_info (thread_list[i]); - - thread_identifier_info_data_t identifier_info = get_thread_identifier_info (thread_list[i]); - - int wordsize; - uint64_t pc = get_current_pc (thread_list[i], &wordsize); - - printf ("thread #%d, system-wide-unique-tid %lld, suspend count is %d, ", i, - identifier_info.thread_id, - basic_info->suspend_count); - if (wordsize == 8) - printf ("pc 0x%016llx, ", pc); - else - printf ("pc 0x%08llx, ", pc); - printf ("run state is "); - switch (basic_info->run_state) { - case TH_STATE_RUNNING: puts ("running"); break; - case TH_STATE_STOPPED: puts ("stopped"); break; - case TH_STATE_WAITING: puts ("waiting"); break; - case TH_STATE_UNINTERRUPTIBLE: puts ("uninterruptible"); break; - case TH_STATE_HALTED: puts ("halted"); break; - default: puts (""); - } - - printf (" pthread handle id 0x%llx (not the same value as pthread_self() returns)\n", (uint64_t) identifier_info.thread_handle); - - struct proc_threadinfo pth; - int proc_threadinfo_succeeded = get_proc_threadinfo (pid, identifier_info.thread_handle, &pth); - - if (proc_threadinfo_succeeded && pth.pth_name[0] != '\0') - printf (" thread name '%s'\n", pth.pth_name); - - printf (" libdispatch qaddr 0x%llx (not the same as the dispatch_queue_t token)\n", (uint64_t) identifier_info.dispatch_qaddr); - - if (verbose) - { - printf (" (examine-threads port namespace) mach port # 0x%4.4x\n", (int) thread_list[i]); - thread_t mach_port_inferior_namespace; - if (inferior_namespace_mach_port_num (task, thread_list[i], &mach_port_inferior_namespace)) - printf (" (inferior port namepsace) mach port # 0x%4.4x\n", (int) mach_port_inferior_namespace); - printf (" user %d.%06ds, system %d.%06ds", - basic_info->user_time.seconds, basic_info->user_time.microseconds, - basic_info->system_time.seconds, basic_info->system_time.microseconds); - if (basic_info->cpu_usage > 0) - { - float cpu_percentage = basic_info->cpu_usage / 10.0; - printf (", using %.1f%% cpu currently", cpu_percentage); - } - if (basic_info->sleep_time > 0) - printf (", this thread has slept for %d seconds", basic_info->sleep_time); - - printf ("\n "); - printf ("scheduling policy %d", basic_info->policy); - - if (basic_info->flags != 0) - { - printf (", flags %d", basic_info->flags); - if ((basic_info->flags | TH_FLAGS_SWAPPED) == TH_FLAGS_SWAPPED) - printf (" (thread is swapped out)"); - if ((basic_info->flags | TH_FLAGS_IDLE) == TH_FLAGS_IDLE) - printf (" (thread is idle)"); - } - if (proc_threadinfo_succeeded) - printf (", current pri %d, max pri %d", pth.pth_curpri, pth.pth_maxpriority); - - printf ("\n\n"); - } - - free ((void *) basic_info); + if (basic_info->sleep_time > 0) + printf(", this thread has slept for %d seconds", + basic_info->sleep_time); + + printf("\n "); + printf("scheduling policy %d", basic_info->policy); + + if (basic_info->flags != 0) { + printf(", flags %d", basic_info->flags); + if ((basic_info->flags | TH_FLAGS_SWAPPED) == TH_FLAGS_SWAPPED) + printf(" (thread is swapped out)"); + if ((basic_info->flags | TH_FLAGS_IDLE) == TH_FLAGS_IDLE) + printf(" (thread is idle)"); } - if (do_loop) - printf ("\n"); - vm_deallocate (mytask, (vm_address_t) thread_list, - thread_count * sizeof (thread_act_t)); - nanosleep (rqtp, NULL); - } while (do_loop); - - while (resume_when_done > 0) - { - kern_return_t err = task_resume (task); - if (err != KERN_SUCCESS) - printf ("Error resuming task: %d.", err); - resume_when_done--; + if (proc_threadinfo_succeeded) + printf(", current pri %d, max pri %d", pth.pth_curpri, + pth.pth_maxpriority); + + printf("\n\n"); + } + + free((void *)basic_info); } + if (do_loop) + printf("\n"); + vm_deallocate(mytask, (vm_address_t)thread_list, + thread_count * sizeof(thread_act_t)); + nanosleep(rqtp, NULL); + } while (do_loop); + + while (resume_when_done > 0) { + kern_return_t err = task_resume(task); + if (err != KERN_SUCCESS) + printf("Error resuming task: %d.", err); + resume_when_done--; + } - vm_deallocate (mytask, (vm_address_t) task, sizeof (task_t)); - free ((void *) process_name); + vm_deallocate(mytask, (vm_address_t)task, sizeof(task_t)); + free((void *)process_name); return 0; } diff --git a/tools/debugserver/debugserver.xcodeproj/project.pbxproj b/tools/debugserver/debugserver.xcodeproj/project.pbxproj index 295a2bf4fa17..a4c3de58113e 100644 --- a/tools/debugserver/debugserver.xcodeproj/project.pbxproj +++ b/tools/debugserver/debugserver.xcodeproj/project.pbxproj @@ -7,8 +7,29 @@ objects = { /* Begin PBXBuildFile section */ + 23043C9D1D35DBEC00FC25CA /* JSON.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 233B4EA51D2DB54300E98261 /* JSON.cpp */; }; + 23043C9E1D35DBFA00FC25CA /* StringConvert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 233B4EA81D2DB96A00E98261 /* StringConvert.cpp */; }; + 2307CCCB1D4A5D630016ABC0 /* LogFilterExactMatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 237821AE1D4917D20028B7A1 /* LogFilterExactMatch.cpp */; }; + 233B4EA71D2DB54300E98261 /* JSON.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 233B4EA51D2DB54300E98261 /* JSON.cpp */; }; + 233B4EA91D2DB96A00E98261 /* StringConvert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 233B4EA81D2DB96A00E98261 /* StringConvert.cpp */; }; + 23562ED21D3424DF00AB2BD4 /* LogMessageOsLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23562ED01D3424DF00AB2BD4 /* LogMessageOsLog.cpp */; }; + 23562ED31D3424DF00AB2BD4 /* LogMessageOsLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23562ED01D3424DF00AB2BD4 /* LogMessageOsLog.cpp */; }; + 23562ED61D342A5A00AB2BD4 /* ActivityStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23562ED51D342A5A00AB2BD4 /* ActivityStore.cpp */; }; + 23562ED71D342A5A00AB2BD4 /* ActivityStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23562ED51D342A5A00AB2BD4 /* ActivityStore.cpp */; }; + 23562ED91D342B0000AB2BD4 /* LogMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23562ED81D342B0000AB2BD4 /* LogMessage.cpp */; }; + 23562EDA1D342B0000AB2BD4 /* LogMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23562ED81D342B0000AB2BD4 /* LogMessage.cpp */; }; + 237821B01D4917D20028B7A1 /* LogFilterExactMatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 237821AE1D4917D20028B7A1 /* LogFilterExactMatch.cpp */; }; + 23AC04C61D2F41A00072351D /* LogFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23AC04C41D2F41A00072351D /* LogFilter.cpp */; }; + 23AC04C71D2F41A00072351D /* LogFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23AC04C41D2F41A00072351D /* LogFilter.cpp */; }; + 23AC04CA1D2F42250072351D /* LogFilterChain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23AC04C81D2F42250072351D /* LogFilterChain.cpp */; }; + 23AC04CB1D2F42250072351D /* LogFilterChain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23AC04C81D2F42250072351D /* LogFilterChain.cpp */; }; + 23AC04CF1D2F58AF0072351D /* LogFilterRegex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23AC04CD1D2F58AF0072351D /* LogFilterRegex.cpp */; }; + 23AC04D01D2F58AF0072351D /* LogFilterRegex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23AC04CD1D2F58AF0072351D /* LogFilterRegex.cpp */; }; + 23AE72E41D25DECF00945BCE /* DarwinLogCollector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23AE72E21D25DECF00945BCE /* DarwinLogCollector.cpp */; }; + 23AE72E51D25DEE100945BCE /* DarwinLogCollector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23AE72E21D25DECF00945BCE /* DarwinLogCollector.cpp */; }; + 23D1B0291D497E8B00FF831B /* OsLogger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23D1B0271D497E8B00FF831B /* OsLogger.cpp */; }; + 23D1B02A1D497E8B00FF831B /* OsLogger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23D1B0271D497E8B00FF831B /* OsLogger.cpp */; }; 264D5D581293835600ED4C01 /* DNBArch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264D5D571293835600ED4C01 /* DNBArch.cpp */; }; - 2660D9CE1192280900958FBD /* StringExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2660D9CC1192280900958FBD /* StringExtractor.cpp */; }; 266B5ED11460A68200E43F0A /* DNBArchImplARM64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266B5ECF1460A68200E43F0A /* DNBArchImplARM64.cpp */; }; 26CE05A7115C360D0022F371 /* DNBError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637DE0C71334A0024798E /* DNBError.cpp */; }; 26CE05A8115C36170022F371 /* DNBThreadResumeActions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260E7331114BFFE600D1DFB3 /* DNBThreadResumeActions.cpp */; }; @@ -38,7 +59,6 @@ 26CE05C1115C36510022F371 /* DNBArchImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2675D4220CCEB705000F49AF /* DNBArchImpl.cpp */; }; 26CE05C2115C36550022F371 /* DNBArchImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637FB0C71334A0024798E /* DNBArchImpl.cpp */; }; 26CE05C3115C36580022F371 /* CFString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2695DD9B0D3EC160007E4CA2 /* CFString.cpp */; }; - 26CE05C4115C36590022F371 /* CFData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2695DE2E0D3EE55B007E4CA2 /* CFData.cpp */; }; 26CE05C5115C36590022F371 /* CFBundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2695DD910D3EBFF6007E4CA2 /* CFBundle.cpp */; }; 26CE05CF115C36F70022F371 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26ACA3340D3E956300A2120B /* CoreFoundation.framework */; settings = {ATTRIBUTES = (Required, ); }; }; 26CE05F1115C387C0022F371 /* PseudoTerminal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF67ABFF0D34604D0022D128 /* PseudoTerminal.cpp */; }; @@ -71,19 +91,46 @@ 456F67601AD46CE9002850C2 /* DNBArchImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2675D4220CCEB705000F49AF /* DNBArchImpl.cpp */; }; 456F67611AD46CE9002850C2 /* DNBArchImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637FB0C71334A0024798E /* DNBArchImpl.cpp */; }; 456F67621AD46CE9002850C2 /* CFString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2695DD9B0D3EC160007E4CA2 /* CFString.cpp */; }; - 456F67631AD46CE9002850C2 /* CFData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2695DE2E0D3EE55B007E4CA2 /* CFData.cpp */; }; 456F67641AD46CE9002850C2 /* CFBundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2695DD910D3EBFF6007E4CA2 /* CFBundle.cpp */; }; 456F67651AD46CE9002850C2 /* PseudoTerminal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF67ABFF0D34604D0022D128 /* PseudoTerminal.cpp */; }; - 456F67661AD46CE9002850C2 /* StringExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2660D9CC1192280900958FBD /* StringExtractor.cpp */; }; 456F67671AD46CE9002850C2 /* DNBArch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264D5D571293835600ED4C01 /* DNBArch.cpp */; }; 456F67681AD46CE9002850C2 /* HasAVX.s in Sources */ = {isa = PBXBuildFile; fileRef = 4971AE7113D10F4F00649E37 /* HasAVX.s */; }; 456F67691AD46CE9002850C2 /* DNBArchImplARM64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266B5ECF1460A68200E43F0A /* DNBArchImplARM64.cpp */; }; 456F676B1AD46CE9002850C2 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26ACA3340D3E956300A2120B /* CoreFoundation.framework */; settings = {ATTRIBUTES = (Required, ); }; }; 4971AE7213D10F4F00649E37 /* HasAVX.s in Sources */ = {isa = PBXBuildFile; fileRef = 4971AE7113D10F4F00649E37 /* HasAVX.s */; }; + AF48558C1D75126800D19C07 /* StdStringExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF48558B1D75126800D19C07 /* StdStringExtractor.cpp */; }; + AF48558D1D75127500D19C07 /* StdStringExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF48558B1D75126800D19C07 /* StdStringExtractor.cpp */; }; AFEC3364194A8B0B00FF05C6 /* Genealogy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFEC3363194A8B0B00FF05C6 /* Genealogy.cpp */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 2307CCCC1D4A5DAE0016ABC0 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; }; + 233B4EA51D2DB54300E98261 /* JSON.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSON.cpp; sourceTree = "<group>"; }; + 233B4EA61D2DB54300E98261 /* JSON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSON.h; sourceTree = "<group>"; }; + 233B4EA81D2DB96A00E98261 /* StringConvert.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringConvert.cpp; path = ../../../source/Host/common/StringConvert.cpp; sourceTree = "<group>"; }; + 23562ECF1D34110D00AB2BD4 /* DarwinLogTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DarwinLogTypes.h; sourceTree = "<group>"; }; + 23562ED01D3424DF00AB2BD4 /* LogMessageOsLog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LogMessageOsLog.cpp; sourceTree = "<group>"; }; + 23562ED11D3424DF00AB2BD4 /* LogMessageOsLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LogMessageOsLog.h; sourceTree = "<group>"; }; + 23562ED41D3426DD00AB2BD4 /* ActivityStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ActivityStore.h; sourceTree = "<group>"; }; + 23562ED51D342A5A00AB2BD4 /* ActivityStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ActivityStore.cpp; sourceTree = "<group>"; }; + 23562ED81D342B0000AB2BD4 /* LogMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LogMessage.cpp; sourceTree = "<group>"; }; + 237821AD1D4917D20028B7A1 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; }; + 237821AE1D4917D20028B7A1 /* LogFilterExactMatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LogFilterExactMatch.cpp; sourceTree = "<group>"; }; + 237821AF1D4917D20028B7A1 /* LogFilterExactMatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LogFilterExactMatch.h; sourceTree = "<group>"; }; + 23AC04C41D2F41A00072351D /* LogFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LogFilter.cpp; sourceTree = "<group>"; }; + 23AC04C51D2F41A00072351D /* LogFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LogFilter.h; sourceTree = "<group>"; }; + 23AC04C81D2F42250072351D /* LogFilterChain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LogFilterChain.cpp; sourceTree = "<group>"; }; + 23AC04C91D2F42250072351D /* LogFilterChain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LogFilterChain.h; sourceTree = "<group>"; }; + 23AC04CC1D2F42F10072351D /* DarwinLogInterfaces.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DarwinLogInterfaces.h; sourceTree = "<group>"; }; + 23AC04CD1D2F58AF0072351D /* LogFilterRegex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LogFilterRegex.cpp; sourceTree = "<group>"; }; + 23AC04CE1D2F58AF0072351D /* LogFilterRegex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LogFilterRegex.h; sourceTree = "<group>"; }; + 23AC04D11D2F60130072351D /* LogMessage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LogMessage.h; sourceTree = "<group>"; }; + 23AE72E21D25DECF00945BCE /* DarwinLogCollector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DarwinLogCollector.cpp; sourceTree = "<group>"; }; + 23AE72E31D25DECF00945BCE /* DarwinLogCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DarwinLogCollector.h; sourceTree = "<group>"; }; + 23AE72E61D25DEFB00945BCE /* ActivityStreamSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ActivityStreamSPI.h; sourceTree = "<group>"; }; + 23CF6F5E1D28A3760088ADC9 /* DarwinLogEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DarwinLogEvent.h; sourceTree = "<group>"; }; + 23D1B0271D497E8B00FF831B /* OsLogger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OsLogger.cpp; sourceTree = "<group>"; }; + 23D1B0281D497E8B00FF831B /* OsLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OsLogger.h; sourceTree = "<group>"; }; 260828DE0CBAF7F400F95054 /* DNBRuntimeAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNBRuntimeAction.h; sourceTree = "<group>"; }; 260E7331114BFFE600D1DFB3 /* DNBThreadResumeActions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DNBThreadResumeActions.cpp; sourceTree = "<group>"; }; 260E7332114BFFE600D1DFB3 /* DNBThreadResumeActions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNBThreadResumeActions.h; sourceTree = "<group>"; }; @@ -94,7 +141,6 @@ 264D5D571293835600ED4C01 /* DNBArch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DNBArch.cpp; sourceTree = "<group>"; }; 264F679A1B2F9EB200140093 /* JSONGenerator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSONGenerator.h; sourceTree = "<group>"; }; 26593A060D4931CC001C9FE3 /* ChangeLog */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ChangeLog; sourceTree = "<group>"; }; - 2660D9CC1192280900958FBD /* StringExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringExtractor.cpp; path = ../../source/Utility/StringExtractor.cpp; sourceTree = SOURCE_ROOT; }; 266B5ECF1460A68200E43F0A /* DNBArchImplARM64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DNBArchImplARM64.cpp; sourceTree = "<group>"; }; 266B5ED01460A68200E43F0A /* DNBArchImplARM64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNBArchImplARM64.h; sourceTree = "<group>"; }; 2672DBEE0EEF446700E92059 /* PThreadMutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PThreadMutex.cpp; sourceTree = "<group>"; }; @@ -104,8 +150,6 @@ 2695DD920D3EBFF6007E4CA2 /* CFBundle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CFBundle.h; sourceTree = "<group>"; }; 2695DD9A0D3EC160007E4CA2 /* CFString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CFString.h; sourceTree = "<group>"; }; 2695DD9B0D3EC160007E4CA2 /* CFString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CFString.cpp; sourceTree = "<group>"; }; - 2695DE2D0D3EE55B007E4CA2 /* CFData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CFData.h; sourceTree = "<group>"; }; - 2695DE2E0D3EE55B007E4CA2 /* CFData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CFData.cpp; sourceTree = "<group>"; }; 269E8DF8164B2ED200AD65F6 /* com.apple.debugserver.posix.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.debugserver.posix.plist; sourceTree = "<group>"; }; 26A02918114AB9240029C479 /* debugserver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debugserver.cpp; sourceTree = "<group>"; }; 26A4BAED0D498B7D00A9BEAB /* com.apple.debugserver.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = com.apple.debugserver.plist; sourceTree = "<group>"; }; @@ -171,6 +215,7 @@ 9457ECF61419864100DFE7D8 /* stack_logging.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = stack_logging.h; sourceTree = "<group>"; }; AF0934BA18E12B92005A11FD /* Genealogy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Genealogy.h; sourceTree = "<group>"; }; AF0934BB18E12B92005A11FD /* GenealogySPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenealogySPI.h; sourceTree = "<group>"; }; + AF48558B1D75126800D19C07 /* StdStringExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StdStringExtractor.cpp; sourceTree = "<group>"; }; AF61C60418F75ABC00B48D9D /* debugserver-macosx-entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "debugserver-macosx-entitlements.plist"; sourceTree = "<group>"; }; AF67ABFF0D34604D0022D128 /* PseudoTerminal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PseudoTerminal.cpp; sourceTree = "<group>"; }; AF67AC000D34604D0022D128 /* PseudoTerminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PseudoTerminal.h; sourceTree = "<group>"; }; @@ -221,6 +266,34 @@ name = Products; sourceTree = "<group>"; }; + 23AC04C31D2F3E9A0072351D /* DarwinLog */ = { + isa = PBXGroup; + children = ( + 237821AD1D4917D20028B7A1 /* CMakeLists.txt */, + 23562ED41D3426DD00AB2BD4 /* ActivityStore.h */, + 23562ED51D342A5A00AB2BD4 /* ActivityStore.cpp */, + 23AE72E61D25DEFB00945BCE /* ActivityStreamSPI.h */, + 23AE72E31D25DECF00945BCE /* DarwinLogCollector.h */, + 23AE72E21D25DECF00945BCE /* DarwinLogCollector.cpp */, + 23CF6F5E1D28A3760088ADC9 /* DarwinLogEvent.h */, + 23AC04CC1D2F42F10072351D /* DarwinLogInterfaces.h */, + 23562ECF1D34110D00AB2BD4 /* DarwinLogTypes.h */, + 23AC04C51D2F41A00072351D /* LogFilter.h */, + 23AC04C41D2F41A00072351D /* LogFilter.cpp */, + 23AC04C91D2F42250072351D /* LogFilterChain.h */, + 23AC04C81D2F42250072351D /* LogFilterChain.cpp */, + 237821AF1D4917D20028B7A1 /* LogFilterExactMatch.h */, + 237821AE1D4917D20028B7A1 /* LogFilterExactMatch.cpp */, + 23AC04CE1D2F58AF0072351D /* LogFilterRegex.h */, + 23AC04CD1D2F58AF0072351D /* LogFilterRegex.cpp */, + 23AC04D11D2F60130072351D /* LogMessage.h */, + 23562ED81D342B0000AB2BD4 /* LogMessage.cpp */, + 23562ED11D3424DF00AB2BD4 /* LogMessageOsLog.h */, + 23562ED01D3424DF00AB2BD4 /* LogMessageOsLog.cpp */, + ); + path = DarwinLog; + sourceTree = "<group>"; + }; 266B5ECE1460A68200E43F0A /* arm64 */ = { isa = PBXGroup; children = ( @@ -277,6 +350,8 @@ 26C637E20C71334A0024798E /* DNBRegisterInfo.cpp */, 260E7332114BFFE600D1DFB3 /* DNBThreadResumeActions.h */, 260E7331114BFFE600D1DFB3 /* DNBThreadResumeActions.cpp */, + 233B4EA61D2DB54300E98261 /* JSON.h */, + 233B4EA51D2DB54300E98261 /* JSON.cpp */, 264F679A1B2F9EB200140093 /* JSONGenerator.h */, AF67AC000D34604D0022D128 /* PseudoTerminal.h */, AF67ABFF0D34604D0022D128 /* PseudoTerminal.cpp */, @@ -285,6 +360,7 @@ 26C637FE0C71334A0024798E /* PThreadEvent.cpp */, 26C638000C71334A0024798E /* PThreadMutex.h */, 2672DBEE0EEF446700E92059 /* PThreadMutex.cpp */, + 233B4EA81D2DB96A00E98261 /* StringConvert.cpp */, 26C638020C71334A0024798E /* SysSignal.h */, 26C638010C71334A0024798E /* SysSignal.cpp */, 26C638060C71334A0024798E /* TTYState.h */, @@ -319,15 +395,13 @@ 26C637E60C71334A0024798E /* MacOSX */ = { isa = PBXGroup; children = ( - AF0934BA18E12B92005A11FD /* Genealogy.h */, - AF0934BB18E12B92005A11FD /* GenealogySPI.h */, + 23AC04C31D2F3E9A0072351D /* DarwinLog */, 2695DD920D3EBFF6007E4CA2 /* CFBundle.h */, 2695DD910D3EBFF6007E4CA2 /* CFBundle.cpp */, - 2695DE2D0D3EE55B007E4CA2 /* CFData.h */, - 2695DE2E0D3EE55B007E4CA2 /* CFData.cpp */, 2695DD9A0D3EC160007E4CA2 /* CFString.h */, 2695DD9B0D3EC160007E4CA2 /* CFString.cpp */, 26C637E70C71334A0024798E /* CFUtils.h */, + 2307CCCC1D4A5DAE0016ABC0 /* CMakeLists.txt */, 2675D41C0CCEB6CF000F49AF /* arm */, 266B5ECE1460A68200E43F0A /* arm64 */, 26C637E90C71334A0024798E /* i386 */, @@ -337,6 +411,8 @@ 4971AE7113D10F4F00649E37 /* HasAVX.s */, 26C637E80C71334A0024798E /* dbgnub-mig.defs */, AFEC3363194A8B0B00FF05C6 /* Genealogy.cpp */, + AF0934BA18E12B92005A11FD /* Genealogy.h */, + AF0934BB18E12B92005A11FD /* GenealogySPI.h */, 26C637EF0C71334A0024798E /* MachException.h */, 26C637EE0C71334A0024798E /* MachException.cpp */, 26C637F10C71334A0024798E /* MachProcess.h */, @@ -351,6 +427,8 @@ 26C637F80C71334A0024798E /* MachVMRegion.cpp */, 26B67DE00EE9BC30006C8BC0 /* MachTask.h */, 26B67DE10EE9BC30006C8BC0 /* MachTask.mm */, + 23D1B0281D497E8B00FF831B /* OsLogger.h */, + 23D1B0271D497E8B00FF831B /* OsLogger.cpp */, 9457ECF61419864100DFE7D8 /* stack_logging.h */, ); path = MacOSX; @@ -399,7 +477,7 @@ 26A68FD50D10574500665A9E /* RNBRemote.h */, 26A68FD60D10574500665A9E /* RNBRemote.cpp */, 26E6B9DA0D1329010037ECDD /* RNBDefs.h */, - 2660D9CC1192280900958FBD /* StringExtractor.cpp */, + AF48558B1D75126800D19C07 /* StdStringExtractor.cpp */, ); name = debugserver; sourceTree = "<group>"; @@ -494,38 +572,48 @@ 26CE05A7115C360D0022F371 /* DNBError.cpp in Sources */, 26CE05A8115C36170022F371 /* DNBThreadResumeActions.cpp in Sources */, 26CE05A9115C36250022F371 /* debugserver.cpp in Sources */, + AF48558C1D75126800D19C07 /* StdStringExtractor.cpp in Sources */, 26CE05AA115C36260022F371 /* RNBContext.cpp in Sources */, 26CE05AB115C36270022F371 /* RNBServices.cpp in Sources */, + 23D1B0291D497E8B00FF831B /* OsLogger.cpp in Sources */, 26CE05AC115C36280022F371 /* RNBSocket.cpp in Sources */, 26CE05AD115C36280022F371 /* RNBRemote.cpp in Sources */, 26CE05AE115C36320022F371 /* dbgnub-mig.defs in Sources */, 26CE05B0115C36340022F371 /* MachException.cpp in Sources */, 26CE05B1115C36350022F371 /* MachProcess.mm in Sources */, 26CE05B2115C36360022F371 /* MachThread.cpp in Sources */, + 233B4EA71D2DB54300E98261 /* JSON.cpp in Sources */, 26CE05B3115C36370022F371 /* MachThreadList.cpp in Sources */, 26CE05B4115C36380022F371 /* MachVMMemory.cpp in Sources */, 26CE05B5115C36380022F371 /* MachVMRegion.cpp in Sources */, 26CE05B6115C36390022F371 /* MachTask.mm in Sources */, 26CE05B7115C363B0022F371 /* DNB.cpp in Sources */, AFEC3364194A8B0B00FF05C6 /* Genealogy.cpp in Sources */, + 23AC04CF1D2F58AF0072351D /* LogFilterRegex.cpp in Sources */, + 233B4EA91D2DB96A00E98261 /* StringConvert.cpp in Sources */, + 23562ED21D3424DF00AB2BD4 /* LogMessageOsLog.cpp in Sources */, 26CE05B8115C363C0022F371 /* DNBBreakpoint.cpp in Sources */, 26CE05B9115C363D0022F371 /* DNBDataRef.cpp in Sources */, + 23AC04CA1D2F42250072351D /* LogFilterChain.cpp in Sources */, + 23562ED61D342A5A00AB2BD4 /* ActivityStore.cpp in Sources */, 26CE05BA115C363E0022F371 /* DNBLog.cpp in Sources */, + 23AC04C61D2F41A00072351D /* LogFilter.cpp in Sources */, 26CE05BB115C363F0022F371 /* DNBRegisterInfo.cpp in Sources */, 26CE05BC115C36420022F371 /* PThreadEvent.cpp in Sources */, 26CE05BD115C36430022F371 /* PThreadMutex.cpp in Sources */, 26CE05BE115C36440022F371 /* SysSignal.cpp in Sources */, + 23AE72E41D25DECF00945BCE /* DarwinLogCollector.cpp in Sources */, 26CE05BF115C364D0022F371 /* DNBArchImplX86_64.cpp in Sources */, 26CE05C0115C364F0022F371 /* DNBArchImplI386.cpp in Sources */, 26CE05C1115C36510022F371 /* DNBArchImpl.cpp in Sources */, 26CE05C2115C36550022F371 /* DNBArchImpl.cpp in Sources */, - 26CE05C3115C36580022F371 /* CFString.cpp in Sources */, - 26CE05C4115C36590022F371 /* CFData.cpp in Sources */, 26CE05C5115C36590022F371 /* CFBundle.cpp in Sources */, + 26CE05C3115C36580022F371 /* CFString.cpp in Sources */, + 23562ED91D342B0000AB2BD4 /* LogMessage.cpp in Sources */, 26CE05F1115C387C0022F371 /* PseudoTerminal.cpp in Sources */, - 2660D9CE1192280900958FBD /* StringExtractor.cpp in Sources */, 264D5D581293835600ED4C01 /* DNBArch.cpp in Sources */, 4971AE7213D10F4F00649E37 /* HasAVX.s in Sources */, + 237821B01D4917D20028B7A1 /* LogFilterExactMatch.cpp in Sources */, 266B5ED11460A68200E43F0A /* DNBArchImplARM64.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -537,38 +625,48 @@ 456F67461AD46CE9002850C2 /* DNBError.cpp in Sources */, 456F67471AD46CE9002850C2 /* DNBThreadResumeActions.cpp in Sources */, 456F67481AD46CE9002850C2 /* debugserver.cpp in Sources */, + 23043C9D1D35DBEC00FC25CA /* JSON.cpp in Sources */, 456F67491AD46CE9002850C2 /* RNBContext.cpp in Sources */, + 23D1B02A1D497E8B00FF831B /* OsLogger.cpp in Sources */, 456F674A1AD46CE9002850C2 /* RNBServices.cpp in Sources */, 456F674B1AD46CE9002850C2 /* RNBSocket.cpp in Sources */, 456F674C1AD46CE9002850C2 /* RNBRemote.cpp in Sources */, 456F674D1AD46CE9002850C2 /* dbgnub-mig.defs in Sources */, 456F674E1AD46CE9002850C2 /* MachException.cpp in Sources */, 456F674F1AD46CE9002850C2 /* MachProcess.mm in Sources */, + 2307CCCB1D4A5D630016ABC0 /* LogFilterExactMatch.cpp in Sources */, 456F67501AD46CE9002850C2 /* MachThread.cpp in Sources */, 456F67511AD46CE9002850C2 /* MachThreadList.cpp in Sources */, 456F67521AD46CE9002850C2 /* MachVMMemory.cpp in Sources */, 456F67531AD46CE9002850C2 /* MachVMRegion.cpp in Sources */, + 23562ED71D342A5A00AB2BD4 /* ActivityStore.cpp in Sources */, 456F67541AD46CE9002850C2 /* MachTask.mm in Sources */, 456F67551AD46CE9002850C2 /* DNB.cpp in Sources */, 456F67561AD46CE9002850C2 /* Genealogy.cpp in Sources */, 456F67571AD46CE9002850C2 /* DNBBreakpoint.cpp in Sources */, 456F67581AD46CE9002850C2 /* DNBDataRef.cpp in Sources */, 456F67591AD46CE9002850C2 /* DNBLog.cpp in Sources */, + 23562ED31D3424DF00AB2BD4 /* LogMessageOsLog.cpp in Sources */, 456F675A1AD46CE9002850C2 /* DNBRegisterInfo.cpp in Sources */, 456F675B1AD46CE9002850C2 /* PThreadEvent.cpp in Sources */, 456F675C1AD46CE9002850C2 /* PThreadMutex.cpp in Sources */, 456F675D1AD46CE9002850C2 /* SysSignal.cpp in Sources */, + 23AE72E51D25DEE100945BCE /* DarwinLogCollector.cpp in Sources */, 456F675E1AD46CE9002850C2 /* DNBArchImplX86_64.cpp in Sources */, + 23562EDA1D342B0000AB2BD4 /* LogMessage.cpp in Sources */, 456F675F1AD46CE9002850C2 /* DNBArchImplI386.cpp in Sources */, 456F67601AD46CE9002850C2 /* DNBArchImpl.cpp in Sources */, + 23AC04C71D2F41A00072351D /* LogFilter.cpp in Sources */, + 23043C9E1D35DBFA00FC25CA /* StringConvert.cpp in Sources */, 456F67611AD46CE9002850C2 /* DNBArchImpl.cpp in Sources */, 456F67621AD46CE9002850C2 /* CFString.cpp in Sources */, - 456F67631AD46CE9002850C2 /* CFData.cpp in Sources */, + 23AC04CB1D2F42250072351D /* LogFilterChain.cpp in Sources */, + AF48558D1D75127500D19C07 /* StdStringExtractor.cpp in Sources */, 456F67641AD46CE9002850C2 /* CFBundle.cpp in Sources */, 456F67651AD46CE9002850C2 /* PseudoTerminal.cpp in Sources */, - 456F67661AD46CE9002850C2 /* StringExtractor.cpp in Sources */, 456F67671AD46CE9002850C2 /* DNBArch.cpp in Sources */, 456F67681AD46CE9002850C2 /* HasAVX.s in Sources */, + 23AC04D01D2F58AF0072351D /* LogFilterRegex.cpp in Sources */, 456F67691AD46CE9002850C2 /* DNBArchImplARM64.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -608,8 +706,11 @@ "LLDB_COMPRESSION_CFLAGS[sdk=macosx10.11]" = "-DHAVE_LIBCOMPRESSION=1"; LLDB_COMPRESSION_LDFLAGS = ""; "LLDB_COMPRESSION_LDFLAGS[sdk=macosx10.11]" = "-weak-lcompression"; + LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)"; + LLDB_USE_OS_LOG = 0; LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1"; LLDB_ZLIB_LDFLAGS = "-lz"; + MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ""; STRIP_INSTALLED_PRODUCT = NO; @@ -649,8 +750,11 @@ "LLDB_COMPRESSION_CFLAGS[sdk=macosx10.11]" = "-DHAVE_LIBCOMPRESSION=1"; LLDB_COMPRESSION_LDFLAGS = ""; "LLDB_COMPRESSION_LDFLAGS[sdk=macosx10.11]" = "-weak-lcompression"; + LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)"; + LLDB_USE_OS_LOG = 0; LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1"; LLDB_ZLIB_LDFLAGS = "-lz"; + MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ""; STRIPFLAGS = "-x"; @@ -688,8 +792,11 @@ "LLDB_COMPRESSION_CFLAGS[sdk=macosx10.11]" = "-DHAVE_LIBCOMPRESSION=1"; LLDB_COMPRESSION_LDFLAGS = ""; "LLDB_COMPRESSION_LDFLAGS[sdk=macosx10.11]" = "-weak-lcompression"; + LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)"; + LLDB_USE_OS_LOG = 1; LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1"; LLDB_ZLIB_LDFLAGS = "-lz"; + MACOSX_DEPLOYMENT_TARGET = 10.10; OTHER_CFLAGS = ""; STRIPFLAGS = "-x"; STRIP_STYLE = debugging; @@ -748,6 +855,7 @@ "-DDT_VARIANT_$(DT_VARIANT)", "$(LLDB_COMPRESSION_CFLAGS)", "$(LLDB_ZLIB_CFLAGS)", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CFLAGS[sdk=iphoneos*]" = ( "-Wparentheses", @@ -757,6 +865,7 @@ "-DOS_OBJECT_USE_OBJC=0", "$(LLDB_COMPRESSION_CFLAGS)", "$(LLDB_ZLIB_CFLAGS)", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; OTHER_LDFLAGS = ""; @@ -848,6 +957,7 @@ "-DDT_VARIANT_$(DT_VARIANT)", "$(LLDB_COMPRESSION_CFLAGS)", "$(LLDB_ZLIB_CFLAGS)", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = ( "-Wparentheses", @@ -857,6 +967,7 @@ "-DOS_OBJECT_USE_OBJC=0", "$(LLDB_COMPRESSION_CFLAGS)", "$(LLDB_ZLIB_CFLAGS)", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; OTHER_LDFLAGS = ""; @@ -947,6 +1058,7 @@ "-DDT_VARIANT_$(DT_VARIANT)", "$(LLDB_COMPRESSION_CFLAGS)", "$(LLDB_ZLIB_CFLAGS)", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = ( "-Wparentheses", @@ -956,6 +1068,7 @@ "-DOS_OBJECT_USE_OBJC=0", "$(LLDB_COMPRESSION_CFLAGS)", "$(LLDB_ZLIB_CFLAGS)", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; OTHER_LDFLAGS = ""; @@ -1055,6 +1168,7 @@ "-Wparentheses", "-DOS_OBJECT_USE_OBJC=0", "-DDEBUGSERVER_PROGRAM_SYMBOL=debugserver_nonui", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; OTHER_LDFLAGS = ""; @@ -1124,6 +1238,7 @@ "-Wparentheses", "-DOS_OBJECT_USE_OBJC=0", "-DDEBUGSERVER_PROGRAM_SYMBOL=debugserver_nonui", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; OTHER_LDFLAGS = ""; @@ -1189,11 +1304,13 @@ "$(LLDB_COMPRESSION_CFLAGS)", "$(LLDB_ZLIB_CFLAGS)", "-DDEBUGSERVER_PROGRAM_SYMBOL=debugserver_nonui", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = ( "-Wparentheses", "-DOS_OBJECT_USE_OBJC=0", "-DDEBUGSERVER_PROGRAM_SYMBOL=debugserver_nonui", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; OTHER_LDFLAGS = ""; @@ -1260,12 +1377,15 @@ "-Wparentheses", "$(LLDB_ENERGY_CFLAGS)", "-DDEBUGSERVER_PROGRAM_SYMBOL=debugserver_nonui", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CFLAGS[sdk=iphoneos*]" = ( "-Wparentheses", "-DOS_OBJECT_USE_OBJC=0", "-DDEBUGSERVER_PROGRAM_SYMBOL=debugserver_nonui", + "$(LLDB_OS_LOG_CFLAGS)", ); + OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( "-framework", @@ -1317,6 +1437,9 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)"; + LLDB_USE_OS_LOG = 0; + MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx.internal; "SDKROOT[arch=i386]" = macosx; @@ -1378,6 +1501,7 @@ "-DDT_VARIANT_$(DT_VARIANT)", "$(LLDB_COMPRESSION_CFLAGS)", "$(LLDB_ZLIB_CFLAGS)", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = ( "-Wparentheses", @@ -1387,6 +1511,7 @@ "-DOS_OBJECT_USE_OBJC=0", "$(LLDB_COMPRESSION_CFLAGS)", "$(LLDB_ZLIB_CFLAGS)", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( @@ -1455,6 +1580,9 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)"; + LLDB_USE_OS_LOG = 0; + MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx.internal; "SDKROOT[arch=i386]" = macosx; @@ -1515,6 +1643,7 @@ "$(LLDB_ENERGY_CFLAGS)", "$(LLDB_COMPRESSION_CFLAGS)", "$(LLDB_ZLIB_CFLAGS)", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = ( "-Wparentheses", @@ -1524,6 +1653,7 @@ "-DOS_OBJECT_USE_OBJC=0", "$(LLDB_COMPRESSION_CFLAGS)", "$(LLDB_ZLIB_CFLAGS)", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( @@ -1598,11 +1728,13 @@ "-Wparentheses", "$(LLDB_ENERGY_CFLAGS)", "-DDEBUGSERVER_PROGRAM_SYMBOL=debugserver_nonui", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = ( "-Wparentheses", "-DOS_OBJECT_USE_OBJC=0", "-DDEBUGSERVER_PROGRAM_SYMBOL=debugserver_nonui", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( @@ -1672,6 +1804,9 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)"; + LLDB_USE_OS_LOG = 0; + MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx.internal; "SDKROOT[arch=i386]" = macosx; @@ -1723,6 +1858,7 @@ "-DDT_VARIANT_$(DT_VARIANT)", "$(LLDB_COMPRESSION_CFLAGS)", "$(LLDB_ZLIB_CFLAGS)", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = ( "-Wparentheses", @@ -1732,6 +1868,7 @@ "-DOS_OBJECT_USE_OBJC=0", "$(LLDB_COMPRESSION_CFLAGS)", "$(LLDB_ZLIB_CFLAGS)", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; OTHER_LDFLAGS = ""; @@ -1800,6 +1937,9 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)"; + LLDB_USE_OS_LOG = 0; + MACOSX_DEPLOYMENT_TARGET = 10.10; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx.internal; "SDKROOT[arch=i386]" = macosx; @@ -1852,6 +1992,7 @@ "-DDT_VARIANT_$(DT_VARIANT)", "$(LLDB_COMPRESSION_CFLAGS)", "$(LLDB_ZLIB_CFLAGS)", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = ( "-Wparentheses", @@ -1861,6 +2002,7 @@ "-DOS_OBJECT_USE_OBJC=0", "$(LLDB_COMPRESSION_CFLAGS)", "$(LLDB_ZLIB_CFLAGS)", + "$(LLDB_OS_LOG_CFLAGS)", ); "OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)"; "OTHER_LDFLAGS[sdk=iphoneos*][arch=*]" = ( diff --git a/tools/debugserver/source/ARM_DWARF_Registers.h b/tools/debugserver/source/ARM_DWARF_Registers.h index 845260ba187c..037d28bf1304 100644 --- a/tools/debugserver/source/ARM_DWARF_Registers.h +++ b/tools/debugserver/source/ARM_DWARF_Registers.h @@ -10,200 +10,197 @@ #ifndef ARM_DWARF_Registers_h_ #define ARM_DWARF_Registers_h_ +enum { + dwarf_r0 = 0, + dwarf_r1, + dwarf_r2, + dwarf_r3, + dwarf_r4, + dwarf_r5, + dwarf_r6, + dwarf_r7, + dwarf_r8, + dwarf_r9, + dwarf_r10, + dwarf_r11, + dwarf_r12, + dwarf_sp, + dwarf_lr, + dwarf_pc, + dwarf_cpsr, -enum -{ - dwarf_r0 = 0, - dwarf_r1, - dwarf_r2, - dwarf_r3, - dwarf_r4, - dwarf_r5, - dwarf_r6, - dwarf_r7, - dwarf_r8, - dwarf_r9, - dwarf_r10, - dwarf_r11, - dwarf_r12, - dwarf_sp, - dwarf_lr, - dwarf_pc, - dwarf_cpsr, + dwarf_s0 = 64, + dwarf_s1, + dwarf_s2, + dwarf_s3, + dwarf_s4, + dwarf_s5, + dwarf_s6, + dwarf_s7, + dwarf_s8, + dwarf_s9, + dwarf_s10, + dwarf_s11, + dwarf_s12, + dwarf_s13, + dwarf_s14, + dwarf_s15, + dwarf_s16, + dwarf_s17, + dwarf_s18, + dwarf_s19, + dwarf_s20, + dwarf_s21, + dwarf_s22, + dwarf_s23, + dwarf_s24, + dwarf_s25, + dwarf_s26, + dwarf_s27, + dwarf_s28, + dwarf_s29, + dwarf_s30, + dwarf_s31, - dwarf_s0 = 64, - dwarf_s1, - dwarf_s2, - dwarf_s3, - dwarf_s4, - dwarf_s5, - dwarf_s6, - dwarf_s7, - dwarf_s8, - dwarf_s9, - dwarf_s10, - dwarf_s11, - dwarf_s12, - dwarf_s13, - dwarf_s14, - dwarf_s15, - dwarf_s16, - dwarf_s17, - dwarf_s18, - dwarf_s19, - dwarf_s20, - dwarf_s21, - dwarf_s22, - dwarf_s23, - dwarf_s24, - dwarf_s25, - dwarf_s26, - dwarf_s27, - dwarf_s28, - dwarf_s29, - dwarf_s30, - dwarf_s31, + // FPA Registers 0-7 + dwarf_f0 = 96, + dwarf_f1, + dwarf_f2, + dwarf_f3, + dwarf_f4, + dwarf_f5, + dwarf_f6, + dwarf_f7, - // FPA Registers 0-7 - dwarf_f0 = 96, - dwarf_f1, - dwarf_f2, - dwarf_f3, - dwarf_f4, - dwarf_f5, - dwarf_f6, - dwarf_f7, + // Intel wireless MMX general purpose registers 0 - 7 + dwarf_wCGR0 = 104, + dwarf_wCGR1, + dwarf_wCGR2, + dwarf_wCGR3, + dwarf_wCGR4, + dwarf_wCGR5, + dwarf_wCGR6, + dwarf_wCGR7, - // Intel wireless MMX general purpose registers 0 - 7 - dwarf_wCGR0 = 104, - dwarf_wCGR1, - dwarf_wCGR2, - dwarf_wCGR3, - dwarf_wCGR4, - dwarf_wCGR5, - dwarf_wCGR6, - dwarf_wCGR7, + // XScale accumulator register 0–7 (they do overlap with wCGR0 - wCGR7) + dwarf_ACC0 = 104, + dwarf_ACC1, + dwarf_ACC2, + dwarf_ACC3, + dwarf_ACC4, + dwarf_ACC5, + dwarf_ACC6, + dwarf_ACC7, - // XScale accumulator register 0–7 (they do overlap with wCGR0 - wCGR7) - dwarf_ACC0 = 104, - dwarf_ACC1, - dwarf_ACC2, - dwarf_ACC3, - dwarf_ACC4, - dwarf_ACC5, - dwarf_ACC6, - dwarf_ACC7, + // Intel wireless MMX data registers 0 - 15 + dwarf_wR0 = 112, + dwarf_wR1, + dwarf_wR2, + dwarf_wR3, + dwarf_wR4, + dwarf_wR5, + dwarf_wR6, + dwarf_wR7, + dwarf_wR8, + dwarf_wR9, + dwarf_wR10, + dwarf_wR11, + dwarf_wR12, + dwarf_wR13, + dwarf_wR14, + dwarf_wR15, - // Intel wireless MMX data registers 0 - 15 - dwarf_wR0 = 112, - dwarf_wR1, - dwarf_wR2, - dwarf_wR3, - dwarf_wR4, - dwarf_wR5, - dwarf_wR6, - dwarf_wR7, - dwarf_wR8, - dwarf_wR9, - dwarf_wR10, - dwarf_wR11, - dwarf_wR12, - dwarf_wR13, - dwarf_wR14, - dwarf_wR15, + dwarf_spsr = 128, + dwarf_spsr_fiq, + dwarf_spsr_irq, + dwarf_spsr_abt, + dwarf_spsr_und, + dwarf_spsr_svc, - dwarf_spsr = 128, - dwarf_spsr_fiq, - dwarf_spsr_irq, - dwarf_spsr_abt, - dwarf_spsr_und, - dwarf_spsr_svc, + dwarf_r8_usr = 144, + dwarf_r9_usr, + dwarf_r10_usr, + dwarf_r11_usr, + dwarf_r12_usr, + dwarf_r13_usr, + dwarf_r14_usr, + dwarf_r8_fiq, + dwarf_r9_fiq, + dwarf_r10_fiq, + dwarf_r11_fiq, + dwarf_r12_fiq, + dwarf_r13_fiq, + dwarf_r14_fiq, + dwarf_r13_irq, + dwarf_r14_irq, + dwarf_r13_abt, + dwarf_r14_abt, + dwarf_r13_und, + dwarf_r14_und, + dwarf_r13_svc, + dwarf_r14_svc, - dwarf_r8_usr = 144, - dwarf_r9_usr, - dwarf_r10_usr, - dwarf_r11_usr, - dwarf_r12_usr, - dwarf_r13_usr, - dwarf_r14_usr, - dwarf_r8_fiq, - dwarf_r9_fiq, - dwarf_r10_fiq, - dwarf_r11_fiq, - dwarf_r12_fiq, - dwarf_r13_fiq, - dwarf_r14_fiq, - dwarf_r13_irq, - dwarf_r14_irq, - dwarf_r13_abt, - dwarf_r14_abt, - dwarf_r13_und, - dwarf_r14_und, - dwarf_r13_svc, - dwarf_r14_svc, + // Intel wireless MMX control register in co-processor 0 - 7 + dwarf_wC0 = 192, + dwarf_wC1, + dwarf_wC2, + dwarf_wC3, + dwarf_wC4, + dwarf_wC5, + dwarf_wC6, + dwarf_wC7, - // Intel wireless MMX control register in co-processor 0 - 7 - dwarf_wC0 = 192, - dwarf_wC1, - dwarf_wC2, - dwarf_wC3, - dwarf_wC4, - dwarf_wC5, - dwarf_wC6, - dwarf_wC7, + // VFP-v3/Neon + dwarf_d0 = 256, + dwarf_d1, + dwarf_d2, + dwarf_d3, + dwarf_d4, + dwarf_d5, + dwarf_d6, + dwarf_d7, + dwarf_d8, + dwarf_d9, + dwarf_d10, + dwarf_d11, + dwarf_d12, + dwarf_d13, + dwarf_d14, + dwarf_d15, + dwarf_d16, + dwarf_d17, + dwarf_d18, + dwarf_d19, + dwarf_d20, + dwarf_d21, + dwarf_d22, + dwarf_d23, + dwarf_d24, + dwarf_d25, + dwarf_d26, + dwarf_d27, + dwarf_d28, + dwarf_d29, + dwarf_d30, + dwarf_d31, - // VFP-v3/Neon - dwarf_d0 = 256, - dwarf_d1, - dwarf_d2, - dwarf_d3, - dwarf_d4, - dwarf_d5, - dwarf_d6, - dwarf_d7, - dwarf_d8, - dwarf_d9, - dwarf_d10, - dwarf_d11, - dwarf_d12, - dwarf_d13, - dwarf_d14, - dwarf_d15, - dwarf_d16, - dwarf_d17, - dwarf_d18, - dwarf_d19, - dwarf_d20, - dwarf_d21, - dwarf_d22, - dwarf_d23, - dwarf_d24, - dwarf_d25, - dwarf_d26, - dwarf_d27, - dwarf_d28, - dwarf_d29, - dwarf_d30, - dwarf_d31, - - // Neon quadword registers - dwarf_q0 = 288, - dwarf_q1, - dwarf_q2, - dwarf_q3, - dwarf_q4, - dwarf_q5, - dwarf_q6, - dwarf_q7, - dwarf_q8, - dwarf_q9, - dwarf_q10, - dwarf_q11, - dwarf_q12, - dwarf_q13, - dwarf_q14, - dwarf_q15 + // Neon quadword registers + dwarf_q0 = 288, + dwarf_q1, + dwarf_q2, + dwarf_q3, + dwarf_q4, + dwarf_q5, + dwarf_q6, + dwarf_q7, + dwarf_q8, + dwarf_q9, + dwarf_q10, + dwarf_q11, + dwarf_q12, + dwarf_q13, + dwarf_q14, + dwarf_q15 }; #endif // ARM_DWARF_Registers_h_ - diff --git a/tools/debugserver/source/ARM_ehframe_Registers.h b/tools/debugserver/source/ARM_ehframe_Registers.h index f6d93b3cee02..9d644b7dc50b 100644 --- a/tools/debugserver/source/ARM_ehframe_Registers.h +++ b/tools/debugserver/source/ARM_ehframe_Registers.h @@ -1,4 +1,5 @@ -//===-- ARM_ehframe_Registers.h -------------------------------------*- C++ -*-===// +//===-- ARM_ehframe_Registers.h -------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -10,26 +11,24 @@ #ifndef utility_ARM_ehframe_Registers_h_ #define utility_ARM_ehframe_Registers_h_ -enum -{ - ehframe_r0 = 0, - ehframe_r1, - ehframe_r2, - ehframe_r3, - ehframe_r4, - ehframe_r5, - ehframe_r6, - ehframe_r7, - ehframe_r8, - ehframe_r9, - ehframe_r10, - ehframe_r11, - ehframe_r12, - ehframe_sp, - ehframe_lr, - ehframe_pc, - ehframe_cpsr +enum { + ehframe_r0 = 0, + ehframe_r1, + ehframe_r2, + ehframe_r3, + ehframe_r4, + ehframe_r5, + ehframe_r6, + ehframe_r7, + ehframe_r8, + ehframe_r9, + ehframe_r10, + ehframe_r11, + ehframe_r12, + ehframe_sp, + ehframe_lr, + ehframe_pc, + ehframe_cpsr }; #endif // utility_ARM_ehframe_Registers_h_ - diff --git a/tools/debugserver/source/CMakeLists.txt b/tools/debugserver/source/CMakeLists.txt index 94cef6c31203..43479bd36435 100644 --- a/tools/debugserver/source/CMakeLists.txt +++ b/tools/debugserver/source/CMakeLists.txt @@ -1,5 +1,6 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}/..) include_directories(${LLDB_SOURCE_DIR}/source) +include_directories(MacOSX/DarwinLog) if (CMAKE_SYSTEM_NAME MATCHES "Darwin") include_directories(MacOSX) @@ -42,6 +43,11 @@ add_library(lldbDebugserverCommon DNBLog.cpp DNBRegisterInfo.cpp DNBThreadResumeActions.cpp + JSON.cpp + StdStringExtractor.cpp + # JSON reader depends on the following LLDB-common files + ${LLDB_SOURCE_DIR}/source/Host/common/StringConvert.cpp + # end JSON reader dependencies libdebugserver.cpp PseudoTerminal.cpp PThreadEvent.cpp diff --git a/tools/debugserver/source/DNB.cpp b/tools/debugserver/source/DNB.cpp index bb3603649199..9c6c44d18df1 100644 --- a/tools/debugserver/source/DNB.cpp +++ b/tools/debugserver/source/DNB.cpp @@ -13,20 +13,20 @@ #include "DNB.h" #include <inttypes.h> +#include <libproc.h> +#include <map> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <sys/resource.h> #include <sys/stat.h> +#include <sys/sysctl.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> -#include <sys/sysctl.h> -#include <map> #include <vector> -#include <libproc.h> -#if defined (__APPLE__) +#if defined(__APPLE__) #include <pthread.h> #include <sched.h> #endif @@ -34,32 +34,34 @@ #define TRY_KQUEUE 1 #ifdef TRY_KQUEUE - #include <sys/event.h> - #include <sys/time.h> - #ifdef NOTE_EXIT_DETAIL - #define USE_KQUEUE - #endif +#include <sys/event.h> +#include <sys/time.h> +#ifdef NOTE_EXIT_DETAIL +#define USE_KQUEUE +#endif #endif -#include "MacOSX/MachProcess.h" -#include "MacOSX/MachTask.h" -#include "MacOSX/Genealogy.h" -#include "MacOSX/ThreadInfo.h" +#include "CFBundle.h" #include "CFString.h" -#include "DNBLog.h" #include "DNBDataRef.h" +#include "DNBLog.h" #include "DNBThreadResumeActions.h" #include "DNBTimer.h" -#include "CFBundle.h" - +#include "MacOSX/DarwinLog/DarwinLogCollector.h" +#include "MacOSX/Genealogy.h" +#include "MacOSX/MachProcess.h" +#include "MacOSX/MachTask.h" +#include "MacOSX/ThreadInfo.h" typedef std::shared_ptr<MachProcess> MachProcessSP; typedef std::map<nub_process_t, MachProcessSP> ProcessMap; typedef ProcessMap::iterator ProcessMapIter; typedef ProcessMap::const_iterator ProcessMapConstIter; -size_t GetAllInfos (std::vector<struct kinfo_proc>& proc_infos); -static size_t GetAllInfosMatchingName (const char *process_name, std::vector<struct kinfo_proc>& matching_proc_infos); +size_t GetAllInfos(std::vector<struct kinfo_proc> &proc_infos); +static size_t +GetAllInfosMatchingName(const char *process_name, + std::vector<struct kinfo_proc> &matching_proc_infos); //---------------------------------------------------------------------- // A Thread safe singleton to get a process map pointer. @@ -67,19 +69,16 @@ static size_t GetAllInfosMatchingName (const char *process_name, std::vector<str // Returns a pointer to the existing process map, or a pointer to a // newly created process map if CAN_CREATE is non-zero. //---------------------------------------------------------------------- -static ProcessMap* -GetProcessMap(bool can_create) -{ - static ProcessMap* g_process_map_ptr = NULL; - - if (can_create && g_process_map_ptr == NULL) - { - static pthread_mutex_t g_process_map_mutex = PTHREAD_MUTEX_INITIALIZER; - PTHREAD_MUTEX_LOCKER (locker, &g_process_map_mutex); - if (g_process_map_ptr == NULL) - g_process_map_ptr = new ProcessMap; - } - return g_process_map_ptr; +static ProcessMap *GetProcessMap(bool can_create) { + static ProcessMap *g_process_map_ptr = NULL; + + if (can_create && g_process_map_ptr == NULL) { + static pthread_mutex_t g_process_map_mutex = PTHREAD_MUTEX_INITIALIZER; + PTHREAD_MUTEX_LOCKER(locker, &g_process_map_mutex); + if (g_process_map_ptr == NULL) + g_process_map_ptr = new ProcessMap; + } + return g_process_map_ptr; } //---------------------------------------------------------------------- @@ -89,16 +88,13 @@ GetProcessMap(bool can_create) // The only time this should fail is if we run out of memory and can't // allocate a ProcessMap. //---------------------------------------------------------------------- -static nub_bool_t -AddProcessToMap (nub_process_t pid, MachProcessSP& procSP) -{ - ProcessMap* process_map = GetProcessMap(true); - if (process_map) - { - process_map->insert(std::make_pair(pid, procSP)); - return true; - } - return false; +static nub_bool_t AddProcessToMap(nub_process_t pid, MachProcessSP &procSP) { + ProcessMap *process_map = GetProcessMap(true); + if (process_map) { + process_map->insert(std::make_pair(pid, procSP)); + return true; + } + return false; } //---------------------------------------------------------------------- @@ -106,8 +102,8 @@ AddProcessToMap (nub_process_t pid, MachProcessSP& procSP) // // Returns the number of items removed from the process map. //---------------------------------------------------------------------- -//static size_t -//RemoveProcessFromMap (nub_process_t pid) +// static size_t +// RemoveProcessFromMap (nub_process_t pid) //{ // ProcessMap* process_map = GetProcessMap(false); // if (process_map) @@ -123,1079 +119,958 @@ AddProcessToMap (nub_process_t pid, MachProcessSP& procSP) // Returns true if we successfully find a shared pointer to a // MachProcess object. //---------------------------------------------------------------------- -static nub_bool_t -GetProcessSP (nub_process_t pid, MachProcessSP& procSP) -{ - ProcessMap* process_map = GetProcessMap(false); - if (process_map != NULL) - { - ProcessMapIter pos = process_map->find(pid); - if (pos != process_map->end()) - { - procSP = pos->second; - return true; - } +static nub_bool_t GetProcessSP(nub_process_t pid, MachProcessSP &procSP) { + ProcessMap *process_map = GetProcessMap(false); + if (process_map != NULL) { + ProcessMapIter pos = process_map->find(pid); + if (pos != process_map->end()) { + procSP = pos->second; + return true; } - procSP.reset(); - return false; + } + procSP.reset(); + return false; } #ifdef USE_KQUEUE -void * -kqueue_thread (void *arg) -{ - int kq_id = (int) (intptr_t) arg; - -#if defined (__APPLE__) - pthread_setname_np ("kqueue thread"); -#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) - struct sched_param thread_param; - int thread_sched_policy; - if (pthread_getschedparam(pthread_self(), &thread_sched_policy, &thread_param) == 0) - { - thread_param.sched_priority = 47; - pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param); - } +void *kqueue_thread(void *arg) { + int kq_id = (int)(intptr_t)arg; + +#if defined(__APPLE__) + pthread_setname_np("kqueue thread"); +#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) + struct sched_param thread_param; + int thread_sched_policy; + if (pthread_getschedparam(pthread_self(), &thread_sched_policy, + &thread_param) == 0) { + thread_param.sched_priority = 47; + pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param); + } #endif #endif - struct kevent death_event; - while (1) - { - int n_events = kevent (kq_id, NULL, 0, &death_event, 1, NULL); - if (n_events == -1) - { - if (errno == EINTR) - continue; - else - { - DNBLogError ("kqueue failed with error: (%d): %s", errno, strerror(errno)); - return NULL; - } - } - else if (death_event.flags & EV_ERROR) - { - int error_no = static_cast<int>(death_event.data); - const char *error_str = strerror(error_no); - if (error_str == NULL) - error_str = "Unknown error"; - DNBLogError ("Failed to initialize kqueue event: (%d): %s", error_no, error_str ); - return NULL; + struct kevent death_event; + while (1) { + int n_events = kevent(kq_id, NULL, 0, &death_event, 1, NULL); + if (n_events == -1) { + if (errno == EINTR) + continue; + else { + DNBLogError("kqueue failed with error: (%d): %s", errno, + strerror(errno)); + return NULL; + } + } else if (death_event.flags & EV_ERROR) { + int error_no = static_cast<int>(death_event.data); + const char *error_str = strerror(error_no); + if (error_str == NULL) + error_str = "Unknown error"; + DNBLogError("Failed to initialize kqueue event: (%d): %s", error_no, + error_str); + return NULL; + } else { + int status; + const pid_t pid = (pid_t)death_event.ident; + const pid_t child_pid = waitpid(pid, &status, 0); + + bool exited = false; + int signal = 0; + int exit_status = 0; + if (WIFSTOPPED(status)) { + signal = WSTOPSIG(status); + DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> STOPPED (signal = %i)", + child_pid, signal); + } else if (WIFEXITED(status)) { + exit_status = WEXITSTATUS(status); + exited = true; + DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> EXITED (status = %i)", + child_pid, exit_status); + } else if (WIFSIGNALED(status)) { + signal = WTERMSIG(status); + if (child_pid == abs(pid)) { + DNBLogThreadedIf(LOG_PROCESS, + "waitpid (%i) -> SIGNALED and EXITED (signal = %i)", + child_pid, signal); + char exit_info[64]; + ::snprintf(exit_info, sizeof(exit_info), + "Terminated due to signal %i", signal); + DNBProcessSetExitInfo(child_pid, exit_info); + exited = true; + exit_status = INT8_MAX; + } else { + DNBLogThreadedIf(LOG_PROCESS, + "waitpid (%i) -> SIGNALED (signal = %i)", child_pid, + signal); } - else - { - int status; - const pid_t pid = (pid_t)death_event.ident; - const pid_t child_pid = waitpid (pid, &status, 0); - - - bool exited = false; - int signal = 0; - int exit_status = 0; - if (WIFSTOPPED(status)) - { - signal = WSTOPSIG(status); - DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> STOPPED (signal = %i)", child_pid, signal); - } - else if (WIFEXITED(status)) - { - exit_status = WEXITSTATUS(status); - exited = true; - DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> EXITED (status = %i)", child_pid, exit_status); - } - else if (WIFSIGNALED(status)) - { - signal = WTERMSIG(status); - if (child_pid == abs(pid)) - { - DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> SIGNALED and EXITED (signal = %i)", child_pid, signal); - char exit_info[64]; - ::snprintf (exit_info, sizeof(exit_info), "Terminated due to signal %i", signal); - DNBProcessSetExitInfo (child_pid, exit_info); - exited = true; - exit_status = INT8_MAX; - } - else - { - DNBLogThreadedIf(LOG_PROCESS, "waitpid (%i) -> SIGNALED (signal = %i)", child_pid, signal); - } - } - - if (exited) - { - if (death_event.data & NOTE_EXIT_MEMORY) - DNBProcessSetExitInfo (child_pid, "Terminated due to memory issue"); - else if (death_event.data & NOTE_EXIT_DECRYPTFAIL) - DNBProcessSetExitInfo (child_pid, "Terminated due to decrypt failure"); - else if (death_event.data & NOTE_EXIT_CSERROR) - DNBProcessSetExitInfo (child_pid, "Terminated due to code signing error"); - - DNBLogThreadedIf(LOG_PROCESS, "waitpid_process_thread (): setting exit status for pid = %i to %i", child_pid, exit_status); - DNBProcessSetExitStatus (child_pid, status); - return NULL; - } - } - } -} + } + + if (exited) { + if (death_event.data & NOTE_EXIT_MEMORY) + DNBProcessSetExitInfo(child_pid, "Terminated due to memory issue"); + else if (death_event.data & NOTE_EXIT_DECRYPTFAIL) + DNBProcessSetExitInfo(child_pid, "Terminated due to decrypt failure"); + else if (death_event.data & NOTE_EXIT_CSERROR) + DNBProcessSetExitInfo(child_pid, + "Terminated due to code signing error"); + + DNBLogThreadedIf( + LOG_PROCESS, + "waitpid_process_thread (): setting exit status for pid = %i to %i", + child_pid, exit_status); + DNBProcessSetExitStatus(child_pid, status); + return NULL; + } + } + } +} + +static bool spawn_kqueue_thread(pid_t pid) { + pthread_t thread; + int kq_id; + + kq_id = kqueue(); + if (kq_id == -1) { + DNBLogError("Could not get kqueue for pid = %i.", pid); + return false; + } + + struct kevent reg_event; + + EV_SET(®_event, pid, EVFILT_PROC, EV_ADD, + NOTE_EXIT | NOTE_EXITSTATUS | NOTE_EXIT_DETAIL, 0, NULL); + // Register the event: + int result = kevent(kq_id, ®_event, 1, NULL, 0, NULL); + if (result != 0) { + DNBLogError( + "Failed to register kqueue NOTE_EXIT event for pid %i, error: %d.", pid, + result); + return false; + } -static bool -spawn_kqueue_thread (pid_t pid) -{ - pthread_t thread; - int kq_id; - - kq_id = kqueue(); - if (kq_id == -1) - { - DNBLogError ("Could not get kqueue for pid = %i.", pid); - return false; - } + int ret = + ::pthread_create(&thread, NULL, kqueue_thread, (void *)(intptr_t)kq_id); - struct kevent reg_event; - - EV_SET(®_event, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT|NOTE_EXITSTATUS|NOTE_EXIT_DETAIL, 0, NULL); - // Register the event: - int result = kevent (kq_id, ®_event, 1, NULL, 0, NULL); - if (result != 0) - { - DNBLogError ("Failed to register kqueue NOTE_EXIT event for pid %i, error: %d.", pid, result); - return false; - } - - int ret = ::pthread_create (&thread, NULL, kqueue_thread, (void *)(intptr_t)kq_id); - - // pthread_create returns 0 if successful - if (ret == 0) - { - ::pthread_detach (thread); - return true; - } - return false; + // pthread_create returns 0 if successful + if (ret == 0) { + ::pthread_detach(thread); + return true; + } + return false; } #endif // #if USE_KQUEUE -static void * -waitpid_thread (void *arg) -{ - const pid_t pid = (pid_t)(intptr_t)arg; - int status; - -#if defined (__APPLE__) - pthread_setname_np ("waitpid thread"); -#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) - struct sched_param thread_param; - int thread_sched_policy; - if (pthread_getschedparam(pthread_self(), &thread_sched_policy, &thread_param) == 0) - { - thread_param.sched_priority = 47; - pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param); - } +static void *waitpid_thread(void *arg) { + const pid_t pid = (pid_t)(intptr_t)arg; + int status; + +#if defined(__APPLE__) + pthread_setname_np("waitpid thread"); +#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) + struct sched_param thread_param; + int thread_sched_policy; + if (pthread_getschedparam(pthread_self(), &thread_sched_policy, + &thread_param) == 0) { + thread_param.sched_priority = 47; + pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param); + } #endif #endif - while (1) - { - pid_t child_pid = waitpid(pid, &status, 0); - DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): waitpid (pid = %i, &status, 0) => %i, status = %i, errno = %i", pid, child_pid, status, errno); - - if (child_pid < 0) - { - if (errno == EINTR) - continue; - break; - } - else - { - if (WIFSTOPPED(status)) - { - continue; - } - else// if (WIFEXITED(status) || WIFSIGNALED(status)) - { - DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): setting exit status for pid = %i to %i", child_pid, status); - DNBProcessSetExitStatus (child_pid, status); - return NULL; - } - } - } - - // We should never exit as long as our child process is alive, so if we - // do something else went wrong and we should exit... - DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): main loop exited, setting exit status to an invalid value (-1) for pid %i", pid); - DNBProcessSetExitStatus (pid, -1); - return NULL; -} -static bool -spawn_waitpid_thread (pid_t pid) -{ + while (1) { + pid_t child_pid = waitpid(pid, &status, 0); + DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): waitpid (pid = %i, " + "&status, 0) => %i, status = %i, errno = %i", + pid, child_pid, status, errno); + + if (child_pid < 0) { + if (errno == EINTR) + continue; + break; + } else { + if (WIFSTOPPED(status)) { + continue; + } else // if (WIFEXITED(status) || WIFSIGNALED(status)) + { + DNBLogThreadedIf( + LOG_PROCESS, + "waitpid_thread (): setting exit status for pid = %i to %i", + child_pid, status); + DNBProcessSetExitStatus(child_pid, status); + return NULL; + } + } + } + + // We should never exit as long as our child process is alive, so if we + // do something else went wrong and we should exit... + DNBLogThreadedIf(LOG_PROCESS, "waitpid_thread (): main loop exited, setting " + "exit status to an invalid value (-1) for pid " + "%i", + pid); + DNBProcessSetExitStatus(pid, -1); + return NULL; +} +static bool spawn_waitpid_thread(pid_t pid) { #ifdef USE_KQUEUE - bool success = spawn_kqueue_thread (pid); - if (success) - return true; + bool success = spawn_kqueue_thread(pid); + if (success) + return true; #endif - pthread_t thread; - int ret = ::pthread_create (&thread, NULL, waitpid_thread, (void *)(intptr_t)pid); - // pthread_create returns 0 if successful - if (ret == 0) - { - ::pthread_detach (thread); - return true; - } - return false; -} - -nub_process_t -DNBProcessLaunch (const char *path, - char const *argv[], - const char *envp[], - const char *working_directory, // NULL => don't change, non-NULL => set working directory for inferior to this - const char *stdin_path, - const char *stdout_path, - const char *stderr_path, - bool no_stdio, - nub_launch_flavor_t launch_flavor, - int disable_aslr, - const char *event_data, - char *err_str, - size_t err_len) -{ - DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv = %p, envp = %p, working_dir=%s, stdin=%s, stdout=%s, " - "stderr=%s, no-stdio=%i, launch_flavor = %u, disable_aslr = %d, err = %p, err_len = " - "%llu) called...", - __FUNCTION__, path, static_cast<void *>(argv), static_cast<void *>(envp), working_directory, - stdin_path, stdout_path, stderr_path, no_stdio, launch_flavor, disable_aslr, - static_cast<void *>(err_str), static_cast<uint64_t>(err_len)); - - if (err_str && err_len > 0) - err_str[0] = '\0'; - struct stat path_stat; - if (::stat(path, &path_stat) == -1) - { - char stat_error[256]; - ::strerror_r (errno, stat_error, sizeof(stat_error)); - snprintf(err_str, err_len, "%s (%s)", stat_error, path); - return INVALID_NUB_PROCESS; - } - - MachProcessSP processSP (new MachProcess); - if (processSP.get()) - { - DNBError launch_err; - pid_t pid = processSP->LaunchForDebug (path, - argv, - envp, - working_directory, - stdin_path, - stdout_path, - stderr_path, - no_stdio, - launch_flavor, - disable_aslr, - event_data, - launch_err); - if (err_str) - { - *err_str = '\0'; - if (launch_err.Fail()) - { - const char *launch_err_str = launch_err.AsString(); - if (launch_err_str) - { - strncpy(err_str, launch_err_str, err_len-1); - err_str[err_len-1] = '\0'; // Make sure the error string is terminated - } - } + pthread_t thread; + int ret = + ::pthread_create(&thread, NULL, waitpid_thread, (void *)(intptr_t)pid); + // pthread_create returns 0 if successful + if (ret == 0) { + ::pthread_detach(thread); + return true; + } + return false; +} + +nub_process_t DNBProcessLaunch( + const char *path, char const *argv[], const char *envp[], + const char *working_directory, // NULL => don't change, non-NULL => set + // working directory for inferior to this + const char *stdin_path, const char *stdout_path, const char *stderr_path, + bool no_stdio, nub_launch_flavor_t launch_flavor, int disable_aslr, + const char *event_data, char *err_str, size_t err_len) { + DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv = %p, envp = %p, " + "working_dir=%s, stdin=%s, stdout=%s, " + "stderr=%s, no-stdio=%i, launch_flavor = %u, " + "disable_aslr = %d, err = %p, err_len = " + "%llu) called...", + __FUNCTION__, path, static_cast<void *>(argv), + static_cast<void *>(envp), working_directory, stdin_path, + stdout_path, stderr_path, no_stdio, launch_flavor, + disable_aslr, static_cast<void *>(err_str), + static_cast<uint64_t>(err_len)); + + if (err_str && err_len > 0) + err_str[0] = '\0'; + struct stat path_stat; + if (::stat(path, &path_stat) == -1) { + char stat_error[256]; + ::strerror_r(errno, stat_error, sizeof(stat_error)); + snprintf(err_str, err_len, "%s (%s)", stat_error, path); + return INVALID_NUB_PROCESS; + } + + MachProcessSP processSP(new MachProcess); + if (processSP.get()) { + DNBError launch_err; + pid_t pid = processSP->LaunchForDebug(path, argv, envp, working_directory, + stdin_path, stdout_path, stderr_path, + no_stdio, launch_flavor, disable_aslr, + event_data, launch_err); + if (err_str) { + *err_str = '\0'; + if (launch_err.Fail()) { + const char *launch_err_str = launch_err.AsString(); + if (launch_err_str) { + strncpy(err_str, launch_err_str, err_len - 1); + err_str[err_len - 1] = + '\0'; // Make sure the error string is terminated } - - DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) new pid is %d...", pid); - - if (pid != INVALID_NUB_PROCESS) - { - // Spawn a thread to reap our child inferior process... - spawn_waitpid_thread (pid); - - if (processSP->Task().TaskPortForProcessID (launch_err) == TASK_NULL) - { - // We failed to get the task for our process ID which is bad. - // Kill our process otherwise it will be stopped at the entry - // point and get reparented to someone else and never go away. - DNBLog ("Could not get task port for process, sending SIGKILL and exiting."); - kill (SIGKILL, pid); - - if (err_str && err_len > 0) - { - if (launch_err.AsString()) - { - ::snprintf (err_str, err_len, "failed to get the task for process %i (%s)", pid, launch_err.AsString()); - } - else - { - ::snprintf (err_str, err_len, "failed to get the task for process %i", pid); - } - } - } - else - { - bool res = AddProcessToMap(pid, processSP); - UNUSED_IF_ASSERT_DISABLED(res); - assert(res && "Couldn't add process to map!"); - return pid; - } + } + } + + DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) new pid is %d...", pid); + + if (pid != INVALID_NUB_PROCESS) { + // Spawn a thread to reap our child inferior process... + spawn_waitpid_thread(pid); + + if (processSP->Task().TaskPortForProcessID(launch_err) == TASK_NULL) { + // We failed to get the task for our process ID which is bad. + // Kill our process otherwise it will be stopped at the entry + // point and get reparented to someone else and never go away. + DNBLog("Could not get task port for process, sending SIGKILL and " + "exiting."); + kill(SIGKILL, pid); + + if (err_str && err_len > 0) { + if (launch_err.AsString()) { + ::snprintf(err_str, err_len, + "failed to get the task for process %i (%s)", pid, + launch_err.AsString()); + } else { + ::snprintf(err_str, err_len, + "failed to get the task for process %i", pid); + } } + } else { + bool res = AddProcessToMap(pid, processSP); + UNUSED_IF_ASSERT_DISABLED(res); + assert(res && "Couldn't add process to map!"); + return pid; + } } - return INVALID_NUB_PROCESS; + } + return INVALID_NUB_PROCESS; } // If there is one process with a given name, return the pid for that process. -nub_process_t -DNBProcessGetPIDByName (const char *name) -{ - std::vector<struct kinfo_proc> matching_proc_infos; - size_t num_matching_proc_infos = GetAllInfosMatchingName(name, matching_proc_infos); - if (num_matching_proc_infos == 1) - { - return matching_proc_infos[0].kp_proc.p_pid; - } +nub_process_t DNBProcessGetPIDByName(const char *name) { + std::vector<struct kinfo_proc> matching_proc_infos; + size_t num_matching_proc_infos = + GetAllInfosMatchingName(name, matching_proc_infos); + if (num_matching_proc_infos == 1) { + return matching_proc_infos[0].kp_proc.p_pid; + } + return INVALID_NUB_PROCESS; +} + +nub_process_t DNBProcessAttachByName(const char *name, struct timespec *timeout, + char *err_str, size_t err_len) { + if (err_str && err_len > 0) + err_str[0] = '\0'; + std::vector<struct kinfo_proc> matching_proc_infos; + size_t num_matching_proc_infos = + GetAllInfosMatchingName(name, matching_proc_infos); + if (num_matching_proc_infos == 0) { + DNBLogError("error: no processes match '%s'\n", name); return INVALID_NUB_PROCESS; -} - -nub_process_t -DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_str, size_t err_len) -{ - if (err_str && err_len > 0) - err_str[0] = '\0'; - std::vector<struct kinfo_proc> matching_proc_infos; - size_t num_matching_proc_infos = GetAllInfosMatchingName(name, matching_proc_infos); - if (num_matching_proc_infos == 0) - { - DNBLogError ("error: no processes match '%s'\n", name); - return INVALID_NUB_PROCESS; - } - else if (num_matching_proc_infos > 1) - { - DNBLogError ("error: %llu processes match '%s':\n", (uint64_t)num_matching_proc_infos, name); - size_t i; - for (i=0; i<num_matching_proc_infos; ++i) - DNBLogError ("%6u - %s\n", matching_proc_infos[i].kp_proc.p_pid, matching_proc_infos[i].kp_proc.p_comm); - return INVALID_NUB_PROCESS; - } - - return DNBProcessAttach (matching_proc_infos[0].kp_proc.p_pid, timeout, err_str, err_len); -} - -nub_process_t -DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_str, size_t err_len) -{ - if (err_str && err_len > 0) - err_str[0] = '\0'; - - pid_t pid = INVALID_NUB_PROCESS; - MachProcessSP processSP(new MachProcess); - if (processSP.get()) - { - DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) attaching to pid %d...", attach_pid); - pid = processSP->AttachForDebug (attach_pid, err_str, err_len); - - if (pid != INVALID_NUB_PROCESS) - { - bool res = AddProcessToMap(pid, processSP); - UNUSED_IF_ASSERT_DISABLED(res); - assert(res && "Couldn't add process to map!"); - spawn_waitpid_thread(pid); - } - } - - while (pid != INVALID_NUB_PROCESS) - { - // Wait for process to start up and hit entry point - DNBLogThreadedIf (LOG_PROCESS, - "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE)...", - __FUNCTION__, - pid); - nub_event_t set_events = DNBProcessWaitForEvents (pid, - eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, - true, - timeout); - - DNBLogThreadedIf (LOG_PROCESS, - "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE) => 0x%8.8x", - __FUNCTION__, - pid, - set_events); - - if (set_events == 0) - { - if (err_str && err_len > 0) - snprintf(err_str, err_len, "operation timed out"); - pid = INVALID_NUB_PROCESS; + } else if (num_matching_proc_infos > 1) { + DNBLogError("error: %llu processes match '%s':\n", + (uint64_t)num_matching_proc_infos, name); + size_t i; + for (i = 0; i < num_matching_proc_infos; ++i) + DNBLogError("%6u - %s\n", matching_proc_infos[i].kp_proc.p_pid, + matching_proc_infos[i].kp_proc.p_comm); + return INVALID_NUB_PROCESS; + } + + return DNBProcessAttach(matching_proc_infos[0].kp_proc.p_pid, timeout, + err_str, err_len); +} + +nub_process_t DNBProcessAttach(nub_process_t attach_pid, + struct timespec *timeout, char *err_str, + size_t err_len) { + if (err_str && err_len > 0) + err_str[0] = '\0'; + + pid_t pid = INVALID_NUB_PROCESS; + MachProcessSP processSP(new MachProcess); + if (processSP.get()) { + DNBLogThreadedIf(LOG_PROCESS, "(DebugNub) attaching to pid %d...", + attach_pid); + pid = processSP->AttachForDebug(attach_pid, err_str, err_len); + + if (pid != INVALID_NUB_PROCESS) { + bool res = AddProcessToMap(pid, processSP); + UNUSED_IF_ASSERT_DISABLED(res); + assert(res && "Couldn't add process to map!"); + spawn_waitpid_thread(pid); + } + } + + while (pid != INVALID_NUB_PROCESS) { + // Wait for process to start up and hit entry point + DNBLogThreadedIf(LOG_PROCESS, "%s DNBProcessWaitForEvent (%4.4x, " + "eEventProcessRunningStateChanged | " + "eEventProcessStoppedStateChanged, true, " + "INFINITE)...", + __FUNCTION__, pid); + nub_event_t set_events = + DNBProcessWaitForEvents(pid, eEventProcessRunningStateChanged | + eEventProcessStoppedStateChanged, + true, timeout); + + DNBLogThreadedIf(LOG_PROCESS, "%s DNBProcessWaitForEvent (%4.4x, " + "eEventProcessRunningStateChanged | " + "eEventProcessStoppedStateChanged, true, " + "INFINITE) => 0x%8.8x", + __FUNCTION__, pid, set_events); + + if (set_events == 0) { + if (err_str && err_len > 0) + snprintf(err_str, err_len, "operation timed out"); + pid = INVALID_NUB_PROCESS; + } else { + if (set_events & (eEventProcessRunningStateChanged | + eEventProcessStoppedStateChanged)) { + nub_state_t pid_state = DNBProcessGetState(pid); + DNBLogThreadedIf( + LOG_PROCESS, + "%s process %4.4x state changed (eEventProcessStateChanged): %s", + __FUNCTION__, pid, DNBStateAsString(pid_state)); + + switch (pid_state) { + case eStateInvalid: + case eStateUnloaded: + case eStateAttaching: + case eStateLaunching: + case eStateSuspended: + break; // Ignore + + case eStateRunning: + case eStateStepping: + // Still waiting to stop at entry point... + break; + + case eStateStopped: + case eStateCrashed: + return pid; + + case eStateDetached: + case eStateExited: + if (err_str && err_len > 0) + snprintf(err_str, err_len, "process exited"); + return INVALID_NUB_PROCESS; } - else - { - if (set_events & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged)) - { - nub_state_t pid_state = DNBProcessGetState (pid); - DNBLogThreadedIf (LOG_PROCESS, "%s process %4.4x state changed (eEventProcessStateChanged): %s", - __FUNCTION__, pid, DNBStateAsString(pid_state)); - - switch (pid_state) - { - case eStateInvalid: - case eStateUnloaded: - case eStateAttaching: - case eStateLaunching: - case eStateSuspended: - break; // Ignore - - case eStateRunning: - case eStateStepping: - // Still waiting to stop at entry point... - break; - - case eStateStopped: - case eStateCrashed: - return pid; - - case eStateDetached: - case eStateExited: - if (err_str && err_len > 0) - snprintf(err_str, err_len, "process exited"); - return INVALID_NUB_PROCESS; - } - } + } - DNBProcessResetEvents(pid, set_events); - } + DNBProcessResetEvents(pid, set_events); } + } - return INVALID_NUB_PROCESS; + return INVALID_NUB_PROCESS; } -size_t -GetAllInfos (std::vector<struct kinfo_proc>& proc_infos) -{ - size_t size = 0; - int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; - u_int namelen = sizeof(name)/sizeof(int); - int err; +size_t GetAllInfos(std::vector<struct kinfo_proc> &proc_infos) { + size_t size = 0; + int name[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL}; + u_int namelen = sizeof(name) / sizeof(int); + int err; - // Try to find out how many processes are around so we can - // size the buffer appropriately. sysctl's man page specifically suggests - // this approach, and says it returns a bit larger size than needed to - // handle any new processes created between then and now. + // Try to find out how many processes are around so we can + // size the buffer appropriately. sysctl's man page specifically suggests + // this approach, and says it returns a bit larger size than needed to + // handle any new processes created between then and now. - err = ::sysctl (name, namelen, NULL, &size, NULL, 0); + err = ::sysctl(name, namelen, NULL, &size, NULL, 0); - if ((err < 0) && (err != ENOMEM)) - { - proc_infos.clear(); - perror("sysctl (mib, miblen, NULL, &num_processes, NULL, 0)"); - return 0; - } - - - // Increase the size of the buffer by a few processes in case more have - // been spawned - proc_infos.resize (size / sizeof(struct kinfo_proc)); - size = proc_infos.size() * sizeof(struct kinfo_proc); // Make sure we don't exceed our resize... - err = ::sysctl (name, namelen, &proc_infos[0], &size, NULL, 0); - if (err < 0) - { - proc_infos.clear(); - return 0; - } + if ((err < 0) && (err != ENOMEM)) { + proc_infos.clear(); + perror("sysctl (mib, miblen, NULL, &num_processes, NULL, 0)"); + return 0; + } + + // Increase the size of the buffer by a few processes in case more have + // been spawned + proc_infos.resize(size / sizeof(struct kinfo_proc)); + size = proc_infos.size() * + sizeof(struct kinfo_proc); // Make sure we don't exceed our resize... + err = ::sysctl(name, namelen, &proc_infos[0], &size, NULL, 0); + if (err < 0) { + proc_infos.clear(); + return 0; + } - // Trim down our array to fit what we actually got back - proc_infos.resize(size / sizeof(struct kinfo_proc)); - return proc_infos.size(); + // Trim down our array to fit what we actually got back + proc_infos.resize(size / sizeof(struct kinfo_proc)); + return proc_infos.size(); } static size_t -GetAllInfosMatchingName(const char *full_process_name, std::vector<struct kinfo_proc>& matching_proc_infos) -{ - - matching_proc_infos.clear(); - if (full_process_name && full_process_name[0]) - { - // We only get the process name, not the full path, from the proc_info. So just take the - // base name of the process name... - const char *process_name; - process_name = strrchr (full_process_name, '/'); - if (process_name == NULL) - process_name = full_process_name; - else - process_name++; - - const size_t process_name_len = strlen(process_name); - std::vector<struct kinfo_proc> proc_infos; - const size_t num_proc_infos = GetAllInfos(proc_infos); - if (num_proc_infos > 0) - { - uint32_t i; - for (i=0; i<num_proc_infos; i++) - { - // Skip zombie processes and processes with unset status - if (proc_infos[i].kp_proc.p_stat == 0 || proc_infos[i].kp_proc.p_stat == SZOMB) - continue; - - // Check for process by name. We only check the first MAXCOMLEN - // chars as that is all that kp_proc.p_comm holds. - - if (::strncasecmp(process_name, proc_infos[i].kp_proc.p_comm, MAXCOMLEN) == 0) - { - if (process_name_len > MAXCOMLEN) - { - // We found a matching process name whose first MAXCOMLEN - // characters match, but there is more to the name than - // this. We need to get the full process name. Use proc_pidpath, which will get - // us the full path to the executed process. - - char proc_path_buf[PATH_MAX]; - - int return_val = proc_pidpath (proc_infos[i].kp_proc.p_pid, proc_path_buf, PATH_MAX); - if (return_val > 0) - { - // Okay, now search backwards from that to see if there is a - // slash in the name. Note, even though we got all the args we don't care - // because the list data is just a bunch of concatenated null terminated strings - // so strrchr will start from the end of argv0. - - const char *argv_basename = strrchr(proc_path_buf, '/'); - if (argv_basename) - { - // Skip the '/' - ++argv_basename; - } - else - { - // We didn't find a directory delimiter in the process argv[0], just use what was in there - argv_basename = proc_path_buf; - } - - if (argv_basename) - { - if (::strncasecmp(process_name, argv_basename, PATH_MAX) == 0) - { - matching_proc_infos.push_back(proc_infos[i]); - } - } - } - } - else - { - // We found a matching process, add it to our list - matching_proc_infos.push_back(proc_infos[i]); - } +GetAllInfosMatchingName(const char *full_process_name, + std::vector<struct kinfo_proc> &matching_proc_infos) { + + matching_proc_infos.clear(); + if (full_process_name && full_process_name[0]) { + // We only get the process name, not the full path, from the proc_info. So + // just take the + // base name of the process name... + const char *process_name; + process_name = strrchr(full_process_name, '/'); + if (process_name == NULL) + process_name = full_process_name; + else + process_name++; + + const size_t process_name_len = strlen(process_name); + std::vector<struct kinfo_proc> proc_infos; + const size_t num_proc_infos = GetAllInfos(proc_infos); + if (num_proc_infos > 0) { + uint32_t i; + for (i = 0; i < num_proc_infos; i++) { + // Skip zombie processes and processes with unset status + if (proc_infos[i].kp_proc.p_stat == 0 || + proc_infos[i].kp_proc.p_stat == SZOMB) + continue; + + // Check for process by name. We only check the first MAXCOMLEN + // chars as that is all that kp_proc.p_comm holds. + + if (::strncasecmp(process_name, proc_infos[i].kp_proc.p_comm, + MAXCOMLEN) == 0) { + if (process_name_len > MAXCOMLEN) { + // We found a matching process name whose first MAXCOMLEN + // characters match, but there is more to the name than + // this. We need to get the full process name. Use proc_pidpath, + // which will get + // us the full path to the executed process. + + char proc_path_buf[PATH_MAX]; + + int return_val = proc_pidpath(proc_infos[i].kp_proc.p_pid, + proc_path_buf, PATH_MAX); + if (return_val > 0) { + // Okay, now search backwards from that to see if there is a + // slash in the name. Note, even though we got all the args we + // don't care + // because the list data is just a bunch of concatenated null + // terminated strings + // so strrchr will start from the end of argv0. + + const char *argv_basename = strrchr(proc_path_buf, '/'); + if (argv_basename) { + // Skip the '/' + ++argv_basename; + } else { + // We didn't find a directory delimiter in the process argv[0], + // just use what was in there + argv_basename = proc_path_buf; + } + + if (argv_basename) { + if (::strncasecmp(process_name, argv_basename, PATH_MAX) == 0) { + matching_proc_infos.push_back(proc_infos[i]); } + } } + } else { + // We found a matching process, add it to our list + matching_proc_infos.push_back(proc_infos[i]); + } } + } } - // return the newly added matches. - return matching_proc_infos.size(); -} - -nub_process_t -DNBProcessAttachWait (const char *waitfor_process_name, - nub_launch_flavor_t launch_flavor, - bool ignore_existing, - struct timespec *timeout_abstime, - useconds_t waitfor_interval, - char *err_str, - size_t err_len, - DNBShouldCancelCallback should_cancel_callback, - void *callback_data) -{ - DNBError prepare_error; - std::vector<struct kinfo_proc> exclude_proc_infos; - size_t num_exclude_proc_infos; - - // If the PrepareForAttach returns a valid token, use MachProcess to check - // for the process, otherwise scan the process table. - - const void *attach_token = MachProcess::PrepareForAttach (waitfor_process_name, launch_flavor, true, prepare_error); - - if (prepare_error.Fail()) - { - DNBLogError ("Error in PrepareForAttach: %s", prepare_error.AsString()); - return INVALID_NUB_PROCESS; - } + } + // return the newly added matches. + return matching_proc_infos.size(); +} - if (attach_token == NULL) - { - if (ignore_existing) - num_exclude_proc_infos = GetAllInfosMatchingName (waitfor_process_name, exclude_proc_infos); - else - num_exclude_proc_infos = 0; - } +nub_process_t DNBProcessAttachWait( + const char *waitfor_process_name, nub_launch_flavor_t launch_flavor, + bool ignore_existing, struct timespec *timeout_abstime, + useconds_t waitfor_interval, char *err_str, size_t err_len, + DNBShouldCancelCallback should_cancel_callback, void *callback_data) { + DNBError prepare_error; + std::vector<struct kinfo_proc> exclude_proc_infos; + size_t num_exclude_proc_infos; - DNBLogThreadedIf (LOG_PROCESS, "Waiting for '%s' to appear...\n", waitfor_process_name); - - // Loop and try to find the process by name - nub_process_t waitfor_pid = INVALID_NUB_PROCESS; - - while (waitfor_pid == INVALID_NUB_PROCESS) - { - if (attach_token != NULL) - { - nub_process_t pid; - pid = MachProcess::CheckForProcess(attach_token, launch_flavor); - if (pid != INVALID_NUB_PROCESS) - { - waitfor_pid = pid; - break; - } - } - else - { - - // Get the current process list, and check for matches that - // aren't in our original list. If anyone wants to attach - // to an existing process by name, they should do it with - // --attach=PROCNAME. Else we will wait for the first matching - // process that wasn't in our exclusion list. - std::vector<struct kinfo_proc> proc_infos; - const size_t num_proc_infos = GetAllInfosMatchingName (waitfor_process_name, proc_infos); - for (size_t i=0; i<num_proc_infos; i++) - { - nub_process_t curr_pid = proc_infos[i].kp_proc.p_pid; - for (size_t j=0; j<num_exclude_proc_infos; j++) - { - if (curr_pid == exclude_proc_infos[j].kp_proc.p_pid) - { - // This process was in our exclusion list, don't use it. - curr_pid = INVALID_NUB_PROCESS; - break; - } - } + // If the PrepareForAttach returns a valid token, use MachProcess to check + // for the process, otherwise scan the process table. - // If we didn't find CURR_PID in our exclusion list, then use it. - if (curr_pid != INVALID_NUB_PROCESS) - { - // We found our process! - waitfor_pid = curr_pid; - break; - } - } + const void *attach_token = MachProcess::PrepareForAttach( + waitfor_process_name, launch_flavor, true, prepare_error); + + if (prepare_error.Fail()) { + DNBLogError("Error in PrepareForAttach: %s", prepare_error.AsString()); + return INVALID_NUB_PROCESS; + } + + if (attach_token == NULL) { + if (ignore_existing) + num_exclude_proc_infos = + GetAllInfosMatchingName(waitfor_process_name, exclude_proc_infos); + else + num_exclude_proc_infos = 0; + } + + DNBLogThreadedIf(LOG_PROCESS, "Waiting for '%s' to appear...\n", + waitfor_process_name); + + // Loop and try to find the process by name + nub_process_t waitfor_pid = INVALID_NUB_PROCESS; + + while (waitfor_pid == INVALID_NUB_PROCESS) { + if (attach_token != NULL) { + nub_process_t pid; + pid = MachProcess::CheckForProcess(attach_token, launch_flavor); + if (pid != INVALID_NUB_PROCESS) { + waitfor_pid = pid; + break; + } + } else { + + // Get the current process list, and check for matches that + // aren't in our original list. If anyone wants to attach + // to an existing process by name, they should do it with + // --attach=PROCNAME. Else we will wait for the first matching + // process that wasn't in our exclusion list. + std::vector<struct kinfo_proc> proc_infos; + const size_t num_proc_infos = + GetAllInfosMatchingName(waitfor_process_name, proc_infos); + for (size_t i = 0; i < num_proc_infos; i++) { + nub_process_t curr_pid = proc_infos[i].kp_proc.p_pid; + for (size_t j = 0; j < num_exclude_proc_infos; j++) { + if (curr_pid == exclude_proc_infos[j].kp_proc.p_pid) { + // This process was in our exclusion list, don't use it. + curr_pid = INVALID_NUB_PROCESS; + break; + } } - // If we haven't found our process yet, check for a timeout - // and then sleep for a bit until we poll again. - if (waitfor_pid == INVALID_NUB_PROCESS) - { - if (timeout_abstime != NULL) - { - // Check to see if we have a waitfor-duration option that - // has timed out? - if (DNBTimer::TimeOfDayLaterThan(*timeout_abstime)) - { - if (err_str && err_len > 0) - snprintf(err_str, err_len, "operation timed out"); - DNBLogError ("error: waiting for process '%s' timed out.\n", waitfor_process_name); - return INVALID_NUB_PROCESS; - } - } + // If we didn't find CURR_PID in our exclusion list, then use it. + if (curr_pid != INVALID_NUB_PROCESS) { + // We found our process! + waitfor_pid = curr_pid; + break; + } + } + } + + // If we haven't found our process yet, check for a timeout + // and then sleep for a bit until we poll again. + if (waitfor_pid == INVALID_NUB_PROCESS) { + if (timeout_abstime != NULL) { + // Check to see if we have a waitfor-duration option that + // has timed out? + if (DNBTimer::TimeOfDayLaterThan(*timeout_abstime)) { + if (err_str && err_len > 0) + snprintf(err_str, err_len, "operation timed out"); + DNBLogError("error: waiting for process '%s' timed out.\n", + waitfor_process_name); + return INVALID_NUB_PROCESS; + } + } - // Call the should cancel callback as well... + // Call the should cancel callback as well... - if (should_cancel_callback != NULL - && should_cancel_callback (callback_data)) - { - DNBLogThreadedIf (LOG_PROCESS, "DNBProcessAttachWait cancelled by should_cancel callback."); - waitfor_pid = INVALID_NUB_PROCESS; - break; - } + if (should_cancel_callback != NULL && + should_cancel_callback(callback_data)) { + DNBLogThreadedIf( + LOG_PROCESS, + "DNBProcessAttachWait cancelled by should_cancel callback."); + waitfor_pid = INVALID_NUB_PROCESS; + break; + } - ::usleep (waitfor_interval); // Sleep for WAITFOR_INTERVAL, then poll again - } + ::usleep(waitfor_interval); // Sleep for WAITFOR_INTERVAL, then poll again } + } - if (waitfor_pid != INVALID_NUB_PROCESS) - { - DNBLogThreadedIf (LOG_PROCESS, "Attaching to %s with pid %i...\n", waitfor_process_name, waitfor_pid); - waitfor_pid = DNBProcessAttach (waitfor_pid, timeout_abstime, err_str, err_len); - } + if (waitfor_pid != INVALID_NUB_PROCESS) { + DNBLogThreadedIf(LOG_PROCESS, "Attaching to %s with pid %i...\n", + waitfor_process_name, waitfor_pid); + waitfor_pid = + DNBProcessAttach(waitfor_pid, timeout_abstime, err_str, err_len); + } - bool success = waitfor_pid != INVALID_NUB_PROCESS; - MachProcess::CleanupAfterAttach (attach_token, launch_flavor, success, prepare_error); + bool success = waitfor_pid != INVALID_NUB_PROCESS; + MachProcess::CleanupAfterAttach(attach_token, launch_flavor, success, + prepare_error); - return waitfor_pid; + return waitfor_pid; } -nub_bool_t -DNBProcessDetach (nub_process_t pid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - const bool remove = true; - DNBLogThreaded("Disabling breakpoints and watchpoints, and detaching from %d.", pid); - procSP->DisableAllBreakpoints(remove); - procSP->DisableAllWatchpoints (remove); - return procSP->Detach(); - } - return false; +nub_bool_t DNBProcessDetach(nub_process_t pid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + const bool remove = true; + DNBLogThreaded( + "Disabling breakpoints and watchpoints, and detaching from %d.", pid); + procSP->DisableAllBreakpoints(remove); + procSP->DisableAllWatchpoints(remove); + return procSP->Detach(); + } + return false; } -nub_bool_t -DNBProcessKill (nub_process_t pid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->Kill (); - } - return false; +nub_bool_t DNBProcessKill(nub_process_t pid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + return procSP->Kill(); + } + return false; } -nub_bool_t -DNBProcessSignal (nub_process_t pid, int signal) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->Signal (signal); - } - return false; +nub_bool_t DNBProcessSignal(nub_process_t pid, int signal) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + return procSP->Signal(signal); + } + return false; } - -nub_bool_t -DNBProcessInterrupt(nub_process_t pid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->Interrupt(); - return false; +nub_bool_t DNBProcessInterrupt(nub_process_t pid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->Interrupt(); + return false; } -nub_bool_t -DNBProcessSendEvent (nub_process_t pid, const char *event) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - // FIXME: Do something with the error... - DNBError send_error; - return procSP->SendEvent (event, send_error); - } - return false; +nub_bool_t DNBProcessSendEvent(nub_process_t pid, const char *event) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + // FIXME: Do something with the error... + DNBError send_error; + return procSP->SendEvent(event, send_error); + } + return false; } - -nub_bool_t -DNBProcessIsAlive (nub_process_t pid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return MachTask::IsValid (procSP->Task().TaskPort()); - } - return eStateInvalid; +nub_bool_t DNBProcessIsAlive(nub_process_t pid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + return MachTask::IsValid(procSP->Task().TaskPort()); + } + return eStateInvalid; } //---------------------------------------------------------------------- // Process and Thread state information //---------------------------------------------------------------------- -nub_state_t -DNBProcessGetState (nub_process_t pid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->GetState(); - } - return eStateInvalid; +nub_state_t DNBProcessGetState(nub_process_t pid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + return procSP->GetState(); + } + return eStateInvalid; } //---------------------------------------------------------------------- // Process and Thread state information //---------------------------------------------------------------------- -nub_bool_t -DNBProcessGetExitStatus (nub_process_t pid, int* status) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->GetExitStatus(status); - } - return false; +nub_bool_t DNBProcessGetExitStatus(nub_process_t pid, int *status) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + return procSP->GetExitStatus(status); + } + return false; } -nub_bool_t -DNBProcessSetExitStatus (nub_process_t pid, int status) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - procSP->SetExitStatus(status); - return true; - } - return false; +nub_bool_t DNBProcessSetExitStatus(nub_process_t pid, int status) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + procSP->SetExitStatus(status); + return true; + } + return false; } -const char * -DNBProcessGetExitInfo (nub_process_t pid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->GetExitInfo(); - } - return NULL; +const char *DNBProcessGetExitInfo(nub_process_t pid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + return procSP->GetExitInfo(); + } + return NULL; } -nub_bool_t -DNBProcessSetExitInfo (nub_process_t pid, const char *info) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - procSP->SetExitInfo(info); - return true; - } - return false; +nub_bool_t DNBProcessSetExitInfo(nub_process_t pid, const char *info) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + procSP->SetExitInfo(info); + return true; + } + return false; } -const char * -DNBThreadGetName (nub_process_t pid, nub_thread_t tid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->ThreadGetName(tid); - return NULL; +const char *DNBThreadGetName(nub_process_t pid, nub_thread_t tid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->ThreadGetName(tid); + return NULL; } - nub_bool_t -DNBThreadGetIdentifierInfo (nub_process_t pid, nub_thread_t tid, thread_identifier_info_data_t *ident_info) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->GetThreadList().GetIdentifierInfo(tid, ident_info); - return false; -} - -nub_state_t -DNBThreadGetState (nub_process_t pid, nub_thread_t tid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->ThreadGetState(tid); - } - return eStateInvalid; -} - -const char * -DNBStateAsString(nub_state_t state) -{ - switch (state) - { - case eStateInvalid: return "Invalid"; - case eStateUnloaded: return "Unloaded"; - case eStateAttaching: return "Attaching"; - case eStateLaunching: return "Launching"; - case eStateStopped: return "Stopped"; - case eStateRunning: return "Running"; - case eStateStepping: return "Stepping"; - case eStateCrashed: return "Crashed"; - case eStateDetached: return "Detached"; - case eStateExited: return "Exited"; - case eStateSuspended: return "Suspended"; - } - return "nub_state_t ???"; -} - -Genealogy::ThreadActivitySP -DNBGetGenealogyInfoForThread (nub_process_t pid, nub_thread_t tid, bool &timed_out) -{ - Genealogy::ThreadActivitySP thread_activity_sp; - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - thread_activity_sp = procSP->GetGenealogyInfoForThread (tid, timed_out); - return thread_activity_sp; -} - -Genealogy::ProcessExecutableInfoSP -DNBGetGenealogyImageInfo (nub_process_t pid, size_t idx) -{ - Genealogy::ProcessExecutableInfoSP image_info_sp; - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - image_info_sp = procSP->GetGenealogyImageInfo (idx); - } - return image_info_sp; -} - -ThreadInfo::QoS -DNBGetRequestedQoSForThread (nub_process_t pid, nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->GetRequestedQoS (tid, tsd, dti_qos_class_index); - } - return ThreadInfo::QoS(); -} - -nub_addr_t -DNBGetPThreadT (nub_process_t pid, nub_thread_t tid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->GetPThreadT (tid); - } - return INVALID_NUB_ADDRESS; -} - -nub_addr_t -DNBGetDispatchQueueT (nub_process_t pid, nub_thread_t tid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->GetDispatchQueueT (tid); - } - return INVALID_NUB_ADDRESS; +DNBThreadGetIdentifierInfo(nub_process_t pid, nub_thread_t tid, + thread_identifier_info_data_t *ident_info) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->GetThreadList().GetIdentifierInfo(tid, ident_info); + return false; +} + +nub_state_t DNBThreadGetState(nub_process_t pid, nub_thread_t tid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + return procSP->ThreadGetState(tid); + } + return eStateInvalid; +} + +const char *DNBStateAsString(nub_state_t state) { + switch (state) { + case eStateInvalid: + return "Invalid"; + case eStateUnloaded: + return "Unloaded"; + case eStateAttaching: + return "Attaching"; + case eStateLaunching: + return "Launching"; + case eStateStopped: + return "Stopped"; + case eStateRunning: + return "Running"; + case eStateStepping: + return "Stepping"; + case eStateCrashed: + return "Crashed"; + case eStateDetached: + return "Detached"; + case eStateExited: + return "Exited"; + case eStateSuspended: + return "Suspended"; + } + return "nub_state_t ???"; +} + +Genealogy::ThreadActivitySP DNBGetGenealogyInfoForThread(nub_process_t pid, + nub_thread_t tid, + bool &timed_out) { + Genealogy::ThreadActivitySP thread_activity_sp; + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + thread_activity_sp = procSP->GetGenealogyInfoForThread(tid, timed_out); + return thread_activity_sp; +} + +Genealogy::ProcessExecutableInfoSP DNBGetGenealogyImageInfo(nub_process_t pid, + size_t idx) { + Genealogy::ProcessExecutableInfoSP image_info_sp; + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + image_info_sp = procSP->GetGenealogyImageInfo(idx); + } + return image_info_sp; +} + +ThreadInfo::QoS DNBGetRequestedQoSForThread(nub_process_t pid, nub_thread_t tid, + nub_addr_t tsd, + uint64_t dti_qos_class_index) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + return procSP->GetRequestedQoS(tid, tsd, dti_qos_class_index); + } + return ThreadInfo::QoS(); +} + +nub_addr_t DNBGetPThreadT(nub_process_t pid, nub_thread_t tid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + return procSP->GetPThreadT(tid); + } + return INVALID_NUB_ADDRESS; +} + +nub_addr_t DNBGetDispatchQueueT(nub_process_t pid, nub_thread_t tid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + return procSP->GetDispatchQueueT(tid); + } + return INVALID_NUB_ADDRESS; } nub_addr_t -DNBGetTSDAddressForThread (nub_process_t pid, nub_thread_t tid, uint64_t plo_pthread_tsd_base_address_offset, uint64_t plo_pthread_tsd_base_offset, uint64_t plo_pthread_tsd_entry_size) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->GetTSDAddressForThread (tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size); - } - return INVALID_NUB_ADDRESS; +DNBGetTSDAddressForThread(nub_process_t pid, nub_thread_t tid, + uint64_t plo_pthread_tsd_base_address_offset, + uint64_t plo_pthread_tsd_base_offset, + uint64_t plo_pthread_tsd_entry_size) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + return procSP->GetTSDAddressForThread( + tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, + plo_pthread_tsd_entry_size); + } + return INVALID_NUB_ADDRESS; +} + +JSONGenerator::ObjectSP DNBGetLoadedDynamicLibrariesInfos( + nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + return procSP->GetLoadedDynamicLibrariesInfos(pid, image_list_address, + image_count); + } + return JSONGenerator::ObjectSP(); +} + +JSONGenerator::ObjectSP DNBGetAllLoadedLibrariesInfos(nub_process_t pid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + return procSP->GetAllLoadedLibrariesInfos(pid); + } + return JSONGenerator::ObjectSP(); +} + +JSONGenerator::ObjectSP +DNBGetLibrariesInfoForAddresses(nub_process_t pid, + std::vector<uint64_t> &macho_addresses) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + return procSP->GetLibrariesInfoForAddresses(pid, macho_addresses); + } + return JSONGenerator::ObjectSP(); +} + +JSONGenerator::ObjectSP DNBGetSharedCacheInfo(nub_process_t pid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + return procSP->GetSharedCacheInfo(pid); + } + return JSONGenerator::ObjectSP(); +} + +const char *DNBProcessGetExecutablePath(nub_process_t pid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + return procSP->Path(); + } + return NULL; +} + +nub_size_t DNBProcessGetArgumentCount(nub_process_t pid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + return procSP->ArgumentCount(); + } + return 0; +} + +const char *DNBProcessGetArgumentAtIndex(nub_process_t pid, nub_size_t idx) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + return procSP->ArgumentAtIndex(idx); + } + return NULL; } -JSONGenerator::ObjectSP -DNBGetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->GetLoadedDynamicLibrariesInfos (pid, image_list_address, image_count); - } - return JSONGenerator::ObjectSP(); -} - -JSONGenerator::ObjectSP -DNBGetAllLoadedLibrariesInfos (nub_process_t pid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->GetAllLoadedLibrariesInfos (pid); - } - return JSONGenerator::ObjectSP(); -} - -JSONGenerator::ObjectSP -DNBGetLibrariesInfoForAddresses (nub_process_t pid, std::vector<uint64_t> &macho_addresses) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->GetLibrariesInfoForAddresses (pid, macho_addresses); - } - return JSONGenerator::ObjectSP(); -} - -JSONGenerator::ObjectSP -DNBGetSharedCacheInfo (nub_process_t pid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->GetSharedCacheInfo (pid); - } - return JSONGenerator::ObjectSP(); -} - - - -const char * -DNBProcessGetExecutablePath (nub_process_t pid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->Path(); - } - return NULL; -} - -nub_size_t -DNBProcessGetArgumentCount (nub_process_t pid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->ArgumentCount(); - } - return 0; -} - -const char * -DNBProcessGetArgumentAtIndex (nub_process_t pid, nub_size_t idx) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->ArgumentAtIndex (idx); - } - return NULL; -} - - //---------------------------------------------------------------------- // Execution control //---------------------------------------------------------------------- -nub_bool_t -DNBProcessResume (nub_process_t pid, const DNBThreadResumeAction *actions, size_t num_actions) -{ - DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid); - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - DNBThreadResumeActions thread_actions (actions, num_actions); - - // Below we add a default thread plan just in case one wasn't - // provided so all threads always know what they were supposed to do - if (thread_actions.IsEmpty()) - { - // No thread plans were given, so the default it to run all threads - thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, 0); - } - else - { - // Some thread plans were given which means anything that wasn't - // specified should remain stopped. - thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0); - } - return procSP->Resume (thread_actions); - } - return false; -} - -nub_bool_t -DNBProcessHalt (nub_process_t pid) -{ - DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid); - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->Signal (SIGSTOP); - return false; +nub_bool_t DNBProcessResume(nub_process_t pid, + const DNBThreadResumeAction *actions, + size_t num_actions) { + DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid); + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + DNBThreadResumeActions thread_actions(actions, num_actions); + + // Below we add a default thread plan just in case one wasn't + // provided so all threads always know what they were supposed to do + if (thread_actions.IsEmpty()) { + // No thread plans were given, so the default it to run all threads + thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0); + } else { + // Some thread plans were given which means anything that wasn't + // specified should remain stopped. + thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); + } + return procSP->Resume(thread_actions); + } + return false; +} + +nub_bool_t DNBProcessHalt(nub_process_t pid) { + DNBLogThreadedIf(LOG_PROCESS, "%s(pid = %4.4x)", __FUNCTION__, pid); + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->Signal(SIGSTOP); + return false; } // -//nub_bool_t -//DNBThreadResume (nub_process_t pid, nub_thread_t tid, nub_bool_t step) +// nub_bool_t +// DNBThreadResume (nub_process_t pid, nub_thread_t tid, nub_bool_t step) //{ -// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u)", __FUNCTION__, pid, tid, (uint32_t)step); +// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u)", +// __FUNCTION__, pid, tid, (uint32_t)step); // MachProcessSP procSP; // if (GetProcessSP (pid, procSP)) // { @@ -1204,10 +1079,12 @@ DNBProcessHalt (nub_process_t pid) // return false; //} // -//nub_bool_t -//DNBThreadResumeWithSignal (nub_process_t pid, nub_thread_t tid, nub_bool_t step, int signal) +// nub_bool_t +// DNBThreadResumeWithSignal (nub_process_t pid, nub_thread_t tid, nub_bool_t +// step, int signal) //{ -// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u, signal = %i)", __FUNCTION__, pid, tid, (uint32_t)step, signal); +// DNBLogThreadedIf(LOG_THREAD, "%s(pid = %4.4x, tid = %4.4x, step = %u, +// signal = %i)", __FUNCTION__, pid, tid, (uint32_t)step, signal); // MachProcessSP procSP; // if (GetProcessSP (pid, procSP)) // { @@ -1216,80 +1093,68 @@ DNBProcessHalt (nub_process_t pid) // return false; //} -nub_event_t -DNBProcessWaitForEvents (nub_process_t pid, nub_event_t event_mask, bool wait_for_set, struct timespec* timeout) -{ - nub_event_t result = 0; - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - if (wait_for_set) - result = procSP->Events().WaitForSetEvents(event_mask, timeout); - else - result = procSP->Events().WaitForEventsToReset(event_mask, timeout); - } - return result; +nub_event_t DNBProcessWaitForEvents(nub_process_t pid, nub_event_t event_mask, + bool wait_for_set, + struct timespec *timeout) { + nub_event_t result = 0; + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + if (wait_for_set) + result = procSP->Events().WaitForSetEvents(event_mask, timeout); + else + result = procSP->Events().WaitForEventsToReset(event_mask, timeout); + } + return result; } -void -DNBProcessResetEvents (nub_process_t pid, nub_event_t event_mask) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - procSP->Events().ResetEvents(event_mask); +void DNBProcessResetEvents(nub_process_t pid, nub_event_t event_mask) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + procSP->Events().ResetEvents(event_mask); } // Breakpoints -nub_bool_t -DNBBreakpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, nub_bool_t hardware) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->CreateBreakpoint(addr, size, hardware) != NULL; - return false; +nub_bool_t DNBBreakpointSet(nub_process_t pid, nub_addr_t addr, nub_size_t size, + nub_bool_t hardware) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->CreateBreakpoint(addr, size, hardware) != NULL; + return false; } -nub_bool_t -DNBBreakpointClear (nub_process_t pid, nub_addr_t addr) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->DisableBreakpoint(addr, true); - return false; // Failed +nub_bool_t DNBBreakpointClear(nub_process_t pid, nub_addr_t addr) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->DisableBreakpoint(addr, true); + return false; // Failed } - //---------------------------------------------------------------------- // Watchpoints //---------------------------------------------------------------------- -nub_bool_t -DNBWatchpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, uint32_t watch_flags, nub_bool_t hardware) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->CreateWatchpoint(addr, size, watch_flags, hardware) != NULL; - return false; +nub_bool_t DNBWatchpointSet(nub_process_t pid, nub_addr_t addr, nub_size_t size, + uint32_t watch_flags, nub_bool_t hardware) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->CreateWatchpoint(addr, size, watch_flags, hardware) != NULL; + return false; } -nub_bool_t -DNBWatchpointClear (nub_process_t pid, nub_addr_t addr) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->DisableWatchpoint(addr, true); - return false; // Failed +nub_bool_t DNBWatchpointClear(nub_process_t pid, nub_addr_t addr) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->DisableWatchpoint(addr, true); + return false; // Failed } //---------------------------------------------------------------------- // Return the number of supported hardware watchpoints. //---------------------------------------------------------------------- -uint32_t -DNBWatchpointGetNumSupportedHWP (nub_process_t pid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->GetNumSupportedHardwareWatchpoints(); - return 0; +uint32_t DNBWatchpointGetNumSupportedHWP(nub_process_t pid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->GetNumSupportedHardwareWatchpoints(); + return 0; } //---------------------------------------------------------------------- @@ -1299,95 +1164,89 @@ DNBWatchpointGetNumSupportedHWP (nub_process_t pid) // // RETURNS: number of bytes actually read //---------------------------------------------------------------------- -nub_size_t -DNBProcessMemoryRead (nub_process_t pid, nub_addr_t addr, nub_size_t size, void *buf) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->ReadMemory(addr, size, buf); - return 0; -} - -uint64_t -DNBProcessMemoryReadInteger (nub_process_t pid, nub_addr_t addr, nub_size_t integer_size, uint64_t fail_value) -{ - union Integers - { - uint8_t u8; - uint16_t u16; - uint32_t u32; - uint64_t u64; - }; - - if (integer_size <= sizeof(uint64_t)) - { - Integers ints; - if (DNBProcessMemoryRead(pid, addr, integer_size, &ints) == integer_size) - { - switch (integer_size) - { - case 1: return ints.u8; - case 2: return ints.u16; - case 3: return ints.u32 & 0xffffffu; - case 4: return ints.u32; - case 5: return ints.u32 & 0x000000ffffffffffull; - case 6: return ints.u32 & 0x0000ffffffffffffull; - case 7: return ints.u32 & 0x00ffffffffffffffull; - case 8: return ints.u64; - } - } - } - return fail_value; - +nub_size_t DNBProcessMemoryRead(nub_process_t pid, nub_addr_t addr, + nub_size_t size, void *buf) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->ReadMemory(addr, size, buf); + return 0; +} + +uint64_t DNBProcessMemoryReadInteger(nub_process_t pid, nub_addr_t addr, + nub_size_t integer_size, + uint64_t fail_value) { + union Integers { + uint8_t u8; + uint16_t u16; + uint32_t u32; + uint64_t u64; + }; + + if (integer_size <= sizeof(uint64_t)) { + Integers ints; + if (DNBProcessMemoryRead(pid, addr, integer_size, &ints) == integer_size) { + switch (integer_size) { + case 1: + return ints.u8; + case 2: + return ints.u16; + case 3: + return ints.u32 & 0xffffffu; + case 4: + return ints.u32; + case 5: + return ints.u32 & 0x000000ffffffffffull; + case 6: + return ints.u32 & 0x0000ffffffffffffull; + case 7: + return ints.u32 & 0x00ffffffffffffffull; + case 8: + return ints.u64; + } + } + } + return fail_value; +} + +nub_addr_t DNBProcessMemoryReadPointer(nub_process_t pid, nub_addr_t addr) { + cpu_type_t cputype = DNBProcessGetCPUType(pid); + if (cputype) { + const nub_size_t pointer_size = (cputype & CPU_ARCH_ABI64) ? 8 : 4; + return DNBProcessMemoryReadInteger(pid, addr, pointer_size, 0); + } + return 0; +} + +std::string DNBProcessMemoryReadCString(nub_process_t pid, nub_addr_t addr) { + std::string cstr; + char buffer[256]; + const nub_size_t max_buffer_cstr_length = sizeof(buffer) - 1; + buffer[max_buffer_cstr_length] = '\0'; + nub_size_t length = 0; + nub_addr_t curr_addr = addr; + do { + nub_size_t bytes_read = + DNBProcessMemoryRead(pid, curr_addr, max_buffer_cstr_length, buffer); + if (bytes_read == 0) + break; + length = strlen(buffer); + cstr.append(buffer, length); + curr_addr += length; + } while (length == max_buffer_cstr_length); + return cstr; +} + +std::string DNBProcessMemoryReadCStringFixed(nub_process_t pid, nub_addr_t addr, + nub_size_t fixed_length) { + std::string cstr; + char buffer[fixed_length + 1]; + buffer[fixed_length] = '\0'; + nub_size_t bytes_read = DNBProcessMemoryRead(pid, addr, fixed_length, buffer); + if (bytes_read > 0) + cstr.assign(buffer); + return cstr; } -nub_addr_t -DNBProcessMemoryReadPointer (nub_process_t pid, nub_addr_t addr) -{ - cpu_type_t cputype = DNBProcessGetCPUType (pid); - if (cputype) - { - const nub_size_t pointer_size = (cputype & CPU_ARCH_ABI64) ? 8 : 4; - return DNBProcessMemoryReadInteger(pid, addr, pointer_size, 0); - } - return 0; - -} - -std::string -DNBProcessMemoryReadCString (nub_process_t pid, nub_addr_t addr) -{ - std::string cstr; - char buffer[256]; - const nub_size_t max_buffer_cstr_length = sizeof(buffer)-1; - buffer[max_buffer_cstr_length] = '\0'; - nub_size_t length = 0; - nub_addr_t curr_addr = addr; - do - { - nub_size_t bytes_read = DNBProcessMemoryRead(pid, curr_addr, max_buffer_cstr_length, buffer); - if (bytes_read == 0) - break; - length = strlen(buffer); - cstr.append(buffer, length); - curr_addr += length; - } while (length == max_buffer_cstr_length); - return cstr; -} - -std::string -DNBProcessMemoryReadCStringFixed (nub_process_t pid, nub_addr_t addr, nub_size_t fixed_length) -{ - std::string cstr; - char buffer[fixed_length+1]; - buffer[fixed_length] = '\0'; - nub_size_t bytes_read = DNBProcessMemoryRead(pid, addr, fixed_length, buffer); - if (bytes_read > 0) - cstr.assign(buffer); - return cstr; -} - - //---------------------------------------------------------------------- // Write memory to the address space of process PID. This call will take // care of setting and restoring permissions and breaking up the memory @@ -1395,31 +1254,27 @@ DNBProcessMemoryReadCStringFixed (nub_process_t pid, nub_addr_t addr, nub_size_t // // RETURNS: number of bytes actually written //---------------------------------------------------------------------- -nub_size_t -DNBProcessMemoryWrite (nub_process_t pid, nub_addr_t addr, nub_size_t size, const void *buf) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->WriteMemory(addr, size, buf); - return 0; +nub_size_t DNBProcessMemoryWrite(nub_process_t pid, nub_addr_t addr, + nub_size_t size, const void *buf) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->WriteMemory(addr, size, buf); + return 0; } -nub_addr_t -DNBProcessMemoryAllocate (nub_process_t pid, nub_size_t size, uint32_t permissions) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->Task().AllocateMemory (size, permissions); - return 0; +nub_addr_t DNBProcessMemoryAllocate(nub_process_t pid, nub_size_t size, + uint32_t permissions) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->Task().AllocateMemory(size, permissions); + return 0; } -nub_bool_t -DNBProcessMemoryDeallocate (nub_process_t pid, nub_addr_t addr) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->Task().DeallocateMemory (addr); - return 0; +nub_bool_t DNBProcessMemoryDeallocate(nub_process_t pid, nub_addr_t addr) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->Task().DeallocateMemory(addr); + return 0; } //---------------------------------------------------------------------- @@ -1436,99 +1291,87 @@ DNBProcessMemoryDeallocate (nub_process_t pid, nub_addr_t addr) // or if we do not yet have a valid launched process. // //---------------------------------------------------------------------- -int -DNBProcessMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, DNBRegionInfo *region_info) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->Task().GetMemoryRegionInfo (addr, region_info); +int DNBProcessMemoryRegionInfo(nub_process_t pid, nub_addr_t addr, + DNBRegionInfo *region_info) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->Task().GetMemoryRegionInfo(addr, region_info); - return -1; + return -1; } -std::string -DNBProcessGetProfileData (nub_process_t pid, DNBProfileDataScanType scanType) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->Task().GetProfileData(scanType); - - return std::string(""); +std::string DNBProcessGetProfileData(nub_process_t pid, + DNBProfileDataScanType scanType) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->Task().GetProfileData(scanType); + + return std::string(""); } -nub_bool_t -DNBProcessSetEnableAsyncProfiling (nub_process_t pid, nub_bool_t enable, uint64_t interval_usec, DNBProfileDataScanType scan_type) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - procSP->SetEnableAsyncProfiling(enable, interval_usec, scan_type); - return true; - } - - return false; +nub_bool_t DNBProcessSetEnableAsyncProfiling(nub_process_t pid, + nub_bool_t enable, + uint64_t interval_usec, + DNBProfileDataScanType scan_type) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + procSP->SetEnableAsyncProfiling(enable, interval_usec, scan_type); + return true; + } + + return false; } //---------------------------------------------------------------------- // Get the number of threads for the specified process. //---------------------------------------------------------------------- -nub_size_t -DNBProcessGetNumThreads (nub_process_t pid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->GetNumThreads(); - return 0; +nub_size_t DNBProcessGetNumThreads(nub_process_t pid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->GetNumThreads(); + return 0; } //---------------------------------------------------------------------- // Get the thread ID of the current thread. //---------------------------------------------------------------------- -nub_thread_t -DNBProcessGetCurrentThread (nub_process_t pid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->GetCurrentThread(); - return 0; +nub_thread_t DNBProcessGetCurrentThread(nub_process_t pid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->GetCurrentThread(); + return 0; } //---------------------------------------------------------------------- // Get the mach port number of the current thread. //---------------------------------------------------------------------- -nub_thread_t -DNBProcessGetCurrentThreadMachPort (nub_process_t pid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->GetCurrentThreadMachPort(); - return 0; +nub_thread_t DNBProcessGetCurrentThreadMachPort(nub_process_t pid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->GetCurrentThreadMachPort(); + return 0; } //---------------------------------------------------------------------- // Change the current thread. //---------------------------------------------------------------------- -nub_thread_t -DNBProcessSetCurrentThread (nub_process_t pid, nub_thread_t tid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->SetCurrentThread (tid); - return INVALID_NUB_THREAD; +nub_thread_t DNBProcessSetCurrentThread(nub_process_t pid, nub_thread_t tid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->SetCurrentThread(tid); + return INVALID_NUB_THREAD; } - //---------------------------------------------------------------------- // Dump a string describing a thread's stop reason to the specified file // handle //---------------------------------------------------------------------- -nub_bool_t -DNBThreadGetStopReason (nub_process_t pid, nub_thread_t tid, struct DNBThreadStopInfo *stop_info) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->GetThreadStoppedReason (tid, stop_info); - return false; +nub_bool_t DNBThreadGetStopReason(nub_process_t pid, nub_thread_t tid, + struct DNBThreadStopInfo *stop_info) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->GetThreadStoppedReason(tid, stop_info); + return false; } //---------------------------------------------------------------------- @@ -1538,61 +1381,49 @@ DNBThreadGetStopReason (nub_process_t pid, nub_thread_t tid, struct DNBThreadSto // string from a static buffer that must be copied prior to subsequent // calls. //---------------------------------------------------------------------- -const char * -DNBThreadGetInfo (nub_process_t pid, nub_thread_t tid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->GetThreadInfo (tid); - return NULL; +const char *DNBThreadGetInfo(nub_process_t pid, nub_thread_t tid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->GetThreadInfo(tid); + return NULL; } //---------------------------------------------------------------------- // Get the thread ID given a thread index. //---------------------------------------------------------------------- -nub_thread_t -DNBProcessGetThreadAtIndex (nub_process_t pid, size_t thread_idx) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->GetThreadAtIndex (thread_idx); - return INVALID_NUB_THREAD; +nub_thread_t DNBProcessGetThreadAtIndex(nub_process_t pid, size_t thread_idx) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->GetThreadAtIndex(thread_idx); + return INVALID_NUB_THREAD; } //---------------------------------------------------------------------- -// Do whatever is needed to sync the thread's register state with it's kernel values. +// Do whatever is needed to sync the thread's register state with it's kernel +// values. //---------------------------------------------------------------------- -nub_bool_t -DNBProcessSyncThreadState (nub_process_t pid, nub_thread_t tid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->SyncThreadState (tid); - return false; - +nub_bool_t DNBProcessSyncThreadState(nub_process_t pid, nub_thread_t tid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->SyncThreadState(tid); + return false; } -nub_addr_t -DNBProcessGetSharedLibraryInfoAddress (nub_process_t pid) -{ - MachProcessSP procSP; - DNBError err; - if (GetProcessSP (pid, procSP)) - return procSP->Task().GetDYLDAllImageInfosAddress (err); - return INVALID_NUB_ADDRESS; +nub_addr_t DNBProcessGetSharedLibraryInfoAddress(nub_process_t pid) { + MachProcessSP procSP; + DNBError err; + if (GetProcessSP(pid, procSP)) + return procSP->Task().GetDYLDAllImageInfosAddress(err); + return INVALID_NUB_ADDRESS; } - -nub_bool_t -DNBProcessSharedLibrariesUpdated(nub_process_t pid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - procSP->SharedLibrariesUpdated (); - return true; - } - return false; +nub_bool_t DNBProcessSharedLibrariesUpdated(nub_process_t pid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + procSP->SharedLibrariesUpdated(); + return true; + } + return false; } //---------------------------------------------------------------------- @@ -1601,403 +1432,334 @@ DNBProcessSharedLibrariesUpdated(nub_process_t pid) // state changed event if only_changed is non-zero. //---------------------------------------------------------------------- nub_size_t -DNBProcessGetSharedLibraryInfo (nub_process_t pid, nub_bool_t only_changed, struct DNBExecutableImageInfo **image_infos) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->CopyImageInfos (image_infos, only_changed); +DNBProcessGetSharedLibraryInfo(nub_process_t pid, nub_bool_t only_changed, + struct DNBExecutableImageInfo **image_infos) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->CopyImageInfos(image_infos, only_changed); - // If we have no process, then return NULL for the shared library info - // and zero for shared library count - *image_infos = NULL; - return 0; + // If we have no process, then return NULL for the shared library info + // and zero for shared library count + *image_infos = NULL; + return 0; } -uint32_t -DNBGetRegisterCPUType() -{ - return DNBArchProtocol::GetRegisterCPUType (); - +uint32_t DNBGetRegisterCPUType() { + return DNBArchProtocol::GetRegisterCPUType(); } //---------------------------------------------------------------------- // Get the register set information for a specific thread. //---------------------------------------------------------------------- -const DNBRegisterSetInfo * -DNBGetRegisterSetInfo (nub_size_t *num_reg_sets) -{ - return DNBArchProtocol::GetRegisterSetInfo (num_reg_sets); +const DNBRegisterSetInfo *DNBGetRegisterSetInfo(nub_size_t *num_reg_sets) { + return DNBArchProtocol::GetRegisterSetInfo(num_reg_sets); } - //---------------------------------------------------------------------- // Read a register value by register set and register index. //---------------------------------------------------------------------- -nub_bool_t -DNBThreadGetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *value) -{ - MachProcessSP procSP; - ::bzero (value, sizeof(DNBRegisterValue)); - if (GetProcessSP (pid, procSP)) - { - if (tid != INVALID_NUB_THREAD) - return procSP->GetRegisterValue (tid, set, reg, value); - } - return false; -} - -nub_bool_t -DNBThreadSetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value) -{ +nub_bool_t DNBThreadGetRegisterValueByID(nub_process_t pid, nub_thread_t tid, + uint32_t set, uint32_t reg, + DNBRegisterValue *value) { + MachProcessSP procSP; + ::bzero(value, sizeof(DNBRegisterValue)); + if (GetProcessSP(pid, procSP)) { if (tid != INVALID_NUB_THREAD) - { - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->SetRegisterValue (tid, set, reg, value); - } - return false; + return procSP->GetRegisterValue(tid, set, reg, value); + } + return false; } -nub_size_t -DNBThreadGetRegisterContext (nub_process_t pid, nub_thread_t tid, void *buf, size_t buf_len) -{ +nub_bool_t DNBThreadSetRegisterValueByID(nub_process_t pid, nub_thread_t tid, + uint32_t set, uint32_t reg, + const DNBRegisterValue *value) { + if (tid != INVALID_NUB_THREAD) { MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - if (tid != INVALID_NUB_THREAD) - return procSP->GetThreadList().GetRegisterContext (tid, buf, buf_len); - } - ::bzero (buf, buf_len); - return 0; - + if (GetProcessSP(pid, procSP)) + return procSP->SetRegisterValue(tid, set, reg, value); + } + return false; } -nub_size_t -DNBThreadSetRegisterContext (nub_process_t pid, nub_thread_t tid, const void *buf, size_t buf_len) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - if (tid != INVALID_NUB_THREAD) - return procSP->GetThreadList().SetRegisterContext (tid, buf, buf_len); - } - return 0; -} - -uint32_t -DNBThreadSaveRegisterState (nub_process_t pid, nub_thread_t tid) -{ +nub_size_t DNBThreadGetRegisterContext(nub_process_t pid, nub_thread_t tid, + void *buf, size_t buf_len) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { if (tid != INVALID_NUB_THREAD) - { - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->GetThreadList().SaveRegisterState (tid); - } - return 0; + return procSP->GetThreadList().GetRegisterContext(tid, buf, buf_len); + } + ::bzero(buf, buf_len); + return 0; } -nub_bool_t -DNBThreadRestoreRegisterState (nub_process_t pid, nub_thread_t tid, uint32_t save_id) -{ + +nub_size_t DNBThreadSetRegisterContext(nub_process_t pid, nub_thread_t tid, + const void *buf, size_t buf_len) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { if (tid != INVALID_NUB_THREAD) - { - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->GetThreadList().RestoreRegisterState (tid, save_id); - } - return false; + return procSP->GetThreadList().SetRegisterContext(tid, buf, buf_len); + } + return 0; } - +uint32_t DNBThreadSaveRegisterState(nub_process_t pid, nub_thread_t tid) { + if (tid != INVALID_NUB_THREAD) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->GetThreadList().SaveRegisterState(tid); + } + return 0; +} +nub_bool_t DNBThreadRestoreRegisterState(nub_process_t pid, nub_thread_t tid, + uint32_t save_id) { + if (tid != INVALID_NUB_THREAD) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->GetThreadList().RestoreRegisterState(tid, save_id); + } + return false; +} //---------------------------------------------------------------------- // Read a register value by name. //---------------------------------------------------------------------- -nub_bool_t -DNBThreadGetRegisterValueByName (nub_process_t pid, nub_thread_t tid, uint32_t reg_set, const char *reg_name, DNBRegisterValue *value) -{ - MachProcessSP procSP; - ::bzero (value, sizeof(DNBRegisterValue)); - if (GetProcessSP (pid, procSP)) - { - const struct DNBRegisterSetInfo *set_info; - nub_size_t num_reg_sets = 0; - set_info = DNBGetRegisterSetInfo (&num_reg_sets); - if (set_info) - { - uint32_t set = reg_set; - uint32_t reg; - if (set == REGISTER_SET_ALL) - { - for (set = 1; set < num_reg_sets; ++set) - { - for (reg = 0; reg < set_info[set].num_registers; ++reg) - { - if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0) - return procSP->GetRegisterValue (tid, set, reg, value); - } - } - } - else - { - for (reg = 0; reg < set_info[set].num_registers; ++reg) - { - if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0) - return procSP->GetRegisterValue (tid, set, reg, value); - } - } +nub_bool_t DNBThreadGetRegisterValueByName(nub_process_t pid, nub_thread_t tid, + uint32_t reg_set, + const char *reg_name, + DNBRegisterValue *value) { + MachProcessSP procSP; + ::bzero(value, sizeof(DNBRegisterValue)); + if (GetProcessSP(pid, procSP)) { + const struct DNBRegisterSetInfo *set_info; + nub_size_t num_reg_sets = 0; + set_info = DNBGetRegisterSetInfo(&num_reg_sets); + if (set_info) { + uint32_t set = reg_set; + uint32_t reg; + if (set == REGISTER_SET_ALL) { + for (set = 1; set < num_reg_sets; ++set) { + for (reg = 0; reg < set_info[set].num_registers; ++reg) { + if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0) + return procSP->GetRegisterValue(tid, set, reg, value); + } } + } else { + for (reg = 0; reg < set_info[set].num_registers; ++reg) { + if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0) + return procSP->GetRegisterValue(tid, set, reg, value); + } + } } - return false; + } + return false; } - //---------------------------------------------------------------------- // Read a register set and register number from the register name. //---------------------------------------------------------------------- -nub_bool_t -DNBGetRegisterInfoByName (const char *reg_name, DNBRegisterInfo* info) -{ - const struct DNBRegisterSetInfo *set_info; - nub_size_t num_reg_sets = 0; - set_info = DNBGetRegisterSetInfo (&num_reg_sets); - if (set_info) - { - uint32_t set, reg; - for (set = 1; set < num_reg_sets; ++set) - { - for (reg = 0; reg < set_info[set].num_registers; ++reg) - { - if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0) - { - *info = set_info[set].registers[reg]; - return true; - } - } +nub_bool_t DNBGetRegisterInfoByName(const char *reg_name, + DNBRegisterInfo *info) { + const struct DNBRegisterSetInfo *set_info; + nub_size_t num_reg_sets = 0; + set_info = DNBGetRegisterSetInfo(&num_reg_sets); + if (set_info) { + uint32_t set, reg; + for (set = 1; set < num_reg_sets; ++set) { + for (reg = 0; reg < set_info[set].num_registers; ++reg) { + if (strcasecmp(reg_name, set_info[set].registers[reg].name) == 0) { + *info = set_info[set].registers[reg]; + return true; } + } + } - for (set = 1; set < num_reg_sets; ++set) - { - uint32_t reg; - for (reg = 0; reg < set_info[set].num_registers; ++reg) - { - if (set_info[set].registers[reg].alt == NULL) - continue; - - if (strcasecmp(reg_name, set_info[set].registers[reg].alt) == 0) - { - *info = set_info[set].registers[reg]; - return true; - } - } + for (set = 1; set < num_reg_sets; ++set) { + uint32_t reg; + for (reg = 0; reg < set_info[set].num_registers; ++reg) { + if (set_info[set].registers[reg].alt == NULL) + continue; + + if (strcasecmp(reg_name, set_info[set].registers[reg].alt) == 0) { + *info = set_info[set].registers[reg]; + return true; } + } } + } - ::bzero (info, sizeof(DNBRegisterInfo)); - return false; + ::bzero(info, sizeof(DNBRegisterInfo)); + return false; } - //---------------------------------------------------------------------- // Set the name to address callback function that this nub can use // for any name to address lookups that are needed. //---------------------------------------------------------------------- -nub_bool_t -DNBProcessSetNameToAddressCallback (nub_process_t pid, DNBCallbackNameToAddress callback, void *baton) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - procSP->SetNameToAddressCallback (callback, baton); - return true; - } - return false; +nub_bool_t DNBProcessSetNameToAddressCallback(nub_process_t pid, + DNBCallbackNameToAddress callback, + void *baton) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + procSP->SetNameToAddressCallback(callback, baton); + return true; + } + return false; } - //---------------------------------------------------------------------- // Set the name to address callback function that this nub can use // for any name to address lookups that are needed. //---------------------------------------------------------------------- -nub_bool_t -DNBProcessSetSharedLibraryInfoCallback (nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback, void *baton) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - procSP->SetSharedLibraryInfoCallback (callback, baton); - return true; - } - return false; +nub_bool_t DNBProcessSetSharedLibraryInfoCallback( + nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback, + void *baton) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + procSP->SetSharedLibraryInfoCallback(callback, baton); + return true; + } + return false; } -nub_addr_t -DNBProcessLookupAddress (nub_process_t pid, const char *name, const char *shlib) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - { - return procSP->LookupSymbol (name, shlib); - } - return INVALID_NUB_ADDRESS; +nub_addr_t DNBProcessLookupAddress(nub_process_t pid, const char *name, + const char *shlib) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) { + return procSP->LookupSymbol(name, shlib); + } + return INVALID_NUB_ADDRESS; } +nub_size_t DNBProcessGetAvailableSTDOUT(nub_process_t pid, char *buf, + nub_size_t buf_size) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->GetAvailableSTDOUT(buf, buf_size); + return 0; +} -nub_size_t -DNBProcessGetAvailableSTDOUT (nub_process_t pid, char *buf, nub_size_t buf_size) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->GetAvailableSTDOUT (buf, buf_size); - return 0; +nub_size_t DNBProcessGetAvailableSTDERR(nub_process_t pid, char *buf, + nub_size_t buf_size) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->GetAvailableSTDERR(buf, buf_size); + return 0; } -nub_size_t -DNBProcessGetAvailableSTDERR (nub_process_t pid, char *buf, nub_size_t buf_size) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->GetAvailableSTDERR (buf, buf_size); - return 0; +nub_size_t DNBProcessGetAvailableProfileData(nub_process_t pid, char *buf, + nub_size_t buf_size) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->GetAsyncProfileData(buf, buf_size); + return 0; } -nub_size_t -DNBProcessGetAvailableProfileData (nub_process_t pid, char *buf, nub_size_t buf_size) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->GetAsyncProfileData (buf, buf_size); - return 0; +DarwinLogEventVector DNBProcessGetAvailableDarwinLogEvents(nub_process_t pid) { + return DarwinLogCollector::GetEventsForProcess(pid); } -nub_size_t -DNBProcessGetStopCount (nub_process_t pid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->StopCount(); - return 0; +nub_size_t DNBProcessGetStopCount(nub_process_t pid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->StopCount(); + return 0; } -uint32_t -DNBProcessGetCPUType (nub_process_t pid) -{ - MachProcessSP procSP; - if (GetProcessSP (pid, procSP)) - return procSP->GetCPUType (); - return 0; - +uint32_t DNBProcessGetCPUType(nub_process_t pid) { + MachProcessSP procSP; + if (GetProcessSP(pid, procSP)) + return procSP->GetCPUType(); + return 0; } -nub_bool_t -DNBResolveExecutablePath (const char *path, char *resolved_path, size_t resolved_path_size) -{ - if (path == NULL || path[0] == '\0') - return false; - - char max_path[PATH_MAX]; - std::string result; - CFString::GlobPath(path, result); - - if (result.empty()) - result = path; - - struct stat path_stat; - if (::stat(path, &path_stat) == 0) - { - if ((path_stat.st_mode & S_IFMT) == S_IFDIR) - { - CFBundle bundle (path); - CFReleaser<CFURLRef> url(bundle.CopyExecutableURL ()); - if (url.get()) - { - if (::CFURLGetFileSystemRepresentation (url.get(), true, (UInt8*)resolved_path, resolved_path_size)) - return true; - } - } - } +nub_bool_t DNBResolveExecutablePath(const char *path, char *resolved_path, + size_t resolved_path_size) { + if (path == NULL || path[0] == '\0') + return false; - if (realpath(path, max_path)) - { - // Found the path relatively... - ::strncpy(resolved_path, max_path, resolved_path_size); - return strlen(resolved_path) + 1 < resolved_path_size; - } - else - { - // Not a relative path, check the PATH environment variable if the - const char *PATH = getenv("PATH"); - if (PATH) - { - const char *curr_path_start = PATH; - const char *curr_path_end; - while (curr_path_start && *curr_path_start) - { - curr_path_end = strchr(curr_path_start, ':'); - if (curr_path_end == NULL) - { - result.assign(curr_path_start); - curr_path_start = NULL; - } - else if (curr_path_end > curr_path_start) - { - size_t len = curr_path_end - curr_path_start; - result.assign(curr_path_start, len); - curr_path_start += len + 1; - } - else - break; - - result += '/'; - result += path; - struct stat s; - if (stat(result.c_str(), &s) == 0) - { - ::strncpy(resolved_path, result.c_str(), resolved_path_size); - return result.size() + 1 < resolved_path_size; - } - } + char max_path[PATH_MAX]; + std::string result; + CFString::GlobPath(path, result); + + if (result.empty()) + result = path; + + struct stat path_stat; + if (::stat(path, &path_stat) == 0) { + if ((path_stat.st_mode & S_IFMT) == S_IFDIR) { + CFBundle bundle(path); + CFReleaser<CFURLRef> url(bundle.CopyExecutableURL()); + if (url.get()) { + if (::CFURLGetFileSystemRepresentation( + url.get(), true, (UInt8 *)resolved_path, resolved_path_size)) + return true; + } + } + } + + if (realpath(path, max_path)) { + // Found the path relatively... + ::strncpy(resolved_path, max_path, resolved_path_size); + return strlen(resolved_path) + 1 < resolved_path_size; + } else { + // Not a relative path, check the PATH environment variable if the + const char *PATH = getenv("PATH"); + if (PATH) { + const char *curr_path_start = PATH; + const char *curr_path_end; + while (curr_path_start && *curr_path_start) { + curr_path_end = strchr(curr_path_start, ':'); + if (curr_path_end == NULL) { + result.assign(curr_path_start); + curr_path_start = NULL; + } else if (curr_path_end > curr_path_start) { + size_t len = curr_path_end - curr_path_start; + result.assign(curr_path_start, len); + curr_path_start += len + 1; + } else + break; + + result += '/'; + result += path; + struct stat s; + if (stat(result.c_str(), &s) == 0) { + ::strncpy(resolved_path, result.c_str(), resolved_path_size); + return result.size() + 1 < resolved_path_size; } + } } - return false; + } + return false; } -bool -DNBGetOSVersionNumbers (uint64_t *major, uint64_t *minor, uint64_t *patch) -{ - return MachProcess::GetOSVersionNumbers (major, minor, patch); +bool DNBGetOSVersionNumbers(uint64_t *major, uint64_t *minor, uint64_t *patch) { + return MachProcess::GetOSVersionNumbers(major, minor, patch); } - -void -DNBInitialize() -{ - DNBLogThreadedIf (LOG_PROCESS, "DNBInitialize ()"); -#if defined (__i386__) || defined (__x86_64__) - DNBArchImplI386::Initialize(); - DNBArchImplX86_64::Initialize(); -#elif defined (__arm__) || defined (__arm64__) || defined (__aarch64__) - DNBArchMachARM::Initialize(); - DNBArchMachARM64::Initialize(); +void DNBInitialize() { + DNBLogThreadedIf(LOG_PROCESS, "DNBInitialize ()"); +#if defined(__i386__) || defined(__x86_64__) + DNBArchImplI386::Initialize(); + DNBArchImplX86_64::Initialize(); +#elif defined(__arm__) || defined(__arm64__) || defined(__aarch64__) + DNBArchMachARM::Initialize(); + DNBArchMachARM64::Initialize(); #endif } -void -DNBTerminate() -{ -} - -nub_bool_t -DNBSetArchitecture (const char *arch) -{ - if (arch && arch[0]) - { - if (strcasecmp (arch, "i386") == 0) - return DNBArchProtocol::SetArchitecture (CPU_TYPE_I386); - else if ((strcasecmp (arch, "x86_64") == 0) || (strcasecmp (arch, "x86_64h") == 0)) - return DNBArchProtocol::SetArchitecture (CPU_TYPE_X86_64); - else if (strstr (arch, "arm64") == arch || strstr (arch, "armv8") == arch || strstr (arch, "aarch64") == arch) - return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM64); - else if (strstr (arch, "arm") == arch) - return DNBArchProtocol::SetArchitecture (CPU_TYPE_ARM); - } - return false; +void DNBTerminate() {} + +nub_bool_t DNBSetArchitecture(const char *arch) { + if (arch && arch[0]) { + if (strcasecmp(arch, "i386") == 0) + return DNBArchProtocol::SetArchitecture(CPU_TYPE_I386); + else if ((strcasecmp(arch, "x86_64") == 0) || + (strcasecmp(arch, "x86_64h") == 0)) + return DNBArchProtocol::SetArchitecture(CPU_TYPE_X86_64); + else if (strstr(arch, "arm64") == arch || strstr(arch, "armv8") == arch || + strstr(arch, "aarch64") == arch) + return DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM64); + else if (strstr(arch, "arm") == arch) + return DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM); + } + return false; } diff --git a/tools/debugserver/source/DNB.h b/tools/debugserver/source/DNB.h index fbaf5e348133..7acbd42810cc 100644 --- a/tools/debugserver/source/DNB.h +++ b/tools/debugserver/source/DNB.h @@ -14,47 +14,49 @@ #ifndef __DNB_h__ #define __DNB_h__ +#include "DNBDefs.h" +#include "JSONGenerator.h" +#include "MacOSX/DarwinLog/DarwinLogEvent.h" #include "MacOSX/Genealogy.h" #include "MacOSX/ThreadInfo.h" -#include "JSONGenerator.h" -#include "DNBDefs.h" #include <mach/thread_info.h> #include <string> #define DNB_EXPORT __attribute__((visibility("default"))) #ifndef CPU_TYPE_ARM64 -#define CPU_TYPE_ARM64 ((cpu_type_t) 12 | 0x01000000) +#define CPU_TYPE_ARM64 ((cpu_type_t)12 | 0x01000000) #endif -typedef bool (*DNBShouldCancelCallback) (void *); +typedef bool (*DNBShouldCancelCallback)(void *); -void DNBInitialize (); -void DNBTerminate (); +void DNBInitialize(); +void DNBTerminate(); -nub_bool_t DNBSetArchitecture (const char *arch); +nub_bool_t DNBSetArchitecture(const char *arch); //---------------------------------------------------------------------- // Process control //---------------------------------------------------------------------- -nub_process_t DNBProcessLaunch (const char *path, - char const *argv[], - const char *envp[], - const char *working_directory, // NULL => don't change, non-NULL => set working directory for inferior to this - const char *stdin_path, - const char *stdout_path, - const char *stderr_path, - bool no_stdio, - nub_launch_flavor_t launch_flavor, - int disable_aslr, - const char *event_data, - char *err_str, - size_t err_len); - -nub_process_t DNBProcessGetPIDByName (const char *name); -nub_process_t DNBProcessAttach (nub_process_t pid, struct timespec *timeout, char *err_str, size_t err_len); -nub_process_t DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_str, size_t err_len); -nub_process_t DNBProcessAttachWait (const char *wait_name, nub_launch_flavor_t launch_flavor, bool ignore_existing, struct timespec *timeout, useconds_t interval, char *err_str, size_t err_len, DNBShouldCancelCallback should_cancel = NULL, void *callback_data = NULL); +nub_process_t DNBProcessLaunch( + const char *path, char const *argv[], const char *envp[], + const char *working_directory, // NULL => don't change, non-NULL => set + // working directory for inferior to this + const char *stdin_path, const char *stdout_path, const char *stderr_path, + bool no_stdio, nub_launch_flavor_t launch_flavor, int disable_aslr, + const char *event_data, char *err_str, size_t err_len); + +nub_process_t DNBProcessGetPIDByName(const char *name); +nub_process_t DNBProcessAttach(nub_process_t pid, struct timespec *timeout, + char *err_str, size_t err_len); +nub_process_t DNBProcessAttachByName(const char *name, struct timespec *timeout, + char *err_str, size_t err_len); +nub_process_t +DNBProcessAttachWait(const char *wait_name, nub_launch_flavor_t launch_flavor, + bool ignore_existing, struct timespec *timeout, + useconds_t interval, char *err_str, size_t err_len, + DNBShouldCancelCallback should_cancel = NULL, + void *callback_data = NULL); // Resume a process with exact instructions on what to do with each thread: // - If no thread actions are supplied (actions is NULL or num_actions is zero), // then all threads are continued. @@ -63,115 +65,177 @@ nub_process_t DNBProcessAttachWait (const char *wait_name, nub_launch_flavo // explicit thread action can be made by making a thread action with a tid of // INVALID_NUB_THREAD. If there is no default action, those threads will // remain stopped. -nub_bool_t DNBProcessResume (nub_process_t pid, const DNBThreadResumeAction *actions, size_t num_actions) DNB_EXPORT; -nub_bool_t DNBProcessHalt (nub_process_t pid) DNB_EXPORT; -nub_bool_t DNBProcessDetach (nub_process_t pid) DNB_EXPORT; -nub_bool_t DNBProcessSignal (nub_process_t pid, int signal) DNB_EXPORT; -nub_bool_t DNBProcessInterrupt (nub_process_t pid) DNB_EXPORT; -nub_bool_t DNBProcessKill (nub_process_t pid) DNB_EXPORT; -nub_bool_t DNBProcessSendEvent (nub_process_t pid, const char *event) DNB_EXPORT; -nub_size_t DNBProcessMemoryRead (nub_process_t pid, nub_addr_t addr, nub_size_t size, void *buf) DNB_EXPORT; -uint64_t DNBProcessMemoryReadInteger (nub_process_t pid, nub_addr_t addr, nub_size_t integer_size, uint64_t fail_value) DNB_EXPORT; -nub_addr_t DNBProcessMemoryReadPointer (nub_process_t pid, nub_addr_t addr) DNB_EXPORT; -std::string DNBProcessMemoryReadCString (nub_process_t pid, nub_addr_t addr) DNB_EXPORT; -std::string DNBProcessMemoryReadCStringFixed (nub_process_t pid, nub_addr_t addr, nub_size_t fixed_length) DNB_EXPORT; -nub_size_t DNBProcessMemoryWrite (nub_process_t pid, nub_addr_t addr, nub_size_t size, const void *buf) DNB_EXPORT; -nub_addr_t DNBProcessMemoryAllocate (nub_process_t pid, nub_size_t size, uint32_t permissions) DNB_EXPORT; -nub_bool_t DNBProcessMemoryDeallocate (nub_process_t pid, nub_addr_t addr) DNB_EXPORT; -int DNBProcessMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, DNBRegionInfo *region_info) DNB_EXPORT; -std::string DNBProcessGetProfileData (nub_process_t pid, DNBProfileDataScanType scanType) DNB_EXPORT; -nub_bool_t DNBProcessSetEnableAsyncProfiling (nub_process_t pid, nub_bool_t enable, uint64_t interval_usec, DNBProfileDataScanType scan_type) DNB_EXPORT; +nub_bool_t DNBProcessResume(nub_process_t pid, + const DNBThreadResumeAction *actions, + size_t num_actions) DNB_EXPORT; +nub_bool_t DNBProcessHalt(nub_process_t pid) DNB_EXPORT; +nub_bool_t DNBProcessDetach(nub_process_t pid) DNB_EXPORT; +nub_bool_t DNBProcessSignal(nub_process_t pid, int signal) DNB_EXPORT; +nub_bool_t DNBProcessInterrupt(nub_process_t pid) DNB_EXPORT; +nub_bool_t DNBProcessKill(nub_process_t pid) DNB_EXPORT; +nub_bool_t DNBProcessSendEvent(nub_process_t pid, const char *event) DNB_EXPORT; +nub_size_t DNBProcessMemoryRead(nub_process_t pid, nub_addr_t addr, + nub_size_t size, void *buf) DNB_EXPORT; +uint64_t DNBProcessMemoryReadInteger(nub_process_t pid, nub_addr_t addr, + nub_size_t integer_size, + uint64_t fail_value) DNB_EXPORT; +nub_addr_t DNBProcessMemoryReadPointer(nub_process_t pid, + nub_addr_t addr) DNB_EXPORT; +std::string DNBProcessMemoryReadCString(nub_process_t pid, + nub_addr_t addr) DNB_EXPORT; +std::string +DNBProcessMemoryReadCStringFixed(nub_process_t pid, nub_addr_t addr, + nub_size_t fixed_length) DNB_EXPORT; +nub_size_t DNBProcessMemoryWrite(nub_process_t pid, nub_addr_t addr, + nub_size_t size, const void *buf) DNB_EXPORT; +nub_addr_t DNBProcessMemoryAllocate(nub_process_t pid, nub_size_t size, + uint32_t permissions) DNB_EXPORT; +nub_bool_t DNBProcessMemoryDeallocate(nub_process_t pid, + nub_addr_t addr) DNB_EXPORT; +int DNBProcessMemoryRegionInfo(nub_process_t pid, nub_addr_t addr, + DNBRegionInfo *region_info) DNB_EXPORT; +std::string +DNBProcessGetProfileData(nub_process_t pid, + DNBProfileDataScanType scanType) DNB_EXPORT; +nub_bool_t +DNBProcessSetEnableAsyncProfiling(nub_process_t pid, nub_bool_t enable, + uint64_t interval_usec, + DNBProfileDataScanType scan_type) DNB_EXPORT; +DarwinLogEventVector DNBProcessGetAvailableDarwinLogEvents(nub_process_t pid); //---------------------------------------------------------------------- // Process status //---------------------------------------------------------------------- -nub_bool_t DNBProcessIsAlive (nub_process_t pid) DNB_EXPORT; -nub_state_t DNBProcessGetState (nub_process_t pid) DNB_EXPORT; -nub_bool_t DNBProcessGetExitStatus (nub_process_t pid, int *status) DNB_EXPORT; -nub_bool_t DNBProcessSetExitStatus (nub_process_t pid, int status) DNB_EXPORT; -const char * DNBProcessGetExitInfo (nub_process_t pid) DNB_EXPORT; -nub_bool_t DNBProcessSetExitInfo (nub_process_t pid, const char *info) DNB_EXPORT; -nub_size_t DNBProcessGetNumThreads (nub_process_t pid) DNB_EXPORT; -nub_thread_t DNBProcessGetCurrentThread (nub_process_t pid) DNB_EXPORT; -nub_thread_t DNBProcessGetCurrentThreadMachPort (nub_process_t pid) DNB_EXPORT; -nub_thread_t DNBProcessSetCurrentThread (nub_process_t pid, nub_thread_t tid) DNB_EXPORT; -nub_thread_t DNBProcessGetThreadAtIndex (nub_process_t pid, nub_size_t thread_idx) DNB_EXPORT; -nub_bool_t DNBProcessSyncThreadState (nub_process_t pid, nub_thread_t tid) DNB_EXPORT; -nub_addr_t DNBProcessGetSharedLibraryInfoAddress (nub_process_t pid) DNB_EXPORT; -nub_bool_t DNBProcessSharedLibrariesUpdated (nub_process_t pid) DNB_EXPORT; -nub_size_t DNBProcessGetSharedLibraryInfo (nub_process_t pid, nub_bool_t only_changed, DNBExecutableImageInfo **image_infos) DNB_EXPORT; -nub_bool_t DNBProcessSetNameToAddressCallback (nub_process_t pid, DNBCallbackNameToAddress callback, void *baton) DNB_EXPORT; -nub_bool_t DNBProcessSetSharedLibraryInfoCallback (nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback, void *baton) DNB_EXPORT; -nub_addr_t DNBProcessLookupAddress (nub_process_t pid, const char *name, const char *shlib) DNB_EXPORT; -nub_size_t DNBProcessGetAvailableSTDOUT (nub_process_t pid, char *buf, nub_size_t buf_size) DNB_EXPORT; -nub_size_t DNBProcessGetAvailableSTDERR (nub_process_t pid, char *buf, nub_size_t buf_size) DNB_EXPORT; -nub_size_t DNBProcessGetAvailableProfileData (nub_process_t pid, char *buf, nub_size_t buf_size) DNB_EXPORT; -nub_size_t DNBProcessGetStopCount (nub_process_t pid) DNB_EXPORT; -uint32_t DNBProcessGetCPUType (nub_process_t pid) DNB_EXPORT; +nub_bool_t DNBProcessIsAlive(nub_process_t pid) DNB_EXPORT; +nub_state_t DNBProcessGetState(nub_process_t pid) DNB_EXPORT; +nub_bool_t DNBProcessGetExitStatus(nub_process_t pid, int *status) DNB_EXPORT; +nub_bool_t DNBProcessSetExitStatus(nub_process_t pid, int status) DNB_EXPORT; +const char *DNBProcessGetExitInfo(nub_process_t pid) DNB_EXPORT; +nub_bool_t DNBProcessSetExitInfo(nub_process_t pid, + const char *info) DNB_EXPORT; +nub_size_t DNBProcessGetNumThreads(nub_process_t pid) DNB_EXPORT; +nub_thread_t DNBProcessGetCurrentThread(nub_process_t pid) DNB_EXPORT; +nub_thread_t DNBProcessGetCurrentThreadMachPort(nub_process_t pid) DNB_EXPORT; +nub_thread_t DNBProcessSetCurrentThread(nub_process_t pid, + nub_thread_t tid) DNB_EXPORT; +nub_thread_t DNBProcessGetThreadAtIndex(nub_process_t pid, + nub_size_t thread_idx) DNB_EXPORT; +nub_bool_t DNBProcessSyncThreadState(nub_process_t pid, + nub_thread_t tid) DNB_EXPORT; +nub_addr_t DNBProcessGetSharedLibraryInfoAddress(nub_process_t pid) DNB_EXPORT; +nub_bool_t DNBProcessSharedLibrariesUpdated(nub_process_t pid) DNB_EXPORT; +nub_size_t +DNBProcessGetSharedLibraryInfo(nub_process_t pid, nub_bool_t only_changed, + DNBExecutableImageInfo **image_infos) DNB_EXPORT; +nub_bool_t DNBProcessSetNameToAddressCallback(nub_process_t pid, + DNBCallbackNameToAddress callback, + void *baton) DNB_EXPORT; +nub_bool_t DNBProcessSetSharedLibraryInfoCallback( + nub_process_t pid, DNBCallbackCopyExecutableImageInfos callback, + void *baton) DNB_EXPORT; +nub_addr_t DNBProcessLookupAddress(nub_process_t pid, const char *name, + const char *shlib) DNB_EXPORT; +nub_size_t DNBProcessGetAvailableSTDOUT(nub_process_t pid, char *buf, + nub_size_t buf_size) DNB_EXPORT; +nub_size_t DNBProcessGetAvailableSTDERR(nub_process_t pid, char *buf, + nub_size_t buf_size) DNB_EXPORT; +nub_size_t DNBProcessGetAvailableProfileData(nub_process_t pid, char *buf, + nub_size_t buf_size) DNB_EXPORT; +nub_size_t DNBProcessGetStopCount(nub_process_t pid) DNB_EXPORT; +uint32_t DNBProcessGetCPUType(nub_process_t pid) DNB_EXPORT; //---------------------------------------------------------------------- // Process executable and arguments //---------------------------------------------------------------------- -const char * DNBProcessGetExecutablePath (nub_process_t pid); -const char * DNBProcessGetArgumentAtIndex (nub_process_t pid, nub_size_t idx); -nub_size_t DNBProcessGetArgumentCount (nub_process_t pid); +const char *DNBProcessGetExecutablePath(nub_process_t pid); +const char *DNBProcessGetArgumentAtIndex(nub_process_t pid, nub_size_t idx); +nub_size_t DNBProcessGetArgumentCount(nub_process_t pid); //---------------------------------------------------------------------- // Process events //---------------------------------------------------------------------- -nub_event_t DNBProcessWaitForEvents (nub_process_t pid, nub_event_t event_mask, bool wait_for_set, struct timespec* timeout); -void DNBProcessResetEvents (nub_process_t pid, nub_event_t event_mask); +nub_event_t DNBProcessWaitForEvents(nub_process_t pid, nub_event_t event_mask, + bool wait_for_set, + struct timespec *timeout); +void DNBProcessResetEvents(nub_process_t pid, nub_event_t event_mask); //---------------------------------------------------------------------- // Thread functions //---------------------------------------------------------------------- -const char * DNBThreadGetName (nub_process_t pid, nub_thread_t tid); -nub_bool_t DNBThreadGetIdentifierInfo (nub_process_t pid, nub_thread_t tid, thread_identifier_info_data_t *ident_info); -nub_state_t DNBThreadGetState (nub_process_t pid, nub_thread_t tid); -nub_bool_t DNBThreadGetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *value); -nub_bool_t DNBThreadSetRegisterValueByID (nub_process_t pid, nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value); -nub_size_t DNBThreadGetRegisterContext (nub_process_t pid, nub_thread_t tid, void *buf, size_t buf_len); -nub_size_t DNBThreadSetRegisterContext (nub_process_t pid, nub_thread_t tid, const void *buf, size_t buf_len); -uint32_t DNBThreadSaveRegisterState (nub_process_t pid, nub_thread_t tid); -nub_bool_t DNBThreadRestoreRegisterState (nub_process_t pid, nub_thread_t tid, uint32_t save_id); -nub_bool_t DNBThreadGetRegisterValueByName (nub_process_t pid, nub_thread_t tid, uint32_t set, const char *name, DNBRegisterValue *value); -nub_bool_t DNBThreadGetStopReason (nub_process_t pid, nub_thread_t tid, DNBThreadStopInfo *stop_info); -const char * DNBThreadGetInfo (nub_process_t pid, nub_thread_t tid); -Genealogy::ThreadActivitySP DNBGetGenealogyInfoForThread (nub_process_t pid, nub_thread_t tid, bool &timed_out); -Genealogy::ProcessExecutableInfoSP DNBGetGenealogyImageInfo (nub_process_t pid, size_t idx); -ThreadInfo::QoS DNBGetRequestedQoSForThread (nub_process_t pid, nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index); -nub_addr_t DNBGetPThreadT (nub_process_t pid, nub_thread_t tid); -nub_addr_t DNBGetDispatchQueueT (nub_process_t pid, nub_thread_t tid); -nub_addr_t DNBGetTSDAddressForThread (nub_process_t pid, nub_thread_t tid, uint64_t plo_pthread_tsd_base_address_offset, uint64_t plo_pthread_tsd_base_offset, uint64_t plo_pthread_tsd_entry_size); -JSONGenerator::ObjectSP DNBGetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count); -JSONGenerator::ObjectSP DNBGetAllLoadedLibrariesInfos (nub_process_t pid); -JSONGenerator::ObjectSP DNBGetLibrariesInfoForAddresses (nub_process_t pid, std::vector<uint64_t> &macho_addresses); -JSONGenerator::ObjectSP DNBGetSharedCacheInfo (nub_process_t pid); +const char *DNBThreadGetName(nub_process_t pid, nub_thread_t tid); +nub_bool_t +DNBThreadGetIdentifierInfo(nub_process_t pid, nub_thread_t tid, + thread_identifier_info_data_t *ident_info); +nub_state_t DNBThreadGetState(nub_process_t pid, nub_thread_t tid); +nub_bool_t DNBThreadGetRegisterValueByID(nub_process_t pid, nub_thread_t tid, + uint32_t set, uint32_t reg, + DNBRegisterValue *value); +nub_bool_t DNBThreadSetRegisterValueByID(nub_process_t pid, nub_thread_t tid, + uint32_t set, uint32_t reg, + const DNBRegisterValue *value); +nub_size_t DNBThreadGetRegisterContext(nub_process_t pid, nub_thread_t tid, + void *buf, size_t buf_len); +nub_size_t DNBThreadSetRegisterContext(nub_process_t pid, nub_thread_t tid, + const void *buf, size_t buf_len); +uint32_t DNBThreadSaveRegisterState(nub_process_t pid, nub_thread_t tid); +nub_bool_t DNBThreadRestoreRegisterState(nub_process_t pid, nub_thread_t tid, + uint32_t save_id); +nub_bool_t DNBThreadGetRegisterValueByName(nub_process_t pid, nub_thread_t tid, + uint32_t set, const char *name, + DNBRegisterValue *value); +nub_bool_t DNBThreadGetStopReason(nub_process_t pid, nub_thread_t tid, + DNBThreadStopInfo *stop_info); +const char *DNBThreadGetInfo(nub_process_t pid, nub_thread_t tid); +Genealogy::ThreadActivitySP DNBGetGenealogyInfoForThread(nub_process_t pid, + nub_thread_t tid, + bool &timed_out); +Genealogy::ProcessExecutableInfoSP DNBGetGenealogyImageInfo(nub_process_t pid, + size_t idx); +ThreadInfo::QoS DNBGetRequestedQoSForThread(nub_process_t pid, nub_thread_t tid, + nub_addr_t tsd, + uint64_t dti_qos_class_index); +nub_addr_t DNBGetPThreadT(nub_process_t pid, nub_thread_t tid); +nub_addr_t DNBGetDispatchQueueT(nub_process_t pid, nub_thread_t tid); +nub_addr_t +DNBGetTSDAddressForThread(nub_process_t pid, nub_thread_t tid, + uint64_t plo_pthread_tsd_base_address_offset, + uint64_t plo_pthread_tsd_base_offset, + uint64_t plo_pthread_tsd_entry_size); +JSONGenerator::ObjectSP DNBGetLoadedDynamicLibrariesInfos( + nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count); +JSONGenerator::ObjectSP DNBGetAllLoadedLibrariesInfos(nub_process_t pid); +JSONGenerator::ObjectSP +DNBGetLibrariesInfoForAddresses(nub_process_t pid, + std::vector<uint64_t> &macho_addresses); +JSONGenerator::ObjectSP DNBGetSharedCacheInfo(nub_process_t pid); // //---------------------------------------------------------------------- // Breakpoint functions //---------------------------------------------------------------------- -nub_bool_t DNBBreakpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, nub_bool_t hardware); -nub_bool_t DNBBreakpointClear (nub_process_t pid, nub_addr_t addr); +nub_bool_t DNBBreakpointSet(nub_process_t pid, nub_addr_t addr, nub_size_t size, + nub_bool_t hardware); +nub_bool_t DNBBreakpointClear(nub_process_t pid, nub_addr_t addr); //---------------------------------------------------------------------- // Watchpoint functions //---------------------------------------------------------------------- -nub_bool_t DNBWatchpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, uint32_t watch_flags, nub_bool_t hardware); -nub_bool_t DNBWatchpointClear (nub_process_t pid, nub_addr_t addr); -uint32_t DNBWatchpointGetNumSupportedHWP (nub_process_t pid); +nub_bool_t DNBWatchpointSet(nub_process_t pid, nub_addr_t addr, nub_size_t size, + uint32_t watch_flags, nub_bool_t hardware); +nub_bool_t DNBWatchpointClear(nub_process_t pid, nub_addr_t addr); +uint32_t DNBWatchpointGetNumSupportedHWP(nub_process_t pid); -uint32_t DNBGetRegisterCPUType (); -const DNBRegisterSetInfo * - DNBGetRegisterSetInfo (nub_size_t *num_reg_sets); -nub_bool_t DNBGetRegisterInfoByName (const char *reg_name, DNBRegisterInfo* info); +uint32_t DNBGetRegisterCPUType(); +const DNBRegisterSetInfo *DNBGetRegisterSetInfo(nub_size_t *num_reg_sets); +nub_bool_t DNBGetRegisterInfoByName(const char *reg_name, + DNBRegisterInfo *info); //---------------------------------------------------------------------- // Other static nub information calls. //---------------------------------------------------------------------- -const char * DNBStateAsString (nub_state_t state); -nub_bool_t DNBResolveExecutablePath (const char *path, char *resolved_path, size_t resolved_path_size); -bool DNBGetOSVersionNumbers (uint64_t *major, uint64_t *minor, uint64_t *patch); +const char *DNBStateAsString(nub_state_t state); +nub_bool_t DNBResolveExecutablePath(const char *path, char *resolved_path, + size_t resolved_path_size); +bool DNBGetOSVersionNumbers(uint64_t *major, uint64_t *minor, uint64_t *patch); #endif diff --git a/tools/debugserver/source/DNBArch.cpp b/tools/debugserver/source/DNBArch.cpp index f17a719e92ec..1312bcf7dfdd 100644 --- a/tools/debugserver/source/DNBArch.cpp +++ b/tools/debugserver/source/DNBArch.cpp @@ -24,74 +24,57 @@ typedef std::map<uint32_t, DNBArchPluginInfo> CPUPluginInfoMap; static uint32_t g_current_cpu_type = 0; CPUPluginInfoMap g_arch_plugins; - -static const DNBArchPluginInfo * -GetArchInfo () -{ - CPUPluginInfoMap::const_iterator pos = g_arch_plugins.find(g_current_cpu_type); - if (pos != g_arch_plugins.end()) - return &pos->second; - return NULL; +static const DNBArchPluginInfo *GetArchInfo() { + CPUPluginInfoMap::const_iterator pos = + g_arch_plugins.find(g_current_cpu_type); + if (pos != g_arch_plugins.end()) + return &pos->second; + return NULL; } +uint32_t DNBArchProtocol::GetArchitecture() { return g_current_cpu_type; } -uint32_t -DNBArchProtocol::GetArchitecture () -{ - return g_current_cpu_type; -} - -bool -DNBArchProtocol::SetArchitecture (uint32_t cpu_type) -{ - g_current_cpu_type = cpu_type; - bool result = g_arch_plugins.find(g_current_cpu_type) != g_arch_plugins.end(); - DNBLogThreadedIf (LOG_PROCESS, "DNBArchProtocol::SetDefaultArchitecture (cpu_type=0x%8.8x) => %i", cpu_type, result); - return result; +bool DNBArchProtocol::SetArchitecture(uint32_t cpu_type) { + g_current_cpu_type = cpu_type; + bool result = g_arch_plugins.find(g_current_cpu_type) != g_arch_plugins.end(); + DNBLogThreadedIf( + LOG_PROCESS, + "DNBArchProtocol::SetDefaultArchitecture (cpu_type=0x%8.8x) => %i", + cpu_type, result); + return result; } -void -DNBArchProtocol::RegisterArchPlugin (const DNBArchPluginInfo &arch_info) -{ - if (arch_info.cpu_type) - g_arch_plugins[arch_info.cpu_type] = arch_info; +void DNBArchProtocol::RegisterArchPlugin(const DNBArchPluginInfo &arch_info) { + if (arch_info.cpu_type) + g_arch_plugins[arch_info.cpu_type] = arch_info; } -uint32_t -DNBArchProtocol::GetRegisterCPUType () -{ - const DNBArchPluginInfo *arch_info = GetArchInfo (); - if (arch_info) - return arch_info->cpu_type; - return 0; +uint32_t DNBArchProtocol::GetRegisterCPUType() { + const DNBArchPluginInfo *arch_info = GetArchInfo(); + if (arch_info) + return arch_info->cpu_type; + return 0; } const DNBRegisterSetInfo * -DNBArchProtocol::GetRegisterSetInfo (nub_size_t *num_reg_sets) -{ - const DNBArchPluginInfo *arch_info = GetArchInfo (); - if (arch_info) - return arch_info->GetRegisterSetInfo (num_reg_sets); - *num_reg_sets = 0; - return NULL; +DNBArchProtocol::GetRegisterSetInfo(nub_size_t *num_reg_sets) { + const DNBArchPluginInfo *arch_info = GetArchInfo(); + if (arch_info) + return arch_info->GetRegisterSetInfo(num_reg_sets); + *num_reg_sets = 0; + return NULL; } -DNBArchProtocol * -DNBArchProtocol::Create (MachThread *thread) -{ - const DNBArchPluginInfo *arch_info = GetArchInfo (); - if (arch_info) - return arch_info->Create (thread); - return NULL; - +DNBArchProtocol *DNBArchProtocol::Create(MachThread *thread) { + const DNBArchPluginInfo *arch_info = GetArchInfo(); + if (arch_info) + return arch_info->Create(thread); + return NULL; } -const uint8_t * -DNBArchProtocol::GetBreakpointOpcode (nub_size_t byte_size) -{ - const DNBArchPluginInfo *arch_info = GetArchInfo (); - if (arch_info) - return arch_info->GetBreakpointOpcode (byte_size); - return NULL; +const uint8_t *DNBArchProtocol::GetBreakpointOpcode(nub_size_t byte_size) { + const DNBArchPluginInfo *arch_info = GetArchInfo(); + if (arch_info) + return arch_info->GetBreakpointOpcode(byte_size); + return NULL; } - diff --git a/tools/debugserver/source/DNBArch.h b/tools/debugserver/source/DNBArch.h index c07d3a67400d..317da70e6422 100644 --- a/tools/debugserver/source/DNBArch.h +++ b/tools/debugserver/source/DNBArch.h @@ -25,105 +25,103 @@ struct DNBRegisterSetInfo; class DNBArchProtocol; class MachThread; -typedef DNBArchProtocol * (* DNBArchCallbackCreate)(MachThread *thread); -typedef const DNBRegisterSetInfo * (* DNBArchCallbackGetRegisterSetInfo)(nub_size_t *num_reg_sets); -typedef const uint8_t * (* DNBArchCallbackGetBreakpointOpcode)(nub_size_t byte_size); - -typedef struct DNBArchPluginInfoTag -{ - uint32_t cpu_type; - DNBArchCallbackCreate Create; - DNBArchCallbackGetRegisterSetInfo GetRegisterSetInfo; - DNBArchCallbackGetBreakpointOpcode GetBreakpointOpcode; +typedef DNBArchProtocol *(*DNBArchCallbackCreate)(MachThread *thread); +typedef const DNBRegisterSetInfo *(*DNBArchCallbackGetRegisterSetInfo)( + nub_size_t *num_reg_sets); +typedef const uint8_t *(*DNBArchCallbackGetBreakpointOpcode)( + nub_size_t byte_size); + +typedef struct DNBArchPluginInfoTag { + uint32_t cpu_type; + DNBArchCallbackCreate Create; + DNBArchCallbackGetRegisterSetInfo GetRegisterSetInfo; + DNBArchCallbackGetBreakpointOpcode GetBreakpointOpcode; } DNBArchPluginInfo; -class DNBArchProtocol -{ +class DNBArchProtocol { public: - static DNBArchProtocol * - Create (MachThread *thread); - - static uint32_t - GetRegisterCPUType (); - - static const DNBRegisterSetInfo * - GetRegisterSetInfo (nub_size_t *num_reg_sets); - - static const uint8_t * - GetBreakpointOpcode (nub_size_t byte_size); - - static void - RegisterArchPlugin (const DNBArchPluginInfo &arch_info); - - static uint32_t - GetArchitecture (); - - static bool - SetArchitecture (uint32_t cpu_type); - - DNBArchProtocol () : - m_save_id(0) - { - - } - - virtual ~DNBArchProtocol () - { - - } - virtual bool GetRegisterValue (uint32_t set, uint32_t reg, DNBRegisterValue *value) = 0; - virtual bool SetRegisterValue (uint32_t set, uint32_t reg, const DNBRegisterValue *value) = 0; - virtual nub_size_t GetRegisterContext (void *buf, nub_size_t buf_len) = 0; - virtual nub_size_t SetRegisterContext (const void *buf, nub_size_t buf_len) = 0; - virtual uint32_t SaveRegisterState () = 0; - virtual bool RestoreRegisterState (uint32_t save_id) = 0; - - virtual kern_return_t GetRegisterState (int set, bool force) = 0; - virtual kern_return_t SetRegisterState (int set) = 0; - virtual bool RegisterSetStateIsValid (int set) const = 0; - - virtual uint64_t GetPC (uint64_t failValue) = 0; // Get program counter - virtual kern_return_t SetPC (uint64_t value) = 0; - virtual uint64_t GetSP (uint64_t failValue) = 0; // Get stack pointer - virtual void ThreadWillResume () = 0; - virtual bool ThreadDidStop () = 0; - virtual bool NotifyException (MachException::Data& exc) { return false; } - virtual uint32_t NumSupportedHardwareBreakpoints() { return 0; } - virtual uint32_t NumSupportedHardwareWatchpoints() { return 0; } - virtual uint32_t EnableHardwareBreakpoint (nub_addr_t addr, nub_size_t size) { return INVALID_NUB_HW_INDEX; } - virtual uint32_t EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task) { return INVALID_NUB_HW_INDEX; } - virtual bool DisableHardwareBreakpoint (uint32_t hw_index) { return false; } - virtual bool DisableHardwareWatchpoint (uint32_t hw_index, bool also_set_on_task) { return false; } - virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr) { return INVALID_NUB_HW_INDEX; } - virtual bool StepNotComplete () { return false; } + static DNBArchProtocol *Create(MachThread *thread); + + static uint32_t GetRegisterCPUType(); + + static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets); + + static const uint8_t *GetBreakpointOpcode(nub_size_t byte_size); + + static void RegisterArchPlugin(const DNBArchPluginInfo &arch_info); + + static uint32_t GetArchitecture(); + + static bool SetArchitecture(uint32_t cpu_type); + + DNBArchProtocol() : m_save_id(0) {} + + virtual ~DNBArchProtocol() {} + virtual bool GetRegisterValue(uint32_t set, uint32_t reg, + DNBRegisterValue *value) = 0; + virtual bool SetRegisterValue(uint32_t set, uint32_t reg, + const DNBRegisterValue *value) = 0; + virtual nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len) = 0; + virtual nub_size_t SetRegisterContext(const void *buf, + nub_size_t buf_len) = 0; + virtual uint32_t SaveRegisterState() = 0; + virtual bool RestoreRegisterState(uint32_t save_id) = 0; + + virtual kern_return_t GetRegisterState(int set, bool force) = 0; + virtual kern_return_t SetRegisterState(int set) = 0; + virtual bool RegisterSetStateIsValid(int set) const = 0; + + virtual uint64_t GetPC(uint64_t failValue) = 0; // Get program counter + virtual kern_return_t SetPC(uint64_t value) = 0; + virtual uint64_t GetSP(uint64_t failValue) = 0; // Get stack pointer + virtual void ThreadWillResume() = 0; + virtual bool ThreadDidStop() = 0; + virtual bool NotifyException(MachException::Data &exc) { return false; } + virtual uint32_t NumSupportedHardwareBreakpoints() { return 0; } + virtual uint32_t NumSupportedHardwareWatchpoints() { return 0; } + virtual uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size) { + return INVALID_NUB_HW_INDEX; + } + virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, + bool read, bool write, + bool also_set_on_task) { + return INVALID_NUB_HW_INDEX; + } + virtual bool DisableHardwareBreakpoint(uint32_t hw_index) { return false; } + virtual bool DisableHardwareWatchpoint(uint32_t hw_index, + bool also_set_on_task) { + return false; + } + virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr) { + return INVALID_NUB_HW_INDEX; + } + virtual bool StepNotComplete() { return false; } protected: - friend class MachThread; - - uint32_t GetNextRegisterStateSaveID () - { - return ++m_save_id; - } - - enum - { - Trans_Pending = 0, // Transaction is pending, and checkpoint state has been snapshotted. - Trans_Done = 1, // Transaction is done, the current state is committed, and checkpoint state is irrelevant. - Trans_Rolled_Back = 2 // Transaction is done, the current state has been rolled back to the checkpoint state. - }; - virtual bool StartTransForHWP() { return true; } - virtual bool RollbackTransForHWP() { return true; } - virtual bool FinishTransForHWP() { return true; } - - uint32_t m_save_id; // An always incrementing integer ID used with SaveRegisterState/RestoreRegisterState - + friend class MachThread; + + uint32_t GetNextRegisterStateSaveID() { return ++m_save_id; } + + enum { + Trans_Pending = + 0, // Transaction is pending, and checkpoint state has been snapshotted. + Trans_Done = 1, // Transaction is done, the current state is committed, and + // checkpoint state is irrelevant. + Trans_Rolled_Back = 2 // Transaction is done, the current state has been + // rolled back to the checkpoint state. + }; + virtual bool StartTransForHWP() { return true; } + virtual bool RollbackTransForHWP() { return true; } + virtual bool FinishTransForHWP() { return true; } + + uint32_t m_save_id; // An always incrementing integer ID used with + // SaveRegisterState/RestoreRegisterState }; - #include "MacOSX/arm/DNBArchImpl.h" #include "MacOSX/arm64/DNBArchImplARM64.h" #include "MacOSX/i386/DNBArchImplI386.h" -#include "MacOSX/x86_64/DNBArchImplX86_64.h" #include "MacOSX/ppc/DNBArchImpl.h" +#include "MacOSX/x86_64/DNBArchImplX86_64.h" #endif diff --git a/tools/debugserver/source/DNBBreakpoint.cpp b/tools/debugserver/source/DNBBreakpoint.cpp index 2645f173306b..89a91287f9e3 100644 --- a/tools/debugserver/source/DNBBreakpoint.cpp +++ b/tools/debugserver/source/DNBBreakpoint.cpp @@ -12,214 +12,167 @@ //===----------------------------------------------------------------------===// #include "DNBBreakpoint.h" +#include "DNBLog.h" #include "MachProcess.h" -#include <assert.h> #include <algorithm> +#include <assert.h> #include <inttypes.h> -#include "DNBLog.h" - - -#pragma mark -- DNBBreakpoint -DNBBreakpoint::DNBBreakpoint(nub_addr_t addr, nub_size_t byte_size, bool hardware) : - m_retain_count (1), - m_byte_size (static_cast<uint32_t>(byte_size)), - m_opcode(), - m_addr(addr), - m_enabled(0), - m_hw_preferred(hardware), - m_is_watchpoint(0), - m_watch_read(0), - m_watch_write(0), - m_hw_index(INVALID_NUB_HW_INDEX) -{ -} - -DNBBreakpoint::~DNBBreakpoint() -{ -} - -void -DNBBreakpoint::Dump() const -{ - if (IsBreakpoint()) - { - DNBLog ("DNBBreakpoint addr = 0x%llx state = %s type = %s breakpoint hw_index = %i", - (uint64_t)m_addr, - m_enabled ? "enabled " : "disabled", - IsHardware() ? "hardware" : "software", - GetHardwareIndex()); - } - else - { - DNBLog ("DNBBreakpoint addr = 0x%llx size = %llu state = %s type = %s watchpoint (%s%s) hw_index = %i", - (uint64_t)m_addr, - (uint64_t)m_byte_size, - m_enabled ? "enabled " : "disabled", - IsHardware() ? "hardware" : "software", - m_watch_read ? "r" : "", - m_watch_write ? "w" : "", - GetHardwareIndex()); - } -} - -#pragma mark -- DNBBreakpointList - -DNBBreakpointList::DNBBreakpointList() -{ -} -DNBBreakpointList::~DNBBreakpointList() -{ -} - - -DNBBreakpoint * -DNBBreakpointList::Add(nub_addr_t addr, nub_size_t length, bool hardware) -{ - m_breakpoints.insert(std::make_pair(addr, DNBBreakpoint(addr, length, hardware))); - iterator pos = m_breakpoints.find (addr); +#pragma mark-- DNBBreakpoint +DNBBreakpoint::DNBBreakpoint(nub_addr_t addr, nub_size_t byte_size, + bool hardware) + : m_retain_count(1), m_byte_size(static_cast<uint32_t>(byte_size)), + m_opcode(), m_addr(addr), m_enabled(0), m_hw_preferred(hardware), + m_is_watchpoint(0), m_watch_read(0), m_watch_write(0), + m_hw_index(INVALID_NUB_HW_INDEX) {} + +DNBBreakpoint::~DNBBreakpoint() {} + +void DNBBreakpoint::Dump() const { + if (IsBreakpoint()) { + DNBLog("DNBBreakpoint addr = 0x%llx state = %s type = %s breakpoint " + "hw_index = %i", + (uint64_t)m_addr, m_enabled ? "enabled " : "disabled", + IsHardware() ? "hardware" : "software", GetHardwareIndex()); + } else { + DNBLog("DNBBreakpoint addr = 0x%llx size = %llu state = %s type = %s " + "watchpoint (%s%s) hw_index = %i", + (uint64_t)m_addr, (uint64_t)m_byte_size, + m_enabled ? "enabled " : "disabled", + IsHardware() ? "hardware" : "software", m_watch_read ? "r" : "", + m_watch_write ? "w" : "", GetHardwareIndex()); + } +} + +#pragma mark-- DNBBreakpointList + +DNBBreakpointList::DNBBreakpointList() {} + +DNBBreakpointList::~DNBBreakpointList() {} + +DNBBreakpoint *DNBBreakpointList::Add(nub_addr_t addr, nub_size_t length, + bool hardware) { + m_breakpoints.insert( + std::make_pair(addr, DNBBreakpoint(addr, length, hardware))); + iterator pos = m_breakpoints.find(addr); + return &pos->second; +} + +bool DNBBreakpointList::Remove(nub_addr_t addr) { + iterator pos = m_breakpoints.find(addr); + if (pos != m_breakpoints.end()) { + m_breakpoints.erase(pos); + return true; + } + return false; +} + +DNBBreakpoint *DNBBreakpointList::FindByAddress(nub_addr_t addr) { + iterator pos = m_breakpoints.find(addr); + if (pos != m_breakpoints.end()) return &pos->second; -} -bool -DNBBreakpointList::Remove (nub_addr_t addr) -{ - iterator pos = m_breakpoints.find(addr); - if (pos != m_breakpoints.end()) - { - m_breakpoints.erase(pos); - return true; - } - return false; + return NULL; } -DNBBreakpoint * -DNBBreakpointList::FindByAddress (nub_addr_t addr) -{ - iterator pos = m_breakpoints.find(addr); - if (pos != m_breakpoints.end()) - return &pos->second; - - return NULL; -} +const DNBBreakpoint *DNBBreakpointList::FindByAddress(nub_addr_t addr) const { + const_iterator pos = m_breakpoints.find(addr); + if (pos != m_breakpoints.end()) + return &pos->second; -const DNBBreakpoint * -DNBBreakpointList::FindByAddress (nub_addr_t addr) const -{ - const_iterator pos = m_breakpoints.find(addr); - if (pos != m_breakpoints.end()) - return &pos->second; - - return NULL; + return NULL; } // Finds the next breakpoint at an address greater than or equal to "addr" -size_t -DNBBreakpointList::FindBreakpointsThatOverlapRange (nub_addr_t addr, - nub_addr_t size, - std::vector<DNBBreakpoint *> &bps) -{ - bps.clear(); - iterator end = m_breakpoints.end(); - // Find the first breakpoint with an address >= to "addr" - iterator pos = m_breakpoints.lower_bound(addr); - if (pos != end) - { - if (pos != m_breakpoints.begin()) - { - // Watch out for a breakpoint at an address less than "addr" that might still overlap - iterator prev_pos = pos; - --prev_pos; - if (prev_pos->second.IntersectsRange (addr, size, NULL, NULL, NULL)) - bps.push_back (&pos->second); - - } - - while (pos != end) - { - // When we hit a breakpoint whose start address is greater than "addr + size" we are done. - // Do the math in a way that doesn't risk unsigned overflow with bad input. - if ((pos->second.Address() - addr) >= size) - break; - - // Check if this breakpoint overlaps, and if it does, add it to the list - if (pos->second.IntersectsRange (addr, size, NULL, NULL, NULL)) - { - bps.push_back (&pos->second); - ++pos; - } - } +size_t DNBBreakpointList::FindBreakpointsThatOverlapRange( + nub_addr_t addr, nub_addr_t size, std::vector<DNBBreakpoint *> &bps) { + bps.clear(); + iterator end = m_breakpoints.end(); + // Find the first breakpoint with an address >= to "addr" + iterator pos = m_breakpoints.lower_bound(addr); + if (pos != end) { + if (pos != m_breakpoints.begin()) { + // Watch out for a breakpoint at an address less than "addr" that might + // still overlap + iterator prev_pos = pos; + --prev_pos; + if (prev_pos->second.IntersectsRange(addr, size, NULL, NULL, NULL)) + bps.push_back(&pos->second); } - return bps.size(); -} -void -DNBBreakpointList::Dump() const -{ - const_iterator pos; - const_iterator end = m_breakpoints.end(); - for (pos = m_breakpoints.begin(); pos != end; ++pos) - pos->second.Dump(); -} - -void -DNBBreakpointList::DisableAll () -{ - iterator pos, end = m_breakpoints.end(); - for (pos = m_breakpoints.begin(); pos != end; ++pos) - pos->second.SetEnabled(false); -} - - -void -DNBBreakpointList::RemoveTrapsFromBuffer (nub_addr_t addr, nub_size_t size, void *p) const -{ - uint8_t *buf = (uint8_t *)p; - const_iterator end = m_breakpoints.end(); - const_iterator pos = m_breakpoints.lower_bound(addr); - while (pos != end && (pos->first < (addr + size))) - { - nub_addr_t intersect_addr; - nub_size_t intersect_size; - nub_size_t opcode_offset; - const DNBBreakpoint &bp = pos->second; - if (bp.IntersectsRange(addr, size, &intersect_addr, &intersect_size, &opcode_offset)) - { - assert(addr <= intersect_addr && intersect_addr < addr + size); - assert(addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= addr + size); - assert(opcode_offset + intersect_size <= bp.ByteSize()); - nub_size_t buf_offset = intersect_addr - addr; - ::memcpy(buf + buf_offset, bp.SavedOpcodeBytes() + opcode_offset, intersect_size); - } + while (pos != end) { + // When we hit a breakpoint whose start address is greater than "addr + + // size" we are done. + // Do the math in a way that doesn't risk unsigned overflow with bad + // input. + if ((pos->second.Address() - addr) >= size) + break; + + // Check if this breakpoint overlaps, and if it does, add it to the list + if (pos->second.IntersectsRange(addr, size, NULL, NULL, NULL)) { + bps.push_back(&pos->second); ++pos; + } + } + } + return bps.size(); +} + +void DNBBreakpointList::Dump() const { + const_iterator pos; + const_iterator end = m_breakpoints.end(); + for (pos = m_breakpoints.begin(); pos != end; ++pos) + pos->second.Dump(); +} + +void DNBBreakpointList::DisableAll() { + iterator pos, end = m_breakpoints.end(); + for (pos = m_breakpoints.begin(); pos != end; ++pos) + pos->second.SetEnabled(false); +} + +void DNBBreakpointList::RemoveTrapsFromBuffer(nub_addr_t addr, nub_size_t size, + void *p) const { + uint8_t *buf = (uint8_t *)p; + const_iterator end = m_breakpoints.end(); + const_iterator pos = m_breakpoints.lower_bound(addr); + while (pos != end && (pos->first < (addr + size))) { + nub_addr_t intersect_addr; + nub_size_t intersect_size; + nub_size_t opcode_offset; + const DNBBreakpoint &bp = pos->second; + if (bp.IntersectsRange(addr, size, &intersect_addr, &intersect_size, + &opcode_offset)) { + assert(addr <= intersect_addr && intersect_addr < addr + size); + assert(addr < intersect_addr + intersect_size && + intersect_addr + intersect_size <= addr + size); + assert(opcode_offset + intersect_size <= bp.ByteSize()); + nub_size_t buf_offset = intersect_addr - addr; + ::memcpy(buf + buf_offset, bp.SavedOpcodeBytes() + opcode_offset, + intersect_size); } + ++pos; + } } -void -DNBBreakpointList::DisableAllBreakpoints(MachProcess *process) -{ - iterator pos, end = m_breakpoints.end(); - for (pos = m_breakpoints.begin(); pos != end; ++pos) - process->DisableBreakpoint(pos->second.Address(), false); +void DNBBreakpointList::DisableAllBreakpoints(MachProcess *process) { + iterator pos, end = m_breakpoints.end(); + for (pos = m_breakpoints.begin(); pos != end; ++pos) + process->DisableBreakpoint(pos->second.Address(), false); } -void -DNBBreakpointList::DisableAllWatchpoints(MachProcess *process) -{ - iterator pos, end = m_breakpoints.end(); - for (pos = m_breakpoints.begin(); pos != end; ++pos) - process->DisableWatchpoint(pos->second.Address(), false); +void DNBBreakpointList::DisableAllWatchpoints(MachProcess *process) { + iterator pos, end = m_breakpoints.end(); + for (pos = m_breakpoints.begin(); pos != end; ++pos) + process->DisableWatchpoint(pos->second.Address(), false); } -void -DNBBreakpointList::RemoveDisabled() -{ - iterator pos = m_breakpoints.begin(); - while (pos != m_breakpoints.end()) - { - if (!pos->second.IsEnabled()) - pos = m_breakpoints.erase(pos); - else - ++pos; - } +void DNBBreakpointList::RemoveDisabled() { + iterator pos = m_breakpoints.begin(); + while (pos != m_breakpoints.end()) { + if (!pos->second.IsEnabled()) + pos = m_breakpoints.erase(pos); + else + ++pos; + } } diff --git a/tools/debugserver/source/DNBBreakpoint.h b/tools/debugserver/source/DNBBreakpoint.h index c764dbd6cf29..889478b28957 100644 --- a/tools/debugserver/source/DNBBreakpoint.h +++ b/tools/debugserver/source/DNBBreakpoint.h @@ -23,143 +23,127 @@ class MachProcess; -class DNBBreakpoint -{ +class DNBBreakpoint { public: - DNBBreakpoint(nub_addr_t m_addr, nub_size_t byte_size, bool hardware); - ~DNBBreakpoint(); - - nub_size_t ByteSize() const { return m_byte_size; } - uint8_t * SavedOpcodeBytes() { return &m_opcode[0]; } - const uint8_t * - SavedOpcodeBytes() const { return &m_opcode[0]; } - nub_addr_t Address() const { return m_addr; } -// nub_thread_t ThreadID() const { return m_tid; } - bool IsEnabled() const { return m_enabled; } - bool IntersectsRange(nub_addr_t addr, - nub_size_t size, - nub_addr_t *intersect_addr, - nub_size_t *intersect_size, - nub_size_t *opcode_offset) const - { - // We only use software traps for software breakpoints - if (IsBreakpoint() && IsEnabled() && !IsHardware()) - { - if (m_byte_size > 0) - { - const nub_addr_t bp_end_addr = m_addr + m_byte_size; - const nub_addr_t end_addr = addr + size; - // Is the breakpoint end address before the passed in start address? - if (bp_end_addr <= addr) - return false; - // Is the breakpoint start address after passed in end address? - if (end_addr <= m_addr) - return false; - if (intersect_addr || intersect_size || opcode_offset) - { - if (m_addr < addr) - { - if (intersect_addr) - *intersect_addr = addr; - if (intersect_size) - *intersect_size = std::min<nub_addr_t>(bp_end_addr, end_addr) - addr; - if (opcode_offset) - *opcode_offset = addr - m_addr; - } - else - { - if (intersect_addr) - *intersect_addr = m_addr; - if (intersect_size) - *intersect_size = std::min<nub_addr_t>(bp_end_addr, end_addr) - m_addr; - if (opcode_offset) - *opcode_offset = 0; - } - } - return true; - } - } - return false; - } - void SetEnabled(bool enabled) - { - if (!enabled) - SetHardwareIndex(INVALID_NUB_HW_INDEX); - m_enabled = enabled; - } - void SetIsWatchpoint (uint32_t type) - { - m_is_watchpoint = 1; - m_watch_read = (type & WATCH_TYPE_READ) != 0; - m_watch_write = (type & WATCH_TYPE_WRITE) != 0; - } - bool IsBreakpoint() const { return m_is_watchpoint == 0; } - bool IsWatchpoint() const { return m_is_watchpoint == 1; } - bool WatchpointRead() const { return m_watch_read != 0; } - bool WatchpointWrite() const { return m_watch_write != 0; } - bool HardwarePreferred() const { return m_hw_preferred; } - bool IsHardware() const { return m_hw_index != INVALID_NUB_HW_INDEX; } - uint32_t GetHardwareIndex() const { return m_hw_index; } - void SetHardwareIndex(uint32_t hw_index) { m_hw_index = hw_index; } - void Dump() const; - uint32_t Retain () - { - return ++m_retain_count; - } - uint32_t Release () - { - if (m_retain_count == 0) - return 0; - return --m_retain_count; - } + DNBBreakpoint(nub_addr_t m_addr, nub_size_t byte_size, bool hardware); + ~DNBBreakpoint(); + + nub_size_t ByteSize() const { return m_byte_size; } + uint8_t *SavedOpcodeBytes() { return &m_opcode[0]; } + const uint8_t *SavedOpcodeBytes() const { return &m_opcode[0]; } + nub_addr_t Address() const { return m_addr; } + // nub_thread_t ThreadID() const { return m_tid; } + bool IsEnabled() const { return m_enabled; } + bool IntersectsRange(nub_addr_t addr, nub_size_t size, + nub_addr_t *intersect_addr, nub_size_t *intersect_size, + nub_size_t *opcode_offset) const { + // We only use software traps for software breakpoints + if (IsBreakpoint() && IsEnabled() && !IsHardware()) { + if (m_byte_size > 0) { + const nub_addr_t bp_end_addr = m_addr + m_byte_size; + const nub_addr_t end_addr = addr + size; + // Is the breakpoint end address before the passed in start address? + if (bp_end_addr <= addr) + return false; + // Is the breakpoint start address after passed in end address? + if (end_addr <= m_addr) + return false; + if (intersect_addr || intersect_size || opcode_offset) { + if (m_addr < addr) { + if (intersect_addr) + *intersect_addr = addr; + if (intersect_size) + *intersect_size = + std::min<nub_addr_t>(bp_end_addr, end_addr) - addr; + if (opcode_offset) + *opcode_offset = addr - m_addr; + } else { + if (intersect_addr) + *intersect_addr = m_addr; + if (intersect_size) + *intersect_size = + std::min<nub_addr_t>(bp_end_addr, end_addr) - m_addr; + if (opcode_offset) + *opcode_offset = 0; + } + } + return true; + } + } + return false; + } + void SetEnabled(bool enabled) { + if (!enabled) + SetHardwareIndex(INVALID_NUB_HW_INDEX); + m_enabled = enabled; + } + void SetIsWatchpoint(uint32_t type) { + m_is_watchpoint = 1; + m_watch_read = (type & WATCH_TYPE_READ) != 0; + m_watch_write = (type & WATCH_TYPE_WRITE) != 0; + } + bool IsBreakpoint() const { return m_is_watchpoint == 0; } + bool IsWatchpoint() const { return m_is_watchpoint == 1; } + bool WatchpointRead() const { return m_watch_read != 0; } + bool WatchpointWrite() const { return m_watch_write != 0; } + bool HardwarePreferred() const { return m_hw_preferred; } + bool IsHardware() const { return m_hw_index != INVALID_NUB_HW_INDEX; } + uint32_t GetHardwareIndex() const { return m_hw_index; } + void SetHardwareIndex(uint32_t hw_index) { m_hw_index = hw_index; } + void Dump() const; + uint32_t Retain() { return ++m_retain_count; } + uint32_t Release() { + if (m_retain_count == 0) + return 0; + return --m_retain_count; + } private: - uint32_t m_retain_count; // Each breakpoint is maintained by address and is ref counted in case multiple people set a breakpoint at the same address - uint32_t m_byte_size; // Length in bytes of the breakpoint if set in memory - uint8_t m_opcode[8]; // Saved opcode bytes - nub_addr_t m_addr; // Address of this breakpoint - uint32_t m_enabled:1, // Flags for this breakpoint - m_hw_preferred:1, // 1 if this point has been requested to be set using hardware (which may fail due to lack of resources) - m_is_watchpoint:1, // 1 if this is a watchpoint - m_watch_read:1, // 1 if we stop when the watched data is read from - m_watch_write:1; // 1 if we stop when the watched data is written to - uint32_t m_hw_index; // The hardware resource index for this breakpoint/watchpoint + uint32_t m_retain_count; // Each breakpoint is maintained by address and is + // ref counted in case multiple people set a + // breakpoint at the same address + uint32_t m_byte_size; // Length in bytes of the breakpoint if set in memory + uint8_t m_opcode[8]; // Saved opcode bytes + nub_addr_t m_addr; // Address of this breakpoint + uint32_t m_enabled : 1, // Flags for this breakpoint + m_hw_preferred : 1, // 1 if this point has been requested to be set using + // hardware (which may fail due to lack of resources) + m_is_watchpoint : 1, // 1 if this is a watchpoint + m_watch_read : 1, // 1 if we stop when the watched data is read from + m_watch_write : 1; // 1 if we stop when the watched data is written to + uint32_t + m_hw_index; // The hardware resource index for this breakpoint/watchpoint }; - -class DNBBreakpointList -{ +class DNBBreakpointList { public: - DNBBreakpointList(); - ~DNBBreakpointList(); + DNBBreakpointList(); + ~DNBBreakpointList(); + + DNBBreakpoint *Add(nub_addr_t addr, nub_size_t length, bool hardware); + bool Remove(nub_addr_t addr); + DNBBreakpoint *FindByAddress(nub_addr_t addr); + const DNBBreakpoint *FindByAddress(nub_addr_t addr) const; - DNBBreakpoint * Add (nub_addr_t addr, nub_size_t length, bool hardware); - bool Remove (nub_addr_t addr); - DNBBreakpoint * FindByAddress (nub_addr_t addr); - const DNBBreakpoint * FindByAddress (nub_addr_t addr) const; + size_t FindBreakpointsThatOverlapRange(nub_addr_t addr, nub_addr_t size, + std::vector<DNBBreakpoint *> &bps); - size_t FindBreakpointsThatOverlapRange (nub_addr_t addr, - nub_addr_t size, - std::vector<DNBBreakpoint *> &bps); + void Dump() const; - void Dump () const; + size_t Size() const { return m_breakpoints.size(); } + void DisableAll(); - size_t Size() const { return m_breakpoints.size(); } - void DisableAll (); + void RemoveTrapsFromBuffer(nub_addr_t addr, nub_size_t size, void *buf) const; - void RemoveTrapsFromBuffer (nub_addr_t addr, - nub_size_t size, - void *buf) const; + void DisableAllBreakpoints(MachProcess *process); + void DisableAllWatchpoints(MachProcess *process); + void RemoveDisabled(); - void DisableAllBreakpoints (MachProcess *process); - void DisableAllWatchpoints(MachProcess *process); - void RemoveDisabled (); protected: - typedef std::map<nub_addr_t, DNBBreakpoint> collection; - typedef collection::iterator iterator; - typedef collection::const_iterator const_iterator; - collection m_breakpoints; + typedef std::map<nub_addr_t, DNBBreakpoint> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + collection m_breakpoints; }; #endif - diff --git a/tools/debugserver/source/DNBDataRef.cpp b/tools/debugserver/source/DNBDataRef.cpp index d52f28ee2fb9..d7dce1ab7338 100644 --- a/tools/debugserver/source/DNBDataRef.cpp +++ b/tools/debugserver/source/DNBDataRef.cpp @@ -21,165 +21,139 @@ // Constructor //---------------------------------------------------------------------- -DNBDataRef::DNBDataRef() : - m_start(NULL), - m_end(NULL), - m_swap(false), - m_ptrSize(0), - m_addrPCRelative(INVALID_NUB_ADDRESS), - m_addrTEXT(INVALID_NUB_ADDRESS), - m_addrDATA(INVALID_NUB_ADDRESS) -{ -} - +DNBDataRef::DNBDataRef() + : m_start(NULL), m_end(NULL), m_swap(false), m_ptrSize(0), + m_addrPCRelative(INVALID_NUB_ADDRESS), m_addrTEXT(INVALID_NUB_ADDRESS), + m_addrDATA(INVALID_NUB_ADDRESS) {} //---------------------------------------------------------------------- // Constructor //---------------------------------------------------------------------- -DNBDataRef::DNBDataRef(const uint8_t *start, size_t size, bool swap) : - m_start(start), - m_end(start+size), - m_swap(swap), - m_ptrSize(0), - m_addrPCRelative(INVALID_NUB_ADDRESS), - m_addrTEXT(INVALID_NUB_ADDRESS), - m_addrDATA(INVALID_NUB_ADDRESS) -{ -} - +DNBDataRef::DNBDataRef(const uint8_t *start, size_t size, bool swap) + : m_start(start), m_end(start + size), m_swap(swap), m_ptrSize(0), + m_addrPCRelative(INVALID_NUB_ADDRESS), m_addrTEXT(INVALID_NUB_ADDRESS), + m_addrDATA(INVALID_NUB_ADDRESS) {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -DNBDataRef::~DNBDataRef() -{ -} - +DNBDataRef::~DNBDataRef() {} //---------------------------------------------------------------------- // Get8 //---------------------------------------------------------------------- -uint8_t -DNBDataRef::Get8(offset_t *offset_ptr) const -{ - uint8_t val = 0; - if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) ) - { - val = *(m_start + *offset_ptr); - *offset_ptr += sizeof(val); - } - return val; +uint8_t DNBDataRef::Get8(offset_t *offset_ptr) const { + uint8_t val = 0; + if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) { + val = *(m_start + *offset_ptr); + *offset_ptr += sizeof(val); + } + return val; } - //---------------------------------------------------------------------- // Get16 //---------------------------------------------------------------------- -uint16_t -DNBDataRef::Get16(offset_t *offset_ptr) const -{ - uint16_t val = 0; - if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) ) - { - const uint8_t *p = m_start + *offset_ptr; - val = *(uint16_t*)p; - - if (m_swap) - val = OSSwapInt16(val); - - // Advance the offset - *offset_ptr += sizeof(val); - } - return val; +uint16_t DNBDataRef::Get16(offset_t *offset_ptr) const { + uint16_t val = 0; + if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) { + const uint8_t *p = m_start + *offset_ptr; + val = *(uint16_t *)p; + + if (m_swap) + val = OSSwapInt16(val); + + // Advance the offset + *offset_ptr += sizeof(val); + } + return val; } - //---------------------------------------------------------------------- // Get32 //---------------------------------------------------------------------- -uint32_t -DNBDataRef::Get32(offset_t *offset_ptr) const -{ - uint32_t val = 0; - if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) ) - { - const uint8_t *p = m_start + *offset_ptr; - val = *(uint32_t*)p; - if (m_swap) - val = OSSwapInt32(val); - - // Advance the offset - *offset_ptr += sizeof(val); - } - return val; +uint32_t DNBDataRef::Get32(offset_t *offset_ptr) const { + uint32_t val = 0; + if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) { + const uint8_t *p = m_start + *offset_ptr; + val = *(uint32_t *)p; + if (m_swap) + val = OSSwapInt32(val); + + // Advance the offset + *offset_ptr += sizeof(val); + } + return val; } - //---------------------------------------------------------------------- // Get64 //---------------------------------------------------------------------- -uint64_t -DNBDataRef::Get64(offset_t *offset_ptr) const -{ - uint64_t val = 0; - if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) ) - { - const uint8_t *p = m_start + *offset_ptr; - val = *(uint64_t*)p; - if (m_swap) - val = OSSwapInt64(val); - - // Advance the offset - *offset_ptr += sizeof(val); - } - return val; +uint64_t DNBDataRef::Get64(offset_t *offset_ptr) const { + uint64_t val = 0; + if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) { + const uint8_t *p = m_start + *offset_ptr; + val = *(uint64_t *)p; + if (m_swap) + val = OSSwapInt64(val); + + // Advance the offset + *offset_ptr += sizeof(val); + } + return val; } - //---------------------------------------------------------------------- // GetMax32 // // Used for calls when the size can vary. Fill in extra cases if they // are ever needed. //---------------------------------------------------------------------- -uint32_t -DNBDataRef::GetMax32(offset_t *offset_ptr, uint32_t byte_size) const -{ - switch (byte_size) - { - case 1: return Get8 (offset_ptr); break; - case 2: return Get16(offset_ptr); break; - case 4: return Get32(offset_ptr); break; - default: - assert(!"GetMax32 unhandled case!"); - break; - } - return 0; +uint32_t DNBDataRef::GetMax32(offset_t *offset_ptr, uint32_t byte_size) const { + switch (byte_size) { + case 1: + return Get8(offset_ptr); + break; + case 2: + return Get16(offset_ptr); + break; + case 4: + return Get32(offset_ptr); + break; + default: + assert(!"GetMax32 unhandled case!"); + break; + } + return 0; } - //---------------------------------------------------------------------- // GetMax64 // // Used for calls when the size can vary. Fill in extra cases if they // are ever needed. //---------------------------------------------------------------------- -uint64_t -DNBDataRef::GetMax64(offset_t *offset_ptr, uint32_t size) const -{ - switch (size) - { - case 1: return Get8 (offset_ptr); break; - case 2: return Get16(offset_ptr); break; - case 4: return Get32(offset_ptr); break; - case 8: return Get64(offset_ptr); break; - default: - assert(!"GetMax64 unhandled case!"); - break; - } - return 0; +uint64_t DNBDataRef::GetMax64(offset_t *offset_ptr, uint32_t size) const { + switch (size) { + case 1: + return Get8(offset_ptr); + break; + case 2: + return Get16(offset_ptr); + break; + case 4: + return Get32(offset_ptr); + break; + case 8: + return Get64(offset_ptr); + break; + default: + assert(!"GetMax64 unhandled case!"); + break; + } + return 0; } //---------------------------------------------------------------------- @@ -188,198 +162,190 @@ DNBDataRef::GetMax64(offset_t *offset_ptr, uint32_t size) const // Extract a pointer value from the buffer. The pointer size must be // set prior to using this using one of the SetPointerSize functions. //---------------------------------------------------------------------- -uint64_t -DNBDataRef::GetPointer(offset_t *offset_ptr) const -{ - // Must set pointer size prior to using this call - assert(m_ptrSize != 0); - return GetMax64(offset_ptr, m_ptrSize); +uint64_t DNBDataRef::GetPointer(offset_t *offset_ptr) const { + // Must set pointer size prior to using this call + assert(m_ptrSize != 0); + return GetMax64(offset_ptr, m_ptrSize); } //---------------------------------------------------------------------- // GetCStr //---------------------------------------------------------------------- -const char * -DNBDataRef::GetCStr(offset_t *offset_ptr, uint32_t fixed_length) const -{ - const char *s = NULL; - if ( m_start < m_end ) - { - s = (char*)m_start + *offset_ptr; - - // Advance the offset - if (fixed_length) - *offset_ptr += fixed_length; - else - *offset_ptr += strlen(s) + 1; - } - return s; +const char *DNBDataRef::GetCStr(offset_t *offset_ptr, + uint32_t fixed_length) const { + const char *s = NULL; + if (m_start < m_end) { + s = (char *)m_start + *offset_ptr; + + // Advance the offset + if (fixed_length) + *offset_ptr += fixed_length; + else + *offset_ptr += strlen(s) + 1; + } + return s; } - //---------------------------------------------------------------------- // GetData //---------------------------------------------------------------------- -const uint8_t * -DNBDataRef::GetData(offset_t *offset_ptr, uint32_t length) const -{ - const uint8_t *data = NULL; - if ( length > 0 && ValidOffsetForDataOfSize(*offset_ptr, length) ) - { - data = m_start + *offset_ptr; - *offset_ptr += length; - } - return data; +const uint8_t *DNBDataRef::GetData(offset_t *offset_ptr, + uint32_t length) const { + const uint8_t *data = NULL; + if (length > 0 && ValidOffsetForDataOfSize(*offset_ptr, length)) { + data = m_start + *offset_ptr; + *offset_ptr += length; + } + return data; } - //---------------------------------------------------------------------- // Get_ULEB128 //---------------------------------------------------------------------- -uint64_t -DNBDataRef::Get_ULEB128 (offset_t *offset_ptr) const -{ - uint64_t result = 0; - if ( m_start < m_end ) - { - int shift = 0; - const uint8_t *src = m_start + *offset_ptr; - uint8_t byte; - int bytecount = 0; - - while (src < m_end) - { - bytecount++; - byte = *src++; - result |= (uint64_t)(byte & 0x7f) << shift; - shift += 7; - if ((byte & 0x80) == 0) - break; - } - - *offset_ptr += bytecount; +uint64_t DNBDataRef::Get_ULEB128(offset_t *offset_ptr) const { + uint64_t result = 0; + if (m_start < m_end) { + int shift = 0; + const uint8_t *src = m_start + *offset_ptr; + uint8_t byte; + int bytecount = 0; + + while (src < m_end) { + bytecount++; + byte = *src++; + result |= (uint64_t)(byte & 0x7f) << shift; + shift += 7; + if ((byte & 0x80) == 0) + break; } - return result; -} + *offset_ptr += bytecount; + } + return result; +} //---------------------------------------------------------------------- // Get_SLEB128 //---------------------------------------------------------------------- -int64_t -DNBDataRef::Get_SLEB128 (offset_t *offset_ptr) const -{ - int64_t result = 0; - - if ( m_start < m_end ) - { - int shift = 0; - int size = sizeof (uint32_t) * 8; - const uint8_t *src = m_start + *offset_ptr; - - uint8_t byte = 0; - int bytecount = 0; - - while (src < m_end) - { - bytecount++; - byte = *src++; - result |= (int64_t)(byte & 0x7f) << shift; - shift += 7; - if ((byte & 0x80) == 0) - break; - } - - // Sign bit of byte is 2nd high order bit (0x40) - if (shift < size && (byte & 0x40)) - result |= - (1ll << shift); - - *offset_ptr += bytecount; +int64_t DNBDataRef::Get_SLEB128(offset_t *offset_ptr) const { + int64_t result = 0; + + if (m_start < m_end) { + int shift = 0; + int size = sizeof(uint32_t) * 8; + const uint8_t *src = m_start + *offset_ptr; + + uint8_t byte = 0; + int bytecount = 0; + + while (src < m_end) { + bytecount++; + byte = *src++; + result |= (int64_t)(byte & 0x7f) << shift; + shift += 7; + if ((byte & 0x80) == 0) + break; } - return result; -} + // Sign bit of byte is 2nd high order bit (0x40) + if (shift < size && (byte & 0x40)) + result |= -(1ll << shift); + + *offset_ptr += bytecount; + } + return result; +} //---------------------------------------------------------------------- // Skip_LEB128 // // Skips past ULEB128 and SLEB128 numbers (just updates the offset) //---------------------------------------------------------------------- -void -DNBDataRef::Skip_LEB128 (offset_t *offset_ptr) const -{ - if ( m_start < m_end ) - { - const uint8_t *start = m_start + *offset_ptr; - const uint8_t *src = start; - - while ((src < m_end) && (*src++ & 0x80)) - /* Do nothing */; - - *offset_ptr += src - start; - } +void DNBDataRef::Skip_LEB128(offset_t *offset_ptr) const { + if (m_start < m_end) { + const uint8_t *start = m_start + *offset_ptr; + const uint8_t *src = start; + + while ((src < m_end) && (*src++ & 0x80)) + /* Do nothing */; + + *offset_ptr += src - start; + } } -uint32_t -DNBDataRef::Dump -( - uint32_t startOffset, - uint32_t endOffset, - uint64_t offsetBase, - DNBDataRef::Type type, - uint32_t numPerLine, - const char *format -) -{ - uint32_t offset; - uint32_t count; - char str[1024]; - str[0] = '\0'; - size_t str_offset = 0; - - for (offset = startOffset, count = 0; ValidOffset(offset) && offset < endOffset; ++count) - { - if ((count % numPerLine) == 0) - { - // Print out any previous string - if (str[0] != '\0') - DNBLog("%s", str); - // Reset string offset and fill the current line string with address: - str_offset = 0; - str_offset += snprintf(str, sizeof(str), "0x%8.8llx:", (uint64_t)(offsetBase + (offset - startOffset))); - } - - // Make sure we don't pass the bounds of our current string buffer on each iteration through this loop - if (str_offset >= sizeof(str)) - { - // The last snprintf consumed our string buffer, we will need to dump this out - // and reset the string with no address - DNBLog("%s", str); - str_offset = 0; - str[0] = '\0'; - } - - // We already checked that there is at least some room in the string str above, so it is safe to make - // the snprintf call each time through this loop - switch (type) - { - case TypeUInt8: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %2.2x", Get8(&offset)); break; - case TypeChar: - { - char ch = Get8(&offset); - str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %c", isprint(ch) ? ch : ' '); - } - break; - case TypeUInt16: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %4.4x", Get16(&offset)); break; - case TypeUInt32: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %8.8x", Get32(&offset)); break; - case TypeUInt64: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %16.16llx", Get64(&offset)); break; - case TypePointer: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " 0x%llx", GetPointer(&offset)); break; - case TypeULEB128: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " 0x%llx", Get_ULEB128(&offset)); break; - case TypeSLEB128: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %lld", Get_SLEB128(&offset)); break; - } +uint32_t DNBDataRef::Dump(uint32_t startOffset, uint32_t endOffset, + uint64_t offsetBase, DNBDataRef::Type type, + uint32_t numPerLine, const char *format) { + uint32_t offset; + uint32_t count; + char str[1024]; + str[0] = '\0'; + size_t str_offset = 0; + + for (offset = startOffset, count = 0; + ValidOffset(offset) && offset < endOffset; ++count) { + if ((count % numPerLine) == 0) { + // Print out any previous string + if (str[0] != '\0') + DNBLog("%s", str); + // Reset string offset and fill the current line string with address: + str_offset = 0; + str_offset += snprintf(str, sizeof(str), "0x%8.8llx:", + (uint64_t)(offsetBase + (offset - startOffset))); } - if (str[0] != '\0') - DNBLog("%s", str); + // Make sure we don't pass the bounds of our current string buffer on each + // iteration through this loop + if (str_offset >= sizeof(str)) { + // The last snprintf consumed our string buffer, we will need to dump this + // out + // and reset the string with no address + DNBLog("%s", str); + str_offset = 0; + str[0] = '\0'; + } + + // We already checked that there is at least some room in the string str + // above, so it is safe to make + // the snprintf call each time through this loop + switch (type) { + case TypeUInt8: + str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, + format ? format : " %2.2x", Get8(&offset)); + break; + case TypeChar: { + char ch = Get8(&offset); + str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, + format ? format : " %c", isprint(ch) ? ch : ' '); + } break; + case TypeUInt16: + str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, + format ? format : " %4.4x", Get16(&offset)); + break; + case TypeUInt32: + str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, + format ? format : " %8.8x", Get32(&offset)); + break; + case TypeUInt64: + str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, + format ? format : " %16.16llx", Get64(&offset)); + break; + case TypePointer: + str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, + format ? format : " 0x%llx", GetPointer(&offset)); + break; + case TypeULEB128: + str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, + format ? format : " 0x%llx", Get_ULEB128(&offset)); + break; + case TypeSLEB128: + str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, + format ? format : " %lld", Get_SLEB128(&offset)); + break; + } + } + + if (str[0] != '\0') + DNBLog("%s", str); - return offset; // Return the offset at which we ended up + return offset; // Return the offset at which we ended up } diff --git a/tools/debugserver/source/DNBDataRef.h b/tools/debugserver/source/DNBDataRef.h index d0c34ced6233..9a19f20227e6 100644 --- a/tools/debugserver/source/DNBDataRef.h +++ b/tools/debugserver/source/DNBDataRef.h @@ -24,102 +24,102 @@ #define __DNBDataRef_h__ #include "DNBDefs.h" +#include <limits.h> #include <stdint.h> #include <stdio.h> #include <string.h> -#include <limits.h> -class DNBDataRef -{ +class DNBDataRef { public: - // For use with Dump - typedef enum - { - TypeUInt8 = 0, - TypeChar, - TypeUInt16, - TypeUInt32, - TypeUInt64, - TypePointer, - TypeULEB128, - TypeSLEB128 - } Type; - typedef uint32_t offset_t; - typedef nub_addr_t addr_t; + // For use with Dump + typedef enum { + TypeUInt8 = 0, + TypeChar, + TypeUInt16, + TypeUInt32, + TypeUInt64, + TypePointer, + TypeULEB128, + TypeSLEB128 + } Type; + typedef uint32_t offset_t; + typedef nub_addr_t addr_t; + + DNBDataRef(); + DNBDataRef(const uint8_t *start, size_t size, bool swap); + ~DNBDataRef(); + void Clear() { + DNBDataRef::SetData(NULL, 0); + m_swap = false; + } - DNBDataRef(); - DNBDataRef(const uint8_t *start, size_t size, bool swap); - ~DNBDataRef(); - void Clear() - { - DNBDataRef::SetData(NULL, 0); - m_swap = false; - } + size_t BytesLeft(size_t offset) const { + const size_t size = GetSize(); + if (size > offset) + return size - offset; + return 0; + } - size_t BytesLeft (size_t offset) const - { - const size_t size = GetSize(); - if (size > offset) - return size - offset; - return 0; - } + bool ValidOffset(offset_t offset) const { return BytesLeft(offset) > 0; } + bool ValidOffsetForDataOfSize(offset_t offset, uint32_t num_bytes) const { + return num_bytes <= BytesLeft(offset); + } + size_t GetSize() const { return m_end - m_start; } + const uint8_t *GetDataStart() const { return m_start; } + const uint8_t *GetDataEnd() const { return m_end; } + bool GetSwap() const { return m_swap; } + void SetSwap(bool swap) { m_swap = swap; } + void SetData(const uint8_t *start, size_t size) { + m_start = start; + if (m_start != NULL) + m_end = start + size; + else + m_end = NULL; + } + uint8_t GetPointerSize() const { return m_ptrSize; } + void SetPointerSize(uint8_t size) { m_ptrSize = size; } + void SetEHPtrBaseAddrPCRelative(addr_t addr = INVALID_NUB_ADDRESS) { + m_addrPCRelative = addr; + } + void SetEHPtrBaseAddrTEXT(addr_t addr = INVALID_NUB_ADDRESS) { + m_addrTEXT = addr; + } + void SetEHPtrBaseAddrDATA(addr_t addr = INVALID_NUB_ADDRESS) { + m_addrDATA = addr; + } + uint8_t Get8(offset_t *offset_ptr) const; + uint16_t Get16(offset_t *offset_ptr) const; + uint32_t Get32(offset_t *offset_ptr) const; + uint64_t Get64(offset_t *offset_ptr) const; + uint32_t GetMax32(offset_t *offset_ptr, uint32_t byte_size) const; + uint64_t GetMax64(offset_t *offset_ptr, uint32_t byte_size) const; + uint64_t GetPointer(offset_t *offset_ptr) const; + // uint64_t GetDwarfEHPtr(offset_t *offset_ptr, uint32_t eh_ptr_enc) + // const; + const char *GetCStr(offset_t *offset_ptr, uint32_t fixed_length = 0) const; + const char *PeekCStr(offset_t offset) const { + if (ValidOffset(offset)) + return (const char *)m_start + offset; + return NULL; + } - bool ValidOffset(offset_t offset) const - { - return BytesLeft(offset) > 0; - } - bool ValidOffsetForDataOfSize(offset_t offset, uint32_t num_bytes) const - { - return num_bytes <= BytesLeft (offset); - } - size_t GetSize() const { return m_end - m_start; } - const uint8_t * GetDataStart() const { return m_start; } - const uint8_t * GetDataEnd() const { return m_end; } - bool GetSwap() const { return m_swap; } - void SetSwap(bool swap) { m_swap = swap; } - void SetData(const uint8_t *start, size_t size) - { - m_start = start; - if (m_start != NULL) - m_end = start + size; - else - m_end = NULL; - } - uint8_t GetPointerSize() const { return m_ptrSize; } - void SetPointerSize(uint8_t size) { m_ptrSize = size; } - void SetEHPtrBaseAddrPCRelative(addr_t addr = INVALID_NUB_ADDRESS) { m_addrPCRelative = addr; } - void SetEHPtrBaseAddrTEXT(addr_t addr = INVALID_NUB_ADDRESS) { m_addrTEXT = addr; } - void SetEHPtrBaseAddrDATA(addr_t addr = INVALID_NUB_ADDRESS) { m_addrDATA = addr; } - uint8_t Get8(offset_t *offset_ptr) const; - uint16_t Get16(offset_t *offset_ptr) const; - uint32_t Get32(offset_t *offset_ptr) const; - uint64_t Get64(offset_t *offset_ptr) const; - uint32_t GetMax32(offset_t *offset_ptr, uint32_t byte_size) const; - uint64_t GetMax64(offset_t *offset_ptr, uint32_t byte_size) const; - uint64_t GetPointer(offset_t *offset_ptr) const; -// uint64_t GetDwarfEHPtr(offset_t *offset_ptr, uint32_t eh_ptr_enc) const; - const char * GetCStr(offset_t *offset_ptr, uint32_t fixed_length = 0) const; - const char * PeekCStr(offset_t offset) const - { - if (ValidOffset(offset)) - return (const char*)m_start + offset; - return NULL; - } + const uint8_t *GetData(offset_t *offset_ptr, uint32_t length) const; + uint64_t Get_ULEB128(offset_t *offset_ptr) const; + int64_t Get_SLEB128(offset_t *offset_ptr) const; + void Skip_LEB128(offset_t *offset_ptr) const; - const uint8_t * GetData( offset_t *offset_ptr, uint32_t length) const; - uint64_t Get_ULEB128 (offset_t *offset_ptr) const; - int64_t Get_SLEB128 (offset_t *offset_ptr) const; - void Skip_LEB128 (offset_t *offset_ptr) const; + uint32_t Dump(offset_t startOffset, offset_t endOffset, uint64_t offsetBase, + DNBDataRef::Type type, uint32_t numPerLine, + const char *typeFormat = NULL); - uint32_t Dump(offset_t startOffset, offset_t endOffset, uint64_t offsetBase, DNBDataRef::Type type, uint32_t numPerLine, const char *typeFormat = NULL); protected: - const uint8_t * m_start; - const uint8_t * m_end; - bool m_swap; - uint8_t m_ptrSize; - addr_t m_addrPCRelative; - addr_t m_addrTEXT; - addr_t m_addrDATA; + const uint8_t *m_start; + const uint8_t *m_end; + bool m_swap; + uint8_t m_ptrSize; + addr_t m_addrPCRelative; + addr_t m_addrTEXT; + addr_t m_addrDATA; }; #endif // #ifndef __DNBDataRef_h__ diff --git a/tools/debugserver/source/DNBDefs.h b/tools/debugserver/source/DNBDefs.h index e3757e903e59..5762bd16e2b7 100644 --- a/tools/debugserver/source/DNBDefs.h +++ b/tools/debugserver/source/DNBDefs.h @@ -14,8 +14,8 @@ #ifndef __DNBDefs_h__ #define __DNBDefs_h__ -#include <stdint.h> #include <signal.h> +#include <stdint.h> #include <stdio.h> #include <sys/syslimits.h> #include <unistd.h> @@ -23,22 +23,24 @@ //---------------------------------------------------------------------- // Define nub_addr_t and the invalid address value from the architecture //---------------------------------------------------------------------- -#if defined (__x86_64__) || defined (__ppc64__) || defined (__arm64__) || defined (__aarch64__) +#if defined(__x86_64__) || defined(__ppc64__) || defined(__arm64__) || \ + defined(__aarch64__) //---------------------------------------------------------------------- // 64 bit address architectures //---------------------------------------------------------------------- -typedef uint64_t nub_addr_t; -#define INVALID_NUB_ADDRESS ((nub_addr_t)~0ull) +typedef uint64_t nub_addr_t; +#define INVALID_NUB_ADDRESS ((nub_addr_t)~0ull) -#elif defined (__i386__) || defined (__powerpc__) || defined (__ppc__) || defined (__arm__) +#elif defined(__i386__) || defined(__powerpc__) || defined(__ppc__) || \ + defined(__arm__) //---------------------------------------------------------------------- // 32 bit address architectures //---------------------------------------------------------------------- -typedef uint32_t nub_addr_t; -#define INVALID_NUB_ADDRESS ((nub_addr_t)~0ul) +typedef uint32_t nub_addr_t; +#define INVALID_NUB_ADDRESS ((nub_addr_t)~0ul) #else @@ -47,326 +49,325 @@ typedef uint32_t nub_addr_t; //---------------------------------------------------------------------- #warning undefined architecture, defaulting to 8 byte addresses -typedef uint64_t nub_addr_t; -#define INVALID_NUB_ADDRESS ((nub_addr_t)~0ull) - +typedef uint64_t nub_addr_t; +#define INVALID_NUB_ADDRESS ((nub_addr_t)~0ull) #endif -typedef size_t nub_size_t; -typedef ssize_t nub_ssize_t; -typedef uint32_t nub_index_t; -typedef pid_t nub_process_t; -typedef uint64_t nub_thread_t; -typedef uint32_t nub_event_t; -typedef uint32_t nub_bool_t; - -#define INVALID_NUB_PROCESS ((nub_process_t)0) -#define INVALID_NUB_THREAD ((nub_thread_t)0) -#define INVALID_NUB_WATCH_ID ((nub_watch_t)0) -#define INVALID_NUB_HW_INDEX UINT32_MAX -#define INVALID_NUB_REGNUM UINT32_MAX -#define NUB_GENERIC_ERROR UINT32_MAX +typedef size_t nub_size_t; +typedef ssize_t nub_ssize_t; +typedef uint32_t nub_index_t; +typedef pid_t nub_process_t; +typedef uint64_t nub_thread_t; +typedef uint32_t nub_event_t; +typedef uint32_t nub_bool_t; + +#define INVALID_NUB_PROCESS ((nub_process_t)0) +#define INVALID_NUB_THREAD ((nub_thread_t)0) +#define INVALID_NUB_WATCH_ID ((nub_watch_t)0) +#define INVALID_NUB_HW_INDEX UINT32_MAX +#define INVALID_NUB_REGNUM UINT32_MAX +#define NUB_GENERIC_ERROR UINT32_MAX // Watchpoint types -#define WATCH_TYPE_READ (1u << 0) -#define WATCH_TYPE_WRITE (1u << 1) - -typedef enum -{ - eStateInvalid = 0, - eStateUnloaded, - eStateAttaching, - eStateLaunching, - eStateStopped, - eStateRunning, - eStateStepping, - eStateCrashed, - eStateDetached, - eStateExited, - eStateSuspended +#define WATCH_TYPE_READ (1u << 0) +#define WATCH_TYPE_WRITE (1u << 1) + +typedef enum { + eStateInvalid = 0, + eStateUnloaded, + eStateAttaching, + eStateLaunching, + eStateStopped, + eStateRunning, + eStateStepping, + eStateCrashed, + eStateDetached, + eStateExited, + eStateSuspended } nub_state_t; -typedef enum -{ - eLaunchFlavorDefault = 0, - eLaunchFlavorPosixSpawn = 1, - eLaunchFlavorForkExec = 2, +typedef enum { + eLaunchFlavorDefault = 0, + eLaunchFlavorPosixSpawn = 1, + eLaunchFlavorForkExec = 2, #ifdef WITH_SPRINGBOARD - eLaunchFlavorSpringBoard = 3, + eLaunchFlavorSpringBoard = 3, #endif #ifdef WITH_BKS - eLaunchFlavorBKS = 4, + eLaunchFlavorBKS = 4, #endif #ifdef WITH_FBS - eLaunchFlavorFBS = 5 + eLaunchFlavorFBS = 5 #endif } nub_launch_flavor_t; -#define NUB_STATE_IS_RUNNING(s) ((s) == eStateAttaching ||\ - (s) == eStateLaunching ||\ - (s) == eStateRunning ||\ - (s) == eStateStepping ||\ - (s) == eStateDetached) - -#define NUB_STATE_IS_STOPPED(s) ((s) == eStateUnloaded ||\ - (s) == eStateStopped ||\ - (s) == eStateCrashed ||\ - (s) == eStateExited) - -enum -{ - eEventProcessRunningStateChanged = 1 << 0, // The process has changed state to running - eEventProcessStoppedStateChanged = 1 << 1, // The process has changed state to stopped - eEventSharedLibsStateChange = 1 << 2, // Shared libraries loaded/unloaded state has changed - eEventStdioAvailable = 1 << 3, // Something is available on stdout/stderr - eEventProfileDataAvailable = 1 << 4, // Profile data ready for retrieval - kAllEventsMask = eEventProcessRunningStateChanged | - eEventProcessStoppedStateChanged | - eEventSharedLibsStateChange | - eEventStdioAvailable | - eEventProfileDataAvailable +#define NUB_STATE_IS_RUNNING(s) \ + ((s) == eStateAttaching || (s) == eStateLaunching || (s) == eStateRunning || \ + (s) == eStateStepping || (s) == eStateDetached) + +#define NUB_STATE_IS_STOPPED(s) \ + ((s) == eStateUnloaded || (s) == eStateStopped || (s) == eStateCrashed || \ + (s) == eStateExited) + +enum { + eEventProcessRunningStateChanged = + 1 << 0, // The process has changed state to running + eEventProcessStoppedStateChanged = + 1 << 1, // The process has changed state to stopped + eEventSharedLibsStateChange = + 1 << 2, // Shared libraries loaded/unloaded state has changed + eEventStdioAvailable = 1 << 3, // Something is available on stdout/stderr + eEventProfileDataAvailable = 1 << 4, // Profile data ready for retrieval + kAllEventsMask = eEventProcessRunningStateChanged | + eEventProcessStoppedStateChanged | + eEventSharedLibsStateChange | eEventStdioAvailable | + eEventProfileDataAvailable }; -#define LOG_VERBOSE (1u << 0) -#define LOG_PROCESS (1u << 1) -#define LOG_THREAD (1u << 2) -#define LOG_EXCEPTIONS (1u << 3) -#define LOG_SHLIB (1u << 4) -#define LOG_MEMORY (1u << 5) // Log memory reads/writes calls -#define LOG_MEMORY_DATA_SHORT (1u << 6) // Log short memory reads/writes bytes -#define LOG_MEMORY_DATA_LONG (1u << 7) // Log all memory reads/writes bytes -#define LOG_MEMORY_PROTECTIONS (1u << 8) // Log memory protection changes -#define LOG_BREAKPOINTS (1u << 9) -#define LOG_EVENTS (1u << 10) -#define LOG_WATCHPOINTS (1u << 11) -#define LOG_STEP (1u << 12) -#define LOG_TASK (1u << 13) -#define LOG_LO_USER (1u << 16) -#define LOG_HI_USER (1u << 31) -#define LOG_ALL 0xFFFFFFFFu -#define LOG_DEFAULT ((LOG_PROCESS) |\ - (LOG_TASK) |\ - (LOG_THREAD) |\ - (LOG_EXCEPTIONS) |\ - (LOG_SHLIB) |\ - (LOG_MEMORY) |\ - (LOG_BREAKPOINTS) |\ - (LOG_WATCHPOINTS) |\ - (LOG_STEP)) - - -#define REGISTER_SET_ALL 0 +#define LOG_VERBOSE (1u << 0) +#define LOG_PROCESS (1u << 1) +#define LOG_THREAD (1u << 2) +#define LOG_EXCEPTIONS (1u << 3) +#define LOG_SHLIB (1u << 4) +#define LOG_MEMORY (1u << 5) // Log memory reads/writes calls +#define LOG_MEMORY_DATA_SHORT (1u << 6) // Log short memory reads/writes bytes +#define LOG_MEMORY_DATA_LONG (1u << 7) // Log all memory reads/writes bytes +#define LOG_MEMORY_PROTECTIONS (1u << 8) // Log memory protection changes +#define LOG_BREAKPOINTS (1u << 9) +#define LOG_EVENTS (1u << 10) +#define LOG_WATCHPOINTS (1u << 11) +#define LOG_STEP (1u << 12) +#define LOG_TASK (1u << 13) +#define LOG_DARWIN_LOG (1u << 14) +#define LOG_LO_USER (1u << 16) +#define LOG_HI_USER (1u << 31) +#define LOG_ALL 0xFFFFFFFFu +#define LOG_DEFAULT \ + ((LOG_PROCESS) | (LOG_TASK) | (LOG_THREAD) | (LOG_EXCEPTIONS) | \ + (LOG_SHLIB) | (LOG_MEMORY) | (LOG_BREAKPOINTS) | (LOG_WATCHPOINTS) | \ + (LOG_STEP)) + +#define REGISTER_SET_ALL 0 // Generic Register set to be defined by each architecture for access to common // register values. -#define REGISTER_SET_GENERIC ((uint32_t)0xFFFFFFFFu) -#define GENERIC_REGNUM_PC 0 // Program Counter -#define GENERIC_REGNUM_SP 1 // Stack Pointer -#define GENERIC_REGNUM_FP 2 // Frame Pointer -#define GENERIC_REGNUM_RA 3 // Return Address -#define GENERIC_REGNUM_FLAGS 4 // Processor flags register -#define GENERIC_REGNUM_ARG1 5 // The register that would contain pointer size or less argument 1 (if any) -#define GENERIC_REGNUM_ARG2 6 // The register that would contain pointer size or less argument 2 (if any) -#define GENERIC_REGNUM_ARG3 7 // The register that would contain pointer size or less argument 3 (if any) -#define GENERIC_REGNUM_ARG4 8 // The register that would contain pointer size or less argument 4 (if any) -#define GENERIC_REGNUM_ARG5 9 // The register that would contain pointer size or less argument 5 (if any) -#define GENERIC_REGNUM_ARG6 10 // The register that would contain pointer size or less argument 6 (if any) -#define GENERIC_REGNUM_ARG7 11 // The register that would contain pointer size or less argument 7 (if any) -#define GENERIC_REGNUM_ARG8 12 // The register that would contain pointer size or less argument 8 (if any) - -enum DNBRegisterType -{ - InvalidRegType = 0, - Uint, // unsigned integer - Sint, // signed integer - IEEE754, // float - Vector // vector registers +#define REGISTER_SET_GENERIC ((uint32_t)0xFFFFFFFFu) +#define GENERIC_REGNUM_PC 0 // Program Counter +#define GENERIC_REGNUM_SP 1 // Stack Pointer +#define GENERIC_REGNUM_FP 2 // Frame Pointer +#define GENERIC_REGNUM_RA 3 // Return Address +#define GENERIC_REGNUM_FLAGS 4 // Processor flags register +#define GENERIC_REGNUM_ARG1 \ + 5 // The register that would contain pointer size or less argument 1 (if any) +#define GENERIC_REGNUM_ARG2 \ + 6 // The register that would contain pointer size or less argument 2 (if any) +#define GENERIC_REGNUM_ARG3 \ + 7 // The register that would contain pointer size or less argument 3 (if any) +#define GENERIC_REGNUM_ARG4 \ + 8 // The register that would contain pointer size or less argument 4 (if any) +#define GENERIC_REGNUM_ARG5 \ + 9 // The register that would contain pointer size or less argument 5 (if any) +#define GENERIC_REGNUM_ARG6 \ + 10 // The register that would contain pointer size or less argument 6 (if any) +#define GENERIC_REGNUM_ARG7 \ + 11 // The register that would contain pointer size or less argument 7 (if any) +#define GENERIC_REGNUM_ARG8 \ + 12 // The register that would contain pointer size or less argument 8 (if any) + +enum DNBRegisterType { + InvalidRegType = 0, + Uint, // unsigned integer + Sint, // signed integer + IEEE754, // float + Vector // vector registers }; -enum DNBRegisterFormat -{ - InvalidRegFormat = 0, - Binary, - Decimal, - Hex, - Float, - VectorOfSInt8, - VectorOfUInt8, - VectorOfSInt16, - VectorOfUInt16, - VectorOfSInt32, - VectorOfUInt32, - VectorOfFloat32, - VectorOfUInt128 +enum DNBRegisterFormat { + InvalidRegFormat = 0, + Binary, + Decimal, + Hex, + Float, + VectorOfSInt8, + VectorOfUInt8, + VectorOfSInt16, + VectorOfUInt16, + VectorOfSInt32, + VectorOfUInt32, + VectorOfFloat32, + VectorOfUInt128 }; -struct DNBRegisterInfo -{ - uint32_t set; // Register set - uint32_t reg; // Register number - const char *name; // Name of this register - const char *alt; // Alternate name - uint16_t type; // Type of the register bits (DNBRegisterType) - uint16_t format; // Default format for display (DNBRegisterFormat), - uint32_t size; // Size in bytes of the register - uint32_t offset; // Offset from the beginning of the register context - uint32_t reg_ehframe; // eh_frame register number (INVALID_NUB_REGNUM when none) - uint32_t reg_dwarf; // DWARF register number (INVALID_NUB_REGNUM when none) - uint32_t reg_generic; // Generic register number (INVALID_NUB_REGNUM when none) - uint32_t reg_debugserver;// The debugserver register number we'll use over gdb-remote protocol (INVALID_NUB_REGNUM when none) - const char **value_regs; // If this register is a part of other registers, list the register names terminated by NULL - const char **update_regs; // If modifying this register will invalidate other registers, list the register names terminated by NULL +struct DNBRegisterInfo { + uint32_t set; // Register set + uint32_t reg; // Register number + const char *name; // Name of this register + const char *alt; // Alternate name + uint16_t type; // Type of the register bits (DNBRegisterType) + uint16_t format; // Default format for display (DNBRegisterFormat), + uint32_t size; // Size in bytes of the register + uint32_t offset; // Offset from the beginning of the register context + uint32_t + reg_ehframe; // eh_frame register number (INVALID_NUB_REGNUM when none) + uint32_t reg_dwarf; // DWARF register number (INVALID_NUB_REGNUM when none) + uint32_t + reg_generic; // Generic register number (INVALID_NUB_REGNUM when none) + uint32_t reg_debugserver; // The debugserver register number we'll use over + // gdb-remote protocol (INVALID_NUB_REGNUM when + // none) + const char **value_regs; // If this register is a part of other registers, + // list the register names terminated by NULL + const char **update_regs; // If modifying this register will invalidate other + // registers, list the register names terminated by + // NULL }; -struct DNBRegisterSetInfo -{ - const char *name; // Name of this register set - const struct DNBRegisterInfo *registers; // An array of register descriptions - nub_size_t num_registers; // The number of registers in REGISTERS array above +struct DNBRegisterSetInfo { + const char *name; // Name of this register set + const struct DNBRegisterInfo *registers; // An array of register descriptions + nub_size_t num_registers; // The number of registers in REGISTERS array above }; -struct DNBThreadResumeAction -{ - nub_thread_t tid; // The thread ID that this action applies to, INVALID_NUB_THREAD for the default thread action - nub_state_t state; // Valid values are eStateStopped/eStateSuspended, eStateRunning, and eStateStepping. - int signal; // When resuming this thread, resume it with this signal - nub_addr_t addr; // If not INVALID_NUB_ADDRESS, then set the PC for the thread to ADDR before resuming/stepping +struct DNBThreadResumeAction { + nub_thread_t tid; // The thread ID that this action applies to, + // INVALID_NUB_THREAD for the default thread action + nub_state_t state; // Valid values are eStateStopped/eStateSuspended, + // eStateRunning, and eStateStepping. + int signal; // When resuming this thread, resume it with this signal + nub_addr_t addr; // If not INVALID_NUB_ADDRESS, then set the PC for the thread + // to ADDR before resuming/stepping }; -enum DNBThreadStopType -{ - eStopTypeInvalid = 0, - eStopTypeSignal, - eStopTypeException, - eStopTypeExec +enum DNBThreadStopType { + eStopTypeInvalid = 0, + eStopTypeSignal, + eStopTypeException, + eStopTypeExec }; -enum DNBMemoryPermissions -{ - eMemoryPermissionsWritable = (1 << 0), - eMemoryPermissionsReadable = (1 << 1), - eMemoryPermissionsExecutable = (1 << 2) +enum DNBMemoryPermissions { + eMemoryPermissionsWritable = (1 << 0), + eMemoryPermissionsReadable = (1 << 1), + eMemoryPermissionsExecutable = (1 << 2) }; -#define DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH 256 -#define DNB_THREAD_STOP_INFO_MAX_EXC_DATA 8 +#define DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH 256 +#define DNB_THREAD_STOP_INFO_MAX_EXC_DATA 8 //---------------------------------------------------------------------- // DNBThreadStopInfo // // Describes the reason a thread stopped. //---------------------------------------------------------------------- -struct DNBThreadStopInfo -{ - DNBThreadStopType reason; - char description[DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH]; - union - { - // eStopTypeSignal - struct - { - uint32_t signo; - } signal; - - // eStopTypeException - struct - { - uint32_t type; - nub_size_t data_count; - nub_addr_t data[DNB_THREAD_STOP_INFO_MAX_EXC_DATA]; - } exception; - } details; +struct DNBThreadStopInfo { + DNBThreadStopType reason; + char description[DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH]; + union { + // eStopTypeSignal + struct { + uint32_t signo; + } signal; + + // eStopTypeException + struct { + uint32_t type; + nub_size_t data_count; + nub_addr_t data[DNB_THREAD_STOP_INFO_MAX_EXC_DATA]; + } exception; + } details; }; - -struct DNBRegisterValue -{ - struct DNBRegisterInfo info; // Register information for this register - union - { - int8_t sint8; - int16_t sint16; - int32_t sint32; - int64_t sint64; - uint8_t uint8; - uint16_t uint16; - uint32_t uint32; - uint64_t uint64; - float float32; - double float64; - int8_t v_sint8[32]; - int16_t v_sint16[16]; - int32_t v_sint32[8]; - int64_t v_sint64[4]; - uint8_t v_uint8[32]; - uint16_t v_uint16[16]; - uint32_t v_uint32[8]; - uint64_t v_uint64[4]; - float v_float32[8]; - double v_float64[4]; - void *pointer; - char *c_str; - } value; +struct DNBRegisterValue { + struct DNBRegisterInfo info; // Register information for this register + union { + int8_t sint8; + int16_t sint16; + int32_t sint32; + int64_t sint64; + uint8_t uint8; + uint16_t uint16; + uint32_t uint32; + uint64_t uint64; + float float32; + double float64; + int8_t v_sint8[32]; + int16_t v_sint16[16]; + int32_t v_sint32[8]; + int64_t v_sint64[4]; + uint8_t v_uint8[32]; + uint16_t v_uint16[16]; + uint32_t v_uint32[8]; + uint64_t v_uint64[4]; + float v_float32[8]; + double v_float64[4]; + void *pointer; + char *c_str; + } value; }; -enum DNBSharedLibraryState -{ - eShlibStateUnloaded = 0, - eShlibStateLoaded = 1 -}; +enum DNBSharedLibraryState { eShlibStateUnloaded = 0, eShlibStateLoaded = 1 }; #ifndef DNB_MAX_SEGMENT_NAME_LENGTH -#define DNB_MAX_SEGMENT_NAME_LENGTH 32 +#define DNB_MAX_SEGMENT_NAME_LENGTH 32 #endif -struct DNBSegment -{ - char name[DNB_MAX_SEGMENT_NAME_LENGTH]; - nub_addr_t addr; - nub_addr_t size; +struct DNBSegment { + char name[DNB_MAX_SEGMENT_NAME_LENGTH]; + nub_addr_t addr; + nub_addr_t size; }; -struct DNBExecutableImageInfo -{ - char name[PATH_MAX]; // Name of the executable image (usually a full path) - uint32_t state; // State of the executable image (see enum DNBSharedLibraryState) - nub_addr_t header_addr; // Executable header address - uuid_t uuid; // Unique identifier for matching with symbols - uint32_t num_segments; // Number of contiguous memory segments to in SEGMENTS array - DNBSegment *segments; // Array of contiguous memory segments in executable +struct DNBExecutableImageInfo { + char name[PATH_MAX]; // Name of the executable image (usually a full path) + uint32_t + state; // State of the executable image (see enum DNBSharedLibraryState) + nub_addr_t header_addr; // Executable header address + uuid_t uuid; // Unique identifier for matching with symbols + uint32_t + num_segments; // Number of contiguous memory segments to in SEGMENTS array + DNBSegment *segments; // Array of contiguous memory segments in executable }; -struct DNBRegionInfo -{ - nub_addr_t addr; - nub_addr_t size; - uint32_t permissions; +struct DNBRegionInfo { + nub_addr_t addr; + nub_addr_t size; + uint32_t permissions; }; -enum DNBProfileDataScanType -{ - eProfileHostCPU = (1 << 0), - eProfileCPU = (1 << 1), - - eProfileThreadsCPU = (1 << 2), // By default excludes eProfileThreadName and eProfileQueueName. - eProfileThreadName = (1 << 3), // Assume eProfileThreadsCPU, get thread name as well. - eProfileQueueName = (1 << 4), // Assume eProfileThreadsCPU, get queue name as well. - - eProfileHostMemory = (1 << 5), - - eProfileMemory = (1 << 6), // By default, excludes eProfileMemoryDirtyPage. - eProfileMemoryDirtyPage = (1 << 7), // Assume eProfileMemory, get Dirty Page size as well. - eProfileMemoryAnonymous = (1 << 8), // Assume eProfileMemory, get Anonymous memory as well. - - eProfileEnergy = (1 << 9), - - eProfileAll = 0xffffffff +enum DNBProfileDataScanType { + eProfileHostCPU = (1 << 0), + eProfileCPU = (1 << 1), + + eProfileThreadsCPU = + (1 << 2), // By default excludes eProfileThreadName and eProfileQueueName. + eProfileThreadName = + (1 << 3), // Assume eProfileThreadsCPU, get thread name as well. + eProfileQueueName = + (1 << 4), // Assume eProfileThreadsCPU, get queue name as well. + + eProfileHostMemory = (1 << 5), + + eProfileMemory = (1 << 6), // By default, excludes eProfileMemoryDirtyPage. + eProfileMemoryDirtyPage = + (1 << 7), // Assume eProfileMemory, get Dirty Page size as well. + eProfileMemoryAnonymous = + (1 << 8), // Assume eProfileMemory, get Anonymous memory as well. + + eProfileEnergy = (1 << 9), + + eProfileAll = 0xffffffff }; -typedef nub_addr_t (*DNBCallbackNameToAddress)(nub_process_t pid, const char *name, const char *shlib_regex, void *baton); -typedef nub_size_t (*DNBCallbackCopyExecutableImageInfos)(nub_process_t pid, struct DNBExecutableImageInfo **image_infos, nub_bool_t only_changed, void *baton); -typedef void (*DNBCallbackLog)(void *baton, uint32_t flags, const char *format, va_list args); +typedef nub_addr_t (*DNBCallbackNameToAddress)(nub_process_t pid, + const char *name, + const char *shlib_regex, + void *baton); +typedef nub_size_t (*DNBCallbackCopyExecutableImageInfos)( + nub_process_t pid, struct DNBExecutableImageInfo **image_infos, + nub_bool_t only_changed, void *baton); +typedef void (*DNBCallbackLog)(void *baton, uint32_t flags, const char *format, + va_list args); #define UNUSED_IF_ASSERT_DISABLED(x) ((void)(x)) -#endif // #ifndef __DNBDefs_h__ +#endif // #ifndef __DNBDefs_h__ diff --git a/tools/debugserver/source/DNBError.cpp b/tools/debugserver/source/DNBError.cpp index c9d8ebd58d89..cd04358a4eca 100644 --- a/tools/debugserver/source/DNBError.cpp +++ b/tools/debugserver/source/DNBError.cpp @@ -20,109 +20,97 @@ #include <SpringBoardServices/SpringBoardServer.h> #endif -const char * -DNBError::AsString() const -{ - if (Success()) - return NULL; +const char *DNBError::AsString() const { + if (Success()) + return NULL; - if (m_str.empty()) - { - const char *s = NULL; - switch (m_flavor) - { - case MachKernel: - s = ::mach_error_string (m_err); - break; + if (m_str.empty()) { + const char *s = NULL; + switch (m_flavor) { + case MachKernel: + s = ::mach_error_string(m_err); + break; - case POSIX: - s = ::strerror (m_err); - break; + case POSIX: + s = ::strerror(m_err); + break; #ifdef WITH_SPRINGBOARD - case SpringBoard: - { - CFStringRef statusStr = SBSApplicationLaunchingErrorString (m_err); - if (CFString::UTF8 (statusStr, m_str) == NULL) - m_str.clear(); - } - break; + case SpringBoard: { + CFStringRef statusStr = SBSApplicationLaunchingErrorString(m_err); + if (CFString::UTF8(statusStr, m_str) == NULL) + m_str.clear(); + } break; #endif #ifdef WITH_BKS - case BackBoard: - { - // You have to call ObjC routines to get the error string from BackBoardServices. - // Not sure I want to make DNBError.cpp an .mm file. For now just make sure you - // pre-populate the error string when you make the DNBError of type BackBoard. - m_str.assign("Should have set BackBoard error when making the error string."); - } - break; + case BackBoard: { + // You have to call ObjC routines to get the error string from + // BackBoardServices. + // Not sure I want to make DNBError.cpp an .mm file. For now just make + // sure you + // pre-populate the error string when you make the DNBError of type + // BackBoard. + m_str.assign( + "Should have set BackBoard error when making the error string."); + } break; #endif #ifdef WITH_FBS - case FrontBoard: - { - // You have to call ObjC routines to get the error string from FrontBoardServices. - // Not sure I want to make DNBError.cpp an .mm file. For now just make sure you - // pre-populate the error string when you make the DNBError of type FrontBoard. - m_str.assign("Should have set FrontBoard error when making the error string."); - } - break; + case FrontBoard: { + // You have to call ObjC routines to get the error string from + // FrontBoardServices. + // Not sure I want to make DNBError.cpp an .mm file. For now just make + // sure you + // pre-populate the error string when you make the DNBError of type + // FrontBoard. + m_str.assign( + "Should have set FrontBoard error when making the error string."); + } break; #endif - default: - break; - } - if (s) - m_str.assign(s); + default: + break; } - if (m_str.empty()) - return NULL; - return m_str.c_str(); + if (s) + m_str.assign(s); + } + if (m_str.empty()) + return NULL; + return m_str.c_str(); } -void -DNBError::LogThreadedIfError(const char *format, ...) const -{ - if (Fail()) - { - char *arg_msg = NULL; - va_list args; - va_start (args, format); - ::vasprintf (&arg_msg, format, args); - va_end (args); +void DNBError::LogThreadedIfError(const char *format, ...) const { + if (Fail()) { + char *arg_msg = NULL; + va_list args; + va_start(args, format); + ::vasprintf(&arg_msg, format, args); + va_end(args); - if (arg_msg != NULL) - { - const char *err_str = AsString(); - if (err_str == NULL) - err_str = "???"; - DNBLogThreaded ("error: %s err = %s (0x%8.8x)", arg_msg, err_str, m_err); - free (arg_msg); - } + if (arg_msg != NULL) { + const char *err_str = AsString(); + if (err_str == NULL) + err_str = "???"; + DNBLogThreaded("error: %s err = %s (0x%8.8x)", arg_msg, err_str, m_err); + free(arg_msg); } + } } -void -DNBError::LogThreaded(const char *format, ...) const -{ - char *arg_msg = NULL; - va_list args; - va_start (args, format); - ::vasprintf (&arg_msg, format, args); - va_end (args); +void DNBError::LogThreaded(const char *format, ...) const { + char *arg_msg = NULL; + va_list args; + va_start(args, format); + ::vasprintf(&arg_msg, format, args); + va_end(args); - if (arg_msg != NULL) - { - if (Fail()) - { - const char *err_str = AsString(); - if (err_str == NULL) - err_str = "???"; - DNBLogThreaded ("error: %s err = %s (0x%8.8x)", arg_msg, err_str, m_err); - } - else - { - DNBLogThreaded ("%s err = 0x%8.8x", arg_msg, m_err); - } - free (arg_msg); + if (arg_msg != NULL) { + if (Fail()) { + const char *err_str = AsString(); + if (err_str == NULL) + err_str = "???"; + DNBLogThreaded("error: %s err = %s (0x%8.8x)", arg_msg, err_str, m_err); + } else { + DNBLogThreaded("%s err = 0x%8.8x", arg_msg, m_err); } + free(arg_msg); + } } diff --git a/tools/debugserver/source/DNBError.h b/tools/debugserver/source/DNBError.h index 274ae0d44773..edca38ad6db7 100644 --- a/tools/debugserver/source/DNBError.h +++ b/tools/debugserver/source/DNBError.h @@ -19,84 +19,80 @@ #include <stdio.h> #include <string> -class DNBError -{ +class DNBError { public: - typedef uint32_t ValueType; - typedef enum - { - Generic = 0, - MachKernel = 1, - POSIX = 2 + typedef uint32_t ValueType; + typedef enum { + Generic = 0, + MachKernel = 1, + POSIX = 2 #ifdef WITH_SPRINGBOARD - , SpringBoard = 3 + , + SpringBoard = 3 #endif #ifdef WITH_BKS - , BackBoard = 4 + , + BackBoard = 4 #endif #ifdef WITH_FBS - , FrontBoard = 5 + , + FrontBoard = 5 #endif - } FlavorType; + } FlavorType; - explicit DNBError( ValueType err = 0, - FlavorType flavor = Generic) : - m_err(err), - m_flavor(flavor) - { - } + explicit DNBError(ValueType err = 0, FlavorType flavor = Generic) + : m_err(err), m_flavor(flavor) {} - const char * AsString() const; - void Clear() { m_err = 0; m_flavor = Generic; m_str.clear(); } - ValueType Error() const { return m_err; } - FlavorType Flavor() const { return m_flavor; } + const char *AsString() const; + void Clear() { + m_err = 0; + m_flavor = Generic; + m_str.clear(); + } + ValueType Error() const { return m_err; } + FlavorType Flavor() const { return m_flavor; } - ValueType operator = (kern_return_t err) - { - m_err = err; - m_flavor = MachKernel; - m_str.clear(); - return m_err; - } + ValueType operator=(kern_return_t err) { + m_err = err; + m_flavor = MachKernel; + m_str.clear(); + return m_err; + } - void SetError(kern_return_t err) - { - m_err = err; - m_flavor = MachKernel; - m_str.clear(); - } + void SetError(kern_return_t err) { + m_err = err; + m_flavor = MachKernel; + m_str.clear(); + } - void SetErrorToErrno() - { - m_err = errno; - m_flavor = POSIX; - m_str.clear(); - } + void SetErrorToErrno() { + m_err = errno; + m_flavor = POSIX; + m_str.clear(); + } - void SetError(ValueType err, FlavorType flavor) - { - m_err = err; - m_flavor = flavor; - m_str.clear(); - } + void SetError(ValueType err, FlavorType flavor) { + m_err = err; + m_flavor = flavor; + m_str.clear(); + } + + // Generic errors can set their own string values + void SetErrorString(const char *err_str) { + if (err_str && err_str[0]) + m_str = err_str; + else + m_str.clear(); + } + bool Success() const { return m_err == 0; } + bool Fail() const { return m_err != 0; } + void LogThreadedIfError(const char *format, ...) const; + void LogThreaded(const char *format, ...) const; - // Generic errors can set their own string values - void SetErrorString(const char *err_str) - { - if (err_str && err_str[0]) - m_str = err_str; - else - m_str.clear(); - } - bool Success() const { return m_err == 0; } - bool Fail() const { return m_err != 0; } - void LogThreadedIfError(const char *format, ...) const; - void LogThreaded(const char *format, ...) const; protected: - ValueType m_err; - FlavorType m_flavor; - mutable std::string m_str; + ValueType m_err; + FlavorType m_flavor; + mutable std::string m_str; }; - -#endif // #ifndef __DNBError_h__ +#endif // #ifndef __DNBError_h__ diff --git a/tools/debugserver/source/DNBLog.cpp b/tools/debugserver/source/DNBLog.cpp index 18d8d2ad3a67..c3d42a2a84da 100644 --- a/tools/debugserver/source/DNBLog.cpp +++ b/tools/debugserver/source/DNBLog.cpp @@ -16,362 +16,272 @@ static int g_debug = 0; static int g_verbose = 0; -#if defined (DNBLOG_ENABLED) +#if defined(DNBLOG_ENABLED) -#include <stdio.h> +#include "PThreadMutex.h" +#include <mach/mach.h> +#include <pthread.h> #include <stdarg.h> +#include <stdio.h> #include <stdlib.h> #include <sys/time.h> #include <unistd.h> -#include <mach/mach.h> -#include <pthread.h> -#include "PThreadMutex.h" uint32_t g_log_bits = 0; static DNBCallbackLog g_log_callback = NULL; static void *g_log_baton = NULL; +int DNBLogGetDebug() { return g_debug; } -int -DNBLogGetDebug () -{ - return g_debug; -} - +void DNBLogSetDebug(int g) { g_debug = g; } -void -DNBLogSetDebug (int g) -{ - g_debug = g; -} +int DNBLogGetVerbose() { return g_verbose; } -int -DNBLogGetVerbose () -{ - return g_verbose; -} +void DNBLogSetVerbose(int v) { g_verbose = v; } -void -DNBLogSetVerbose (int v) -{ - g_verbose = v; -} +bool DNBLogCheckLogBit(uint32_t bit) { return (g_log_bits & bit) != 0; } -bool -DNBLogCheckLogBit (uint32_t bit) -{ - return (g_log_bits & bit) != 0; +uint32_t DNBLogSetLogMask(uint32_t mask) { + uint32_t old = g_log_bits; + g_log_bits = mask; + return old; } -uint32_t -DNBLogSetLogMask (uint32_t mask) -{ - uint32_t old = g_log_bits; - g_log_bits = mask; - return old; -} +uint32_t DNBLogGetLogMask() { return g_log_bits; } -uint32_t -DNBLogGetLogMask () -{ - return g_log_bits; +void DNBLogSetLogCallback(DNBCallbackLog callback, void *baton) { + g_log_callback = callback; + g_log_baton = baton; } -void -DNBLogSetLogCallback (DNBCallbackLog callback, void *baton) -{ - g_log_callback = callback; - g_log_baton = baton; -} +DNBCallbackLog DNBLogGetLogCallback() { return g_log_callback; } -DNBCallbackLog -DNBLogGetLogCallback () -{ - return g_log_callback; -} +bool DNBLogEnabled() { return g_log_callback != NULL; } -bool -DNBLogEnabled () -{ - return g_log_callback != NULL; +bool DNBLogEnabledForAny(uint32_t mask) { + if (g_log_callback) + return (g_log_bits & mask) != 0; + return false; } +static inline void _DNBLogVAPrintf(uint32_t flags, const char *format, + va_list args) { + static PThreadMutex g_LogThreadedMutex(PTHREAD_MUTEX_RECURSIVE); + PTHREAD_MUTEX_LOCKER(locker, g_LogThreadedMutex); -bool -DNBLogEnabledForAny (uint32_t mask) -{ - if (g_log_callback) - return (g_log_bits & mask) != 0; - return false; -} -static inline void -_DNBLogVAPrintf(uint32_t flags, const char *format, va_list args) -{ - static PThreadMutex g_LogThreadedMutex(PTHREAD_MUTEX_RECURSIVE); - PTHREAD_MUTEX_LOCKER(locker, g_LogThreadedMutex); - - if (g_log_callback) - g_log_callback(g_log_baton, flags, format, args); + if (g_log_callback) + g_log_callback(g_log_baton, flags, format, args); } -void -_DNBLog(uint32_t flags, const char *format, ...) -{ - va_list args; - va_start (args, format); - _DNBLogVAPrintf(flags, format, args); - va_end (args); +void _DNBLog(uint32_t flags, const char *format, ...) { + va_list args; + va_start(args, format); + _DNBLogVAPrintf(flags, format, args); + va_end(args); } //---------------------------------------------------------------------- // Print debug strings if and only if the global g_debug is set to // a non-zero value. //---------------------------------------------------------------------- -void -_DNBLogDebug (const char *format, ...) -{ - if (DNBLogEnabled () && g_debug) - { - va_list args; - va_start (args, format); - _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG, format, args); - va_end (args); - } +void _DNBLogDebug(const char *format, ...) { + if (DNBLogEnabled() && g_debug) { + va_list args; + va_start(args, format); + _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG, format, args); + va_end(args); + } } - //---------------------------------------------------------------------- // Print debug strings if and only if the global g_debug is set to // a non-zero value. //---------------------------------------------------------------------- -void -_DNBLogDebugVerbose (const char *format, ...) -{ - if (DNBLogEnabled () && g_debug && g_verbose) - { - va_list args; - va_start (args, format); - _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG | DNBLOG_FLAG_VERBOSE, format, args); - va_end (args); - } +void _DNBLogDebugVerbose(const char *format, ...) { + if (DNBLogEnabled() && g_debug && g_verbose) { + va_list args; + va_start(args, format); + _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG | DNBLOG_FLAG_VERBOSE, format, args); + va_end(args); + } } - static uint32_t g_message_id = 0; //---------------------------------------------------------------------- // Prefix the formatted log string with process and thread IDs and // suffix it with a newline. //---------------------------------------------------------------------- -void -_DNBLogThreaded (const char *format, ...) -{ - if (DNBLogEnabled ()) - { - //PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex()); - - char *arg_msg = NULL; - va_list args; - va_start (args, format); - ::vasprintf (&arg_msg, format, args); - va_end (args); - - if (arg_msg != NULL) - { - static struct timeval g_timeval = { 0 , 0 }; - static struct timeval tv; - static struct timeval delta; - gettimeofday(&tv, NULL); - if (g_timeval.tv_sec == 0) - { - delta.tv_sec = 0; - delta.tv_usec = 0; - } - else - { - timersub (&tv, &g_timeval, &delta); - } - g_timeval = tv; - - // Calling "mach_port_deallocate()" bumps the reference count on the thread - // port, so we need to deallocate it. mach_task_self() doesn't bump the ref - // count. - thread_port_t thread_self = mach_thread_self(); - - _DNBLog (DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s", - ++g_message_id, - delta.tv_sec, - delta.tv_usec, - getpid(), - thread_self, - arg_msg); - - mach_port_deallocate(mach_task_self(), thread_self); - free (arg_msg); - } +void _DNBLogThreaded(const char *format, ...) { + if (DNBLogEnabled()) { + // PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex()); + + char *arg_msg = NULL; + va_list args; + va_start(args, format); + ::vasprintf(&arg_msg, format, args); + va_end(args); + + if (arg_msg != NULL) { + static struct timeval g_timeval = {0, 0}; + static struct timeval tv; + static struct timeval delta; + gettimeofday(&tv, NULL); + if (g_timeval.tv_sec == 0) { + delta.tv_sec = 0; + delta.tv_usec = 0; + } else { + timersub(&tv, &g_timeval, &delta); + } + g_timeval = tv; + + // Calling "mach_port_deallocate()" bumps the reference count on the + // thread + // port, so we need to deallocate it. mach_task_self() doesn't bump the + // ref + // count. + thread_port_t thread_self = mach_thread_self(); + + _DNBLog(DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s", + ++g_message_id, delta.tv_sec, delta.tv_usec, getpid(), + thread_self, arg_msg); + + mach_port_deallocate(mach_task_self(), thread_self); + free(arg_msg); } + } } //---------------------------------------------------------------------- // Prefix the formatted log string with process and thread IDs and // suffix it with a newline. //---------------------------------------------------------------------- -void -_DNBLogThreadedIf (uint32_t log_bit, const char *format, ...) -{ - if (DNBLogEnabled () && (log_bit & g_log_bits) == log_bit) - { - //PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex()); - - char *arg_msg = NULL; - va_list args; - va_start (args, format); - ::vasprintf (&arg_msg, format, args); - va_end (args); - - if (arg_msg != NULL) - { - static struct timeval g_timeval = { 0 , 0 }; - static struct timeval tv; - static struct timeval delta; - gettimeofday(&tv, NULL); - if (g_timeval.tv_sec == 0) - { - delta.tv_sec = 0; - delta.tv_usec = 0; - } - else - { - timersub (&tv, &g_timeval, &delta); - } - g_timeval = tv; - - // Calling "mach_port_deallocate()" bumps the reference count on the thread - // port, so we need to deallocate it. mach_task_self() doesn't bump the ref - // count. - thread_port_t thread_self = mach_thread_self(); - - _DNBLog (DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s", - ++g_message_id, - delta.tv_sec, - delta.tv_usec, - getpid(), - thread_self, - arg_msg); - - mach_port_deallocate(mach_task_self(), thread_self); - - free (arg_msg); - } +void _DNBLogThreadedIf(uint32_t log_bit, const char *format, ...) { + if (DNBLogEnabled() && (log_bit & g_log_bits) == log_bit) { + // PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex()); + + char *arg_msg = NULL; + va_list args; + va_start(args, format); + ::vasprintf(&arg_msg, format, args); + va_end(args); + + if (arg_msg != NULL) { + static struct timeval g_timeval = {0, 0}; + static struct timeval tv; + static struct timeval delta; + gettimeofday(&tv, NULL); + if (g_timeval.tv_sec == 0) { + delta.tv_sec = 0; + delta.tv_usec = 0; + } else { + timersub(&tv, &g_timeval, &delta); + } + g_timeval = tv; + + // Calling "mach_port_deallocate()" bumps the reference count on the + // thread + // port, so we need to deallocate it. mach_task_self() doesn't bump the + // ref + // count. + thread_port_t thread_self = mach_thread_self(); + + _DNBLog(DNBLOG_FLAG_THREADED, "%u +%lu.%06u sec [%4.4x/%4.4x]: %s", + ++g_message_id, delta.tv_sec, delta.tv_usec, getpid(), + thread_self, arg_msg); + + mach_port_deallocate(mach_task_self(), thread_self); + + free(arg_msg); } + } } - - //---------------------------------------------------------------------- // Printing of errors that are not fatal. //---------------------------------------------------------------------- -void -_DNBLogError (const char *format, ...) -{ - if (DNBLogEnabled ()) - { - char *arg_msg = NULL; - va_list args; - va_start (args, format); - ::vasprintf (&arg_msg, format, args); - va_end (args); - - if (arg_msg != NULL) - { - _DNBLog (DNBLOG_FLAG_ERROR, "error: %s", arg_msg); - free (arg_msg); - } +void _DNBLogError(const char *format, ...) { + if (DNBLogEnabled()) { + char *arg_msg = NULL; + va_list args; + va_start(args, format); + ::vasprintf(&arg_msg, format, args); + va_end(args); + + if (arg_msg != NULL) { + _DNBLog(DNBLOG_FLAG_ERROR, "error: %s", arg_msg); + free(arg_msg); } + } } //---------------------------------------------------------------------- // Printing of errors that ARE fatal. Exit with ERR exit code // immediately. //---------------------------------------------------------------------- -void -_DNBLogFatalError (int err, const char *format, ...) -{ - if (DNBLogEnabled ()) - { - char *arg_msg = NULL; - va_list args; - va_start (args, format); - ::vasprintf (&arg_msg, format, args); - va_end (args); - - if (arg_msg != NULL) - { - _DNBLog (DNBLOG_FLAG_ERROR | DNBLOG_FLAG_FATAL, "error: %s", arg_msg); - free (arg_msg); - } - ::exit (err); +void _DNBLogFatalError(int err, const char *format, ...) { + if (DNBLogEnabled()) { + char *arg_msg = NULL; + va_list args; + va_start(args, format); + ::vasprintf(&arg_msg, format, args); + va_end(args); + + if (arg_msg != NULL) { + _DNBLog(DNBLOG_FLAG_ERROR | DNBLOG_FLAG_FATAL, "error: %s", arg_msg); + free(arg_msg); } + ::exit(err); + } } - //---------------------------------------------------------------------- // Printing of warnings that are not fatal only if verbose mode is // enabled. //---------------------------------------------------------------------- -void -_DNBLogVerbose (const char *format, ...) -{ - if (DNBLogEnabled () && g_verbose) - { - va_list args; - va_start (args, format); - _DNBLogVAPrintf(DNBLOG_FLAG_VERBOSE, format, args); - va_end (args); - } +void _DNBLogVerbose(const char *format, ...) { + if (DNBLogEnabled() && g_verbose) { + va_list args; + va_start(args, format); + _DNBLogVAPrintf(DNBLOG_FLAG_VERBOSE, format, args); + va_end(args); + } } //---------------------------------------------------------------------- // Printing of warnings that are not fatal only if verbose mode is // enabled. //---------------------------------------------------------------------- -void -_DNBLogWarningVerbose (const char *format, ...) -{ - if (DNBLogEnabled () && g_verbose) - { - char *arg_msg = NULL; - va_list args; - va_start (args, format); - ::vasprintf (&arg_msg, format, args); - va_end (args); - - if (arg_msg != NULL) - { - _DNBLog (DNBLOG_FLAG_WARNING | DNBLOG_FLAG_VERBOSE, "warning: %s", arg_msg); - free (arg_msg); - } +void _DNBLogWarningVerbose(const char *format, ...) { + if (DNBLogEnabled() && g_verbose) { + char *arg_msg = NULL; + va_list args; + va_start(args, format); + ::vasprintf(&arg_msg, format, args); + va_end(args); + + if (arg_msg != NULL) { + _DNBLog(DNBLOG_FLAG_WARNING | DNBLOG_FLAG_VERBOSE, "warning: %s", + arg_msg); + free(arg_msg); } + } } //---------------------------------------------------------------------- // Printing of warnings that are not fatal. //---------------------------------------------------------------------- -void -_DNBLogWarning (const char *format, ...) -{ - if (DNBLogEnabled ()) - { - char *arg_msg = NULL; - va_list args; - va_start (args, format); - ::vasprintf (&arg_msg, format, args); - va_end (args); - - if (arg_msg != NULL) - { - _DNBLog (DNBLOG_FLAG_WARNING, "warning: %s", arg_msg); - free (arg_msg); - } +void _DNBLogWarning(const char *format, ...) { + if (DNBLogEnabled()) { + char *arg_msg = NULL; + va_list args; + va_start(args, format); + ::vasprintf(&arg_msg, format, args); + va_end(args); + + if (arg_msg != NULL) { + _DNBLog(DNBLOG_FLAG_WARNING, "warning: %s", arg_msg); + free(arg_msg); } + } } #endif diff --git a/tools/debugserver/source/DNBLog.h b/tools/debugserver/source/DNBLog.h index 01add065abcd..65181caa412d 100644 --- a/tools/debugserver/source/DNBLog.h +++ b/tools/debugserver/source/DNBLog.h @@ -14,78 +14,135 @@ #ifndef __DNBLog_h__ #define __DNBLog_h__ -#include <stdio.h> -#include <stdint.h> #include "DNBDefs.h" +#include <stdint.h> +#include <stdio.h> #ifdef __cplusplus extern "C" { #endif -// Flags that get filled in automatically before calling the log callback function -#define DNBLOG_FLAG_FATAL (1u << 0) -#define DNBLOG_FLAG_ERROR (1u << 1) -#define DNBLOG_FLAG_WARNING (1u << 2) -#define DNBLOG_FLAG_DEBUG (1u << 3) -#define DNBLOG_FLAG_VERBOSE (1u << 4) -#define DNBLOG_FLAG_THREADED (1u << 5) +// Flags that get filled in automatically before calling the log callback +// function +#define DNBLOG_FLAG_FATAL (1u << 0) +#define DNBLOG_FLAG_ERROR (1u << 1) +#define DNBLOG_FLAG_WARNING (1u << 2) +#define DNBLOG_FLAG_DEBUG (1u << 3) +#define DNBLOG_FLAG_VERBOSE (1u << 4) +#define DNBLOG_FLAG_THREADED (1u << 5) #define DNBLOG_ENABLED -#if defined (DNBLOG_ENABLED) +#if defined(DNBLOG_ENABLED) -void _DNBLog(uint32_t flags, const char *format, ...) __attribute__ ((format (printf, 2, 3))); -void _DNBLogDebug (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); -void _DNBLogDebugVerbose (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))) ; -void _DNBLogThreaded (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); -void _DNBLogThreadedIf (uint32_t mask, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); -void _DNBLogError (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); -void _DNBLogFatalError (int err, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); -void _DNBLogVerbose (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); -void _DNBLogWarning (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); -void _DNBLogWarningVerbose (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); -bool DNBLogCheckLogBit (uint32_t bit); -uint32_t DNBLogSetLogMask (uint32_t mask); -uint32_t DNBLogGetLogMask (); -void DNBLogSetLogCallback (DNBCallbackLog callback, void *baton); -DNBCallbackLog DNBLogGetLogCallback (); -bool DNBLogEnabled (); -bool DNBLogEnabledForAny (uint32_t mask); -int DNBLogGetDebug (); -void DNBLogSetDebug (int g); -int DNBLogGetVerbose (); -void DNBLogSetVerbose (int g); +void _DNBLog(uint32_t flags, const char *format, ...) + __attribute__((format(printf, 2, 3))); +void _DNBLogDebug(const char *fmt, ...) __attribute__((format(printf, 1, 2))); +void _DNBLogDebugVerbose(const char *fmt, ...) + __attribute__((format(printf, 1, 2))); +void _DNBLogThreaded(const char *fmt, ...) + __attribute__((format(printf, 1, 2))); +void _DNBLogThreadedIf(uint32_t mask, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); +void _DNBLogError(const char *fmt, ...) __attribute__((format(printf, 1, 2))); +void _DNBLogFatalError(int err, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); +void _DNBLogVerbose(const char *fmt, ...) __attribute__((format(printf, 1, 2))); +void _DNBLogWarning(const char *fmt, ...) __attribute__((format(printf, 1, 2))); +void _DNBLogWarningVerbose(const char *fmt, ...) + __attribute__((format(printf, 1, 2))); +bool DNBLogCheckLogBit(uint32_t bit); +uint32_t DNBLogSetLogMask(uint32_t mask); +uint32_t DNBLogGetLogMask(); +void DNBLogSetLogCallback(DNBCallbackLog callback, void *baton); +DNBCallbackLog DNBLogGetLogCallback(); +bool DNBLogEnabled(); +bool DNBLogEnabledForAny(uint32_t mask); +int DNBLogGetDebug(); +void DNBLogSetDebug(int g); +int DNBLogGetVerbose(); +void DNBLogSetVerbose(int g); -#define DNBLog(fmt, ...) do { if (DNBLogEnabled()) { _DNBLog(0, fmt, ## __VA_ARGS__); } } while (0) -#define DNBLogDebug(fmt, ...) do { if (DNBLogEnabled()) { _DNBLogDebug(fmt, ## __VA_ARGS__); } } while (0) -#define DNBLogDebugVerbose(fmt, ...) do { if (DNBLogEnabled()) { _DNBLogDebugVerbose(fmt, ## __VA_ARGS__); } } while (0) -#define DNBLogThreaded(fmt, ...) do { if (DNBLogEnabled()) { _DNBLogThreaded(fmt, ## __VA_ARGS__); } } while (0) -#define DNBLogThreadedIf(mask, fmt, ...) do { if (DNBLogEnabledForAny(mask)) { _DNBLogThreaded(fmt, ## __VA_ARGS__); } } while (0) -#define DNBLogError(fmt, ...) do { if (DNBLogEnabled()) { _DNBLogError(fmt, ## __VA_ARGS__); } } while (0) -#define DNBLogFatalError(err, fmt, ...) do { if (DNBLogEnabled()) { _DNBLogFatalError(err, fmt, ## __VA_ARGS__); } } while (0) -#define DNBLogVerbose(fmt, ...) do { if (DNBLogEnabled()) { _DNBLogVerbose(fmt, ## __VA_ARGS__); } } while (0) -#define DNBLogWarning(fmt, ...) do { if (DNBLogEnabled()) { _DNBLogWarning(fmt, ## __VA_ARGS__); } } while (0) -#define DNBLogWarningVerbose(fmt, ...) do { if (DNBLogEnabled()) { _DNBLogWarningVerbose(fmt, ## __VA_ARGS__); } } while (0) +#define DNBLog(fmt, ...) \ + do { \ + if (DNBLogEnabled()) { \ + _DNBLog(0, fmt, ##__VA_ARGS__); \ + } \ + } while (0) +#define DNBLogDebug(fmt, ...) \ + do { \ + if (DNBLogEnabled()) { \ + _DNBLogDebug(fmt, ##__VA_ARGS__); \ + } \ + } while (0) +#define DNBLogDebugVerbose(fmt, ...) \ + do { \ + if (DNBLogEnabled()) { \ + _DNBLogDebugVerbose(fmt, ##__VA_ARGS__); \ + } \ + } while (0) +#define DNBLogThreaded(fmt, ...) \ + do { \ + if (DNBLogEnabled()) { \ + _DNBLogThreaded(fmt, ##__VA_ARGS__); \ + } \ + } while (0) +#define DNBLogThreadedIf(mask, fmt, ...) \ + do { \ + if (DNBLogEnabledForAny(mask)) { \ + _DNBLogThreaded(fmt, ##__VA_ARGS__); \ + } \ + } while (0) +#define DNBLogError(fmt, ...) \ + do { \ + if (DNBLogEnabled()) { \ + _DNBLogError(fmt, ##__VA_ARGS__); \ + } \ + } while (0) +#define DNBLogFatalError(err, fmt, ...) \ + do { \ + if (DNBLogEnabled()) { \ + _DNBLogFatalError(err, fmt, ##__VA_ARGS__); \ + } \ + } while (0) +#define DNBLogVerbose(fmt, ...) \ + do { \ + if (DNBLogEnabled()) { \ + _DNBLogVerbose(fmt, ##__VA_ARGS__); \ + } \ + } while (0) +#define DNBLogWarning(fmt, ...) \ + do { \ + if (DNBLogEnabled()) { \ + _DNBLogWarning(fmt, ##__VA_ARGS__); \ + } \ + } while (0) +#define DNBLogWarningVerbose(fmt, ...) \ + do { \ + if (DNBLogEnabled()) { \ + _DNBLogWarningVerbose(fmt, ##__VA_ARGS__); \ + } \ + } while (0) -#else // #if defined(DNBLOG_ENABLED) +#else // #if defined(DNBLOG_ENABLED) -#define DNBLogDebug(...) ((void)0) -#define DNBLogDebugVerbose(...) ((void)0) -#define DNBLogThreaded(...) ((void)0) -#define DNBLogThreadedIf(...) ((void)0) -#define DNBLogError(...) ((void)0) -#define DNBLogFatalError(...) ((void)0) -#define DNBLogVerbose(...) ((void)0) -#define DNBLogWarning(...) ((void)0) -#define DNBLogWarningVerbose(...) ((void)0) -#define DNBLogGetLogFile() ((FILE *)NULL) -#define DNBLogSetLogFile(f) ((void)0) -#define DNBLogCheckLogBit(bit) ((bool)false) -#define DNBLogSetLogMask(mask) ((uint32_t)0u) -#define DNBLogGetLogMask() ((uint32_t)0u) -#define DNBLogToASL() ((void)0) -#define DNBLogToFile() ((void)0) -#define DNBLogCloseLogFile() ((void)0) +#define DNBLogDebug(...) ((void)0) +#define DNBLogDebugVerbose(...) ((void)0) +#define DNBLogThreaded(...) ((void)0) +#define DNBLogThreadedIf(...) ((void)0) +#define DNBLogError(...) ((void)0) +#define DNBLogFatalError(...) ((void)0) +#define DNBLogVerbose(...) ((void)0) +#define DNBLogWarning(...) ((void)0) +#define DNBLogWarningVerbose(...) ((void)0) +#define DNBLogGetLogFile() ((FILE *)NULL) +#define DNBLogSetLogFile(f) ((void)0) +#define DNBLogCheckLogBit(bit) ((bool)false) +#define DNBLogSetLogMask(mask) ((uint32_t)0u) +#define DNBLogGetLogMask() ((uint32_t)0u) +#define DNBLogToASL() ((void)0) +#define DNBLogToFile() ((void)0) +#define DNBLogCloseLogFile() ((void)0) #endif // #else defined(DNBLOG_ENABLED) diff --git a/tools/debugserver/source/DNBRegisterInfo.cpp b/tools/debugserver/source/DNBRegisterInfo.cpp index acc7ba9946be..fadcc5ddb06e 100644 --- a/tools/debugserver/source/DNBRegisterInfo.cpp +++ b/tools/debugserver/source/DNBRegisterInfo.cpp @@ -15,205 +15,237 @@ #include "DNBLog.h" #include <string.h> -DNBRegisterValueClass::DNBRegisterValueClass(const DNBRegisterInfo *regInfo) -{ - Clear(); - if (regInfo) - info = *regInfo; +DNBRegisterValueClass::DNBRegisterValueClass(const DNBRegisterInfo *regInfo) { + Clear(); + if (regInfo) + info = *regInfo; } -void -DNBRegisterValueClass::Clear() -{ - memset(&info, 0, sizeof(DNBRegisterInfo)); - memset(&value, 0, sizeof(value)); +void DNBRegisterValueClass::Clear() { + memset(&info, 0, sizeof(DNBRegisterInfo)); + memset(&value, 0, sizeof(value)); } -bool -DNBRegisterValueClass::IsValid() const -{ - return - info.name != NULL && - info.type != InvalidRegType && - info.size > 0 && info.size <= sizeof(value); +bool DNBRegisterValueClass::IsValid() const { + return info.name != NULL && info.type != InvalidRegType && info.size > 0 && + info.size <= sizeof(value); } -#define PRINT_COMMA_SEPARATOR do { if (pos < end) { if (i > 0) { strncpy(pos, ", ", end - pos); pos += 2; } } } while (0) - -void -DNBRegisterValueClass::Dump(const char *pre, const char *post) const -{ - if (info.name != NULL) - { - char str[1024]; - char *pos; - char *end = str + sizeof(str); - if (info.format == Hex) - { - switch (info.size) - { - case 0: snprintf(str, sizeof(str), "%s", "error: invalid register size of zero."); break; - case 1: snprintf(str, sizeof(str), "0x%2.2x", value.uint8); break; - case 2: snprintf(str, sizeof(str), "0x%4.4x", value.uint16); break; - case 4: snprintf(str, sizeof(str), "0x%8.8x", value.uint32); break; - case 8: snprintf(str, sizeof(str), "0x%16.16llx", value.uint64); break; - case 16: snprintf(str, sizeof(str), "0x%16.16llx%16.16llx", value.v_uint64[0], value.v_uint64[1]); break; - default: - strncpy(str, "0x", 3); - pos = str + 2; - for (uint32_t i=0; i<info.size; ++i) - { - if (pos < end) - pos += snprintf(pos, end - pos, "%2.2x", (uint32_t)value.v_uint8[i]); - } - break; - } +#define PRINT_COMMA_SEPARATOR \ + do { \ + if (pos < end) { \ + if (i > 0) { \ + strncpy(pos, ", ", end - pos); \ + pos += 2; \ + } \ + } \ + } while (0) + +void DNBRegisterValueClass::Dump(const char *pre, const char *post) const { + if (info.name != NULL) { + char str[1024]; + char *pos; + char *end = str + sizeof(str); + if (info.format == Hex) { + switch (info.size) { + case 0: + snprintf(str, sizeof(str), "%s", + "error: invalid register size of zero."); + break; + case 1: + snprintf(str, sizeof(str), "0x%2.2x", value.uint8); + break; + case 2: + snprintf(str, sizeof(str), "0x%4.4x", value.uint16); + break; + case 4: + snprintf(str, sizeof(str), "0x%8.8x", value.uint32); + break; + case 8: + snprintf(str, sizeof(str), "0x%16.16llx", value.uint64); + break; + case 16: + snprintf(str, sizeof(str), "0x%16.16llx%16.16llx", value.v_uint64[0], + value.v_uint64[1]); + break; + default: + strncpy(str, "0x", 3); + pos = str + 2; + for (uint32_t i = 0; i < info.size; ++i) { + if (pos < end) + pos += + snprintf(pos, end - pos, "%2.2x", (uint32_t)value.v_uint8[i]); + } + break; + } + } else { + switch (info.type) { + case Uint: + switch (info.size) { + case 1: + snprintf(str, sizeof(str), "%u", value.uint8); + break; + case 2: + snprintf(str, sizeof(str), "%u", value.uint16); + break; + case 4: + snprintf(str, sizeof(str), "%u", value.uint32); + break; + case 8: + snprintf(str, sizeof(str), "%llu", value.uint64); + break; + default: + snprintf(str, sizeof(str), "error: unsupported uint byte size %d.", + info.size); + break; + } + break; + + case Sint: + switch (info.size) { + case 1: + snprintf(str, sizeof(str), "%d", value.sint8); + break; + case 2: + snprintf(str, sizeof(str), "%d", value.sint16); + break; + case 4: + snprintf(str, sizeof(str), "%d", value.sint32); + break; + case 8: + snprintf(str, sizeof(str), "%lld", value.sint64); + break; + default: + snprintf(str, sizeof(str), "error: unsupported sint byte size %d.", + info.size); + break; } - else - { - switch (info.type) - { - case Uint: - switch (info.size) - { - case 1: snprintf(str, sizeof(str), "%u", value.uint8); break; - case 2: snprintf(str, sizeof(str), "%u", value.uint16); break; - case 4: snprintf(str, sizeof(str), "%u", value.uint32); break; - case 8: snprintf(str, sizeof(str), "%llu", value.uint64); break; - default: snprintf(str, sizeof(str), "error: unsupported uint byte size %d.", info.size); break; - } - break; - - case Sint: - switch (info.size) - { - case 1: snprintf(str, sizeof(str), "%d", value.sint8); break; - case 2: snprintf(str, sizeof(str), "%d", value.sint16); break; - case 4: snprintf(str, sizeof(str), "%d", value.sint32); break; - case 8: snprintf(str, sizeof(str), "%lld", value.sint64); break; - default: snprintf(str, sizeof(str), "error: unsupported sint byte size %d.", info.size); break; - } - break; - - case IEEE754: - switch (info.size) - { - case 4: snprintf(str, sizeof(str), "%f", value.float32); break; - case 8: snprintf(str, sizeof(str), "%g", value.float64); break; - default: snprintf(str, sizeof(str), "error: unsupported float byte size %d.", info.size); break; - } - break; - - case Vector: - if (info.size > 0) - { - switch (info.format) - { - case VectorOfSInt8: - snprintf(str, sizeof(str), "%s", "sint8 { "); - pos = str + strlen(str); - for (uint32_t i=0; i<info.size; ++i) - { - PRINT_COMMA_SEPARATOR; - if (pos < end) - pos += snprintf(pos, end - pos, "%d", (int32_t)value.v_sint8[i]); - } - strlcat(str, " }", sizeof(str)); - break; - - default: - DNBLogError("unsupported vector format %d, defaulting to hex bytes.", info.format); - case VectorOfUInt8: - snprintf(str, sizeof(str), "%s", "uint8 { "); - pos = str + strlen(str); - for (uint32_t i=0; i<info.size; ++i) - { - PRINT_COMMA_SEPARATOR; - if (pos < end) - pos += snprintf(pos, end - pos, "%u", (uint32_t)value.v_uint8[i]); - } - break; - - case VectorOfSInt16: - snprintf(str, sizeof(str), "%s", "sint16 { "); - pos = str + strlen(str); - for (uint32_t i=0; i<info.size/2; ++i) - { - PRINT_COMMA_SEPARATOR; - if (pos < end) - pos += snprintf(pos, end - pos, "%d", (int32_t)value.v_sint16[i]); - } - break; - - case VectorOfUInt16: - snprintf(str, sizeof(str), "%s", "uint16 { "); - pos = str + strlen(str); - for (uint32_t i=0; i<info.size/2; ++i) - { - PRINT_COMMA_SEPARATOR; - if (pos < end) - pos += snprintf(pos, end - pos, "%u", (uint32_t)value.v_uint16[i]); - } - break; - - case VectorOfSInt32: - snprintf(str, sizeof(str), "%s", "sint32 { "); - pos = str + strlen(str); - for (uint32_t i=0; i<info.size/4; ++i) - { - PRINT_COMMA_SEPARATOR; - if (pos < end) - pos += snprintf(pos, end - pos, "%d", (int32_t)value.v_sint32[i]); - } - break; - - case VectorOfUInt32: - snprintf(str, sizeof(str), "%s", "uint32 { "); - pos = str + strlen(str); - for (uint32_t i=0; i<info.size/4; ++i) - { - PRINT_COMMA_SEPARATOR; - if (pos < end) - pos += snprintf(pos, end - pos, "%u", (uint32_t)value.v_uint32[i]); - } - break; - - case VectorOfFloat32: - snprintf(str, sizeof(str), "%s", "float32 { "); - pos = str + strlen(str); - for (uint32_t i=0; i<info.size/4; ++i) - { - PRINT_COMMA_SEPARATOR; - if (pos < end) - pos += snprintf(pos, end - pos, "%f", value.v_float32[i]); - } - break; - - case VectorOfUInt128: - snprintf(str, sizeof(str), "%s", "uint128 { "); - pos = str + strlen(str); - for (uint32_t i=0; i<info.size/16; ++i) - { - PRINT_COMMA_SEPARATOR; - if (pos < end) - pos += snprintf(pos, end - pos, "0x%16.16llx%16.16llx", value.v_uint64[i], value.v_uint64[i+1]); - } - break; - } - strlcat(str, " }", sizeof(str)); - } - else - { - snprintf(str, sizeof(str), "error: unsupported vector size %d.", info.size); - } - break; - - default: - snprintf(str, sizeof(str), "error: unsupported register type %d.", info.type); - break; + break; + + case IEEE754: + switch (info.size) { + case 4: + snprintf(str, sizeof(str), "%f", value.float32); + break; + case 8: + snprintf(str, sizeof(str), "%g", value.float64); + break; + default: + snprintf(str, sizeof(str), "error: unsupported float byte size %d.", + info.size); + break; + } + break; + + case Vector: + if (info.size > 0) { + switch (info.format) { + case VectorOfSInt8: + snprintf(str, sizeof(str), "%s", "sint8 { "); + pos = str + strlen(str); + for (uint32_t i = 0; i < info.size; ++i) { + PRINT_COMMA_SEPARATOR; + if (pos < end) + pos += + snprintf(pos, end - pos, "%d", (int32_t)value.v_sint8[i]); + } + strlcat(str, " }", sizeof(str)); + break; + + default: + DNBLogError( + "unsupported vector format %d, defaulting to hex bytes.", + info.format); + case VectorOfUInt8: + snprintf(str, sizeof(str), "%s", "uint8 { "); + pos = str + strlen(str); + for (uint32_t i = 0; i < info.size; ++i) { + PRINT_COMMA_SEPARATOR; + if (pos < end) + pos += + snprintf(pos, end - pos, "%u", (uint32_t)value.v_uint8[i]); + } + break; + + case VectorOfSInt16: + snprintf(str, sizeof(str), "%s", "sint16 { "); + pos = str + strlen(str); + for (uint32_t i = 0; i < info.size / 2; ++i) { + PRINT_COMMA_SEPARATOR; + if (pos < end) + pos += + snprintf(pos, end - pos, "%d", (int32_t)value.v_sint16[i]); } + break; + + case VectorOfUInt16: + snprintf(str, sizeof(str), "%s", "uint16 { "); + pos = str + strlen(str); + for (uint32_t i = 0; i < info.size / 2; ++i) { + PRINT_COMMA_SEPARATOR; + if (pos < end) + pos += + snprintf(pos, end - pos, "%u", (uint32_t)value.v_uint16[i]); + } + break; + + case VectorOfSInt32: + snprintf(str, sizeof(str), "%s", "sint32 { "); + pos = str + strlen(str); + for (uint32_t i = 0; i < info.size / 4; ++i) { + PRINT_COMMA_SEPARATOR; + if (pos < end) + pos += + snprintf(pos, end - pos, "%d", (int32_t)value.v_sint32[i]); + } + break; + + case VectorOfUInt32: + snprintf(str, sizeof(str), "%s", "uint32 { "); + pos = str + strlen(str); + for (uint32_t i = 0; i < info.size / 4; ++i) { + PRINT_COMMA_SEPARATOR; + if (pos < end) + pos += + snprintf(pos, end - pos, "%u", (uint32_t)value.v_uint32[i]); + } + break; + + case VectorOfFloat32: + snprintf(str, sizeof(str), "%s", "float32 { "); + pos = str + strlen(str); + for (uint32_t i = 0; i < info.size / 4; ++i) { + PRINT_COMMA_SEPARATOR; + if (pos < end) + pos += snprintf(pos, end - pos, "%f", value.v_float32[i]); + } + break; + + case VectorOfUInt128: + snprintf(str, sizeof(str), "%s", "uint128 { "); + pos = str + strlen(str); + for (uint32_t i = 0; i < info.size / 16; ++i) { + PRINT_COMMA_SEPARATOR; + if (pos < end) + pos += snprintf(pos, end - pos, "0x%16.16llx%16.16llx", + value.v_uint64[i], value.v_uint64[i + 1]); + } + break; + } + strlcat(str, " }", sizeof(str)); + } else { + snprintf(str, sizeof(str), "error: unsupported vector size %d.", + info.size); } + break; - DNBLog("%s%4s = %s%s", pre ? pre : "", info.name, str, post ? post : ""); + default: + snprintf(str, sizeof(str), "error: unsupported register type %d.", + info.type); + break; + } } + + DNBLog("%s%4s = %s%s", pre ? pre : "", info.name, str, post ? post : ""); + } } diff --git a/tools/debugserver/source/DNBRegisterInfo.h b/tools/debugserver/source/DNBRegisterInfo.h index 666c397e0b5e..d665e3cb9485 100644 --- a/tools/debugserver/source/DNBRegisterInfo.h +++ b/tools/debugserver/source/DNBRegisterInfo.h @@ -14,17 +14,16 @@ #ifndef __DNBRegisterInfo_h__ #define __DNBRegisterInfo_h__ +#include "DNBDefs.h" #include <stdint.h> #include <stdio.h> -#include "DNBDefs.h" -struct DNBRegisterValueClass : public DNBRegisterValue -{ +struct DNBRegisterValueClass : public DNBRegisterValue { #ifdef __cplusplus - DNBRegisterValueClass(const DNBRegisterInfo *regInfo = NULL); - void Clear(); - void Dump(const char *pre, const char *post) const; - bool IsValid() const; + DNBRegisterValueClass(const DNBRegisterInfo *regInfo = NULL); + void Clear(); + void Dump(const char *pre, const char *post) const; + bool IsValid() const; #endif }; diff --git a/tools/debugserver/source/DNBRuntimeAction.h b/tools/debugserver/source/DNBRuntimeAction.h index d77bda8c604d..85d7bc1df0a5 100644 --- a/tools/debugserver/source/DNBRuntimeAction.h +++ b/tools/debugserver/source/DNBRuntimeAction.h @@ -14,12 +14,11 @@ #ifndef __DNBRuntimeAction_h__ #define __DNBRuntimeAction_h__ -class DNBRuntimeAction -{ - virtual void Initialize (nub_process_t pid) = 0; - virtual void ProcessStateChanged (nub_state_t state) = 0; - virtual void SharedLibraryStateChanged (DNBExecutableImageInfo *image_infos, nub_size_t num_image_infos) = 0; +class DNBRuntimeAction { + virtual void Initialize(nub_process_t pid) = 0; + virtual void ProcessStateChanged(nub_state_t state) = 0; + virtual void SharedLibraryStateChanged(DNBExecutableImageInfo *image_infos, + nub_size_t num_image_infos) = 0; }; - #endif // #ifndef __DNBRuntimeAction_h__ diff --git a/tools/debugserver/source/DNBThreadResumeActions.cpp b/tools/debugserver/source/DNBThreadResumeActions.cpp index b50dd0617843..4a97abc20e24 100644 --- a/tools/debugserver/source/DNBThreadResumeActions.cpp +++ b/tools/debugserver/source/DNBThreadResumeActions.cpp @@ -13,104 +13,77 @@ #include "DNBThreadResumeActions.h" -DNBThreadResumeActions::DNBThreadResumeActions() : - m_actions (), - m_signal_handled () -{ -} +DNBThreadResumeActions::DNBThreadResumeActions() + : m_actions(), m_signal_handled() {} -DNBThreadResumeActions::DNBThreadResumeActions (const DNBThreadResumeAction *actions, size_t num_actions) : - m_actions (), - m_signal_handled () -{ - if (actions && num_actions) - { - m_actions.assign (actions, actions + num_actions); - m_signal_handled.assign (num_actions, false); - } +DNBThreadResumeActions::DNBThreadResumeActions( + const DNBThreadResumeAction *actions, size_t num_actions) + : m_actions(), m_signal_handled() { + if (actions && num_actions) { + m_actions.assign(actions, actions + num_actions); + m_signal_handled.assign(num_actions, false); + } } -DNBThreadResumeActions::DNBThreadResumeActions (nub_state_t default_action, int signal) : - m_actions(), - m_signal_handled () -{ - SetDefaultThreadActionIfNeeded (default_action, signal); +DNBThreadResumeActions::DNBThreadResumeActions(nub_state_t default_action, + int signal) + : m_actions(), m_signal_handled() { + SetDefaultThreadActionIfNeeded(default_action, signal); } -void -DNBThreadResumeActions::Append (const DNBThreadResumeAction &action) -{ - m_actions.push_back (action); - m_signal_handled.push_back (false); +void DNBThreadResumeActions::Append(const DNBThreadResumeAction &action) { + m_actions.push_back(action); + m_signal_handled.push_back(false); } -void -DNBThreadResumeActions::AppendAction -( - nub_thread_t tid, - nub_state_t state, - int signal, - nub_addr_t addr -) -{ - DNBThreadResumeAction action = { tid, state, signal, addr }; - Append (action); +void DNBThreadResumeActions::AppendAction(nub_thread_t tid, nub_state_t state, + int signal, nub_addr_t addr) { + DNBThreadResumeAction action = {tid, state, signal, addr}; + Append(action); } - const DNBThreadResumeAction * -DNBThreadResumeActions::GetActionForThread (nub_thread_t tid, bool default_ok) const -{ - const size_t num_actions = m_actions.size(); - for (size_t i=0; i<num_actions; ++i) - { - if (m_actions[i].tid == tid) - return &m_actions[i]; - } - if (default_ok && tid != INVALID_NUB_THREAD) - return GetActionForThread (INVALID_NUB_THREAD, false); - return NULL; +DNBThreadResumeActions::GetActionForThread(nub_thread_t tid, + bool default_ok) const { + const size_t num_actions = m_actions.size(); + for (size_t i = 0; i < num_actions; ++i) { + if (m_actions[i].tid == tid) + return &m_actions[i]; + } + if (default_ok && tid != INVALID_NUB_THREAD) + return GetActionForThread(INVALID_NUB_THREAD, false); + return NULL; } -size_t -DNBThreadResumeActions::NumActionsWithState (nub_state_t state) const -{ - size_t count = 0; - const size_t num_actions = m_actions.size(); - for (size_t i=0; i<num_actions; ++i) - { - if (m_actions[i].state == state) - ++count; - } - return count; +size_t DNBThreadResumeActions::NumActionsWithState(nub_state_t state) const { + size_t count = 0; + const size_t num_actions = m_actions.size(); + for (size_t i = 0; i < num_actions; ++i) { + if (m_actions[i].state == state) + ++count; + } + return count; } - -bool -DNBThreadResumeActions::SetDefaultThreadActionIfNeeded (nub_state_t action, int signal) -{ - if (GetActionForThread (INVALID_NUB_THREAD, true) == NULL) - { - // There isn't a default action so we do need to set it. - DNBThreadResumeAction default_action = {INVALID_NUB_THREAD, action, signal, INVALID_NUB_ADDRESS }; - m_actions.push_back (default_action); - m_signal_handled.push_back (false); - return true; // Return true as we did add the default action - } - return false; +bool DNBThreadResumeActions::SetDefaultThreadActionIfNeeded(nub_state_t action, + int signal) { + if (GetActionForThread(INVALID_NUB_THREAD, true) == NULL) { + // There isn't a default action so we do need to set it. + DNBThreadResumeAction default_action = {INVALID_NUB_THREAD, action, signal, + INVALID_NUB_ADDRESS}; + m_actions.push_back(default_action); + m_signal_handled.push_back(false); + return true; // Return true as we did add the default action + } + return false; } - -void -DNBThreadResumeActions::SetSignalHandledForThread (nub_thread_t tid) const -{ - if (tid != INVALID_NUB_THREAD) - { - const size_t num_actions = m_actions.size(); - for (size_t i=0; i<num_actions; ++i) - { - if (m_actions[i].tid == tid) - m_signal_handled[i] = true; - } +void DNBThreadResumeActions::SetSignalHandledForThread(nub_thread_t tid) const { + if (tid != INVALID_NUB_THREAD) { + const size_t num_actions = m_actions.size(); + for (size_t i = 0; i < num_actions; ++i) { + if (m_actions[i].tid == tid) + m_signal_handled[i] = true; } + } } diff --git a/tools/debugserver/source/DNBThreadResumeActions.h b/tools/debugserver/source/DNBThreadResumeActions.h index 81c7c43b7222..40d2da03e9e4 100644 --- a/tools/debugserver/source/DNBThreadResumeActions.h +++ b/tools/debugserver/source/DNBThreadResumeActions.h @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// - #ifndef __DNBThreadResumeActions_h__ #define __DNBThreadResumeActions_h__ @@ -19,84 +18,49 @@ #include "DNBDefs.h" - -class DNBThreadResumeActions -{ +class DNBThreadResumeActions { public: - DNBThreadResumeActions (); - - DNBThreadResumeActions (nub_state_t default_action, int signal); - - DNBThreadResumeActions (const DNBThreadResumeAction *actions, size_t num_actions); - - bool - IsEmpty() const - { - return m_actions.empty(); - } - - void - Append (const DNBThreadResumeAction &action); - - void - AppendAction (nub_thread_t tid, - nub_state_t state, - int signal = 0, - nub_addr_t addr = INVALID_NUB_ADDRESS); - - void - AppendResumeAll () - { - AppendAction (INVALID_NUB_THREAD, eStateRunning); - } - - void - AppendSuspendAll () - { - AppendAction (INVALID_NUB_THREAD, eStateStopped); - } - - void - AppendStepAll () - { - AppendAction (INVALID_NUB_THREAD, eStateStepping); - } - - const DNBThreadResumeAction * - GetActionForThread (nub_thread_t tid, bool default_ok) const; - - size_t - NumActionsWithState (nub_state_t state) const; - - bool - SetDefaultThreadActionIfNeeded (nub_state_t action, int signal); - - void - SetSignalHandledForThread (nub_thread_t tid) const; - - const DNBThreadResumeAction * - GetFirst() const - { - return m_actions.data(); - } - - size_t - GetSize () const - { - return m_actions.size(); - } - - void - Clear() - { - m_actions.clear(); - m_signal_handled.clear(); - } + DNBThreadResumeActions(); + + DNBThreadResumeActions(nub_state_t default_action, int signal); + + DNBThreadResumeActions(const DNBThreadResumeAction *actions, + size_t num_actions); + + bool IsEmpty() const { return m_actions.empty(); } + + void Append(const DNBThreadResumeAction &action); + + void AppendAction(nub_thread_t tid, nub_state_t state, int signal = 0, + nub_addr_t addr = INVALID_NUB_ADDRESS); + + void AppendResumeAll() { AppendAction(INVALID_NUB_THREAD, eStateRunning); } + + void AppendSuspendAll() { AppendAction(INVALID_NUB_THREAD, eStateStopped); } + + void AppendStepAll() { AppendAction(INVALID_NUB_THREAD, eStateStepping); } + + const DNBThreadResumeAction *GetActionForThread(nub_thread_t tid, + bool default_ok) const; + + size_t NumActionsWithState(nub_state_t state) const; + + bool SetDefaultThreadActionIfNeeded(nub_state_t action, int signal); + + void SetSignalHandledForThread(nub_thread_t tid) const; + + const DNBThreadResumeAction *GetFirst() const { return m_actions.data(); } + + size_t GetSize() const { return m_actions.size(); } + + void Clear() { + m_actions.clear(); + m_signal_handled.clear(); + } protected: - std::vector<DNBThreadResumeAction> m_actions; - mutable std::vector<bool> m_signal_handled; + std::vector<DNBThreadResumeAction> m_actions; + mutable std::vector<bool> m_signal_handled; }; - -#endif // #ifndef __DNBThreadResumeActions_h__ +#endif // #ifndef __DNBThreadResumeActions_h__ diff --git a/tools/debugserver/source/DNBTimer.h b/tools/debugserver/source/DNBTimer.h index ca56e30c7090..881b8cdcde76 100644 --- a/tools/debugserver/source/DNBTimer.h +++ b/tools/debugserver/source/DNBTimer.h @@ -14,150 +14,132 @@ #ifndef __DNBTimer_h__ #define __DNBTimer_h__ -#include <sys/time.h> -#include <stdint.h> -#include <memory> #include "DNBDefs.h" #include "PThreadMutex.h" +#include <memory> +#include <stdint.h> +#include <sys/time.h> -class DNBTimer -{ +class DNBTimer { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - DNBTimer (bool threadSafe) : - m_mutexAP() - { - if (threadSafe) - m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE)); - Reset(); - } + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + DNBTimer(bool threadSafe) : m_mutexAP() { + if (threadSafe) + m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE)); + Reset(); + } + + DNBTimer(const DNBTimer &rhs) : m_mutexAP() { + // Create a new mutex to make this timer thread safe as well if + // the timer we are copying is thread safe + if (rhs.IsThreadSafe()) + m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE)); + m_timeval = rhs.m_timeval; + } - DNBTimer (const DNBTimer& rhs) : - m_mutexAP() - { - // Create a new mutex to make this timer thread safe as well if - // the timer we are copying is thread safe - if (rhs.IsThreadSafe()) - m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE)); - m_timeval = rhs.m_timeval; - } + DNBTimer &operator=(const DNBTimer &rhs) { + // Create a new mutex to make this timer thread safe as well if + // the timer we are copying is thread safe + if (rhs.IsThreadSafe()) + m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE)); + m_timeval = rhs.m_timeval; + return *this; + } - DNBTimer& operator= (const DNBTimer& rhs) - { - // Create a new mutex to make this timer thread safe as well if - // the timer we are copying is thread safe - if (rhs.IsThreadSafe()) - m_mutexAP.reset(new PThreadMutex(PTHREAD_MUTEX_RECURSIVE)); - m_timeval = rhs.m_timeval; - return *this; - } + ~DNBTimer() {} - ~DNBTimer () - { - } + bool IsThreadSafe() const { return m_mutexAP.get() != NULL; } + //------------------------------------------------------------------ + // Reset the time value to now + //------------------------------------------------------------------ + void Reset() { + PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); + gettimeofday(&m_timeval, NULL); + } + //------------------------------------------------------------------ + // Get the total mircoseconds since Jan 1, 1970 + //------------------------------------------------------------------ + uint64_t TotalMicroSeconds() const { + PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); + return (uint64_t)(m_timeval.tv_sec) * 1000000ull + + (uint64_t)m_timeval.tv_usec; + } - bool - IsThreadSafe() const - { - return m_mutexAP.get() != NULL; - } - //------------------------------------------------------------------ - // Reset the time value to now - //------------------------------------------------------------------ - void - Reset () - { - PTHREAD_MUTEX_LOCKER (locker, m_mutexAP.get()); - gettimeofday (&m_timeval, NULL); - } - //------------------------------------------------------------------ - // Get the total mircoseconds since Jan 1, 1970 - //------------------------------------------------------------------ - uint64_t - TotalMicroSeconds () const - { - PTHREAD_MUTEX_LOCKER (locker, m_mutexAP.get()); - return (uint64_t)(m_timeval.tv_sec) * 1000000ull + (uint64_t)m_timeval.tv_usec; - } + void GetTime(uint64_t &sec, uint32_t &usec) const { + PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); + sec = m_timeval.tv_sec; + usec = m_timeval.tv_usec; + } + //------------------------------------------------------------------ + // Return the number of microseconds elapsed between now and the + // m_timeval + //------------------------------------------------------------------ + uint64_t ElapsedMicroSeconds(bool update) { + PTHREAD_MUTEX_LOCKER(locker, m_mutexAP.get()); + struct timeval now; + gettimeofday(&now, NULL); + uint64_t now_usec = + (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec; + uint64_t this_usec = + (uint64_t)(m_timeval.tv_sec) * 1000000ull + (uint64_t)m_timeval.tv_usec; + uint64_t elapsed = now_usec - this_usec; + // Update the timer time value if requeseted + if (update) + m_timeval = now; + return elapsed; + } - void - GetTime (uint64_t& sec, uint32_t& usec) const - { - PTHREAD_MUTEX_LOCKER (locker, m_mutexAP.get()); - sec = m_timeval.tv_sec; - usec = m_timeval.tv_usec; - } - //------------------------------------------------------------------ - // Return the number of microseconds elapsed between now and the - // m_timeval - //------------------------------------------------------------------ - uint64_t - ElapsedMicroSeconds (bool update) - { - PTHREAD_MUTEX_LOCKER (locker, m_mutexAP.get()); - struct timeval now; - gettimeofday (&now, NULL); - uint64_t now_usec = (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec; - uint64_t this_usec = (uint64_t)(m_timeval.tv_sec) * 1000000ull + (uint64_t)m_timeval.tv_usec; - uint64_t elapsed = now_usec - this_usec; - // Update the timer time value if requeseted - if (update) - m_timeval = now; - return elapsed; - } + static uint64_t GetTimeOfDay() { + struct timeval now; + gettimeofday(&now, NULL); + uint64_t now_usec = + (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec; + return now_usec; + } - static uint64_t GetTimeOfDay() - { - struct timeval now; - gettimeofday (&now, NULL); - uint64_t now_usec = (uint64_t)(now.tv_sec) * 1000000ull + (uint64_t)now.tv_usec; - return now_usec; - } + static void OffsetTimeOfDay(struct timespec *ts, + __darwin_time_t sec_offset = 0, + long nsec_offset = 0) { + if (ts == NULL) + return; + // Get the current time in a timeval structure + struct timeval now; + gettimeofday(&now, NULL); + // Morph it into a timespec + TIMEVAL_TO_TIMESPEC(&now, ts); + // Offset the timespec if requested + if (sec_offset != 0 || nsec_offset != 0) { + // Offset the nano seconds + ts->tv_nsec += nsec_offset; + // Offset the seconds taking into account a nano-second overflow + ts->tv_sec = ts->tv_sec + ts->tv_nsec / 1000000000 + sec_offset; + // Trim the nanoseconds back there was an overflow + ts->tv_nsec = ts->tv_nsec % 1000000000; + } + } + static bool TimeOfDayLaterThan(struct timespec &ts) { + struct timespec now; + OffsetTimeOfDay(&now); + if (now.tv_sec > ts.tv_sec) + return true; + else if (now.tv_sec < ts.tv_sec) + return false; + else { + if (now.tv_nsec > ts.tv_nsec) + return true; + else + return false; + } + } - static void OffsetTimeOfDay (struct timespec* ts, __darwin_time_t sec_offset = 0, long nsec_offset = 0) - { - if (ts == NULL) - return; - // Get the current time in a timeval structure - struct timeval now; - gettimeofday (&now, NULL); - // Morph it into a timespec - TIMEVAL_TO_TIMESPEC(&now, ts); - // Offset the timespec if requested - if (sec_offset != 0 || nsec_offset != 0) - { - // Offset the nano seconds - ts->tv_nsec += nsec_offset; - // Offset the seconds taking into account a nano-second overflow - ts->tv_sec = ts->tv_sec + ts->tv_nsec / 1000000000 + sec_offset; - // Trim the nanoseconds back there was an overflow - ts->tv_nsec = ts->tv_nsec % 1000000000; - } - } - static bool TimeOfDayLaterThan (struct timespec &ts) - { - struct timespec now; - OffsetTimeOfDay(&now); - if (now.tv_sec > ts.tv_sec) - return true; - else if (now.tv_sec < ts.tv_sec) - return false; - else - { - if (now.tv_nsec > ts.tv_nsec) - return true; - else - return false; - } - } protected: - //------------------------------------------------------------------ - // Classes that inherit from DNBTimer can see and modify these - //------------------------------------------------------------------ - std::unique_ptr<PThreadMutex> m_mutexAP; - struct timeval m_timeval; + //------------------------------------------------------------------ + // Classes that inherit from DNBTimer can see and modify these + //------------------------------------------------------------------ + std::unique_ptr<PThreadMutex> m_mutexAP; + struct timeval m_timeval; }; #endif // #ifndef __DNBTimer_h__ diff --git a/tools/debugserver/source/JSON.cpp b/tools/debugserver/source/JSON.cpp new file mode 100644 index 000000000000..19ebfd000f51 --- /dev/null +++ b/tools/debugserver/source/JSON.cpp @@ -0,0 +1,588 @@ +//===--------------------- JSON.cpp -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "JSON.h" + +// C includes +#include <assert.h> +#include <limits.h> + +// C++ includes +#include "lldb/Host/StringConvert.h" +#include <iomanip> +#include <sstream> + +using namespace lldb_private; + +std::string JSONString::json_string_quote_metachars(const std::string &s) { + if (s.find('"') == std::string::npos) + return s; + + std::string output; + const size_t s_size = s.size(); + const char *s_chars = s.c_str(); + for (size_t i = 0; i < s_size; i++) { + unsigned char ch = *(s_chars + i); + if (ch == '"') { + output.push_back('\\'); + } + output.push_back(ch); + } + return output; +} + +JSONString::JSONString() : JSONValue(JSONValue::Kind::String), m_data() {} + +JSONString::JSONString(const char *s) + : JSONValue(JSONValue::Kind::String), m_data(s ? s : "") {} + +JSONString::JSONString(const std::string &s) + : JSONValue(JSONValue::Kind::String), m_data(s) {} + +void JSONString::Write(std::ostream &s) { + s << "\"" << json_string_quote_metachars(m_data).c_str() << "\""; +} + +uint64_t JSONNumber::GetAsUnsigned() const { + switch (m_data_type) { + case DataType::Unsigned: + return m_data.m_unsigned; + case DataType::Signed: + return (uint64_t)m_data.m_signed; + case DataType::Double: + return (uint64_t)m_data.m_double; + } + assert("Unhandled data type"); +} + +int64_t JSONNumber::GetAsSigned() const { + switch (m_data_type) { + case DataType::Unsigned: + return (int64_t)m_data.m_unsigned; + case DataType::Signed: + return m_data.m_signed; + case DataType::Double: + return (int64_t)m_data.m_double; + } + assert("Unhandled data type"); +} + +double JSONNumber::GetAsDouble() const { + switch (m_data_type) { + case DataType::Unsigned: + return (double)m_data.m_unsigned; + case DataType::Signed: + return (double)m_data.m_signed; + case DataType::Double: + return m_data.m_double; + } + assert("Unhandled data type"); +} + +void JSONNumber::Write(std::ostream &s) { + switch (m_data_type) { + case DataType::Unsigned: + s << m_data.m_unsigned; + break; + case DataType::Signed: + s << m_data.m_signed; + break; + case DataType::Double: + // Set max precision to emulate %g. + s << std::setprecision(std::numeric_limits<double>::digits10 + 1); + s << m_data.m_double; + break; + } +} + +JSONTrue::JSONTrue() : JSONValue(JSONValue::Kind::True) {} + +void JSONTrue::Write(std::ostream &s) { s << "true"; } + +JSONFalse::JSONFalse() : JSONValue(JSONValue::Kind::False) {} + +void JSONFalse::Write(std::ostream &s) { s << "false"; } + +JSONNull::JSONNull() : JSONValue(JSONValue::Kind::Null) {} + +void JSONNull::Write(std::ostream &s) { s << "null"; } + +JSONObject::JSONObject() : JSONValue(JSONValue::Kind::Object) {} + +void JSONObject::Write(std::ostream &s) { + bool first = true; + s << '{'; + auto iter = m_elements.begin(), end = m_elements.end(); + for (; iter != end; iter++) { + if (first) + first = false; + else + s << ','; + JSONString key(iter->first); + JSONValue::SP value(iter->second); + key.Write(s); + s << ':'; + value->Write(s); + } + s << '}'; +} + +bool JSONObject::SetObject(const std::string &key, JSONValue::SP value) { + if (key.empty() || nullptr == value.get()) + return false; + m_elements[key] = value; + return true; +} + +JSONValue::SP JSONObject::GetObject(const std::string &key) const { + auto iter = m_elements.find(key), end = m_elements.end(); + if (iter == end) + return JSONValue::SP(); + return iter->second; +} + +bool JSONObject::GetObjectAsBool(const std::string &key, bool &value) const { + auto value_sp = GetObject(key); + if (!value_sp) { + // The given key doesn't exist, so we have no value. + return false; + } + + if (JSONTrue::classof(value_sp.get())) { + // We have the value, and it is true. + value = true; + return true; + } else if (JSONFalse::classof(value_sp.get())) { + // We have the value, and it is false. + value = false; + return true; + } else { + // We don't have a valid bool value for the given key. + return false; + } +} + +bool JSONObject::GetObjectAsString(const std::string &key, + std::string &value) const { + auto value_sp = GetObject(key); + if (!value_sp) { + // The given key doesn't exist, so we have no value. + return false; + } + + if (!JSONString::classof(value_sp.get())) + return false; + + value = static_cast<JSONString *>(value_sp.get())->GetData(); + return true; +} + +JSONArray::JSONArray() : JSONValue(JSONValue::Kind::Array) {} + +void JSONArray::Write(std::ostream &s) { + bool first = true; + s << '['; + auto iter = m_elements.begin(), end = m_elements.end(); + for (; iter != end; iter++) { + if (first) + first = false; + else + s << ','; + (*iter)->Write(s); + } + s << ']'; +} + +bool JSONArray::SetObject(Index i, JSONValue::SP value) { + if (value.get() == nullptr) + return false; + if (i < m_elements.size()) { + m_elements[i] = value; + return true; + } + if (i == m_elements.size()) { + m_elements.push_back(value); + return true; + } + return false; +} + +bool JSONArray::AppendObject(JSONValue::SP value) { + if (value.get() == nullptr) + return false; + m_elements.push_back(value); + return true; +} + +JSONValue::SP JSONArray::GetObject(Index i) { + if (i < m_elements.size()) + return m_elements[i]; + return JSONValue::SP(); +} + +JSONArray::Size JSONArray::GetNumElements() { return m_elements.size(); } + +JSONParser::JSONParser(const char *cstr) : StdStringExtractor(cstr) {} + +JSONParser::Token JSONParser::GetToken(std::string &value) { + std::ostringstream error; + + value.clear(); + SkipSpaces(); + const uint64_t start_index = m_index; + const char ch = GetChar(); + switch (ch) { + case '{': + return Token::ObjectStart; + case '}': + return Token::ObjectEnd; + case '[': + return Token::ArrayStart; + case ']': + return Token::ArrayEnd; + case ',': + return Token::Comma; + case ':': + return Token::Colon; + case '\0': + return Token::EndOfFile; + case 't': + if (GetChar() == 'r') + if (GetChar() == 'u') + if (GetChar() == 'e') + return Token::True; + break; + + case 'f': + if (GetChar() == 'a') + if (GetChar() == 'l') + if (GetChar() == 's') + if (GetChar() == 'e') + return Token::False; + break; + + case 'n': + if (GetChar() == 'u') + if (GetChar() == 'l') + if (GetChar() == 'l') + return Token::Null; + break; + + case '"': { + while (1) { + bool was_escaped = false; + int escaped_ch = GetEscapedChar(was_escaped); + if (escaped_ch == -1) { + error << "error: an error occurred getting a character from offset " + << start_index; + value = error.str(); + return Token::Error; + + } else { + const bool is_end_quote = escaped_ch == '"'; + const bool is_null = escaped_ch == 0; + if (was_escaped || (!is_end_quote && !is_null)) { + if (CHAR_MIN <= escaped_ch && escaped_ch <= CHAR_MAX) { + value.append(1, (char)escaped_ch); + } else { + error << "error: wide character support is needed for unicode " + "character 0x" + << std::setprecision(4) << std::hex << escaped_ch; + error << " at offset " << start_index; + value = error.str(); + return Token::Error; + } + } else if (is_end_quote) { + return Token::String; + } else if (is_null) { + value = "error: missing end quote for string"; + return Token::Error; + } + } + } + } break; + + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + bool done = false; + bool got_decimal_point = false; + uint64_t exp_index = 0; + bool got_int_digits = (ch >= '0') && (ch <= '9'); + bool got_frac_digits = false; + bool got_exp_digits = false; + while (!done) { + const char next_ch = PeekChar(); + switch (next_ch) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (exp_index != 0) { + got_exp_digits = true; + } else if (got_decimal_point) { + got_frac_digits = true; + } else { + got_int_digits = true; + } + ++m_index; // Skip this character + break; + + case '.': + if (got_decimal_point) { + error << "error: extra decimal point found at offset " << start_index; + value = error.str(); + return Token::Error; + } else { + got_decimal_point = true; + ++m_index; // Skip this character + } + break; + + case 'e': + case 'E': + if (exp_index != 0) { + error << "error: extra exponent character found at offset " + << start_index; + value = error.str(); + return Token::Error; + } else { + exp_index = m_index; + ++m_index; // Skip this character + } + break; + + case '+': + case '-': + // The '+' and '-' can only come after an exponent character... + if (exp_index == m_index - 1) { + ++m_index; // Skip the exponent sign character + } else { + error << "error: unexpected " << next_ch << " character at offset " + << start_index; + value = error.str(); + return Token::Error; + } + break; + + default: + done = true; + break; + } + } + + if (m_index > start_index) { + value = m_packet.substr(start_index, m_index - start_index); + if (got_decimal_point) { + if (exp_index != 0) { + // We have an exponent, make sure we got exponent digits + if (got_exp_digits) { + return Token::Float; + } else { + error << "error: got exponent character but no exponent digits at " + "offset in float value \"" + << value.c_str() << "\""; + value = error.str(); + return Token::Error; + } + } else { + // No exponent, but we need at least one decimal after the decimal + // point + if (got_frac_digits) { + return Token::Float; + } else { + error << "error: no digits after decimal point \"" << value.c_str() + << "\""; + value = error.str(); + return Token::Error; + } + } + } else { + // No decimal point + if (got_int_digits) { + // We need at least some integer digits to make an integer + return Token::Integer; + } else { + error << "error: no digits negate sign \"" << value.c_str() << "\""; + value = error.str(); + return Token::Error; + } + } + } else { + error << "error: invalid number found at offset " << start_index; + value = error.str(); + return Token::Error; + } + } break; + default: + break; + } + error << "error: failed to parse token at offset " << start_index + << " (around character '" << ch << "')"; + value = error.str(); + return Token::Error; +} + +int JSONParser::GetEscapedChar(bool &was_escaped) { + was_escaped = false; + const char ch = GetChar(); + if (ch == '\\') { + was_escaped = true; + const char ch2 = GetChar(); + switch (ch2) { + case '"': + case '\\': + case '/': + default: + break; + + case 'b': + return '\b'; + case 'f': + return '\f'; + case 'n': + return '\n'; + case 'r': + return '\r'; + case 't': + return '\t'; + case 'u': { + const int hi_byte = DecodeHexU8(); + const int lo_byte = DecodeHexU8(); + if (hi_byte >= 0 && lo_byte >= 0) + return hi_byte << 8 | lo_byte; + return -1; + } break; + } + return ch2; + } + return ch; +} + +JSONValue::SP JSONParser::ParseJSONObject() { + // The "JSONParser::Token::ObjectStart" token should have already been + // consumed + // by the time this function is called + std::unique_ptr<JSONObject> dict_up(new JSONObject()); + + std::string value; + std::string key; + while (1) { + JSONParser::Token token = GetToken(value); + + if (token == JSONParser::Token::String) { + key.swap(value); + token = GetToken(value); + if (token == JSONParser::Token::Colon) { + JSONValue::SP value_sp = ParseJSONValue(); + if (value_sp) + dict_up->SetObject(key, value_sp); + else + break; + } + } else if (token == JSONParser::Token::ObjectEnd) { + return JSONValue::SP(dict_up.release()); + } else if (token == JSONParser::Token::Comma) { + continue; + } else { + break; + } + } + return JSONValue::SP(); +} + +JSONValue::SP JSONParser::ParseJSONArray() { + // The "JSONParser::Token::ObjectStart" token should have already been + // consumed + // by the time this function is called + std::unique_ptr<JSONArray> array_up(new JSONArray()); + + std::string value; + std::string key; + while (1) { + JSONValue::SP value_sp = ParseJSONValue(); + if (value_sp) + array_up->AppendObject(value_sp); + else + break; + + JSONParser::Token token = GetToken(value); + if (token == JSONParser::Token::Comma) { + continue; + } else if (token == JSONParser::Token::ArrayEnd) { + return JSONValue::SP(array_up.release()); + } else { + break; + } + } + return JSONValue::SP(); +} + +JSONValue::SP JSONParser::ParseJSONValue() { + std::string value; + const JSONParser::Token token = GetToken(value); + switch (token) { + case JSONParser::Token::ObjectStart: + return ParseJSONObject(); + + case JSONParser::Token::ArrayStart: + return ParseJSONArray(); + + case JSONParser::Token::Integer: { + if (value.front() == '-') { + bool success = false; + int64_t sval = StringConvert::ToSInt64(value.c_str(), 0, 0, &success); + if (success) + return JSONValue::SP(new JSONNumber(sval)); + } else { + bool success = false; + uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success); + if (success) + return JSONValue::SP(new JSONNumber(uval)); + } + } break; + + case JSONParser::Token::Float: { + bool success = false; + double val = StringConvert::ToDouble(value.c_str(), 0.0, &success); + if (success) + return JSONValue::SP(new JSONNumber(val)); + } break; + + case JSONParser::Token::String: + return JSONValue::SP(new JSONString(value)); + + case JSONParser::Token::True: + return JSONValue::SP(new JSONTrue()); + + case JSONParser::Token::False: + return JSONValue::SP(new JSONFalse()); + + case JSONParser::Token::Null: + return JSONValue::SP(new JSONNull()); + + default: + break; + } + return JSONValue::SP(); +} diff --git a/tools/debugserver/source/JSON.h b/tools/debugserver/source/JSON.h new file mode 100644 index 000000000000..eee62f453327 --- /dev/null +++ b/tools/debugserver/source/JSON.h @@ -0,0 +1,303 @@ +//===---------------------JSON.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_JSON_h_ +#define utility_JSON_h_ + +#include "StdStringExtractor.h" + +// C includes +#include <inttypes.h> +#include <stdint.h> + +// C++ includes +#include <map> +#include <memory> +#include <ostream> +#include <string> +#include <vector> + +class JSONValue { +public: + virtual void Write(std::ostream &s) = 0; + + typedef std::shared_ptr<JSONValue> SP; + + enum class Kind { String, Number, True, False, Null, Object, Array }; + + JSONValue(Kind k) : m_kind(k) {} + + Kind GetKind() const { return m_kind; } + + virtual ~JSONValue() = default; + +private: + const Kind m_kind; +}; + +class JSONString : public JSONValue { +public: + JSONString(); + JSONString(const char *s); + JSONString(const std::string &s); + + JSONString(const JSONString &s) = delete; + JSONString &operator=(const JSONString &s) = delete; + + void Write(std::ostream &s) override; + + typedef std::shared_ptr<JSONString> SP; + + std::string GetData() { return m_data; } + + static bool classof(const JSONValue *V) { + return V->GetKind() == JSONValue::Kind::String; + } + + ~JSONString() override = default; + +private: + static std::string json_string_quote_metachars(const std::string &); + + std::string m_data; +}; + +class JSONNumber : public JSONValue { +public: + typedef std::shared_ptr<JSONNumber> SP; + + // We cretae a constructor for all integer and floating point type with using + // templates and + // SFINAE to avoid having ambiguous overloads because of the implicit type + // promotion. If we + // would have constructors only with int64_t, uint64_t and double types then + // constructing a + // JSONNumber from an int32_t (or any other similar type) would fail to + // compile. + + template <typename T, typename std::enable_if< + std::is_integral<T>::value && + std::is_unsigned<T>::value>::type * = nullptr> + explicit JSONNumber(T u) + : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Unsigned) { + m_data.m_unsigned = u; + } + + template <typename T, + typename std::enable_if<std::is_integral<T>::value && + std::is_signed<T>::value>::type * = nullptr> + explicit JSONNumber(T s) + : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Signed) { + m_data.m_signed = s; + } + + template <typename T, typename std::enable_if< + std::is_floating_point<T>::value>::type * = nullptr> + explicit JSONNumber(T d) + : JSONValue(JSONValue::Kind::Number), m_data_type(DataType::Double) { + m_data.m_double = d; + } + + ~JSONNumber() override = default; + + JSONNumber(const JSONNumber &s) = delete; + JSONNumber &operator=(const JSONNumber &s) = delete; + + void Write(std::ostream &s) override; + + uint64_t GetAsUnsigned() const; + + int64_t GetAsSigned() const; + + double GetAsDouble() const; + + static bool classof(const JSONValue *V) { + return V->GetKind() == JSONValue::Kind::Number; + } + +private: + enum class DataType : uint8_t { Unsigned, Signed, Double } m_data_type; + + union { + uint64_t m_unsigned; + int64_t m_signed; + double m_double; + } m_data; +}; + +class JSONTrue : public JSONValue { +public: + JSONTrue(); + + JSONTrue(const JSONTrue &s) = delete; + JSONTrue &operator=(const JSONTrue &s) = delete; + + void Write(std::ostream &s) override; + + typedef std::shared_ptr<JSONTrue> SP; + + static bool classof(const JSONValue *V) { + return V->GetKind() == JSONValue::Kind::True; + } + + ~JSONTrue() override = default; +}; + +class JSONFalse : public JSONValue { +public: + JSONFalse(); + + JSONFalse(const JSONFalse &s) = delete; + JSONFalse &operator=(const JSONFalse &s) = delete; + + void Write(std::ostream &s) override; + + typedef std::shared_ptr<JSONFalse> SP; + + static bool classof(const JSONValue *V) { + return V->GetKind() == JSONValue::Kind::False; + } + + ~JSONFalse() override = default; +}; + +class JSONNull : public JSONValue { +public: + JSONNull(); + + JSONNull(const JSONNull &s) = delete; + JSONNull &operator=(const JSONNull &s) = delete; + + void Write(std::ostream &s) override; + + typedef std::shared_ptr<JSONNull> SP; + + static bool classof(const JSONValue *V) { + return V->GetKind() == JSONValue::Kind::Null; + } + + ~JSONNull() override = default; +}; + +class JSONObject : public JSONValue { +public: + JSONObject(); + + JSONObject(const JSONObject &s) = delete; + JSONObject &operator=(const JSONObject &s) = delete; + + void Write(std::ostream &s) override; + + typedef std::shared_ptr<JSONObject> SP; + + static bool classof(const JSONValue *V) { + return V->GetKind() == JSONValue::Kind::Object; + } + + bool SetObject(const std::string &key, JSONValue::SP value); + + JSONValue::SP GetObject(const std::string &key) const; + + // ------------------------------------------------------------------------- + /// Return keyed value as bool + /// + /// @param[in] key + /// The value of the key to lookup + /// + /// @param[out] value + /// The value of the key as a bool. Undefined if the key doesn't + /// exist or if the key is not either true or false. + /// + /// @return + /// true if the key existed as was a bool value; false otherwise. + /// Note the return value is *not* the value of the bool, use + /// \b value for that. + // ------------------------------------------------------------------------- + bool GetObjectAsBool(const std::string &key, bool &value) const; + + bool GetObjectAsString(const std::string &key, std::string &value) const; + + ~JSONObject() override = default; + +private: + typedef std::map<std::string, JSONValue::SP> Map; + typedef Map::iterator Iterator; + Map m_elements; +}; + +class JSONArray : public JSONValue { +public: + JSONArray(); + + JSONArray(const JSONArray &s) = delete; + JSONArray &operator=(const JSONArray &s) = delete; + + void Write(std::ostream &s) override; + + typedef std::shared_ptr<JSONArray> SP; + + static bool classof(const JSONValue *V) { + return V->GetKind() == JSONValue::Kind::Array; + } + +private: + typedef std::vector<JSONValue::SP> Vector; + typedef Vector::iterator Iterator; + typedef Vector::size_type Index; + typedef Vector::size_type Size; + +public: + bool SetObject(Index i, JSONValue::SP value); + + bool AppendObject(JSONValue::SP value); + + JSONValue::SP GetObject(Index i); + + Size GetNumElements(); + + ~JSONArray() override = default; + + Vector m_elements; +}; + +class JSONParser : public StdStringExtractor { +public: + enum Token { + Invalid, + Error, + ObjectStart, + ObjectEnd, + ArrayStart, + ArrayEnd, + Comma, + Colon, + String, + Integer, + Float, + True, + False, + Null, + EndOfFile + }; + + JSONParser(const char *cstr); + + int GetEscapedChar(bool &was_escaped); + + Token GetToken(std::string &value); + + JSONValue::SP ParseJSONValue(); + +protected: + JSONValue::SP ParseJSONObject(); + + JSONValue::SP ParseJSONArray(); +}; + +#endif // utility_JSON_h_ diff --git a/tools/debugserver/source/JSONGenerator.h b/tools/debugserver/source/JSONGenerator.h index 423b2bd57927..a85dcb6e8608 100644 --- a/tools/debugserver/source/JSONGenerator.h +++ b/tools/debugserver/source/JSONGenerator.h @@ -29,462 +29,291 @@ /// and printing it as a JSON string. //---------------------------------------------------------------------- -class JSONGenerator -{ +class JSONGenerator { public: + class Object; + class Array; + class Integer; + class Float; + class Boolean; + class String; + class Dictionary; + class Generic; + + typedef std::shared_ptr<Object> ObjectSP; + typedef std::shared_ptr<Array> ArraySP; + typedef std::shared_ptr<Integer> IntegerSP; + typedef std::shared_ptr<Float> FloatSP; + typedef std::shared_ptr<Boolean> BooleanSP; + typedef std::shared_ptr<String> StringSP; + typedef std::shared_ptr<Dictionary> DictionarySP; + typedef std::shared_ptr<Generic> GenericSP; + + enum class Type { + eTypeInvalid = -1, + eTypeNull = 0, + eTypeGeneric, + eTypeArray, + eTypeInteger, + eTypeFloat, + eTypeBoolean, + eTypeString, + eTypeDictionary + }; + + class Object : public std::enable_shared_from_this<Object> { + public: + Object(Type t = Type::eTypeInvalid) : m_type(t) {} + + virtual ~Object() {} + + virtual bool IsValid() const { return true; } + + virtual void Clear() { m_type = Type::eTypeInvalid; } + + Type GetType() const { return m_type; } + + void SetType(Type t) { m_type = t; } + + Array *GetAsArray() { + if (m_type == Type::eTypeArray) + return (Array *)this; + return NULL; + } + + Dictionary *GetAsDictionary() { + if (m_type == Type::eTypeDictionary) + return (Dictionary *)this; + return NULL; + } + + Integer *GetAsInteger() { + if (m_type == Type::eTypeInteger) + return (Integer *)this; + return NULL; + } + + Float *GetAsFloat() { + if (m_type == Type::eTypeFloat) + return (Float *)this; + return NULL; + } + + Boolean *GetAsBoolean() { + if (m_type == Type::eTypeBoolean) + return (Boolean *)this; + return NULL; + } + + String *GetAsString() { + if (m_type == Type::eTypeString) + return (String *)this; + return NULL; + } + + Generic *GetAsGeneric() { + if (m_type == Type::eTypeGeneric) + return (Generic *)this; + return NULL; + } + + virtual void Dump(std::ostream &s) const = 0; + + private: + Type m_type; + }; + + class Array : public Object { + public: + Array() : Object(Type::eTypeArray) {} + + virtual ~Array() {} + + void AddItem(ObjectSP item) { m_items.push_back(item); } + + void Dump(std::ostream &s) const override { + s << "["; + const size_t arrsize = m_items.size(); + for (size_t i = 0; i < arrsize; ++i) { + m_items[i]->Dump(s); + if (i + 1 < arrsize) + s << ","; + } + s << "]"; + } + + protected: + typedef std::vector<ObjectSP> collection; + collection m_items; + }; + + class Integer : public Object { + public: + Integer(uint64_t value = 0) : Object(Type::eTypeInteger), m_value(value) {} + + virtual ~Integer() {} + + void SetValue(uint64_t value) { m_value = value; } + + void Dump(std::ostream &s) const override { s << m_value; } + + protected: + uint64_t m_value; + }; - class Object; |