diff options
Diffstat (limited to 'lldb/tools')
291 files changed, 61234 insertions, 62719 deletions
diff --git a/lldb/tools/argdumper/argdumper.cpp b/lldb/tools/argdumper/argdumper.cpp index 381a9d2f4b2..39991b64c09 100644 --- a/lldb/tools/argdumper/argdumper.cpp +++ b/lldb/tools/argdumper/argdumper.cpp @@ -1,4 +1,5 @@ -//===-- argdumper.cpp --------------------------------------------*- C++ -*-===// +//===-- argdumper.cpp --------------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -14,25 +15,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/lldb/tools/compact-unwind/compact-unwind-dumper.c b/lldb/tools/compact-unwind/compact-unwind-dumper.c index f70f602326b..570c42981a2 100644 --- a/lldb/tools/compact-unwind/compact-unwind-dumper.c +++ b/lldb/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/lldb/tools/darwin-debug/darwin-debug.cpp b/lldb/tools/darwin-debug/darwin-debug.cpp index ca0a8d48328..e754ded474c 100644 --- a/lldb/tools/darwin-debug/darwin-debug.cpp +++ b/lldb/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/lldb/tools/darwin-threads/examine-threads.c b/lldb/tools/darwin-threads/examine-threads.c index 07212e999f9..5d965140cf8 100644 --- a/lldb/tools/darwin-threads/examine-threads.c +++ b/lldb/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/lldb/tools/debugserver/source/ARM_DWARF_Registers.h b/lldb/tools/debugserver/source/ARM_DWARF_Registers.h index 845260ba187..037d28bf130 100644 --- a/lldb/tools/debugserver/source/ARM_DWARF_Registers.h +++ b/lldb/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/lldb/tools/debugserver/source/ARM_ehframe_Registers.h b/lldb/tools/debugserver/source/ARM_ehframe_Registers.h index f6d93b3cee0..9d644b7dc50 100644 --- a/lldb/tools/debugserver/source/ARM_ehframe_Registers.h +++ b/lldb/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/lldb/tools/debugserver/source/DNB.cpp b/lldb/tools/debugserver/source/DNB.cpp index fc36dcec078..9c6c44d18df 100644 --- a/lldb/tools/debugserver/source/DNB.cpp +++ b/lldb/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,33 +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/DarwinLog/DarwinLogCollector.h" -#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. @@ -68,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; } //---------------------------------------------------------------------- @@ -90,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; } //---------------------------------------------------------------------- @@ -107,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) @@ -124,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); + } 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; } - } + } - 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; - } - } - - 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; - - // 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); +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; - if ((err < 0) && (err != ENOMEM)) - { - proc_infos.clear(); - perror("sysctl (mib, miblen, NULL, &num_processes, NULL, 0)"); - return 0; - } + // 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); - // 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(); +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 -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; +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; } -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; -} - -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)) // { @@ -1205,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)) // { @@ -1217,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; } //---------------------------------------------------------------------- @@ -1300,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_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; - +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; } -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 @@ -1396,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; } //---------------------------------------------------------------------- @@ -1437,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; } //---------------------------------------------------------------------- @@ -1539,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; } //---------------------------------------------------------------------- @@ -1602,409 +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); +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/lldb/tools/debugserver/source/DNB.h b/lldb/tools/debugserver/source/DNB.h index 3e928e663d7..7acbd42810c 100644 --- a/lldb/tools/debugserver/source/DNB.h +++ b/lldb/tools/debugserver/source/DNB.h @@ -14,48 +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. @@ -64,117 +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/lldb/tools/debugserver/source/DNBArch.cpp b/lldb/tools/debugserver/source/DNBArch.cpp index f17a719e92e..1312bcf7dfd 100644 --- a/lldb/tools/debugserver/source/DNBArch.cpp +++ b/lldb/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/lldb/tools/debugserver/source/DNBArch.h b/lldb/tools/debugserver/source/DNBArch.h index c07d3a67400..317da70e642 100644 --- a/lldb/tools/debugserver/source/DNBArch.h +++ b/lldb/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/lldb/tools/debugserver/source/DNBBreakpoint.cpp b/lldb/tools/debugserver/source/DNBBreakpoint.cpp index 2645f173306..89a91287f9e 100644 --- a/lldb/tools/debugserver/source/DNBBreakpoint.cpp +++ b/lldb/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/lldb/tools/debugserver/source/DNBBreakpoint.h b/lldb/tools/debugserver/source/DNBBreakpoint.h index c764dbd6cf2..889478b2895 100644 --- a/lldb/tools/debugserver/source/DNBBreakpoint.h +++ b/lldb/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/lldb/tools/debugserver/source/DNBDataRef.cpp b/lldb/tools/debugserver/source/DNBDataRef.cpp index d52f28ee2fb..d7dce1ab733 100644 --- a/lldb/tools/debugserver/source/DNBDataRef.cpp +++ b/lldb/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/lldb/tools/debugserver/source/DNBDataRef.h b/lldb/tools/debugserver/source/DNBDataRef.h index d0c34ced623..9a19f20227e 100644 --- a/lldb/tools/debugserver/source/DNBDataRef.h +++ b/lldb/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/lldb/tools/debugserver/source/DNBDefs.h b/lldb/tools/debugserver/source/DNBDefs.h index 36efad22417..5762bd16e2b 100644 --- a/lldb/tools/debugserver/source/DNBDefs.h +++ b/lldb/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,327 +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_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 +#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/lldb/tools/debugserver/source/DNBError.cpp b/lldb/tools/debugserver/source/DNBError.cpp index c9d8ebd58d8..cd04358a4ec 100644 --- a/lldb/tools/debugserver/source/DNBError.cpp +++ b/lldb/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/lldb/tools/debugserver/source/DNBError.h b/lldb/tools/debugserver/source/DNBError.h index 274ae0d4477..edca38ad6db 100644 --- a/lldb/tools/debugserver/source/DNBError.h +++ b/lldb/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/lldb/tools/debugserver/source/DNBLog.cpp b/lldb/tools/debugserver/source/DNBLog.cpp index 18d8d2ad3a6..c3d42a2a84d 100644 --- a/lldb/tools/debugserver/source/DNBLog.cpp +++ b/lldb/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/lldb/tools/debugserver/source/DNBLog.h b/lldb/tools/debugserver/source/DNBLog.h index 01add065abc..65181caa412 100644 --- a/lldb/tools/debugserver/source/DNBLog.h +++ b/lldb/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/lldb/tools/debugserver/source/DNBRegisterInfo.cpp b/lldb/tools/debugserver/source/DNBRegisterInfo.cpp index acc7ba9946b..fadcc5ddb06 100644 --- a/lldb/tools/debugserver/source/DNBRegisterInfo.cpp +++ b/lldb/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/lldb/tools/debugserver/source/DNBRegisterInfo.h b/lldb/tools/debugserver/source/DNBRegisterInfo.h index 666c397e0b5..d665e3cb948 100644 --- a/lldb/tools/debugserver/source/DNBRegisterInfo.h +++ b/lldb/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/lldb/tools/debugserver/source/DNBRuntimeAction.h b/lldb/tools/debugserver/source/DNBRuntimeAction.h index d77bda8c604..85d7bc1df0a 100644 --- a/lldb/tools/debugserver/source/DNBRuntimeAction.h +++ b/lldb/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/lldb/tools/debugserver/source/DNBThreadResumeActions.cpp b/lldb/tools/debugserver/source/DNBThreadResumeActions.cpp index b50dd061784..4a97abc20e2 100644 --- a/lldb/tools/debugserver/source/DNBThreadResumeActions.cpp +++ b/lldb/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/lldb/tools/debugserver/source/DNBThreadResumeActions.h b/lldb/tools/debugserver/source/DNBThreadResumeActions.h index 81c7c43b722..40d2da03e9e 100644 --- a/lldb/tools/debugserver/source/DNBThreadResumeActions.h +++ b/lldb/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/lldb/tools/debugserver/source/DNBTimer.h b/lldb/tools/debugserver/source/DNBTimer.h index ca56e30c709..881b8cdcde7 100644 --- a/lldb/tools/debugserver/source/DNBTimer.h +++ b/lldb/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/lldb/tools/debugserver/source/JSON.cpp b/lldb/tools/debugserver/source/JSON.cpp index 34a01f4ce44..19ebfd000f5 100644 --- a/lldb/tools/debugserver/source/JSON.cpp +++ b/lldb/tools/debugserver/source/JSON.cpp @@ -14,733 +14,575 @@ #include <limits.h> // C++ includes +#include "lldb/Host/StringConvert.h" #include <iomanip> #include <sstream> -#include "lldb/Host/StringConvert.h" 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); +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('\\'); } - return output; + output.push_back(ch); + } + return output; } -JSONString::JSONString () : - JSONValue(JSONValue::Kind::String), - m_data() -{ -} +JSONString::JSONString() : JSONValue(JSONValue::Kind::String), m_data() {} -JSONString::JSONString (const char* s) : - JSONValue(JSONValue::Kind::String), - m_data(s ? s : "") -{ -} +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) -{ -} +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() <<"\""; +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"); +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"); +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"); +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; - } +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) -{ -} +JSONTrue::JSONTrue() : JSONValue(JSONValue::Kind::True) {} -void -JSONTrue::Write(std::ostream& s) -{ - s << "true"; -} +void JSONTrue::Write(std::ostream &s) { s << "true"; } -JSONFalse::JSONFalse () : - JSONValue(JSONValue::Kind::False) -{ -} +JSONFalse::JSONFalse() : JSONValue(JSONValue::Kind::False) {} -void -JSONFalse::Write(std::ostream& s) -{ - s << "false"; -} - -JSONNull::JSONNull () : - JSONValue(JSONValue::Kind::Null) -{ -} +void JSONFalse::Write(std::ostream &s) { s << "false"; } -void -JSONNull::Write(std::ostream& s) -{ - s << "null"; -} +JSONNull::JSONNull() : JSONValue(JSONValue::Kind::Null) {} -JSONObject::JSONObject () : - JSONValue(JSONValue::Kind::Object) -{ -} +void JSONNull::Write(std::ostream &s) { s << "null"; } -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 << '}'; -} +JSONObject::JSONObject() : JSONValue(JSONValue::Kind::Object) {} -bool -JSONObject::SetObject (const std::string& key, - JSONValue::SP value) -{ - if (key.empty() || nullptr == value.get()) - return false; - m_elements[key] = value; - return true; +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; +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; - } +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; - } + 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; - } +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; + if (!JSONString::classof(value_sp.get())) + return false; - value = static_cast<JSONString*>(value_sp.get())->GetData(); - return true; + value = static_cast<JSONString *>(value_sp.get())->GetData(); + return true; } -JSONArray::JSONArray () : - JSONValue(JSONValue::Kind::Array) -{ -} +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 << ']'; +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; - } +bool JSONArray::SetObject(Index i, JSONValue::SP value) { + if (value.get() == nullptr) return false; -} - -bool -JSONArray::AppendObject (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; } -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; +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; } - 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; - } + } 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; } - else if (token == JSONParser::Token::ObjectEnd) - { - return JSONValue::SP(dict_up.release()); + ++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 } - else if (token == JSONParser::Token::Comma) - { - continue; + 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 } - else - { - break; + 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; } - } - return JSONValue::SP(); -} + break; -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; + default: + done = true; + break; + } + } - JSONParser::Token token = GetToken(value); - if (token == JSONParser::Token::Comma) - { - continue; + 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 if (token == JSONParser::Token::ArrayEnd) - { - return JSONValue::SP(array_up.release()); + } 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; - } + 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(); -} + } + 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; -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::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::String: + return JSONValue::SP(new JSONString(value)); - case JSONParser::Token::True: - return JSONValue::SP(new JSONTrue()); + case JSONParser::Token::True: + return JSONValue::SP(new JSONTrue()); - case JSONParser::Token::False: - return JSONValue::SP(new JSONFalse()); + case JSONParser::Token::False: + return JSONValue::SP(new JSONFalse()); - case JSONParser::Token::Null: - return JSONValue::SP(new JSONNull()); + case JSONParser::Token::Null: + return JSONValue::SP(new JSONNull()); - default: - break; - } - return JSONValue::SP(); - + default: + break; + } + return JSONValue::SP(); } diff --git a/lldb/tools/debugserver/source/JSON.h b/lldb/tools/debugserver/source/JSON.h index e24f928bcf7..d3951776cac 100644 --- a/lldb/tools/debugserver/source/JSON.h +++ b/lldb/tools/debugserver/source/JSON.h @@ -25,358 +25,281 @@ #include <string> #include <vector> -class JSONValue -{ +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; - + 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; + const Kind m_kind; }; -class JSONString : public JSONValue -{ +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; - + 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; + static std::string json_string_quote_metachars(const std::string &); + + std::string m_data; }; -class JSONNumber : public JSONValue -{ +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; - } + 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; + 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 -{ +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; + 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 -{ +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; + 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 -{ +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; + 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 -{ +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; - + 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; + typedef std::map<std::string, JSONValue::SP> Map; + typedef Map::iterator Iterator; + Map m_elements; }; -class JSONArray : public JSONValue -{ +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; - } - + 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; - + 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; + 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 -{ +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 (); + 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 ParseJSONObject(); - JSONValue::SP - ParseJSONArray (); + JSONValue::SP ParseJSONArray(); }; #endif // utility_JSON_h_ diff --git a/lldb/tools/debugserver/source/JSONGenerator.h b/lldb/tools/debugserver/source/JSONGenerator.h index 423b2bd5792..a85dcb6e860 100644 --- a/lldb/tools/debugserver/source/JSONGenerator.h +++ b/lldb/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; - 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 Float : public Object - { - public: - Float (double d = 0.0) : - Object (Type::eTypeFloat), - m_value (d) - { - } - - virtual ~Float() - { - } - - void - SetValue (double value) - { - m_value = value; - } + class Float : public Object { + public: + Float(double d = 0.0) : Object(Type::eTypeFloat), m_value(d) {} + + virtual ~Float() {} + + void SetValue(double value) { m_value = value; } + + void Dump(std::ostream &s) const override { s << m_value; } + + protected: + double m_value; + }; + + class Boolean : public Object { + public: + Boolean(bool b = false) : Object(Type::eTypeBoolean), m_value(b) {} + + virtual ~Boolean() {} + + void SetValue(bool value) { m_value = value; } + + void Dump(std::ostream &s) const override { + if (m_value == true) + s << "true"; + else + s << "false"; + } + + protected: + bool m_value; + }; + + class String : public Object { + public: + String() : Object(Type::eTypeString), m_value() {} + + String(const std::string &s) : Object(Type::eTypeString), m_value(s) {} + + String(const std::string &&s) : Object(Type::eTypeString), m_value(s) {} + + void SetValue(const std::string &string) { m_value = string; } + + void Dump(std::ostream &s) const override { + std::string quoted; + const size_t strsize = m_value.size(); + for (size_t i = 0; i < strsize; ++i) { + char ch = m_value[i]; + if (ch == '"') + quoted.push_back('\\'); + quoted.push_back(ch); + } + s << '"' << quoted.c_str() << '"'; + } - void Dump(std::ostream &s) const override - { - s << m_value; - } - - protected: - double m_value; - }; - - class Boolean : public Object - { - public: - Boolean (bool b = false) : - Object (Type::eTypeBoolean), - m_value (b) - { - } - - virtual ~Boolean() - { - } - - void - SetValue (bool value) - { - m_value = value; - } - - void Dump(std::ostream &s) const override - { - if (m_value == true) - s << "true"; - else - s << "false"; - } - - protected: - bool m_value; - }; - - - - class String : public Object - { - public: - String () : - Object (Type::eTypeString), - m_value () - { - } + protected: + std::string m_value; + }; - String (const std::string &s) : - Object (Type::eTypeString), - m_value (s) - { - } + class Dictionary : public Object { + public: + Dictionary() : Object(Type::eTypeDictionary), m_dict() {} - String (const std::string &&s) : - Object (Type::eTypeString), - m_value (s) - { - } + virtual ~Dictionary() {} - void - SetValue (const std::string &string) - { - m_value = string; - } + void AddItem(std::string key, ObjectSP value) { + m_dict.push_back(Pair(key, value)); + } - void Dump(std::ostream &s) const override - { - std::string quoted; - const size_t strsize = m_value.size(); - for (size_t i = 0; i < strsize ; ++i) - { - char ch = m_value[i]; - if (ch == '"') - quoted.push_back ('\\'); - quoted.push_back (ch); - } - s << '"' << quoted.c_str() << '"'; - } + void AddIntegerItem(std::string key, uint64_t value) { + AddItem(key, ObjectSP(new Integer(value))); + } - protected: - std::string m_value; - }; - - class Dictionary : public Object - { - public: - Dictionary () : - Object (Type::eTypeDictionary), - m_dict () - { - } + void AddFloatItem(std::string key, double value) { + AddItem(key, ObjectSP(new Float(value))); + } - virtual ~Dictionary() - { - } + void AddStringItem(std::string key, std::string value) { + AddItem(key, ObjectSP(new String(std::move(value)))); + } - void - AddItem (std::string key, ObjectSP value) - { - m_dict.push_back(Pair(key, value)); - } - - void - AddIntegerItem (std::string key, uint64_t value) - { - AddItem (key, ObjectSP (new Integer(value))); - } + void AddBytesAsHexASCIIString(std::string key, const uint8_t *src, + size_t src_len) { + if (src && src_len) { + std::ostringstream strm; + for (size_t i = 0; i < src_len; i++) + strm << std::setfill('0') << std::hex << std::right << std::setw(2) + << ((uint32_t)(src[i])); + AddItem(key, ObjectSP(new String(std::move(strm.str())))); + } else { + AddItem(key, ObjectSP(new String())); + } + } - void - AddFloatItem (std::string key, double value) - { - AddItem (key, ObjectSP (new Float(value))); - } - - void - AddStringItem (std::string key, std::string value) - { - AddItem (key, ObjectSP (new String(std::move(value)))); - } + void AddBooleanItem(std::string key, bool value) { + AddItem(key, ObjectSP(new Boolean(value))); + } - void - AddBytesAsHexASCIIString (std::string key, const uint8_t *src, size_t src_len) - { - if (src && src_len) - { - std::ostringstream strm; - for (size_t i = 0; i < src_len; i++) - strm << std::setfill('0') << std::hex << std::right << std::setw(2) << ((uint32_t)(src[i])); - AddItem (key, ObjectSP (new String(std::move(strm.str())))); - } - else - { - AddItem (key, ObjectSP (new String())); - } + void Dump(std::ostream &s) const override { + bool have_printed_one_elem = false; + s << "{"; + for (collection::const_iterator iter = m_dict.begin(); + iter != m_dict.end(); ++iter) { + if (have_printed_one_elem == false) { + have_printed_one_elem = true; + } else { + s << ","; } + s << "\"" << iter->first.c_str() << "\":"; + iter->second->Dump(s); + } + s << "}"; + } - void - AddBooleanItem (std::string key, bool value) - { - AddItem (key, ObjectSP (new Boolean(value))); - } - - void Dump(std::ostream &s) const override - { - bool have_printed_one_elem = false; - s << "{"; - for (collection::const_iterator iter = m_dict.begin(); iter != m_dict.end(); ++iter) - { - if (have_printed_one_elem == false) - { - have_printed_one_elem = true; - } - else - { - s << ","; - } - s << "\"" << iter->first.c_str() << "\":"; - iter->second->Dump(s); - } - s << "}"; - } - - protected: - // Keep the dictionary as a vector so the dictionary doesn't reorder itself when you dump it - // We aren't accessing keys by name, so this won't affect performance - typedef std::pair<std::string, ObjectSP> Pair; - typedef std::vector<Pair> collection; - collection m_dict; - }; - - class Null : public Object - { - public: - Null () : - Object (Type::eTypeNull) - { - } - - virtual ~Null() - { - } - - bool - IsValid() const override - { - return false; - } - - void Dump(std::ostream &s) const override - { - s << "null"; - } - - protected: - }; - - class Generic : public Object - { - public: - explicit Generic(void *object = nullptr) - : Object(Type::eTypeGeneric) - , m_object(object) - { - } - - void - SetValue(void *value) - { - m_object = value; - } - - void * - GetValue() const - { - return m_object; - } - - bool - IsValid() const override - { - return m_object != nullptr; - } - - void Dump(std::ostream &s) const override; - - private: - void *m_object; - }; - -}; // class JSONGenerator - - + protected: + // Keep the dictionary as a vector so the dictionary doesn't reorder itself + // when you dump it + // We aren't accessing keys by name, so this won't affect performance + typedef std::pair<std::string, ObjectSP> Pair; + typedef std::vector<Pair> collection; + collection m_dict; + }; + + class Null : public Object { + public: + Null() : Object(Type::eTypeNull) {} + + virtual ~Null() {} + + bool IsValid() const override { return false; } + + void Dump(std::ostream &s) const override { s << "null"; } + + protected: + }; + + class Generic : public Object { + public: + explicit Generic(void *object = nullptr) + : Object(Type::eTypeGeneric), m_object(object) {} + + void SetValue(void *value) { m_object = value; } + + void *GetValue() const { return m_object; } + + bool IsValid() const override { return m_object != nullptr; } + + void Dump(std::ostream &s) const override; + + private: + void *m_object; + }; + +}; // class JSONGenerator -#endif // __JSONGenerator_h_ +#endif // __JSONGenerator_h_ diff --git a/lldb/tools/debugserver/source/MacOSX/CFBundle.cpp b/lldb/tools/debugserver/source/MacOSX/CFBundle.cpp index fdcb7cc2fcb..7b080e60cdb 100644 --- a/lldb/tools/debugserver/source/MacOSX/CFBundle.cpp +++ b/lldb/tools/debugserver/source/MacOSX/CFBundle.cpp @@ -17,81 +17,63 @@ //---------------------------------------------------------------------- // CFBundle constructor //---------------------------------------------------------------------- -CFBundle::CFBundle(const char *path) : - CFReleaser<CFBundleRef>(), - m_bundle_url() -{ - if (path && path[0]) - SetPath(path); +CFBundle::CFBundle(const char *path) + : CFReleaser<CFBundleRef>(), m_bundle_url() { + if (path && path[0]) + SetPath(path); } //---------------------------------------------------------------------- // CFBundle copy constructor //---------------------------------------------------------------------- -CFBundle::CFBundle(const CFBundle& rhs) : - CFReleaser<CFBundleRef>(rhs), - m_bundle_url(rhs.m_bundle_url) -{ - -} +CFBundle::CFBundle(const CFBundle &rhs) + : CFReleaser<CFBundleRef>(rhs), m_bundle_url(rhs.m_bundle_url) {} //---------------------------------------------------------------------- // CFBundle copy constructor //---------------------------------------------------------------------- -CFBundle& -CFBundle::operator=(const CFBundle& rhs) -{ - *this = rhs; - return *this; +CFBundle &CFBundle::operator=(const CFBundle &rhs) { + *this = rhs; + return *this; } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -CFBundle::~CFBundle() -{ -} +CFBundle::~CFBundle() {} //---------------------------------------------------------------------- // Set the path for a bundle by supplying a //---------------------------------------------------------------------- -bool -CFBundle::SetPath (const char *path) -{ - CFAllocatorRef alloc = kCFAllocatorDefault; - // Release our old bundle and ULR - reset(); // This class is a CFReleaser<CFBundleRef> - m_bundle_url.reset(); - // Make a CFStringRef from the supplied path - CFString cf_path; - cf_path.SetFileSystemRepresentation(path); - if (cf_path.get()) - { - // Make our Bundle URL - m_bundle_url.reset (::CFURLCreateWithFileSystemPath (alloc, cf_path.get(), kCFURLPOSIXPathStyle, true)); - if (m_bundle_url.get()) - { - reset (::CFBundleCreate (alloc, m_bundle_url.get())); - } +bool CFBundle::SetPath(const char *path) { + CFAllocatorRef alloc = kCFAllocatorDefault; + // Release our old bundle and ULR + reset(); // This class is a CFReleaser<CFBundleRef> + m_bundle_url.reset(); + // Make a CFStringRef from the supplied path + CFString cf_path; + cf_path.SetFileSystemRepresentation(path); + if (cf_path.get()) { + // Make our Bundle URL + m_bundle_url.reset(::CFURLCreateWithFileSystemPath( + alloc, cf_path.get(), kCFURLPOSIXPathStyle, true)); + if (m_bundle_url.get()) { + reset(::CFBundleCreate(alloc, m_bundle_url.get())); } - return get() != NULL; + } + return get() != NULL; } -CFStringRef -CFBundle::GetIdentifier () const -{ - CFBundleRef bundle = get(); - if (bundle != NULL) - return ::CFBundleGetIdentifier (bundle); - return NULL; +CFStringRef CFBundle::GetIdentifier() const { + CFBundleRef bundle = get(); + if (bundle != NULL) + return ::CFBundleGetIdentifier(bundle); + return NULL; } - -CFURLRef -CFBundle::CopyExecutableURL () const -{ - CFBundleRef bundle = get(); - if (bundle != NULL) - return CFBundleCopyExecutableURL(bundle); - return NULL; +CFURLRef CFBundle::CopyExecutableURL() const { + CFBundleRef bundle = get(); + if (bundle != NULL) + return CFBundleCopyExecutableURL(bundle); + return NULL; } diff --git a/lldb/tools/debugserver/source/MacOSX/CFBundle.h b/lldb/tools/debugserver/source/MacOSX/CFBundle.h index e08290add73..09957af534b 100644 --- a/lldb/tools/debugserver/source/MacOSX/CFBundle.h +++ b/lldb/tools/debugserver/source/MacOSX/CFBundle.h @@ -16,28 +16,23 @@ #include "CFUtils.h" -class CFBundle : public CFReleaser<CFBundleRef> -{ +class CFBundle : public CFReleaser<CFBundleRef> { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CFBundle(const char *path = NULL); - CFBundle(const CFBundle& rhs); - CFBundle& operator=(const CFBundle& rhs); - virtual - ~CFBundle(); - bool - SetPath (const char *path); + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CFBundle(const char *path = NULL); + CFBundle(const CFBundle &rhs); + CFBundle &operator=(const CFBundle &rhs); + virtual ~CFBundle(); + bool SetPath(const char *path); - CFStringRef - GetIdentifier () const; + CFStringRef GetIdentifier() const; + + CFURLRef CopyExecutableURL() const; - CFURLRef - CopyExecutableURL () const; - protected: - CFReleaser<CFURLRef> m_bundle_url; + CFReleaser<CFURLRef> m_bundle_url; }; #endif // #ifndef __CFBundle_h__ diff --git a/lldb/tools/debugserver/source/MacOSX/CFString.cpp b/lldb/tools/debugserver/source/MacOSX/CFString.cpp index 819024ca3bc..84ad56774d7 100644 --- a/lldb/tools/debugserver/source/MacOSX/CFString.cpp +++ b/lldb/tools/debugserver/source/MacOSX/CFString.cpp @@ -12,136 +12,110 @@ //===----------------------------------------------------------------------===// #include "CFString.h" -#include <string> #include <glob.h> +#include <string> //---------------------------------------------------------------------- // CFString constructor //---------------------------------------------------------------------- -CFString::CFString(CFStringRef s) : - CFReleaser<CFStringRef> (s) -{ -} +CFString::CFString(CFStringRef s) : CFReleaser<CFStringRef>(s) {} //---------------------------------------------------------------------- // CFString copy constructor //---------------------------------------------------------------------- -CFString::CFString(const CFString& rhs) : - CFReleaser<CFStringRef> (rhs) -{ - -} +CFString::CFString(const CFString &rhs) : CFReleaser<CFStringRef>(rhs) {} //---------------------------------------------------------------------- // CFString copy constructor //---------------------------------------------------------------------- -CFString& -CFString::operator=(const CFString& rhs) -{ - if (this != &rhs) - *this = rhs; - return *this; +CFString &CFString::operator=(const CFString &rhs) { + if (this != &rhs) + *this = rhs; + return *this; } -CFString::CFString (const char *cstr, CFStringEncoding cstr_encoding) : - CFReleaser<CFStringRef> () -{ - if (cstr && cstr[0]) - { - reset(::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding)); - } +CFString::CFString(const char *cstr, CFStringEncoding cstr_encoding) + : CFReleaser<CFStringRef>() { + if (cstr && cstr[0]) { + reset( + ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, cstr_encoding)); + } } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -CFString::~CFString() -{ -} +CFString::~CFString() {} -const char * -CFString::GetFileSystemRepresentation(std::string& s) -{ - return CFString::FileSystemRepresentation(get(), s); +const char *CFString::GetFileSystemRepresentation(std::string &s) { + return CFString::FileSystemRepresentation(get(), s); } -CFStringRef -CFString::SetFileSystemRepresentation (const char *path) -{ - CFStringRef new_value = NULL; - if (path && path[0]) - new_value = ::CFStringCreateWithFileSystemRepresentation (kCFAllocatorDefault, path); - reset(new_value); - return get(); +CFStringRef CFString::SetFileSystemRepresentation(const char *path) { + CFStringRef new_value = NULL; + if (path && path[0]) + new_value = + ::CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path); + reset(new_value); + return get(); } - -CFStringRef -CFString::SetFileSystemRepresentationFromCFType (CFTypeRef cf_type) -{ - CFStringRef new_value = NULL; - if (cf_type != NULL) - { - CFTypeID cf_type_id = ::CFGetTypeID(cf_type); - - if (cf_type_id == ::CFStringGetTypeID()) - { - // Retain since we are using the existing object - new_value = (CFStringRef)::CFRetain(cf_type); - } - else if (cf_type_id == ::CFURLGetTypeID()) - { - new_value = ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle); - } +CFStringRef CFString::SetFileSystemRepresentationFromCFType(CFTypeRef cf_type) { + CFStringRef new_value = NULL; + if (cf_type != NULL) { + CFTypeID cf_type_id = ::CFGetTypeID(cf_type); + + if (cf_type_id == ::CFStringGetTypeID()) { + // Retain since we are using the existing object + new_value = (CFStringRef)::CFRetain(cf_type); + } else if (cf_type_id == ::CFURLGetTypeID()) { + new_value = + ::CFURLCopyFileSystemPath((CFURLRef)cf_type, kCFURLPOSIXPathStyle); } - reset(new_value); - return get(); + } + reset(new_value); + return get(); } CFStringRef -CFString::SetFileSystemRepresentationAndExpandTilde (const char *path) -{ - std::string expanded_path; - if (CFString::GlobPath(path, expanded_path)) - SetFileSystemRepresentation(expanded_path.c_str()); - else - reset(); - return get(); +CFString::SetFileSystemRepresentationAndExpandTilde(const char *path) { + std::string expanded_path; + if (CFString::GlobPath(path, expanded_path)) + SetFileSystemRepresentation(expanded_path.c_str()); + else + reset(); + return get(); } -const char * -CFString::UTF8(std::string& str) -{ - return CFString::UTF8(get(), str); +const char *CFString::UTF8(std::string &str) { + return CFString::UTF8(get(), str); } // Static function that puts a copy of the UTF8 contents of CF_STR into STR -// and returns the C string pointer that is contained in STR when successful, else -// NULL is returned. This allows the std::string parameter to own the extracted string, -// and also allows that string to be returned as a C string pointer that can be used. - -const char * -CFString::UTF8 (CFStringRef cf_str, std::string& str) -{ - if (cf_str) - { - const CFStringEncoding encoding = kCFStringEncodingUTF8; - CFIndex max_utf8_str_len = CFStringGetLength (cf_str); - max_utf8_str_len = CFStringGetMaximumSizeForEncoding (max_utf8_str_len, encoding); - if (max_utf8_str_len > 0) - { - str.resize(max_utf8_str_len); - if (!str.empty()) - { - if (CFStringGetCString (cf_str, &str[0], str.size(), encoding)) - { - str.resize(strlen(str.c_str())); - return str.c_str(); - } - } +// and returns the C string pointer that is contained in STR when successful, +// else +// NULL is returned. This allows the std::string parameter to own the extracted +// string, +// and also allows that string to be returned as a C string pointer that can be +// used. + +const char *CFString::UTF8(CFStringRef cf_str, std::string &str) { + if (cf_str) { + const CFStringEncoding encoding = kCFStringEncodingUTF8; + CFIndex max_utf8_str_len = CFStringGetLength(cf_str); + max_utf8_str_len = + CFStringGetMaximumSizeForEncoding(max_utf8_str_len, encoding); + if (max_utf8_str_len > 0) { + str.resize(max_utf8_str_len); + if (!str.empty()) { + if (CFStringGetCString(cf_str, &str[0], str.size(), encoding)) { + str.resize(strlen(str.c_str())); + return str.c_str(); } + } } - return NULL; + } + return NULL; } // Static function that puts a copy of the file system representation of CF_STR @@ -150,52 +124,40 @@ CFString::UTF8 (CFStringRef cf_str, std::string& str) // to own the extracted string, and also allows that string to be returned as // a C string pointer that can be used. -const char * -CFString::FileSystemRepresentation (CFStringRef cf_str, std::string& str) -{ - if (cf_str) - { - CFIndex max_length = ::CFStringGetMaximumSizeOfFileSystemRepresentation (cf_str); - if (max_length > 0) - { - str.resize(max_length); - if (!str.empty()) - { - if (::CFStringGetFileSystemRepresentation (cf_str, &str[0], str.size())) - { - str.erase(::strlen(str.c_str())); - return str.c_str(); - } - } +const char *CFString::FileSystemRepresentation(CFStringRef cf_str, + std::string &str) { + if (cf_str) { + CFIndex max_length = + ::CFStringGetMaximumSizeOfFileSystemRepresentation(cf_str); + if (max_length > 0) { + str.resize(max_length); + if (!str.empty()) { + if (::CFStringGetFileSystemRepresentation(cf_str, &str[0], + str.size())) { + str.erase(::strlen(str.c_str())); + return str.c_str(); } + } } - str.erase(); - return NULL; + } + str.erase(); + return NULL; } - -CFIndex -CFString::GetLength() const -{ - CFStringRef str = get(); - if (str) - return CFStringGetLength (str); - return 0; +CFIndex CFString::GetLength() const { + CFStringRef str = get(); + if (str) + return CFStringGetLength(str); + return 0; } +const char *CFString::GlobPath(const char *path, std::string &expanded_path) { + glob_t globbuf; + if (::glob(path, GLOB_TILDE, NULL, &globbuf) == 0) { + expanded_path = globbuf.gl_pathv[0]; + ::globfree(&globbuf); + } else + expanded_path.clear(); -const char* -CFString::GlobPath(const char* path, std::string &expanded_path) -{ - glob_t globbuf; - if (::glob (path, GLOB_TILDE, NULL, &globbuf) == 0) - { - expanded_path = globbuf.gl_pathv[0]; - ::globfree (&globbuf); - } - else - expanded_path.clear(); - - return expanded_path.c_str(); + return expanded_path.c_str(); } - diff --git a/lldb/tools/debugserver/source/MacOSX/CFString.h b/lldb/tools/debugserver/source/MacOSX/CFString.h index 73945a28a65..18d60a5a74b 100644 --- a/lldb/tools/debugserver/source/MacOSX/CFString.h +++ b/lldb/tools/debugserver/source/MacOSX/CFString.h @@ -17,27 +17,27 @@ #include "CFUtils.h" #include <iosfwd> -class CFString : public CFReleaser<CFStringRef> -{ +class CFString : public CFReleaser<CFStringRef> { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CFString (CFStringRef cf_str = NULL); - CFString (const char *s, CFStringEncoding encoding = kCFStringEncodingUTF8); - CFString (const CFString& rhs); - CFString& operator= (const CFString& rhs); - virtual ~CFString (); + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CFString(CFStringRef cf_str = NULL); + CFString(const char *s, CFStringEncoding encoding = kCFStringEncodingUTF8); + CFString(const CFString &rhs); + CFString &operator=(const CFString &rhs); + virtual ~CFString(); - const char * GetFileSystemRepresentation (std::string& str); - CFStringRef SetFileSystemRepresentation (const char *path); - CFStringRef SetFileSystemRepresentationFromCFType (CFTypeRef cf_type); - CFStringRef SetFileSystemRepresentationAndExpandTilde (const char *path); - const char * UTF8 (std::string& str); - CFIndex GetLength() const; - static const char *UTF8 (CFStringRef cf_str, std::string& str); - static const char *FileSystemRepresentation (CFStringRef cf_str, std::string& str); - static const char* GlobPath(const char* path, std::string &expanded_path); + const char *GetFileSystemRepresentation(std::string &str); + CFStringRef SetFileSystemRepresentation(const char *path); + CFStringRef SetFileSystemRepresentationFromCFType(CFTypeRef cf_type); + CFStringRef SetFileSystemRepresentationAndExpandTilde(const char *path); + const char *UTF8(std::string &str); + CFIndex GetLength() const; + static const char *UTF8(CFStringRef cf_str, std::string &str); + static const char *FileSystemRepresentation(CFStringRef cf_str, + std::string &str); + static const char *GlobPath(const char *path, std::string &expanded_path); }; #endif // #ifndef __CFString_h__ diff --git a/lldb/tools/debugserver/source/MacOSX/CFUtils.h b/lldb/tools/debugserver/source/MacOSX/CFUtils.h index afa984fa11c..a904cd0ea6f 100644 --- a/lldb/tools/debugserver/source/MacOSX/CFUtils.h +++ b/lldb/tools/debugserver/source/MacOSX/CFUtils.h @@ -23,59 +23,56 @@ // call CFRelease() on any valid pointer it owns unless that pointer is // explicitly released using the release() member function. //---------------------------------------------------------------------- -template <class T> -class CFReleaser -{ +template <class T> class CFReleaser { public: - // Type names for the avlue - typedef T element_type; + // Type names for the avlue + typedef T element_type; - // Constructors and destructors - CFReleaser(T ptr = NULL) : _ptr(ptr) { } - CFReleaser(const CFReleaser& copy) : _ptr(copy.get()) - { - if (get()) - ::CFRetain(get()); - } - virtual ~CFReleaser() { reset(); } + // Constructors and destructors + CFReleaser(T ptr = NULL) : _ptr(ptr) {} + CFReleaser(const CFReleaser ©) : _ptr(copy.get()) { + if (get()) + ::CFRetain(get()); + } + virtual ~CFReleaser() { reset(); } - // Assignments - CFReleaser& operator= (const CFReleaser<T>& copy) - { - if (copy != *this) - { - // Replace our owned pointer with the new one - reset(copy.get()); - // Retain the current pointer that we own - if (get()) - ::CFRetain(get()); - } - } - // Get the address of the contained type - T * ptr_address() { return &_ptr; } + // Assignments + CFReleaser &operator=(const CFReleaser<T> ©) { + if (copy != *this) { + // Replace our owned pointer with the new one + reset(copy.get()); + // Retain the current pointer that we own + if (get()) + ::CFRetain(get()); + } + } + // Get the address of the contained type + T *ptr_address() { return &_ptr; } - // Access the pointer itself - const T get() const { return _ptr; } - T get() { return _ptr; } + // Access the pointer itself + const T get() const { return _ptr; } + T get() { return _ptr; } - // Set a new value for the pointer and CFRelease our old - // value if we had a valid one. - void reset(T ptr = NULL) - { - if (ptr != _ptr) - { - if (_ptr != NULL) - ::CFRelease(_ptr); - _ptr = ptr; - } - } + // Set a new value for the pointer and CFRelease our old + // value if we had a valid one. + void reset(T ptr = NULL) { + if (ptr != _ptr) { + if (_ptr != NULL) + ::CFRelease(_ptr); + _ptr = ptr; + } + } + + // Release ownership without calling CFRelease + T release() { + T tmp = _ptr; + _ptr = NULL; + return tmp; + } - // Release ownership without calling CFRelease - T release() { T tmp = _ptr; _ptr = NULL; return tmp; } private: - element_type _ptr; + element_type _ptr; }; -#endif // #ifdef __cplusplus -#endif // #ifndef __CFUtils_h__ - +#endif // #ifdef __cplusplus +#endif // #ifndef __CFUtils_h__ diff --git a/lldb/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.cpp b/lldb/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.cpp index e98a131512a..2cb653894db 100644 --- a/lldb/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.cpp +++ b/lldb/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.cpp @@ -9,10 +9,6 @@ #include "ActivityStore.h" -ActivityStore::ActivityStore() -{ -} +ActivityStore::ActivityStore() {} -ActivityStore::~ActivityStore() -{ -} +ActivityStore::~ActivityStore() {} diff --git a/lldb/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.h b/lldb/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.h index 2e998ba367c..35e0a85ad51 100644 --- a/lldb/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.h +++ b/lldb/tools/debugserver/source/MacOSX/DarwinLog/ActivityStore.h @@ -14,23 +14,17 @@ #include "ActivityStreamSPI.h" -class ActivityStore -{ +class ActivityStore { public: + virtual ~ActivityStore(); - virtual - ~ActivityStore(); + virtual const char *GetActivityForID(os_activity_id_t activity_id) const = 0; - virtual const char* - GetActivityForID(os_activity_id_t activity_id) const = 0; - - virtual std::string - GetActivityChainForID(os_activity_id_t activity_id) const = 0; + virtual std::string + GetActivityChainForID(os_activity_id_t activity_id) const = 0; protected: - - ActivityStore(); - + ActivityStore(); }; #endif /* ActivityStore_h */ diff --git a/lldb/tools/debugserver/source/MacOSX/DarwinLog/ActivityStreamSPI.h b/lldb/tools/debugserver/source/MacOSX/DarwinLog/ActivityStreamSPI.h index 4ddf13b3fcd..8aebc79e6ec 100644 --- a/lldb/tools/debugserver/source/MacOSX/DarwinLog/ActivityStreamSPI.h +++ b/lldb/tools/debugserver/source/MacOSX/DarwinLog/ActivityStreamSPI.h @@ -17,48 +17,45 @@ // Enums -enum -{ - OS_ACTIVITY_STREAM_PROCESS_ONLY = 0x00000001, - OS_ACTIVITY_STREAM_SKIP_DECODE = 0x00000002, - OS_ACTIVITY_STREAM_PAYLOAD = 0x00000004, - OS_ACTIVITY_STREAM_HISTORICAL = 0x00000008, - OS_ACTIVITY_STREAM_CALLSTACK = 0x00000010, - OS_ACTIVITY_STREAM_DEBUG = 0x00000020, - OS_ACTIVITY_STREAM_BUFFERED = 0x00000040, - OS_ACTIVITY_STREAM_NO_SENSITIVE = 0x00000080, - OS_ACTIVITY_STREAM_INFO = 0x00000100, - OS_ACTIVITY_STREAM_PROMISCUOUS = 0x00000200, - OS_ACTIVITY_STREAM_PRECISE_TIMESTAMPS = 0x00000200 +enum { + OS_ACTIVITY_STREAM_PROCESS_ONLY = 0x00000001, + OS_ACTIVITY_STREAM_SKIP_DECODE = 0x00000002, + OS_ACTIVITY_STREAM_PAYLOAD = 0x00000004, + OS_ACTIVITY_STREAM_HISTORICAL = 0x00000008, + OS_ACTIVITY_STREAM_CALLSTACK = 0x00000010, + OS_ACTIVITY_STREAM_DEBUG = 0x00000020, + OS_ACTIVITY_STREAM_BUFFERED = 0x00000040, + OS_ACTIVITY_STREAM_NO_SENSITIVE = 0x00000080, + OS_ACTIVITY_STREAM_INFO = 0x00000100, + OS_ACTIVITY_STREAM_PROMISCUOUS = 0x00000200, + OS_ACTIVITY_STREAM_PRECISE_TIMESTAMPS = 0x00000200 }; typedef uint32_t os_activity_stream_flag_t; -enum -{ - OS_ACTIVITY_STREAM_TYPE_ACTIVITY_CREATE = 0x0201, - OS_ACTIVITY_STREAM_TYPE_ACTIVITY_TRANSITION = 0x0202, - OS_ACTIVITY_STREAM_TYPE_ACTIVITY_USERACTION = 0x0203, +enum { + OS_ACTIVITY_STREAM_TYPE_ACTIVITY_CREATE = 0x0201, + OS_ACTIVITY_STREAM_TYPE_ACTIVITY_TRANSITION = 0x0202, + OS_ACTIVITY_STREAM_TYPE_ACTIVITY_USERACTION = 0x0203, - OS_ACTIVITY_STREAM_TYPE_TRACE_MESSAGE = 0x0300, + OS_ACTIVITY_STREAM_TYPE_TRACE_MESSAGE = 0x0300, - OS_ACTIVITY_STREAM_TYPE_LOG_MESSAGE = 0x0400, - OS_ACTIVITY_STREAM_TYPE_LEGACY_LOG_MESSAGE = 0x0480, + OS_ACTIVITY_STREAM_TYPE_LOG_MESSAGE = 0x0400, + OS_ACTIVITY_STREAM_TYPE_LEGACY_LOG_MESSAGE = 0x0480, - OS_ACTIVITY_STREAM_TYPE_SIGNPOST_BEGIN = 0x0601, - OS_ACTIVITY_STREAM_TYPE_SIGNPOST_END = 0x0602, - OS_ACTIVITY_STREAM_TYPE_SIGNPOST_EVENT = 0x0603, + OS_ACTIVITY_STREAM_TYPE_SIGNPOST_BEGIN = 0x0601, + OS_ACTIVITY_STREAM_TYPE_SIGNPOST_END = 0x0602, + OS_ACTIVITY_STREAM_TYPE_SIGNPOST_EVENT = 0x0603, - OS_ACTIVITY_STREAM_TYPE_STATEDUMP_EVENT = 0x0A00, + OS_ACTIVITY_STREAM_TYPE_STATEDUMP_EVENT = 0x0A00, }; typedef uint32_t os_activity_stream_type_t; -enum -{ - OS_ACTIVITY_STREAM_EVENT_STARTED = 1, - OS_ACTIVITY_STREAM_EVENT_STOPPED = 2, - OS_ACTIVITY_STREAM_EVENT_FAILED = 3, - OS_ACTIVITY_STREAM_EVENT_CHUNK_STARTED = 4, - OS_ACTIVITY_STREAM_EVENT_CHUNK_FINISHED = 5, +enum { + OS_ACTIVITY_STREAM_EVENT_STARTED = 1, + OS_ACTIVITY_STREAM_EVENT_STOPPED = 2, + OS_ACTIVITY_STREAM_EVENT_FAILED = 3, + OS_ACTIVITY_STREAM_EVENT_CHUNK_STARTED = 4, + OS_ACTIVITY_STREAM_EVENT_CHUNK_FINISHED = 5, }; typedef uint32_t os_activity_stream_event_t; @@ -68,105 +65,104 @@ typedef uint64_t os_activity_id_t; typedef struct os_activity_stream_s *os_activity_stream_t; typedef struct os_activity_stream_entry_s *os_activity_stream_entry_t; -#define OS_ACTIVITY_STREAM_COMMON() \ - uint64_t trace_id; \ - uint64_t timestamp; \ - uint64_t thread; \ - const uint8_t *image_uuid; \ - const char *image_path; \ - struct timeval tv_gmt; \ - struct timezone tz; \ - uint32_t offset \ - +#define OS_ACTIVITY_STREAM_COMMON() \ + uint64_t trace_id; \ + uint64_t timestamp; \ + uint64_t thread; \ + const uint8_t *image_uuid; \ + const char *image_path; \ + struct timeval tv_gmt; \ + struct timezone tz; \ + uint32_t offset typedef struct os_activity_stream_common_s { - OS_ACTIVITY_STREAM_COMMON(); -} *os_activity_stream_common_t; + OS_ACTIVITY_STREAM_COMMON(); +} * os_activity_stream_common_t; struct os_activity_create_s { - OS_ACTIVITY_STREAM_COMMON(); - const char *name; - os_activity_id_t creator_aid; - uint64_t unique_pid; + OS_ACTIVITY_STREAM_COMMON(); + const char *name; + os_activity_id_t creator_aid; + uint64_t unique_pid; }; struct os_activity_transition_s { - OS_ACTIVITY_STREAM_COMMON(); - os_activity_id_t transition_id; + OS_ACTIVITY_STREAM_COMMON(); + os_activity_id_t transition_id; }; typedef struct os_log_message_s { - OS_ACTIVITY_STREAM_COMMON(); - const char *format; - const uint8_t *buffer; - size_t buffer_sz; - const uint8_t *privdata; - size_t privdata_sz; - const char *subsystem; - const char *category; - uint32_t oversize_id; - uint8_t ttl; - bool persisted; -} *os_log_message_t; + OS_ACTIVITY_STREAM_COMMON(); + const char *format; + const uint8_t *buffer; + size_t buffer_sz; + const uint8_t *privdata; + size_t privdata_sz; + const char *subsystem; + const char *category; + uint32_t oversize_id; + uint8_t ttl; + bool persisted; +} * os_log_message_t; typedef struct os_trace_message_v2_s { - OS_ACTIVITY_STREAM_COMMON(); - const char *format; - const void *buffer; - size_t bufferLen; - xpc_object_t __unsafe_unretained payload; -} *os_trace_message_v2_t; + OS_ACTIVITY_STREAM_COMMON(); + const char *format; + const void *buffer; + size_t bufferLen; + xpc_object_t __unsafe_unretained payload; +} * os_trace_message_v2_t; typedef struct os_activity_useraction_s { - OS_ACTIVITY_STREAM_COMMON(); - const char *action; - bool persisted; -} *os_activity_useraction_t; + OS_ACTIVITY_STREAM_COMMON(); + const char *action; + bool persisted; +} * os_activity_useraction_t; typedef struct os_signpost_s { - OS_ACTIVITY_STREAM_COMMON(); - const char *format; - const uint8_t *buffer; - size_t buffer_sz; - const uint8_t *privdata; - size_t privdata_sz; - const char *subsystem; - const char *category; - uint64_t duration_nsec; - uint32_t callstack_depth; - uint64_t callstack[OS_ACTIVITY_MAX_CALLSTACK]; -} *os_signpost_t; + OS_ACTIVITY_STREAM_COMMON(); + const char *format; + const uint8_t *buffer; + size_t buffer_sz; + const uint8_t *privdata; + size_t privdata_sz; + const char *subsystem; + const char *category; + uint64_t duration_nsec; + uint32_t callstack_depth; + uint64_t callstack[OS_ACTIVITY_MAX_CALLSTACK]; +} * os_signpost_t; typedef struct os_activity_statedump_s { - OS_ACTIVITY_STREAM_COMMON(); - char *message; - size_t message_size; - char image_path_buffer[PATH_MAX]; -} *os_activity_statedump_t; + OS_ACTIVITY_STREAM_COMMON(); + char *message; + size_t message_size; + char image_path_buffer[PATH_MAX]; +} * os_activity_statedump_t; struct os_activity_stream_entry_s { - os_activity_stream_type_t type; - - // information about the process streaming the data - pid_t pid; - uint64_t proc_id; - const uint8_t *proc_imageuuid; - const char *proc_imagepath; - - // the activity associated with this streamed event - os_activity_id_t activity_id; - os_activity_id_t parent_id; - - union { - struct os_activity_stream_common_s common; - struct os_activity_create_s activity_create; - struct os_activity_transition_s activity_transition; - struct os_log_message_s log_message; - struct os_trace_message_v2_s trace_message; - struct os_activity_useraction_s useraction; - struct os_signpost_s signpost; - struct os_activity_statedump_s statedump; - }; + os_activity_stream_type_t type; + + // information about the process streaming the data + pid_t pid; + uint64_t proc_id; + const uint8_t *proc_imageuuid; + const char *proc_imagepath; + + // the activity associated with this streamed event + os_activity_id_t activity_id; + os_activity_id_t parent_id; + + union { + struct os_activity_stream_common_s common; + struct os_activity_create_s activity_create; + struct os_activity_transition_s activity_transition; + struct os_log_message_s log_message; + struct os_trace_message_v2_s trace_message; + struct os_activity_useraction_s useraction; + struct os_signpost_s signpost; + struct os_activity_statedump_s statedump; + }; }; // Blocks @@ -175,26 +171,21 @@ typedef bool (^os_activity_stream_block_t)(os_activity_stream_entry_t entry, int error); typedef void (^os_activity_stream_event_block_t)( - os_activity_stream_t stream, - os_activity_stream_event_t event); + os_activity_stream_t stream, os_activity_stream_event_t event); // SPI entry point prototypes -typedef os_activity_stream_t - (*os_activity_stream_for_pid_t)(pid_t pid, os_activity_stream_flag_t flags, - os_activity_stream_block_t stream_block); +typedef os_activity_stream_t (*os_activity_stream_for_pid_t)( + pid_t pid, os_activity_stream_flag_t flags, + os_activity_stream_block_t stream_block); -typedef void -(*os_activity_stream_resume_t)(os_activity_stream_t stream); +typedef void (*os_activity_stream_resume_t)(os_activity_stream_t stream); -typedef void - (*os_activity_stream_cancel_t)(os_activity_stream_t stream); +typedef void (*os_activity_stream_cancel_t)(os_activity_stream_t stream); -typedef char * - (*os_log_copy_formatted_message_t)(os_log_message_t log_message); +typedef char *(*os_log_copy_formatted_message_t)(os_log_message_t log_message); -typedef void - (*os_activity_stream_set_event_handler_t) - (os_activity_stream_t stream, os_activity_stream_event_block_t block); +typedef void (*os_activity_stream_set_event_handler_t)( + os_activity_stream_t stream, os_activity_stream_event_block_t block); #endif /* ActivityStreamSPI_h */ diff --git a/lldb/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.cpp b/lldb/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.cpp index 30f3e521669..982367092ed 100644 --- a/lldb/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.cpp +++ b/lldb/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.cpp @@ -16,9 +16,9 @@ #include <mutex> #include <vector> -#include "DarwinLogTypes.h" #include "DNB.h" #include "DNBLog.h" +#include "DarwinLogTypes.h" #include "LogFilterChain.h" #include "LogFilterExactMatch.h" #include "LogFilterRegex.h" @@ -30,806 +30,668 @@ // Use an anonymous namespace for variables and methods that have no // reason to leak out through the interface. -namespace -{ - /// Specify max depth that the activity parent-child chain will search - /// back to get the full activity chain name. If we do more than this, - /// we assume either we hit a loop or it's just too long. - static const size_t MAX_ACTIVITY_CHAIN_DEPTH = 10; - - // Used to tap into and retrieve logs from target process. - // (Consumer of os_log). - static os_activity_stream_for_pid_t s_os_activity_stream_for_pid; - static os_activity_stream_resume_t s_os_activity_stream_resume; - static os_activity_stream_cancel_t s_os_activity_stream_cancel; - static os_log_copy_formatted_message_t s_os_log_copy_formatted_message; - static os_activity_stream_set_event_handler_t +namespace { +/// Specify max depth that the activity parent-child chain will search +/// back to get the full activity chain name. If we do more than this, +/// we assume either we hit a loop or it's just too long. +static const size_t MAX_ACTIVITY_CHAIN_DEPTH = 10; + +// Used to tap into and retrieve logs from target process. +// (Consumer of os_log). +static os_activity_stream_for_pid_t s_os_activity_stream_for_pid; +static os_activity_stream_resume_t s_os_activity_stream_resume; +static os_activity_stream_cancel_t s_os_activity_stream_cancel; +static os_log_copy_formatted_message_t s_os_log_copy_formatted_message; +static os_activity_stream_set_event_handler_t s_os_activity_stream_set_event_handler; - bool - LookupSPICalls() - { - static std::once_flag s_once_flag; - static bool s_has_spi; - - std::call_once(s_once_flag, [] { - s_os_activity_stream_for_pid = (os_activity_stream_for_pid_t) - dlsym(RTLD_DEFAULT, "os_activity_stream_for_pid"); - s_os_activity_stream_resume = (os_activity_stream_resume_t) - dlsym(RTLD_DEFAULT, "os_activity_stream_resume"); - s_os_activity_stream_cancel = (os_activity_stream_cancel_t) - dlsym(RTLD_DEFAULT, "os_activity_stream_cancel"); - s_os_log_copy_formatted_message = (os_log_copy_formatted_message_t) - dlsym(RTLD_DEFAULT, "os_log_copy_formatted_message"); - s_os_activity_stream_set_event_handler = - (os_activity_stream_set_event_handler_t) - dlsym(RTLD_DEFAULT, "os_activity_stream_set_event_handler"); - - // We'll indicate we're all set if every function entry point - // was found. - s_has_spi = - (s_os_activity_stream_for_pid != nullptr) && +bool LookupSPICalls() { + static std::once_flag s_once_flag; + static bool s_has_spi; + + std::call_once(s_once_flag, [] { + s_os_activity_stream_for_pid = (os_activity_stream_for_pid_t)dlsym( + RTLD_DEFAULT, "os_activity_stream_for_pid"); + s_os_activity_stream_resume = (os_activity_stream_resume_t)dlsym( + RTLD_DEFAULT, "os_activity_stream_resume"); + s_os_activity_stream_cancel = (os_activity_stream_cancel_t)dlsym( + RTLD_DEFAULT, "os_activity_stream_cancel"); + s_os_log_copy_formatted_message = (os_log_copy_formatted_message_t)dlsym( + RTLD_DEFAULT, "os_log_copy_formatted_message"); + s_os_activity_stream_set_event_handler = + (os_activity_stream_set_event_handler_t)dlsym( + RTLD_DEFAULT, "os_activity_stream_set_event_handler"); + + // We'll indicate we're all set if every function entry point + // was found. + s_has_spi = (s_os_activity_stream_for_pid != nullptr) && (s_os_activity_stream_resume != nullptr) && (s_os_activity_stream_cancel != nullptr) && (s_os_log_copy_formatted_message != nullptr) && (s_os_activity_stream_set_event_handler != nullptr); - if (s_has_spi) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, "Found os_log SPI calls."); - // Tell LogMessageOsLog how to format messages when search - // criteria requires it. - LogMessageOsLog::SetFormatterFunction( - s_os_log_copy_formatted_message); - } - else - { - DNBLogThreadedIf(LOG_DARWIN_LOG, "Failed to find os_log SPI " - "calls."); - } - }); - - return s_has_spi; + if (s_has_spi) { + DNBLogThreadedIf(LOG_DARWIN_LOG, "Found os_log SPI calls."); + // Tell LogMessageOsLog how to format messages when search + // criteria requires it. + LogMessageOsLog::SetFormatterFunction(s_os_log_copy_formatted_message); + } else { + DNBLogThreadedIf(LOG_DARWIN_LOG, "Failed to find os_log SPI " + "calls."); } + }); - using Mutex = std::mutex; - static Mutex s_collector_mutex; - static std::vector<DarwinLogCollectorSP> s_collectors; + return s_has_spi; +} - static void - TrackCollector(const DarwinLogCollectorSP &collector_sp) - { - std::lock_guard<Mutex> locker(s_collector_mutex); - if (std::find(s_collectors.begin(), s_collectors.end(), collector_sp) - != s_collectors.end()) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "attempted to add same collector multiple times"); - return; - } - s_collectors.push_back(collector_sp); +using Mutex = std::mutex; +static Mutex s_collector_mutex; +static std::vector<DarwinLogCollectorSP> s_collectors; + +static void TrackCollector(const DarwinLogCollectorSP &collector_sp) { + std::lock_guard<Mutex> locker(s_collector_mutex); + if (std::find(s_collectors.begin(), s_collectors.end(), collector_sp) != + s_collectors.end()) { + DNBLogThreadedIf(LOG_DARWIN_LOG, + "attempted to add same collector multiple times"); + return; + } + s_collectors.push_back(collector_sp); +} + +static void StopTrackingCollector(const DarwinLogCollectorSP &collector_sp) { + std::lock_guard<Mutex> locker(s_collector_mutex); + s_collectors.erase( + std::remove(s_collectors.begin(), s_collectors.end(), collector_sp), + s_collectors.end()); +} + +static DarwinLogCollectorSP FindCollectorForProcess(pid_t pid) { + std::lock_guard<Mutex> locker(s_collector_mutex); + for (const auto &collector_sp : s_collectors) { + if (collector_sp && (collector_sp->GetProcessID() == pid)) + return collector_sp; + } + return DarwinLogCollectorSP(); +} + +static FilterTarget TargetStringToEnum(const std::string &filter_target_name) { + if (filter_target_name == "activity") + return eFilterTargetActivity; + else if (filter_target_name == "activity-chain") + return eFilterTargetActivityChain; + else if (filter_target_name == "category") + return eFilterTargetCategory; + else if (filter_target_name == "message") + return eFilterTargetMessage; + else if (filter_target_name == "subsystem") + return eFilterTargetSubsystem; + else + return eFilterTargetInvalid; +} + +class Configuration { +public: + Configuration(const JSONObject &config) + : m_is_valid(false), + m_activity_stream_flags(OS_ACTIVITY_STREAM_PROCESS_ONLY), + m_filter_chain_sp(nullptr) { + // Parse out activity stream flags + if (!ParseSourceFlags(config)) { + m_is_valid = false; + return; } - static void - StopTrackingCollector(const DarwinLogCollectorSP &collector_sp) - { - std::lock_guard<Mutex> locker(s_collector_mutex); - s_collectors.erase(std::remove(s_collectors.begin(), s_collectors.end(), - collector_sp), - s_collectors.end()); + // Parse filter rules + if (!ParseFilterRules(config)) { + m_is_valid = false; + return; } - static DarwinLogCollectorSP - FindCollectorForProcess(pid_t pid) - { - std::lock_guard<Mutex> locker(s_collector_mutex); - for (const auto &collector_sp : s_collectors) - { - if (collector_sp && (collector_sp->GetProcessID() == pid)) - return collector_sp; - } - return DarwinLogCollectorSP(); + // Everything worked. + m_is_valid = true; + } + + bool ParseSourceFlags(const JSONObject &config) { + // Get the source-flags dictionary. + auto source_flags_sp = config.GetObject("source-flags"); + if (!source_flags_sp) + return false; + if (!JSONObject::classof(source_flags_sp.get())) + return false; + + const JSONObject &source_flags = + *static_cast<JSONObject *>(source_flags_sp.get()); + + // Parse out the flags. + bool include_any_process = false; + bool include_callstacks = false; + bool include_info_level = false; + bool include_debug_level = false; + bool live_stream = false; + + if (!source_flags.GetObjectAsBool("any-process", include_any_process)) { + DNBLogThreadedIf(LOG_DARWIN_LOG, "Source-flag 'any-process' missing from " + "configuration."); + return false; + } + if (!source_flags.GetObjectAsBool("callstacks", include_callstacks)) { + // We currently suppress the availability of this on the lldb + // side. We include here for devices when we enable in the + // future. + // DNBLogThreadedIf(LOG_DARWIN_LOG, + // "Source-flag 'callstacks' missing from " + // "configuration."); + + // OK. We just skip callstacks. + // return false; + } + if (!source_flags.GetObjectAsBool("info-level", include_info_level)) { + DNBLogThreadedIf(LOG_DARWIN_LOG, "Source-flag 'info-level' missing from " + "configuration."); + return false; + } + if (!source_flags.GetObjectAsBool("debug-level", include_debug_level)) { + DNBLogThreadedIf(LOG_DARWIN_LOG, "Source-flag 'debug-level' missing from " + "configuration."); + return false; + } + if (!source_flags.GetObjectAsBool("live-stream", live_stream)) { + DNBLogThreadedIf(LOG_DARWIN_LOG, "Source-flag 'live-stream' missing from " + "configuration."); + return false; } - static FilterTarget - TargetStringToEnum(const std::string &filter_target_name) - { - if (filter_target_name == "activity") - return eFilterTargetActivity; - else if (filter_target_name == "activity-chain") - return eFilterTargetActivityChain; - else if (filter_target_name == "category") - return eFilterTargetCategory; - else if (filter_target_name == "message") - return eFilterTargetMessage; - else if (filter_target_name == "subsystem") - return eFilterTargetSubsystem; - else - return eFilterTargetInvalid; + // Setup the SPI flags based on this. + m_activity_stream_flags = 0; + if (!include_any_process) + m_activity_stream_flags |= OS_ACTIVITY_STREAM_PROCESS_ONLY; + if (include_callstacks) + m_activity_stream_flags |= OS_ACTIVITY_STREAM_CALLSTACK; + if (include_info_level) + m_activity_stream_flags |= OS_ACTIVITY_STREAM_INFO; + if (include_debug_level) + m_activity_stream_flags |= OS_ACTIVITY_STREAM_DEBUG; + if (!live_stream) + m_activity_stream_flags |= OS_ACTIVITY_STREAM_BUFFERED; + + DNBLogThreadedIf(LOG_DARWIN_LOG, "m_activity_stream_flags = 0x%03x", + m_activity_stream_flags); + + return true; + } + + bool ParseFilterRules(const JSONObject &config) { + // Retrieve the default rule. + bool filter_default_accept = true; + if (!config.GetObjectAsBool("filter-fall-through-accepts", + filter_default_accept)) { + DNBLogThreadedIf(LOG_DARWIN_LOG, "Setting 'filter-fall-through-accepts' " + "missing from configuration."); + return false; } + m_filter_chain_sp.reset(new LogFilterChain(filter_default_accept)); + DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLog no-match rule: %s.", + filter_default_accept ? "accept" : "reject"); + + // If we don't have the filter-rules array, we're done. + auto filter_rules_sp = config.GetObject("filter-rules"); + if (!filter_rules_sp) { + DNBLogThreadedIf(LOG_DARWIN_LOG, + "No 'filter-rules' config element, all log " + "entries will use the no-match action (%s).", + filter_default_accept ? "accept" : "reject"); + return true; + } + if (!JSONArray::classof(filter_rules_sp.get())) + return false; + const JSONArray &rules_config = + *static_cast<JSONArray *>(filter_rules_sp.get()); + + // Create the filters. + for (auto &rule_sp : rules_config.m_elements) { + if (!JSONObject::classof(rule_sp.get())) + return false; + const JSONObject &rule_config = *static_cast<JSONObject *>(rule_sp.get()); - class Configuration - { - public: + // Get whether this filter accepts or rejects. + bool filter_accepts = true; + if (!rule_config.GetObjectAsBool("accept", filter_accepts)) { + DNBLogThreadedIf(LOG_DARWIN_LOG, "Filter 'accept' element missing."); + return false; + } - Configuration(const JSONObject &config) : - m_is_valid(false), - m_activity_stream_flags(OS_ACTIVITY_STREAM_PROCESS_ONLY), - m_filter_chain_sp(nullptr) - { - // Parse out activity stream flags - if (!ParseSourceFlags(config)) - { - m_is_valid = false; - return; - } - - // Parse filter rules - if (!ParseFilterRules(config)) - { - m_is_valid = false; - return; - } - - // Everything worked. - m_is_valid = true; - } + // Grab the target log field attribute for the match. + std::string target_attribute; + if (!rule_config.GetObjectAsString("attribute", target_attribute)) { + DNBLogThreadedIf(LOG_DARWIN_LOG, "Filter 'attribute' element missing."); + return false; + } + auto target_enum = TargetStringToEnum(target_attribute); + if (target_enum == eFilterTargetInvalid) { + DNBLogThreadedIf(LOG_DARWIN_LOG, "Filter attribute '%s' unsupported.", + target_attribute.c_str()); + return false; + } - bool - ParseSourceFlags(const JSONObject &config) - { - // Get the source-flags dictionary. - auto source_flags_sp = config.GetObject("source-flags"); - if (!source_flags_sp) - return false; - if (!JSONObject::classof(source_flags_sp.get())) - return false; - - const JSONObject &source_flags = - *static_cast<JSONObject*>(source_flags_sp.get()); - - // Parse out the flags. - bool include_any_process = false; - bool include_callstacks = false; - bool include_info_level = false; - bool include_debug_level = false; - bool live_stream = false; - - if (!source_flags.GetObjectAsBool("any-process", - include_any_process)) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "Source-flag 'any-process' missing from " - "configuration."); - return false; - } - if (!source_flags.GetObjectAsBool("callstacks", - include_callstacks)) - { - // We currently suppress the availability of this on the lldb - // side. We include here for devices when we enable in the - // future. - // DNBLogThreadedIf(LOG_DARWIN_LOG, - // "Source-flag 'callstacks' missing from " - // "configuration."); - - // OK. We just skip callstacks. - // return false; - } - if (!source_flags.GetObjectAsBool("info-level", - include_info_level)) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "Source-flag 'info-level' missing from " - "configuration."); - return false; - } - if (!source_flags.GetObjectAsBool("debug-level", - include_debug_level)) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "Source-flag 'debug-level' missing from " - "configuration."); - return false; - } - if (!source_flags.GetObjectAsBool("live-stream", - live_stream)) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "Source-flag 'live-stream' missing from " - "configuration."); - return false; - } - - // Setup the SPI flags based on this. - m_activity_stream_flags = 0; - if (!include_any_process) - m_activity_stream_flags |= OS_ACTIVITY_STREAM_PROCESS_ONLY; - if (include_callstacks) - m_activity_stream_flags |= OS_ACTIVITY_STREAM_CALLSTACK; - if (include_info_level) - m_activity_stream_flags |= OS_ACTIVITY_STREAM_INFO; - if (include_debug_level) - m_activity_stream_flags |= OS_ACTIVITY_STREAM_DEBUG; - if (!live_stream) - m_activity_stream_flags |= OS_ACTIVITY_STREAM_BUFFERED; - - DNBLogThreadedIf(LOG_DARWIN_LOG, "m_activity_stream_flags = 0x%03x", - m_activity_stream_flags); - - return true; + // Handle operation-specific fields and filter creation. + std::string filter_type; + if (!rule_config.GetObjectAsString("type", filter_type)) { + DNBLogThreadedIf(LOG_DARWIN_LOG, "Filter 'type' element missing."); + return false; + } + DNBLogThreadedIf(LOG_DARWIN_LOG, "Reading filter of type '%s'", + filter_type.c_str()); + + LogFilterSP filter_sp; + if (filter_type == "regex") { + // Grab the regex for the match. + std::string regex; + if (!rule_config.GetObjectAsString("regex", regex)) { + DNBLogError("Regex filter missing 'regex' element."); + return false; } - - bool - ParseFilterRules(const JSONObject &config) - { - // Retrieve the default rule. - bool filter_default_accept = true; - if (!config.GetObjectAsBool("filter-fall-through-accepts", - filter_default_accept)) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "Setting 'filter-fall-through-accepts' " - "missing from configuration."); - return false; - } - m_filter_chain_sp.reset(new LogFilterChain(filter_default_accept)); - DNBLogThreadedIf(LOG_DARWIN_LOG, - "DarwinLog no-match rule: %s.", - filter_default_accept ? "accept" : "reject"); - - // If we don't have the filter-rules array, we're done. - auto filter_rules_sp = config.GetObject("filter-rules"); - if (!filter_rules_sp) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "No 'filter-rules' config element, all log " - "entries will use the no-match action (%s).", - filter_default_accept ? "accept" : "reject"); - return true; - } - if (!JSONArray::classof(filter_rules_sp.get())) - return false; - const JSONArray &rules_config = - *static_cast<JSONArray*>(filter_rules_sp.get()); - - // Create the filters. - for (auto &rule_sp : rules_config.m_elements) - { - if (!JSONObject::classof(rule_sp.get())) - return false; - const JSONObject &rule_config = *static_cast<JSONObject*> - (rule_sp.get()); - - // Get whether this filter accepts or rejects. - bool filter_accepts = true; - if (!rule_config.GetObjectAsBool("accept", filter_accepts)) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "Filter 'accept' element missing."); - return false; - } - - // Grab the target log field attribute for the match. - std::string target_attribute; - if (!rule_config.GetObjectAsString("attribute", - target_attribute)) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "Filter 'attribute' element missing."); - return false; - } - auto target_enum = TargetStringToEnum(target_attribute); - if (target_enum == eFilterTargetInvalid) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "Filter attribute '%s' unsupported.", - target_attribute.c_str()); - return false; - } - - // Handle operation-specific fields and filter creation. - std::string filter_type; - if (!rule_config.GetObjectAsString("type", filter_type)) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "Filter 'type' element missing."); - return false; - } - DNBLogThreadedIf(LOG_DARWIN_LOG, - "Reading filter of type '%s'", filter_type - .c_str()); - - LogFilterSP filter_sp; - if (filter_type == "regex") - { - // Grab the regex for the match. - std::string regex; - if (!rule_config.GetObjectAsString("regex", - regex)) - { - DNBLogError("Regex filter missing 'regex' element."); - return false; - } - DNBLogThreadedIf(LOG_DARWIN_LOG, - "regex for filter: \"%s\"", regex.c_str()); - - // Create the regex filter. - auto regex_filter = - new LogFilterRegex(filter_accepts, target_enum, regex); - filter_sp.reset(regex_filter); - - // Validate that the filter is okay. - if (!regex_filter->IsValid()) - { - DNBLogError("Invalid regex in filter: " - "regex=\"%s\", error=%s", - regex.c_str(), - regex_filter->GetErrorAsCString()); - return false; - } - } - else if (filter_type == "match") - { - // Grab the regex for the match. - std::string exact_text; - if (!rule_config.GetObjectAsString("exact_text", - exact_text)) - { - DNBLogError("Exact match filter missing " - "'exact_text' element."); - return false; - } - - // Create the filter. - filter_sp.reset(new LogFilterExactMatch(filter_accepts, - target_enum, - exact_text)); - } - - // Add the filter to the chain. - m_filter_chain_sp->AppendFilter(filter_sp); - } - return true; + DNBLogThreadedIf(LOG_DARWIN_LOG, "regex for filter: \"%s\"", + regex.c_str()); + + // Create the regex filter. + auto regex_filter = + new LogFilterRegex(filter_accepts, target_enum, regex); + filter_sp.reset(regex_filter); + + // Validate that the filter is okay. + if (!regex_filter->IsValid()) { + DNBLogError("Invalid regex in filter: " + "regex=\"%s\", error=%s", + regex.c_str(), regex_filter->GetErrorAsCString()); + return false; } - - bool - IsValid() const - { - return m_is_valid; + } else if (filter_type == "match") { + // Grab the regex for the match. + std::string exact_text; + if (!rule_config.GetObjectAsString("exact_text", exact_text)) { + DNBLogError("Exact match filter missing " + "'exact_text' element."); + return false; } - os_activity_stream_flag_t - GetActivityStreamFlags() const - { - return m_activity_stream_flags; - } + // Create the filter. + filter_sp.reset( + new LogFilterExactMatch(filter_accepts, target_enum, exact_text)); + } - const LogFilterChainSP & - GetLogFilterChain() const - { - return m_filter_chain_sp; - } + // Add the filter to the chain. + m_filter_chain_sp->AppendFilter(filter_sp); + } + return true; + } + + bool IsValid() const { return m_is_valid; } - private: + os_activity_stream_flag_t GetActivityStreamFlags() const { + return m_activity_stream_flags; + } - bool m_is_valid; - os_activity_stream_flag_t m_activity_stream_flags; - LogFilterChainSP m_filter_chain_sp; + const LogFilterChainSP &GetLogFilterChain() const { + return m_filter_chain_sp; + } - }; +private: + bool m_is_valid; + os_activity_stream_flag_t m_activity_stream_flags; + LogFilterChainSP m_filter_chain_sp; +}; } -bool -DarwinLogCollector::IsSupported() -{ - // We're supported if we have successfully looked up the SPI entry points. - return LookupSPICalls(); +bool DarwinLogCollector::IsSupported() { + // We're supported if we have successfully looked up the SPI entry points. + return LookupSPICalls(); } -bool -DarwinLogCollector::StartCollectingForProcess(nub_process_t pid, - const JSONObject &config) -{ - // If we're currently collecting for this process, kill the existing - // collector. - if (CancelStreamForProcess(pid)) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "%s() killed existing DarwinLog collector for pid %d.", - __FUNCTION__, pid); +bool DarwinLogCollector::StartCollectingForProcess(nub_process_t pid, + const JSONObject &config) { + // If we're currently collecting for this process, kill the existing + // collector. + if (CancelStreamForProcess(pid)) { + DNBLogThreadedIf(LOG_DARWIN_LOG, + "%s() killed existing DarwinLog collector for pid %d.", + __FUNCTION__, pid); + } + + // If the process isn't alive, we're done. + if (!DNBProcessIsAlive(pid)) { + DNBLogThreadedIf(LOG_DARWIN_LOG, + "%s() cannot collect for pid %d: process not alive.", + __FUNCTION__, pid); + return false; + } + + // Validate the configuration. + auto spi_config = Configuration(config); + if (!spi_config.IsValid()) { + DNBLogThreadedIf(LOG_DARWIN_LOG, + "%s() invalid configuration, will not enable log " + "collection", + __FUNCTION__); + return false; + } + + // Create the stream collector that will manage collected data + // for this pid. + DarwinLogCollectorSP collector_sp( + new DarwinLogCollector(pid, spi_config.GetLogFilterChain())); + std::weak_ptr<DarwinLogCollector> collector_wp(collector_sp); + + // Setup the stream handling block. + os_activity_stream_block_t block = + ^bool(os_activity_stream_entry_t entry, int error) { + // Check if our collector is still alive. + DarwinLogCollectorSP inner_collector_sp = collector_wp.lock(); + if (!inner_collector_sp) + return false; + return inner_collector_sp->HandleStreamEntry(entry, error); + }; + + os_activity_stream_event_block_t stream_event_block = ^void( + os_activity_stream_t stream, os_activity_stream_event_t event) { + switch (event) { + case OS_ACTIVITY_STREAM_EVENT_STARTED: + DNBLogThreadedIf(LOG_DARWIN_LOG, + "received stream event: " + "OS_ACTIVITY_STREAM_EVENT_STARTED, stream %p.", + (void *)stream); + break; + case OS_ACTIVITY_STREAM_EVENT_STOPPED: + DNBLogThreadedIf(LOG_DARWIN_LOG, + "received stream event: " + "OS_ACTIVITY_STREAM_EVENT_STOPPED, stream %p.", + (void *)stream); + break; + case OS_ACTIVITY_STREAM_EVENT_FAILED: + DNBLogThreadedIf(LOG_DARWIN_LOG, + "received stream event: " + "OS_ACTIVITY_STREAM_EVENT_FAILED, stream %p.", + (void *)stream); + break; + case OS_ACTIVITY_STREAM_EVENT_CHUNK_STARTED: + DNBLogThreadedIf(LOG_DARWIN_LOG, + "received stream event: " + "OS_ACTIVITY_STREAM_EVENT_CHUNK_STARTED, stream %p.", + (void *)stream); + break; + case OS_ACTIVITY_STREAM_EVENT_CHUNK_FINISHED: + DNBLogThreadedIf(LOG_DARWIN_LOG, + "received stream event: " + "OS_ACTIVITY_STREAM_EVENT_CHUNK_FINISHED, stream %p.", + (void *)stream); + break; } + }; - // If the process isn't alive, we're done. - if (!DNBProcessIsAlive(pid)) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "%s() cannot collect for pid %d: process not alive.", - __FUNCTION__, pid); - return false; - } + // Create the stream. + os_activity_stream_t activity_stream = (*s_os_activity_stream_for_pid)( + pid, spi_config.GetActivityStreamFlags(), block); + collector_sp->SetActivityStream(activity_stream); - // Validate the configuration. - auto spi_config = Configuration(config); - if (!spi_config.IsValid()) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, - "%s() invalid configuration, will not enable log " - "collection", __FUNCTION__); - return false; - } + // Specify the stream-related event handler. + (*s_os_activity_stream_set_event_handler)(activity_stream, + stream_event_block); - // Create the stream collector that will manage collected data - // for this pid. - DarwinLogCollectorSP collector_sp(new DarwinLogCollector(pid, - spi_config.GetLogFilterChain())); - std::weak_ptr<DarwinLogCollector> collector_wp(collector_sp); + // Start the stream. + (*s_os_activity_stream_resume)(activity_stream); - // Setup the stream handling block. - os_activity_stream_block_t block = ^bool (os_activity_stream_entry_t entry, - int error) { - // Check if our collector is still alive. - DarwinLogCollectorSP inner_collector_sp = collector_wp.lock(); - if (!inner_collector_sp) - return false; - return inner_collector_sp->HandleStreamEntry(entry, error); - }; - - os_activity_stream_event_block_t stream_event_block = - ^void (os_activity_stream_t stream, os_activity_stream_event_t event) { - switch (event) - { - case OS_ACTIVITY_STREAM_EVENT_STARTED: - DNBLogThreadedIf(LOG_DARWIN_LOG, "received stream event: " - "OS_ACTIVITY_STREAM_EVENT_STARTED, stream %p.", - (void*)stream); - break; - case OS_ACTIVITY_STREAM_EVENT_STOPPED: - DNBLogThreadedIf(LOG_DARWIN_LOG, "received stream event: " - "OS_ACTIVITY_STREAM_EVENT_STOPPED, stream %p.", - (void*)stream); - break; - case OS_ACTIVITY_STREAM_EVENT_FAILED: - DNBLogThreadedIf(LOG_DARWIN_LOG, "received stream event: " - "OS_ACTIVITY_STREAM_EVENT_FAILED, stream %p.", - (void*)stream); - break; - case OS_ACTIVITY_STREAM_EVENT_CHUNK_STARTED: - DNBLogThreadedIf(LOG_DARWIN_LOG, "received stream event: " - "OS_ACTIVITY_STREAM_EVENT_CHUNK_STARTED, stream %p.", - (void*)stream); - break; - case OS_ACTIVITY_STREAM_EVENT_CHUNK_FINISHED: - DNBLogThreadedIf(LOG_DARWIN_LOG, "received stream event: " - "OS_ACTIVITY_STREAM_EVENT_CHUNK_FINISHED, stream %p.", - (void*)stream); - break; - } - }; - - // Create the stream. - os_activity_stream_t activity_stream = - (*s_os_activity_stream_for_pid)(pid, - spi_config.GetActivityStreamFlags(), - block); - collector_sp->SetActivityStream(activity_stream); - - // Specify the stream-related event handler. - (*s_os_activity_stream_set_event_handler)( - activity_stream, stream_event_block); - - // Start the stream. - (*s_os_activity_stream_resume)(activity_stream); - - TrackCollector(collector_sp); - return true; + TrackCollector(collector_sp); + return true; } DarwinLogEventVector -DarwinLogCollector::GetEventsForProcess(nub_process_t pid) -{ - auto collector_sp = FindCollectorForProcess(pid); - if (!collector_sp) - { - // We're not tracking a stream for this process. - return DarwinLogEventVector(); - } - - return collector_sp->RemoveEvents(); +DarwinLogCollector::GetEventsForProcess(nub_process_t pid) { + auto collector_sp = FindCollectorForProcess(pid); + if (!collector_sp) { + // We're not tracking a stream for this process. + return DarwinLogEventVector(); + } + + return collector_sp->RemoveEvents(); } -bool -DarwinLogCollector::CancelStreamForProcess(nub_process_t pid) -{ - auto collector_sp = FindCollectorForProcess(pid); - if (!collector_sp) - { - // We're not tracking a stream for this process. - return false; - } +bool DarwinLogCollector::CancelStreamForProcess(nub_process_t pid) { + auto collector_sp = FindCollectorForProcess(pid); + if (!collector_sp) { + // We're not tracking a stream for this process. + return false; + } - collector_sp->CancelActivityStream(); - StopTrackingCollector(collector_sp); + collector_sp->CancelActivityStream(); + StopTrackingCollector(collector_sp); - return true; + return true; } -const char* -DarwinLogCollector::GetActivityForID(os_activity_id_t activity_id) const -{ - auto find_it = m_activity_map.find(activity_id); - return (find_it != m_activity_map.end()) ? - find_it->second.m_name.c_str() : - nullptr; +const char * +DarwinLogCollector::GetActivityForID(os_activity_id_t activity_id) const { + auto find_it = m_activity_map.find(activity_id); + return (find_it != m_activity_map.end()) ? find_it->second.m_name.c_str() + : nullptr; } /// Retrieve the full parent-child chain for activity names. These /// can be arbitrarily deep. This method assumes the caller has already /// locked the activity mutex. -void -DarwinLogCollector::GetActivityChainForID_internal(os_activity_id_t activity_id, - std::string &result, - size_t depth) const -{ - if (depth > MAX_ACTIVITY_CHAIN_DEPTH) - { - // Terminating condition - too deeply nested. - return; - } - else if (activity_id == 0) - { - // Terminating condition - no activity. - return; - } - - auto find_it = m_activity_map.find(activity_id); - if (find_it == m_activity_map.end()) - { - //Terminating condition - no data for activity_id. - return; - } - - // Activity name becomes parent activity name chain + ':' + our activity - // name. - GetActivityChainForID_internal(find_it->second.m_parent_id, result, - depth + 1); - if (!result.empty()) - result += ':'; - result += find_it->second.m_name; +void DarwinLogCollector::GetActivityChainForID_internal( + os_activity_id_t activity_id, std::string &result, size_t depth) const { + if (depth > MAX_ACTIVITY_CHAIN_DEPTH) { + // Terminating condition - too deeply nested. + return; + } else if (activity_id == 0) { + // Terminating condition - no activity. + return; + } + + auto find_it = m_activity_map.find(activity_id); + if (find_it == m_activity_map.end()) { + // Terminating condition - no data for activity_id. + return; + } + + // Activity name becomes parent activity name chain + ':' + our activity + // name. + GetActivityChainForID_internal(find_it->second.m_parent_id, result, + depth + 1); + if (!result.empty()) + result += ':'; + result += find_it->second.m_name; } std::string -DarwinLogCollector::GetActivityChainForID(os_activity_id_t activity_id) const -{ - std::string result; - { - std::lock_guard<std::mutex> locker(m_activity_info_mutex); - GetActivityChainForID_internal(activity_id, result, 1); - } - return result; +DarwinLogCollector::GetActivityChainForID(os_activity_id_t activity_id) const { + std::string result; + { + std::lock_guard<std::mutex> locker(m_activity_info_mutex); + GetActivityChainForID_internal(activity_id, result, 1); + } + return result; } DarwinLogCollector::DarwinLogCollector(nub_process_t pid, - const LogFilterChainSP &filter_chain_sp): - ActivityStore(), - m_pid(pid), - m_activity_stream(0), - m_events(), - m_events_mutex(), - m_filter_chain_sp(filter_chain_sp), - m_activity_info_mutex(), - m_activity_map() -{ + const LogFilterChainSP &filter_chain_sp) + : ActivityStore(), m_pid(pid), m_activity_stream(0), m_events(), + m_events_mutex(), m_filter_chain_sp(filter_chain_sp), + m_activity_info_mutex(), m_activity_map() {} + +DarwinLogCollector::~DarwinLogCollector() { + // Cancel the stream. + if (m_activity_stream) { + DNBLogThreadedIf(LOG_DARWIN_LOG, "tearing down activity stream " + "collector for %d", + m_pid); + (*s_os_activity_stream_cancel)(m_activity_stream); + m_activity_stream = 0; + } else { + DNBLogThreadedIf(LOG_DARWIN_LOG, "no stream to tear down for %d", m_pid); + } } -DarwinLogCollector::~DarwinLogCollector() -{ - // Cancel the stream. - if (m_activity_stream) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, "tearing down activity stream " - "collector for %d", m_pid); - (*s_os_activity_stream_cancel)(m_activity_stream); - m_activity_stream = 0; - } - else - { - DNBLogThreadedIf(LOG_DARWIN_LOG, "no stream to tear down for %d", - m_pid); - } +void DarwinLogCollector::SignalDataAvailable() { + RNBRemoteSP remoteSP(g_remoteSP); + if (!remoteSP) { + // We're done. This is unexpected. + StopTrackingCollector(shared_from_this()); + return; + } + + RNBContext &ctx = remoteSP->Context(); + ctx.Events().SetEvents(RNBContext::event_darwin_log_data_available); + // Wait for the main thread to consume this notification if it requested + // we wait for it. + ctx.Events().WaitForResetAck(RNBContext::event_darwin_log_data_available); +} + +void DarwinLogCollector::SetActivityStream( + os_activity_stream_t activity_stream) { + m_activity_stream = activity_stream; } -void -DarwinLogCollector::SignalDataAvailable() -{ - RNBRemoteSP remoteSP(g_remoteSP); - if (!remoteSP) - { - // We're done. This is unexpected. - StopTrackingCollector(shared_from_this()); - return; +bool DarwinLogCollector::HandleStreamEntry(os_activity_stream_entry_t entry, + int error) { + if ((error == 0) && (entry != nullptr)) { + if (entry->pid != m_pid) { + // For now, skip messages not originating from our process. + // Later we might want to keep all messages related to an event + // that we're tracking, even when it came from another process, + // possibly doing work on our behalf. + return true; } - RNBContext& ctx = remoteSP->Context(); - ctx.Events().SetEvents(RNBContext::event_darwin_log_data_available); - // Wait for the main thread to consume this notification if it requested - // we wait for it. - ctx.Events().WaitForResetAck(RNBContext::event_darwin_log_data_available); -} + switch (entry->type) { + case OS_ACTIVITY_STREAM_TYPE_ACTIVITY_CREATE: + DNBLogThreadedIf( + LOG_DARWIN_LOG, "received activity create: " + "%s, creator aid %" PRIu64 ", unique_pid %" PRIu64 + "(activity id=%" PRIu64 ", parent id=%" PRIu64 ")", + entry->activity_create.name, entry->activity_create.creator_aid, + entry->activity_create.unique_pid, entry->activity_id, + entry->parent_id); + { + std::lock_guard<std::mutex> locker(m_activity_info_mutex); + m_activity_map.insert( + std::make_pair(entry->activity_id, + ActivityInfo(entry->activity_create.name, + entry->activity_id, entry->parent_id))); + } + break; + + case OS_ACTIVITY_STREAM_TYPE_ACTIVITY_TRANSITION: + DNBLogThreadedIf( + LOG_DARWIN_LOG, "received activity transition:" + "new aid: %" PRIu64 "(activity id=%" PRIu64 + ", parent id=%" PRIu64 ", tid %" PRIu64 ")", + entry->activity_transition.transition_id, entry->activity_id, + entry->parent_id, entry->activity_transition.thread); + break; + + case OS_ACTIVITY_STREAM_TYPE_LOG_MESSAGE: { + DNBLogThreadedIf( + LOG_DARWIN_LOG, "received log message: " + "(activity id=%" PRIu64 ", parent id=%" PRIu64 ", " + "tid %" PRIu64 "): format %s", + entry->activity_id, entry->parent_id, entry->log_message.thread, + entry->log_message.format ? entry->log_message.format + : "<invalid-format>"); + + // Do the real work here. + { + // Ensure our process is still alive. If not, we can + // cancel the collection. + if (!DNBProcessIsAlive(m_pid)) { + // We're outta here. This is the manner in which we + // stop collecting for a process. + StopTrackingCollector(shared_from_this()); + return false; + } -void -DarwinLogCollector::SetActivityStream(os_activity_stream_t activity_stream) -{ - m_activity_stream = activity_stream; -} + LogMessageOsLog os_log_message(*this, *entry); + if (!m_filter_chain_sp || + !m_filter_chain_sp->GetAcceptMessage(os_log_message)) { + // This log message was rejected by the filter, + // so stop processing it now. + return true; + } -bool -DarwinLogCollector::HandleStreamEntry(os_activity_stream_entry_t entry, - int error) -{ - if ((error == 0) && (entry != nullptr)) - { - if (entry->pid != m_pid) - { - // For now, skip messages not originating from our process. - // Later we might want to keep all messages related to an event - // that we're tracking, even when it came from another process, - // possibly doing work on our behalf. - return true; + // Copy over the relevant bits from the message. + const struct os_log_message_s &log_message = entry->log_message; + + DarwinLogEventSP message_sp(new DarwinLogEvent()); + // Indicate this event is a log message event. + message_sp->AddStringItem("type", "log"); + + // Add the message contents (fully expanded). + // Consider expanding on the remote side. + // Then we don't pay for expansion until when it is + // used. + const char *message_text = os_log_message.GetMessage(); + if (message_text) + message_sp->AddStringItem("message", message_text); + + // Add some useful data fields. + message_sp->AddIntegerItem("timestamp", log_message.timestamp); + + // Do we want to do all activity name resolution on this + // side? Maybe. For now, send IDs and ID->name mappings + // and fix this up on that side. Later, when we add + // debugserver-side filtering, we'll want to get the + // activity names over here, so we should probably + // just send them as resolved strings. + message_sp->AddIntegerItem("activity_id", entry->activity_id); + message_sp->AddIntegerItem("parent_id", entry->parent_id); + message_sp->AddIntegerItem("thread_id", log_message.thread); + if (log_message.subsystem && strlen(log_message.subsystem) > 0) + message_sp->AddStringItem("subsystem", log_message.subsystem); + if (log_message.category && strlen(log_message.category) > 0) + message_sp->AddStringItem("category", log_message.category); + if (entry->activity_id != 0) { + std::string activity_chain = + GetActivityChainForID(entry->activity_id); + if (!activity_chain.empty()) + message_sp->AddStringItem("activity-chain", activity_chain); } - switch (entry->type) + // Add it to the list for later collection. { - case OS_ACTIVITY_STREAM_TYPE_ACTIVITY_CREATE: - DNBLogThreadedIf(LOG_DARWIN_LOG, "received activity create: " - "%s, creator aid %" PRIu64 ", unique_pid %" PRIu64 - "(activity id=%" PRIu64 ", parent id=%" PRIu64 ")", - entry->activity_create.name, - entry->activity_create.creator_aid, - entry->activity_create.unique_pid, entry->activity_id, - entry->parent_id - ); - { - std::lock_guard<std::mutex> locker(m_activity_info_mutex); - m_activity_map.insert(std::make_pair( - entry->activity_id, - ActivityInfo( - entry->activity_create.name, - entry->activity_id, - entry->parent_id))); - } - break; - - case OS_ACTIVITY_STREAM_TYPE_ACTIVITY_TRANSITION: - DNBLogThreadedIf(LOG_DARWIN_LOG, "received activity transition:" - "new aid: %" PRIu64 "(activity id=%" PRIu64 - ", parent id=%" PRIu64 ", tid %" PRIu64 ")", - entry->activity_transition.transition_id, - entry->activity_id, entry->parent_id, - entry->activity_transition.thread); - break; - - case OS_ACTIVITY_STREAM_TYPE_LOG_MESSAGE: - { - DNBLogThreadedIf(LOG_DARWIN_LOG, "received log message: " - "(activity id=%" PRIu64 ", parent id=%" PRIu64 ", " - "tid %" PRIu64 "): format %s", - entry->activity_id, entry->parent_id, - entry->log_message.thread, - entry->log_message.format ? entry->log_message.format : - "<invalid-format>"); - - // Do the real work here. - { - // Ensure our process is still alive. If not, we can - // cancel the collection. - if (!DNBProcessIsAlive(m_pid)) - { - // We're outta here. This is the manner in which we - // stop collecting for a process. - StopTrackingCollector(shared_from_this()); - return false; - } - - LogMessageOsLog os_log_message(*this, *entry); - if (!m_filter_chain_sp || - !m_filter_chain_sp->GetAcceptMessage(os_log_message)) - { - // This log message was rejected by the filter, - // so stop processing it now. - return true; - } - - // Copy over the relevant bits from the message. - const struct os_log_message_s &log_message = - entry->log_message; - - DarwinLogEventSP message_sp(new DarwinLogEvent()); - // Indicate this event is a log message event. - message_sp->AddStringItem("type", "log"); - - // Add the message contents (fully expanded). - // Consider expanding on the remote side. - // Then we don't pay for expansion until when it is - // used. - const char *message_text = os_log_message.GetMessage(); - if (message_text) - message_sp->AddStringItem("message", message_text); - - // Add some useful data fields. - message_sp->AddIntegerItem("timestamp", - log_message.timestamp); - - // Do we want to do all activity name resolution on this - // side? Maybe. For now, send IDs and ID->name mappings - // and fix this up on that side. Later, when we add - // debugserver-side filtering, we'll want to get the - // activity names over here, so we should probably - // just send them as resolved strings. - message_sp->AddIntegerItem("activity_id", - entry->activity_id); - message_sp->AddIntegerItem("parent_id", - entry->parent_id); - message_sp->AddIntegerItem("thread_id", - log_message.thread); - if (log_message.subsystem && strlen(log_message.subsystem) - > 0) - message_sp->AddStringItem("subsystem", - log_message.subsystem); - if (log_message.category && strlen(log_message.category) - > 0) - message_sp->AddStringItem("category", - log_message.category); - if (entry->activity_id != 0) - { - std::string activity_chain = - GetActivityChainForID(entry->activity_id); - if (!activity_chain.empty()) - message_sp->AddStringItem("activity-chain", - activity_chain); - } - - // Add it to the list for later collection. - { - std::lock_guard<std::mutex> locker(m_events_mutex); - m_events.push_back(message_sp); - } - SignalDataAvailable(); - } - break; - } + std::lock_guard<std::mutex> locker(m_events_mutex); + m_events.push_back(message_sp); } + SignalDataAvailable(); + } + break; } - else - { - DNBLogThreadedIf(LOG_DARWIN_LOG, "HandleStreamEntry: final call, " - "error %d", error); } - return true; + } else { + DNBLogThreadedIf(LOG_DARWIN_LOG, "HandleStreamEntry: final call, " + "error %d", + error); + } + return true; } -DarwinLogEventVector -DarwinLogCollector::RemoveEvents() -{ - DarwinLogEventVector returned_events; - { - std::lock_guard<std::mutex> locker(m_events_mutex); - returned_events.swap(m_events); - } - DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLogCollector::%s(): removing %lu " - "queued log entries", __FUNCTION__, - returned_events.size()); - return returned_events; +DarwinLogEventVector DarwinLogCollector::RemoveEvents() { + DarwinLogEventVector returned_events; + { + std::lock_guard<std::mutex> locker(m_events_mutex); + returned_events.swap(m_events); + } + DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLogCollector::%s(): removing %lu " + "queued log entries", + __FUNCTION__, returned_events.size()); + return returned_events; } -void -DarwinLogCollector::CancelActivityStream() -{ - if (!m_activity_stream) - return; +void DarwinLogCollector::CancelActivityStream() { + if (!m_activity_stream) + return; - DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLogCollector::%s(): canceling " - "activity stream %p", __FUNCTION__, - m_activity_stream); - (*s_os_activity_stream_cancel)(m_activity_stream); - m_activity_stream = nullptr; + DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLogCollector::%s(): canceling " + "activity stream %p", + __FUNCTION__, m_activity_stream); + (*s_os_activity_stream_cancel)(m_activity_stream); + m_activity_stream = nullptr; } diff --git a/lldb/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.h b/lldb/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.h index 8263423fce1..a7d4e8a774c 100644 --- a/lldb/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.h +++ b/lldb/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogCollector.h @@ -18,122 +18,97 @@ #include "ActivityStore.h" #include "ActivityStreamSPI.h" +#include "DNBDefs.h" #include "DarwinLogEvent.h" #include "DarwinLogInterfaces.h" -#include "DNBDefs.h" #include "JSON.h" class DarwinLogCollector; typedef std::shared_ptr<DarwinLogCollector> DarwinLogCollectorSP; -class DarwinLogCollector: - public std::enable_shared_from_this<DarwinLogCollector>, - public ActivityStore -{ +class DarwinLogCollector + : public std::enable_shared_from_this<DarwinLogCollector>, + public ActivityStore { public: + //------------------------------------------------------------------ + /// Return whether the os_log and activity tracing SPI is available. + /// + /// @return \b true if the activity stream support is available, + /// \b false otherwise. + //------------------------------------------------------------------ + static bool IsSupported(); - //------------------------------------------------------------------ - /// Return whether the os_log and activity tracing SPI is available. - /// - /// @return \b true if the activity stream support is available, - /// \b false otherwise. - //------------------------------------------------------------------ - static bool - IsSupported(); - - //------------------------------------------------------------------ - /// Return a log function suitable for DNBLog to use as the internal - /// logging function. - /// - /// @return a DNBLog-style logging function if IsSupported() returns - /// true; otherwise, returns nullptr. - //------------------------------------------------------------------ - static DNBCallbackLog - GetLogFunction(); + //------------------------------------------------------------------ + /// Return a log function suitable for DNBLog to use as the internal + /// logging function. + /// + /// @return a DNBLog-style logging function if IsSupported() returns + /// true; otherwise, returns nullptr. + //------------------------------------------------------------------ + static DNBCallbackLog GetLogFunction(); - static bool - StartCollectingForProcess(nub_process_t pid, const JSONObject &config); + static bool StartCollectingForProcess(nub_process_t pid, + const JSONObject &config); - static bool - CancelStreamForProcess(nub_process_t pid); + static bool CancelStreamForProcess(nub_process_t pid); - static DarwinLogEventVector - GetEventsForProcess(nub_process_t pid); + static DarwinLogEventVector GetEventsForProcess(nub_process_t pid); - ~DarwinLogCollector(); + ~DarwinLogCollector(); - pid_t - GetProcessID() const - { - return m_pid; - } + pid_t GetProcessID() const { return m_pid; } - //------------------------------------------------------------------ - // ActivityStore API - //------------------------------------------------------------------ - const char* - GetActivityForID(os_activity_id_t activity_id) const override; - - std::string - GetActivityChainForID(os_activity_id_t activity_id) const override; + //------------------------------------------------------------------ + // ActivityStore API + //------------------------------------------------------------------ + const char *GetActivityForID(os_activity_id_t activity_id) const override; + std::string + GetActivityChainForID(os_activity_id_t activity_id) const override; private: + DarwinLogCollector() = delete; + DarwinLogCollector(const DarwinLogCollector &) = delete; + DarwinLogCollector &operator=(const DarwinLogCollector &) = delete; - DarwinLogCollector() = delete; - DarwinLogCollector(const DarwinLogCollector&) = delete; - DarwinLogCollector &operator=(const DarwinLogCollector&) = delete; - - explicit - DarwinLogCollector(nub_process_t pid, - const LogFilterChainSP &filter_chain_sp); + explicit DarwinLogCollector(nub_process_t pid, + const LogFilterChainSP &filter_chain_sp); - void - SignalDataAvailable(); + void SignalDataAvailable(); - void - SetActivityStream(os_activity_stream_t activity_stream); + void SetActivityStream(os_activity_stream_t activity_stream); - bool - HandleStreamEntry(os_activity_stream_entry_t entry, int error); + bool HandleStreamEntry(os_activity_stream_entry_t entry, int error); - DarwinLogEventVector - RemoveEvents(); + DarwinLogEventVector RemoveEvents(); - void - CancelActivityStream(); + void CancelActivityStream(); - void - GetActivityChainForID_internal(os_activity_id_t activity_id, - std::string &result, size_t depth) const; + void GetActivityChainForID_internal(os_activity_id_t activity_id, + std::string &result, size_t depth) const; - struct ActivityInfo - { - ActivityInfo(const char *name, os_activity_id_t activity_id, - os_activity_id_t parent_activity_id) : - m_name(name), - m_id(activity_id), - m_parent_id(parent_activity_id) - { - } + struct ActivityInfo { + ActivityInfo(const char *name, os_activity_id_t activity_id, + os_activity_id_t parent_activity_id) + : m_name(name), m_id(activity_id), m_parent_id(parent_activity_id) {} - const std::string m_name; - const os_activity_id_t m_id; - const os_activity_id_t m_parent_id; - }; + const std::string m_name; + const os_activity_id_t m_id; + const os_activity_id_t m_parent_id; + }; - using ActivityMap = std::unordered_map<os_activity_id_t, ActivityInfo>; + using ActivityMap = std::unordered_map<os_activity_id_t, ActivityInfo>; - const nub_process_t m_pid; - os_activity_stream_t m_activity_stream; - DarwinLogEventVector m_events; - std::mutex m_events_mutex; - LogFilterChainSP m_filter_chain_sp; + const nub_process_t m_pid; + os_activity_stream_t m_activity_stream; + DarwinLogEventVector m_events; + std::mutex m_events_mutex; + LogFilterChainSP m_filter_chain_sp; - /// Mutex to protect activity info (activity name and parent structures) - mutable std::mutex m_activity_info_mutex; - /// Map of activity id to ActivityInfo - ActivityMap m_activity_map; + /// Mutex to protect activity info (activity name and parent structures) + mutable std::mutex m_activity_info_mutex; + /// Map of activity id to ActivityInfo + ActivityMap m_activity_map; }; #endif /* LogStreamCollector_h */ diff --git a/lldb/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogTypes.h b/lldb/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogTypes.h index a090fba0c14..e285e732e56 100644 --- a/lldb/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogTypes.h +++ b/lldb/tools/debugserver/source/MacOSX/DarwinLog/DarwinLogTypes.h @@ -10,14 +10,13 @@ #ifndef DarwinLogTypes_h #define DarwinLogTypes_h -enum FilterTarget -{ - eFilterTargetInvalid, - eFilterTargetActivity, - eFilterTargetActivityChain, - eFilterTargetCategory, - eFilterTargetMessage, - eFilterTargetSubsystem +enum FilterTarget { + eFilterTargetInvalid, + eFilterTargetActivity, + eFilterTargetActivityChain, + eFilterTargetCategory, + eFilterTargetMessage, + eFilterTargetSubsystem }; #endif /* DarwinLogTypes_h */ diff --git a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.cpp b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.cpp index 80af86ec505..d78419d4661 100644 --- a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.cpp +++ b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.cpp @@ -9,6 +9,4 @@ #include "LogFilter.h" -LogFilter::~LogFilter() -{ -} +LogFilter::~LogFilter() {} diff --git a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.h b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.h index 4d54394cb32..92caac29725 100644 --- a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.h +++ b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilter.h @@ -12,33 +12,19 @@ #include "DarwinLogInterfaces.h" -class LogFilter -{ +class LogFilter { public: + virtual ~LogFilter(); - virtual - ~LogFilter(); + virtual bool DoesMatch(const LogMessage &message) const = 0; - virtual bool - DoesMatch(const LogMessage &message) const = 0; - - bool - MatchesAreAccepted() const - { - return m_matches_accept; - } + bool MatchesAreAccepted() const { return m_matches_accept; } protected: - - LogFilter(bool matches_accept) : - m_matches_accept(matches_accept) - { - } + LogFilter(bool matches_accept) : m_matches_accept(matches_accept) {} private: - - bool m_matches_accept; - + bool m_matches_accept; }; #endif /* LogFilter_h */ diff --git a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.cpp b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.cpp index 888fbd9bfb1..12fbe77a906 100644 --- a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.cpp +++ b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.cpp @@ -11,51 +11,32 @@ #include "LogFilter.h" -LogFilterChain::LogFilterChain(bool default_accept) : - m_filters(), - m_default_accept(default_accept) -{ -} +LogFilterChain::LogFilterChain(bool default_accept) + : m_filters(), m_default_accept(default_accept) {} -void -LogFilterChain::AppendFilter(const LogFilterSP &filter_sp) -{ - if (filter_sp) - m_filters.push_back(filter_sp); +void LogFilterChain::AppendFilter(const LogFilterSP &filter_sp) { + if (filter_sp) + m_filters.push_back(filter_sp); } -void -LogFilterChain::ClearFilterChain() -{ - m_filters.clear(); -} +void LogFilterChain::ClearFilterChain() { m_filters.clear(); } -bool -LogFilterChain::GetDefaultAccepts() const -{ - return m_default_accept; -} +bool LogFilterChain::GetDefaultAccepts() const { return m_default_accept; } -void -LogFilterChain::SetDefaultAccepts(bool default_accept) -{ - m_default_accept = default_accept; +void LogFilterChain::SetDefaultAccepts(bool default_accept) { + m_default_accept = default_accept; } -bool -LogFilterChain::GetAcceptMessage(const LogMessage &message) const -{ - for (auto filter_sp : m_filters) - { - if (filter_sp->DoesMatch(message)) - { - // This message matches this filter. If the filter accepts matches, - // this message matches; otherwise, it rejects matches. - return filter_sp->MatchesAreAccepted(); - } +bool LogFilterChain::GetAcceptMessage(const LogMessage &message) const { + for (auto filter_sp : m_filters) { + if (filter_sp->DoesMatch(message)) { + // This message matches this filter. If the filter accepts matches, + // this message matches; otherwise, it rejects matches. + return filter_sp->MatchesAreAccepted(); } + } - // None of the filters matched. Therefore, we do whatever the - // default fall-through rule says. - return m_default_accept; + // None of the filters matched. Therefore, we do whatever the + // default fall-through rule says. + return m_default_accept; } diff --git a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.h b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.h index 8774c15d98c..e4888361e71 100644 --- a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.h +++ b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterChain.h @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - #ifndef LogFilterChain_h #define LogFilterChain_h @@ -15,34 +14,25 @@ #include "DarwinLogInterfaces.h" -class LogFilterChain -{ +class LogFilterChain { public: + LogFilterChain(bool default_accept); - LogFilterChain(bool default_accept); - - void - AppendFilter(const LogFilterSP &filter_sp); + void AppendFilter(const LogFilterSP &filter_sp); - void - ClearFilterChain(); + void ClearFilterChain(); - bool - GetDefaultAccepts() const; + bool GetDefaultAccepts() const; - void - SetDefaultAccepts(bool default_accepts); + void SetDefaultAccepts(bool default_accepts); - bool - GetAcceptMessage(const LogMessage &message) const; + bool GetAcceptMessage(const LogMessage &message) const; private: + using FilterVector = std::vector<LogFilterSP>; - using FilterVector = std::vector<LogFilterSP>; - - FilterVector m_filters; - bool m_default_accept; - + FilterVector m_filters; + bool m_default_accept; }; #endif /* LogFilterChain_hpp */ diff --git a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.cpp b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.cpp index b85458618fd..c8034fe1f22 100644 --- a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.cpp +++ b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.cpp @@ -12,46 +12,38 @@ LogFilterExactMatch::LogFilterExactMatch(bool match_accepts, FilterTarget filter_target, - const std::string &match_text) : - LogFilter(match_accepts), - m_filter_target(filter_target), - m_match_text(match_text) -{ -} + const std::string &match_text) + : LogFilter(match_accepts), m_filter_target(filter_target), + m_match_text(match_text) {} -bool -LogFilterExactMatch::DoesMatch(const LogMessage &message) const -{ - switch (m_filter_target) - { - case eFilterTargetActivity: - // Empty fields never match a condition. - if (!message.HasActivity()) - return false; - return m_match_text == message.GetActivity(); - case eFilterTargetActivityChain: - // Empty fields never match a condition. - if (!message.HasActivity()) - return false; - return m_match_text == message.GetActivityChain(); - case eFilterTargetCategory: - // Empty fields never match a condition. - if (!message.HasCategory()) - return false; - return m_match_text == message.GetCategory(); - case eFilterTargetMessage: - { - const char *message_text = message.GetMessage(); - return (message_text != nullptr) && - (m_match_text == message_text); - } - case eFilterTargetSubsystem: - // Empty fields never match a condition. - if (!message.HasSubsystem()) - return false; - return m_match_text == message.GetSubsystem(); - default: - // We don't know this type. - return false; - } +bool LogFilterExactMatch::DoesMatch(const LogMessage &message) const { + switch (m_filter_target) { + case eFilterTargetActivity: + // Empty fields never match a condition. + if (!message.HasActivity()) + return false; + return m_match_text == message.GetActivity(); + case eFilterTargetActivityChain: + // Empty fields never match a condition. + if (!message.HasActivity()) + return false; + return m_match_text == message.GetActivityChain(); + case eFilterTargetCategory: + // Empty fields never match a condition. + if (!message.HasCategory()) + return false; + return m_match_text == message.GetCategory(); + case eFilterTargetMessage: { + const char *message_text = message.GetMessage(); + return (message_text != nullptr) && (m_match_text == message_text); + } + case eFilterTargetSubsystem: + // Empty fields never match a condition. + if (!message.HasSubsystem()) + return false; + return m_match_text == message.GetSubsystem(); + default: + // We don't know this type. + return false; + } } diff --git a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.h b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.h index 131afaf234b..dd514bc8274 100644 --- a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.h +++ b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterExactMatch.h @@ -16,21 +16,16 @@ #include "DarwinLogTypes.h" #include "LogFilter.h" -class LogFilterExactMatch : public LogFilter -{ +class LogFilterExactMatch : public LogFilter { public: + LogFilterExactMatch(bool match_accepts, FilterTarget filter_target, + const std::string &match_text); - LogFilterExactMatch(bool match_accepts, FilterTarget filter_target, - const std::string &match_text); - - bool - DoesMatch(const LogMessage &message) const override; + bool DoesMatch(const LogMessage &message) const override; private: - - const FilterTarget m_filter_target; - const std::string m_match_text; - + const FilterTarget m_filter_target; + const std::string m_match_text; }; #endif diff --git a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.cpp b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.cpp index 128c7514493..d21ce81c832 100644 --- a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.cpp +++ b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - #include "LogFilterRegex.h" #include "DNBLog.h" @@ -19,100 +18,80 @@ // everywhere. //---------------------------------------------------------------------- #if defined(REG_ENHANCED) -#define DEFAULT_COMPILE_FLAGS (REG_ENHANCED|REG_EXTENDED) +#define DEFAULT_COMPILE_FLAGS (REG_ENHANCED | REG_EXTENDED) #else #define DEFAULT_COMPILE_FLAGS (REG_EXTENDED) #endif -LogFilterRegex::LogFilterRegex(bool match_accepts, - FilterTarget filter_target, - const std::string ®ex) : - LogFilter(match_accepts), - m_filter_target(filter_target), - m_regex_text(regex), - m_regex(), - m_is_valid(false), - m_error_text() -{ - // Clear it. - memset(&m_regex, 0, sizeof(m_regex)); +LogFilterRegex::LogFilterRegex(bool match_accepts, FilterTarget filter_target, + const std::string ®ex) + : LogFilter(match_accepts), m_filter_target(filter_target), + m_regex_text(regex), m_regex(), m_is_valid(false), m_error_text() { + // Clear it. + memset(&m_regex, 0, sizeof(m_regex)); - // Compile it. - if (!regex.empty()) - { - auto comp_err = ::regcomp(&m_regex, regex.c_str(), - DEFAULT_COMPILE_FLAGS); - m_is_valid = (comp_err == 0); - if (!m_is_valid) - { - char buffer[256]; - buffer[0] = '\0'; - ::regerror(comp_err, &m_regex, buffer, sizeof(buffer)); - m_error_text = buffer; - } + // Compile it. + if (!regex.empty()) { + auto comp_err = ::regcomp(&m_regex, regex.c_str(), DEFAULT_COMPILE_FLAGS); + m_is_valid = (comp_err == 0); + if (!m_is_valid) { + char buffer[256]; + buffer[0] = '\0'; + ::regerror(comp_err, &m_regex, buffer, sizeof(buffer)); + m_error_text = buffer; } + } } -LogFilterRegex::~LogFilterRegex() -{ - if (m_is_valid) - { - // Free the regex internals. - regfree(&m_regex); - } +LogFilterRegex::~LogFilterRegex() { + if (m_is_valid) { + // Free the regex internals. + regfree(&m_regex); + } } -bool -LogFilterRegex::DoesMatch(const LogMessage &message) const -{ - switch (m_filter_target) - { - case eFilterTargetActivity: - // Empty fields never match a condition. - if (!message.HasActivity()) - return false; - return ::regexec(&m_regex, message.GetActivity(), 0, nullptr, 0) - == 0; - case eFilterTargetActivityChain: - // Empty fields never match a condition. - if (!message.HasActivity()) - return false; - return ::regexec(&m_regex, message.GetActivityChain().c_str(), 0, - nullptr, 0) == 0; - case eFilterTargetCategory: - // Empty fields never match a condition. - if (!message.HasCategory()) - return false; - return ::regexec(&m_regex, message.GetCategory(), 0, nullptr, - 0) == 0; - case eFilterTargetMessage: - { - const char *message_text = message.GetMessage(); - if (!message_text) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, "LogFilterRegex: regex " - "\"%s\" no match due to nullptr message.", - m_regex_text.c_str()); - return false; - } - - bool match = ::regexec(&m_regex, message_text, 0, - nullptr, 0) == 0; - DNBLogThreadedIf(LOG_DARWIN_LOG, "LogFilterRegex: regex " - "\"%s\" %s message \"%s\".", - m_regex_text.c_str(), - match ? "matches" : "does not match", - message_text); - return match; - } - case eFilterTargetSubsystem: - // Empty fields never match a condition. - if (!message.HasSubsystem()) - return false; - return ::regexec(&m_regex, message.GetSubsystem(), 0, nullptr, - 0) == 0; - default: - // We don't know this type. - return false; +bool LogFilterRegex::DoesMatch(const LogMessage &message) const { + switch (m_filter_target) { + case eFilterTargetActivity: + // Empty fields never match a condition. + if (!message.HasActivity()) + return false; + return ::regexec(&m_regex, message.GetActivity(), 0, nullptr, 0) == 0; + case eFilterTargetActivityChain: + // Empty fields never match a condition. + if (!message.HasActivity()) + return false; + return ::regexec(&m_regex, message.GetActivityChain().c_str(), 0, nullptr, + 0) == 0; + case eFilterTargetCategory: + // Empty fields never match a condition. + if (!message.HasCategory()) + return false; + return ::regexec(&m_regex, message.GetCategory(), 0, nullptr, 0) == 0; + case eFilterTargetMessage: { + const char *message_text = message.GetMessage(); + if (!message_text) { + DNBLogThreadedIf(LOG_DARWIN_LOG, + "LogFilterRegex: regex " + "\"%s\" no match due to nullptr message.", + m_regex_text.c_str()); + return false; } + + bool match = ::regexec(&m_regex, message_text, 0, nullptr, 0) == 0; + DNBLogThreadedIf(LOG_DARWIN_LOG, "LogFilterRegex: regex " + "\"%s\" %s message \"%s\".", + m_regex_text.c_str(), match ? "matches" : "does not match", + message_text); + return match; + } + case eFilterTargetSubsystem: + // Empty fields never match a condition. + if (!message.HasSubsystem()) + return false; + return ::regexec(&m_regex, message.GetSubsystem(), 0, nullptr, 0) == 0; + default: + // We don't know this type. + return false; + } } diff --git a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.h b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.h index 796a62500ff..4a5939217f0 100644 --- a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.h +++ b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.h @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - #ifndef LogFilterRegex_h #define LogFilterRegex_h @@ -21,38 +20,25 @@ #include "DarwinLogTypes.h" #include "LogFilter.h" -class LogFilterRegex : public LogFilter -{ +class LogFilterRegex : public LogFilter { public: + LogFilterRegex(bool match_accepts, FilterTarget filter_target, + const std::string ®ex); - LogFilterRegex(bool match_accepts, FilterTarget filter_target, - const std::string ®ex); - - virtual - ~LogFilterRegex(); + virtual ~LogFilterRegex(); - bool - IsValid() const - { - return m_is_valid; - } + bool IsValid() const { return m_is_valid; } - const char* - GetErrorAsCString() const - { - return m_error_text.c_str(); - } + const char *GetErrorAsCString() const { return m_error_text.c_str(); } - bool - DoesMatch(const LogMessage &message) const override; + bool DoesMatch(const LogMessage &message) const override; private: - - const FilterTarget m_filter_target; - const std::string m_regex_text; - regex_t m_regex; - bool m_is_valid; - std::string m_error_text; + const FilterTarget m_filter_target; + const std::string m_regex_text; + regex_t m_regex; + bool m_is_valid; + std::string m_error_text; }; #endif /* LogFilterSubsystemRegex_hpp */ diff --git a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.cpp b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.cpp index d98bb3de3c1..5a31087f231 100644 --- a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.cpp +++ b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.cpp @@ -7,13 +7,8 @@ // //===----------------------------------------------------------------------===// - #include "LogMessage.h" -LogMessage::LogMessage() -{ -} +LogMessage::LogMessage() {} -LogMessage::~LogMessage() -{ -} +LogMessage::~LogMessage() {} diff --git a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.h b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.h index 0ec2b4277a4..bbc975133ec 100644 --- a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.h +++ b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogMessage.h @@ -12,42 +12,29 @@ #include <string> -class LogMessage -{ +class LogMessage { public: + virtual ~LogMessage(); - virtual - ~LogMessage(); + virtual bool HasActivity() const = 0; - virtual bool - HasActivity() const = 0; + virtual const char *GetActivity() const = 0; - virtual const char* - GetActivity() const = 0; + virtual std::string GetActivityChain() const = 0; - virtual std::string - GetActivityChain() const = 0; + virtual bool HasCategory() const = 0; - virtual bool - HasCategory() const = 0; + virtual const char *GetCategory() const = 0; - virtual const char* - GetCategory() const = 0; + virtual bool HasSubsystem() const = 0; - virtual bool - HasSubsystem() const = 0; + virtual const char *GetSubsystem() const = 0; - virtual const char* - GetSubsystem() const = 0; - - // This can be expensive, so once we ask for it, we'll cache the result. - virtual const char* - GetMessage() const = 0; + // This can be expensive, so once we ask for it, we'll cache the result. + virtual const char *GetMessage() const = 0; protected: - - LogMessage(); - + LogMessage(); }; #endif /* LogMessage_h */ diff --git a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.cpp b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.cpp index f3b6e443918..91347eaf12c 100644 --- a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.cpp +++ b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.cpp @@ -12,84 +12,57 @@ #include "ActivityStore.h" #include "ActivityStreamSPI.h" -namespace -{ - static os_log_copy_formatted_message_t s_log_copy_formatted_message; +namespace { +static os_log_copy_formatted_message_t s_log_copy_formatted_message; } -void -LogMessageOsLog::SetFormatterFunction(os_log_copy_formatted_message_t - format_func) -{ - s_log_copy_formatted_message = format_func; +void LogMessageOsLog::SetFormatterFunction( + os_log_copy_formatted_message_t format_func) { + s_log_copy_formatted_message = format_func; } LogMessageOsLog::LogMessageOsLog(const ActivityStore &activity_store, - ActivityStreamEntry &entry) : - LogMessage(), - m_activity_store(activity_store), - m_entry(entry), - m_message() -{ -} + ActivityStreamEntry &entry) + : LogMessage(), m_activity_store(activity_store), m_entry(entry), + m_message() {} -bool -LogMessageOsLog::HasActivity() const -{ - return m_entry.activity_id != 0; -} +bool LogMessageOsLog::HasActivity() const { return m_entry.activity_id != 0; } -const char* -LogMessageOsLog::GetActivity() const -{ - return m_activity_store.GetActivityForID(m_entry.activity_id); +const char *LogMessageOsLog::GetActivity() const { + return m_activity_store.GetActivityForID(m_entry.activity_id); } -std::string -LogMessageOsLog::GetActivityChain() const -{ - return m_activity_store.GetActivityChainForID(m_entry.activity_id); +std::string LogMessageOsLog::GetActivityChain() const { + return m_activity_store.GetActivityChainForID(m_entry.activity_id); } -bool -LogMessageOsLog::HasCategory() const -{ - return m_entry.log_message.category && - (m_entry.log_message.category[0] != 0); +bool LogMessageOsLog::HasCategory() const { + return m_entry.log_message.category && (m_entry.log_message.category[0] != 0); } -const char* -LogMessageOsLog::GetCategory() const -{ - return m_entry.log_message.category; +const char *LogMessageOsLog::GetCategory() const { + return m_entry.log_message.category; } -bool -LogMessageOsLog::HasSubsystem() const -{ - return m_entry.log_message.subsystem && - (m_entry.log_message.subsystem[0] != 0); +bool LogMessageOsLog::HasSubsystem() const { + return m_entry.log_message.subsystem && + (m_entry.log_message.subsystem[0] != 0); } -const char* -LogMessageOsLog::GetSubsystem() const -{ - return m_entry.log_message.subsystem; +const char *LogMessageOsLog::GetSubsystem() const { + return m_entry.log_message.subsystem; } -const char* -LogMessageOsLog::GetMessage() const -{ - if (m_message.empty()) - { - std::unique_ptr<char[]> formatted_message( - s_log_copy_formatted_message(&m_entry.log_message)); - if (formatted_message) - m_message = formatted_message.get(); - // else - // TODO log - } +const char *LogMessageOsLog::GetMessage() const { + if (m_message.empty()) { + std::unique_ptr<char[]> formatted_message( + s_log_copy_formatted_message(&m_entry.log_message)); + if (formatted_message) + m_message = formatted_message.get(); + // else + // TODO log + } - // This is safe to return as we're not modifying it once we've formatted it. - return m_message.c_str(); + // This is safe to return as we're not modifying it once we've formatted it. + return m_message.c_str(); } diff --git a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.h b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.h index 7c02059fc57..18103e03159 100644 --- a/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.h +++ b/lldb/tools/debugserver/source/MacOSX/DarwinLog/LogMessageOsLog.h @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - #ifndef LogMessageOsLog_h #define LogMessageOsLog_h @@ -26,48 +25,35 @@ using ActivityStreamEntry = struct os_activity_stream_entry_s; /// outlive this LogMessageOsLog entry. // ----------------------------------------------------------------------------- -class LogMessageOsLog : public LogMessage -{ +class LogMessageOsLog : public LogMessage { public: + static void SetFormatterFunction(os_log_copy_formatted_message_t format_func); - static void - SetFormatterFunction(os_log_copy_formatted_message_t format_func); - - LogMessageOsLog(const ActivityStore &activity_store, - ActivityStreamEntry &entry); + LogMessageOsLog(const ActivityStore &activity_store, + ActivityStreamEntry &entry); - // API methods + // API methods - bool - HasActivity() const override; + bool HasActivity() const override; - const char* - GetActivity() const override; + const char *GetActivity() const override; - std::string - GetActivityChain() const override; + std::string GetActivityChain() const override; - bool - HasCategory() const override; + bool HasCategory() const override; - const char* - GetCategory() const override; + const char *GetCategory() const override; - bool - HasSubsystem() const override; + bool HasSubsystem() const override; - const char* - GetSubsystem() const override; + const char *GetSubsystem() const override; - const char* - GetMessage() const override; + const char *GetMessage() const override; private: - - const ActivityStore &m_activity_store; - ActivityStreamEntry &m_entry; - mutable std::string m_message; - + const ActivityStore &m_activity_store; + ActivityStreamEntry &m_entry; + mutable std::string m_message; }; #endif /* LogMessageOsLog_h */ diff --git a/lldb/tools/debugserver/source/MacOSX/Genealogy.cpp b/lldb/tools/debugserver/source/MacOSX/Genealogy.cpp index a5ee097aa2a..22ff52abaa4 100644 --- a/lldb/tools/debugserver/source/MacOSX/Genealogy.cpp +++ b/lldb/tools/debugserver/source/MacOSX/Genealogy.cpp @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// #include <Availability.h> -#include <string> #include <dlfcn.h> +#include <string> #include <uuid/uuid.h> #include "DNBDefs.h" @@ -21,280 +21,299 @@ /// Constructor //--------------------------- -Genealogy::Genealogy () : - m_os_activity_diagnostic_for_pid (nullptr), - m_os_activity_iterate_processes (nullptr), - m_os_activity_iterate_breadcrumbs (nullptr), - m_os_activity_iterate_messages (nullptr), - m_os_activity_iterate_activities (nullptr), - m_os_trace_get_type (nullptr), - m_os_trace_copy_formatted_message (nullptr), - m_os_activity_for_thread (nullptr), - m_os_activity_for_task_thread (nullptr), - m_thread_activities(), - m_process_executable_infos(), - m_diagnosticd_call_timed_out(false) -{ - m_os_activity_diagnostic_for_pid = (bool (*)(pid_t, os_activity_t, uint32_t, os_diagnostic_block_t))dlsym (RTLD_DEFAULT, "os_activity_diagnostic_for_pid"); - m_os_activity_iterate_processes = (void (*)(os_activity_process_list_t, bool (^)(os_activity_process_t)))dlsym (RTLD_DEFAULT, "os_activity_iterate_processes"); - m_os_activity_iterate_breadcrumbs = (void (*)(os_activity_process_t, bool (^)(os_activity_breadcrumb_t))) dlsym (RTLD_DEFAULT, "os_activity_iterate_breadcrumbs"); - m_os_activity_iterate_messages = (void (*)(os_trace_message_list_t, os_activity_process_t, bool (^)(os_trace_message_t)))dlsym (RTLD_DEFAULT, "os_activity_iterate_messages"); - m_os_activity_iterate_activities = (void (*)(os_activity_list_t, os_activity_process_t, bool (^)(os_activity_entry_t)))dlsym (RTLD_DEFAULT, "os_activity_iterate_activities"); - m_os_trace_get_type = (uint8_t (*)(os_trace_message_t)) dlsym (RTLD_DEFAULT, "os_trace_get_type"); - m_os_trace_copy_formatted_message = (char *(*)(os_trace_message_t)) dlsym (RTLD_DEFAULT, "os_trace_copy_formatted_message"); - m_os_activity_for_thread = (os_activity_t (*)(os_activity_process_t, uint64_t)) dlsym (RTLD_DEFAULT, "os_activity_for_thread"); - m_os_activity_for_task_thread = (os_activity_t (*)(task_t, uint64_t)) dlsym (RTLD_DEFAULT, "os_activity_for_task_thread"); - m_os_activity_messages_for_thread = (os_trace_message_list_t (*) (os_activity_process_t process, os_activity_t activity, uint64_t thread_id)) dlsym (RTLD_DEFAULT, "os_activity_messages_for_thread"); +Genealogy::Genealogy() + : m_os_activity_diagnostic_for_pid(nullptr), + m_os_activity_iterate_processes(nullptr), + m_os_activity_iterate_breadcrumbs(nullptr), + m_os_activity_iterate_messages(nullptr), + m_os_activity_iterate_activities(nullptr), m_os_trace_get_type(nullptr), + m_os_trace_copy_formatted_message(nullptr), + m_os_activity_for_thread(nullptr), m_os_activity_for_task_thread(nullptr), + m_thread_activities(), m_process_executable_infos(), + m_diagnosticd_call_timed_out(false) { + m_os_activity_diagnostic_for_pid = + (bool (*)(pid_t, os_activity_t, uint32_t, os_diagnostic_block_t))dlsym( + RTLD_DEFAULT, "os_activity_diagnostic_for_pid"); + m_os_activity_iterate_processes = + (void (*)(os_activity_process_list_t, bool (^)(os_activity_process_t))) + dlsym(RTLD_DEFAULT, "os_activity_iterate_processes"); + m_os_activity_iterate_breadcrumbs = + (void (*)(os_activity_process_t, bool (^)(os_activity_breadcrumb_t))) + dlsym(RTLD_DEFAULT, "os_activity_iterate_breadcrumbs"); + m_os_activity_iterate_messages = (void (*)( + os_trace_message_list_t, os_activity_process_t, + bool (^)(os_trace_message_t)))dlsym(RTLD_DEFAULT, + "os_activity_iterate_messages"); + m_os_activity_iterate_activities = (void (*)( + os_activity_list_t, os_activity_process_t, + bool (^)(os_activity_entry_t)))dlsym(RTLD_DEFAULT, + "os_activity_iterate_activities"); + m_os_trace_get_type = + (uint8_t(*)(os_trace_message_t))dlsym(RTLD_DEFAULT, "os_trace_get_type"); + m_os_trace_copy_formatted_message = (char *(*)(os_trace_message_t))dlsym( + RTLD_DEFAULT, "os_trace_copy_formatted_message"); + m_os_activity_for_thread = + (os_activity_t(*)(os_activity_process_t, uint64_t))dlsym( + RTLD_DEFAULT, "os_activity_for_thread"); + m_os_activity_for_task_thread = (os_activity_t(*)(task_t, uint64_t))dlsym( + RTLD_DEFAULT, "os_activity_for_task_thread"); + m_os_activity_messages_for_thread = (os_trace_message_list_t(*)( + os_activity_process_t process, os_activity_t activity, + uint64_t thread_id))dlsym(RTLD_DEFAULT, + "os_activity_messages_for_thread"); } Genealogy::ThreadActivitySP -Genealogy::GetGenealogyInfoForThread (pid_t pid, nub_thread_t tid, const MachThreadList &thread_list, task_t task, bool &timed_out) -{ - ThreadActivitySP activity; - // - // if we've timed out trying to get the activities, don't try again at this process stop. - // (else we'll need to hit the timeout for every thread we're asked about.) - // We'll try again at the next public stop. +Genealogy::GetGenealogyInfoForThread(pid_t pid, nub_thread_t tid, + const MachThreadList &thread_list, + task_t task, bool &timed_out) { + ThreadActivitySP activity; + // + // if we've timed out trying to get the activities, don't try again at this + // process stop. + // (else we'll need to hit the timeout for every thread we're asked about.) + // We'll try again at the next public stop. - if (m_thread_activities.size() == 0 && m_diagnosticd_call_timed_out == false) - { - GetActivities(pid, thread_list, task); - } - std::map<nub_thread_t, ThreadActivitySP>::const_iterator search; - search = m_thread_activities.find(tid); - if (search != m_thread_activities.end()) - { - activity = search->second; - } - timed_out = m_diagnosticd_call_timed_out; - return activity; + if (m_thread_activities.size() == 0 && + m_diagnosticd_call_timed_out == false) { + GetActivities(pid, thread_list, task); + } + std::map<nub_thread_t, ThreadActivitySP>::const_iterator search; + search = m_thread_activities.find(tid); + if (search != m_thread_activities.end()) { + activity = search->second; + } + timed_out = m_diagnosticd_call_timed_out; + return activity; } -void -Genealogy::Clear() -{ - m_thread_activities.clear(); - m_diagnosticd_call_timed_out = false; +void Genealogy::Clear() { + m_thread_activities.clear(); + m_diagnosticd_call_timed_out = false; } -void -Genealogy::GetActivities(pid_t pid, const MachThreadList &thread_list, task_t task) -{ - if (m_os_activity_diagnostic_for_pid != nullptr - && m_os_activity_iterate_processes != nullptr - && m_os_activity_iterate_breadcrumbs != nullptr - && m_os_activity_iterate_messages != nullptr - && m_os_activity_iterate_activities != nullptr - && m_os_trace_get_type != nullptr - && m_os_trace_copy_formatted_message != nullptr - && (m_os_activity_for_thread != nullptr || m_os_activity_for_task_thread != nullptr) - ) - { - __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); - __block BreadcrumbList breadcrumbs; - __block ActivityList activities; - __block MessageList messages; - __block std::map<nub_thread_t, uint64_t> thread_activity_mapping; +void Genealogy::GetActivities(pid_t pid, const MachThreadList &thread_list, + task_t task) { + if (m_os_activity_diagnostic_for_pid != nullptr && + m_os_activity_iterate_processes != nullptr && + m_os_activity_iterate_breadcrumbs != nullptr && + m_os_activity_iterate_messages != nullptr && + m_os_activity_iterate_activities != nullptr && + m_os_trace_get_type != nullptr && + m_os_trace_copy_formatted_message != nullptr && + (m_os_activity_for_thread != nullptr || + m_os_activity_for_task_thread != nullptr)) { + __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + __block BreadcrumbList breadcrumbs; + __block ActivityList activities; + __block MessageList messages; + __block std::map<nub_thread_t, uint64_t> thread_activity_mapping; - os_activity_diagnostic_flag_t flags = OS_ACTIVITY_DIAGNOSTIC_ALL_ACTIVITIES | OS_ACTIVITY_DIAGNOSTIC_PROCESS_ONLY; - if (m_os_activity_diagnostic_for_pid (pid, 0, flags, ^(os_activity_process_list_t processes, int error) - { - if (error == 0) - { - m_os_activity_iterate_processes (processes, ^bool(os_activity_process_t process_info) - { - if (pid == process_info->pid) - { - // Collect all the Breadcrumbs - m_os_activity_iterate_breadcrumbs (process_info, ^bool(os_activity_breadcrumb_t breadcrumb) - { - Breadcrumb bc; - bc.breadcrumb_id = breadcrumb->breadcrumb_id; - bc.activity_id = breadcrumb->activity_id; - bc.timestamp = breadcrumb->timestamp; - if (breadcrumb->name) - bc.name = breadcrumb->name; - breadcrumbs.push_back (bc); - return true; + os_activity_diagnostic_flag_t flags = + OS_ACTIVITY_DIAGNOSTIC_ALL_ACTIVITIES | + OS_ACTIVITY_DIAGNOSTIC_PROCESS_ONLY; + if (m_os_activity_diagnostic_for_pid( + pid, 0, flags, ^(os_activity_process_list_t processes, int error) { + if (error == 0) { + m_os_activity_iterate_processes(processes, ^bool( + os_activity_process_t + process_info) { + if (pid == process_info->pid) { + // Collect all the Breadcrumbs + m_os_activity_iterate_breadcrumbs( + process_info, + ^bool(os_activity_breadcrumb_t breadcrumb) { + Breadcrumb bc; + bc.breadcrumb_id = breadcrumb->breadcrumb_id; + bc.activity_id = breadcrumb->activity_id; + bc.timestamp = breadcrumb->timestamp; + if (breadcrumb->name) + bc.name = breadcrumb->name; + breadcrumbs.push_back(bc); + return true; }); - // Collect all the Activites - m_os_activity_iterate_activities (process_info->activities, process_info, ^bool(os_activity_entry_t activity) - { - Activity ac; - ac.activity_start = activity->activity_start; - ac.activity_id = activity->activity_id; - ac.parent_id = activity->parent_id; - if (activity->activity_name) - ac.activity_name = activity->activity_name; - if (activity->reason) - ac.reason = activity->reason; - activities.push_back (ac); - return true; + // Collect all the Activites + m_os_activity_iterate_activities( + process_info->activities, process_info, + ^bool(os_activity_entry_t activity) { + Activity ac; + ac.activity_start = activity->activity_start; + ac.activity_id = activity->activity_id; + ac.parent_id = activity->parent_id; + if (activity->activity_name) + ac.activity_name = activity->activity_name; + if (activity->reason) + ac.reason = activity->reason; + activities.push_back(ac); + return true; }); - - // Collect all the Messages -- messages not associated with any thread - m_os_activity_iterate_messages (process_info->messages, process_info, ^bool(os_trace_message_t trace_msg) - { - Message msg; - msg.timestamp = trace_msg->timestamp; - msg.trace_id = trace_msg->trace_id; - msg.thread = trace_msg->thread; - msg.type = m_os_trace_get_type (trace_msg); - msg.activity_id = 0; - if (trace_msg->image_uuid && trace_msg->image_path) - { - ProcessExecutableInfoSP process_info_sp (new ProcessExecutableInfo()); - uuid_copy (process_info_sp->image_uuid, trace_msg->image_uuid); - process_info_sp->image_path = trace_msg->image_path; - msg.process_info_index = AddProcessExecutableInfo (process_info_sp); - } - const char *message_text = m_os_trace_copy_formatted_message (trace_msg); - if (message_text) - msg.message = message_text; - messages.push_back (msg); - return true; + // Collect all the Messages -- messages not associated with + // any thread + m_os_activity_iterate_messages( + process_info->messages, process_info, + ^bool(os_trace_message_t trace_msg) { + Message msg; + msg.timestamp = trace_msg->timestamp; + msg.trace_id = trace_msg->trace_id; + msg.thread = trace_msg->thread; + msg.type = m_os_trace_get_type(trace_msg); + msg.activity_id = 0; + if (trace_msg->image_uuid && trace_msg->image_path) { + ProcessExecutableInfoSP process_info_sp( + new ProcessExecutableInfo()); + uuid_copy(process_info_sp->image_uuid, + trace_msg->image_uuid); + process_info_sp->image_path = trace_msg->image_path; + msg.process_info_index = + AddProcessExecutableInfo(process_info_sp); + } + const char *message_text = + m_os_trace_copy_formatted_message(trace_msg); + if (message_text) + msg.message = message_text; + messages.push_back(msg); + return true; }); - // Discover which activities are said to be running on threads currently - const nub_size_t num_threads = thread_list.NumThreads(); - for (nub_size_t i = 0; i < num_threads; ++i) - { - nub_thread_t thread_id = thread_list.ThreadIDAtIndex(i); - os_activity_t act = 0; - if (m_os_activity_for_task_thread != nullptr) - { - act = m_os_activity_for_task_thread (task, thread_id); - } - else if (m_os_activity_for_thread != nullptr) - { - act = m_os_activity_for_thread (process_info, thread_id); - } - if (act != 0) - thread_activity_mapping[thread_id] = act; - } + // Discover which activities are said to be running on + // threads currently + const nub_size_t num_threads = thread_list.NumThreads(); + for (nub_size_t i = 0; i < num_threads; ++i) { + nub_thread_t thread_id = thread_list.ThreadIDAtIndex(i); + os_activity_t act = 0; + if (m_os_activity_for_task_thread != nullptr) { + act = m_os_activity_for_task_thread(task, thread_id); + } else if (m_os_activity_for_thread != nullptr) { + act = m_os_activity_for_thread(process_info, thread_id); + } + if (act != 0) + thread_activity_mapping[thread_id] = act; + } - // Collect all Messages -- messages associated with a thread + // Collect all Messages -- messages associated with a thread - // When there's no genealogy information, an early version of os_activity_messages_for_thread - // can crash in rare circumstances. Check to see if this process has any activities before - // making the call to get messages. - if (process_info->activities != nullptr && thread_activity_mapping.size() > 0) - { - std::map<nub_thread_t, uint64_t>::const_iterator iter; - for (iter = thread_activity_mapping.begin(); iter != thread_activity_mapping.end(); ++iter) - { - nub_thread_t thread_id = iter->first; - os_activity_t act = iter->second; - os_trace_message_list_t this_thread_messages = m_os_activity_messages_for_thread (process_info, act, thread_id); - m_os_activity_iterate_messages (this_thread_messages, process_info, ^bool(os_trace_message_t trace_msg) - { - Message msg; - msg.timestamp = trace_msg->timestamp; - msg.trace_id = trace_msg->trace_id; - msg.thread = trace_msg->thread; - msg.type = m_os_trace_get_type (trace_msg); - msg.activity_id = act; - if (trace_msg->image_uuid && trace_msg->image_path) - { - ProcessExecutableInfoSP process_info_sp (new ProcessExecutableInfo()); - uuid_copy (process_info_sp->image_uuid, trace_msg->image_uuid); - process_info_sp->image_path = trace_msg->image_path; - msg.process_info_index = AddProcessExecutableInfo (process_info_sp); - } - const char *message_text = m_os_trace_copy_formatted_message (trace_msg); - if (message_text) - msg.message = message_text; - messages.push_back (msg); - return true; - }); - } - } + // When there's no genealogy information, an early version + // of os_activity_messages_for_thread + // can crash in rare circumstances. Check to see if this + // process has any activities before + // making the call to get messages. + if (process_info->activities != nullptr && + thread_activity_mapping.size() > 0) { + std::map<nub_thread_t, uint64_t>::const_iterator iter; + for (iter = thread_activity_mapping.begin(); + iter != thread_activity_mapping.end(); ++iter) { + nub_thread_t thread_id = iter->first; + os_activity_t act = iter->second; + os_trace_message_list_t this_thread_messages = + m_os_activity_messages_for_thread(process_info, act, + thread_id); + m_os_activity_iterate_messages( + this_thread_messages, process_info, + ^bool(os_trace_message_t trace_msg) { + Message msg; + msg.timestamp = trace_msg->timestamp; + msg.trace_id = trace_msg->trace_id; + msg.thread = trace_msg->thread; + msg.type = m_os_trace_get_type(trace_msg); + msg.activity_id = act; + if (trace_msg->image_uuid && + trace_msg->image_path) { + ProcessExecutableInfoSP process_info_sp( + new ProcessExecutableInfo()); + uuid_copy(process_info_sp->image_uuid, + trace_msg->image_uuid); + process_info_sp->image_path = + trace_msg->image_path; + msg.process_info_index = + AddProcessExecutableInfo(process_info_sp); + } + const char *message_text = + m_os_trace_copy_formatted_message(trace_msg); + if (message_text) + msg.message = message_text; + messages.push_back(msg); + return true; + }); + } } - return true; + } + return true; }); - } - dispatch_semaphore_signal(semaphore); - }) == true) - { - // Wait for the diagnosticd xpc calls to all finish up -- or half a second to elapse. - dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC / 2); - bool success = dispatch_semaphore_wait(semaphore, timeout) == 0; - if (!success) - { - m_diagnosticd_call_timed_out = true; - return; - } - } + } + dispatch_semaphore_signal(semaphore); + }) == true) { + // Wait for the diagnosticd xpc calls to all finish up -- or half a second + // to elapse. + dispatch_time_t timeout = + dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC / 2); + bool success = dispatch_semaphore_wait(semaphore, timeout) == 0; + if (!success) { + m_diagnosticd_call_timed_out = true; + return; + } + } - // breadcrumbs, activities, and messages have all now been filled in. + // breadcrumbs, activities, and messages have all now been filled in. - std::map<nub_thread_t, uint64_t>::const_iterator iter; - for (iter = thread_activity_mapping.begin(); iter != thread_activity_mapping.end(); ++iter) - { - nub_thread_t thread_id = iter->first; - uint64_t activity_id = iter->second; - ActivityList::const_iterator activity_search; - for (activity_search = activities.begin(); activity_search != activities.end(); ++activity_search) - { - if (activity_search->activity_id == activity_id) - { - ThreadActivitySP thread_activity_sp (new ThreadActivity()); - thread_activity_sp->current_activity = *activity_search; - - BreadcrumbList::const_iterator breadcrumb_search; - for (breadcrumb_search = breadcrumbs.begin(); breadcrumb_search != breadcrumbs.end(); ++breadcrumb_search) - { - if (breadcrumb_search->activity_id == activity_id) - { - thread_activity_sp->breadcrumbs.push_back (*breadcrumb_search); - } - } - MessageList::const_iterator message_search; - for (message_search = messages.begin(); message_search != messages.end(); ++message_search) - { - if (message_search->thread == thread_id) - { - thread_activity_sp->messages.push_back (*message_search); - } - } - - m_thread_activities[thread_id] = thread_activity_sp; - break; - } + std::map<nub_thread_t, uint64_t>::const_iterator iter; + for (iter = thread_activity_mapping.begin(); + iter != thread_activity_mapping.end(); ++iter) { + nub_thread_t thread_id = iter->first; + uint64_t activity_id = iter->second; + ActivityList::const_iterator activity_search; + for (activity_search = activities.begin(); + activity_search != activities.end(); ++activity_search) { + if (activity_search->activity_id == activity_id) { + ThreadActivitySP thread_activity_sp(new ThreadActivity()); + thread_activity_sp->current_activity = *activity_search; + + BreadcrumbList::const_iterator breadcrumb_search; + for (breadcrumb_search = breadcrumbs.begin(); + breadcrumb_search != breadcrumbs.end(); ++breadcrumb_search) { + if (breadcrumb_search->activity_id == activity_id) { + thread_activity_sp->breadcrumbs.push_back(*breadcrumb_search); } + } + MessageList::const_iterator message_search; + for (message_search = messages.begin(); + message_search != messages.end(); ++message_search) { + if (message_search->thread == thread_id) { + thread_activity_sp->messages.push_back(*message_search); + } + } + + m_thread_activities[thread_id] = thread_activity_sp; + break; } + } } + } } uint32_t -Genealogy::AddProcessExecutableInfo (ProcessExecutableInfoSP process_exe_info) -{ - const uint32_t info_size = static_cast<uint32_t>(m_process_executable_infos.size()); - for (uint32_t idx = 0; idx < info_size; ++idx) - { - if (uuid_compare (m_process_executable_infos[idx]->image_uuid, process_exe_info->image_uuid) == 0) - { - return idx + 1; - } +Genealogy::AddProcessExecutableInfo(ProcessExecutableInfoSP process_exe_info) { + const uint32_t info_size = + static_cast<uint32_t>(m_process_executable_infos.size()); + for (uint32_t idx = 0; idx < info_size; ++idx) { + if (uuid_compare(m_process_executable_infos[idx]->image_uuid, + process_exe_info->image_uuid) == 0) { + return idx + 1; } - m_process_executable_infos.push_back (process_exe_info); - return info_size + 1; + } + m_process_executable_infos.push_back(process_exe_info); + return info_size + 1; } Genealogy::ProcessExecutableInfoSP -Genealogy::GetProcessExecutableInfosAtIndex(size_t idx) -{ - ProcessExecutableInfoSP info_sp; - if (idx > 0) - { - idx--; - if (idx <= m_process_executable_infos.size()) - { - info_sp = m_process_executable_infos[idx]; - } +Genealogy::GetProcessExecutableInfosAtIndex(size_t idx) { + ProcessExecutableInfoSP info_sp; + if (idx > 0) { + idx--; + if (idx <= m_process_executable_infos.size()) { + info_sp = m_process_executable_infos[idx]; } - return info_sp; + } + return info_sp; } - diff --git a/lldb/tools/debugserver/source/MacOSX/Genealogy.h b/lldb/tools/debugserver/source/MacOSX/Genealogy.h index d39145a06f2..f398b63c6d9 100644 --- a/lldb/tools/debugserver/source/MacOSX/Genealogy.h +++ b/lldb/tools/debugserver/source/MacOSX/Genealogy.h @@ -1,4 +1,5 @@ -//===-- Activity.h -----------------------------------------------*- C++ -*-===// +//===-- Activity.h -----------------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -10,107 +11,110 @@ #ifndef __Genealogy_h__ #define __Genealogy_h__ -#include <string> -#include <vector> +#include <mach/task.h> #include <map> #include <pthread.h> -#include <mach/task.h> +#include <string> +#include <vector> #include "GenealogySPI.h" #include "MachThreadList.h" -class Genealogy -{ +class Genealogy { public: - - Genealogy (); - - ~Genealogy () - { - } - - void - Clear(); - - struct Breadcrumb - { - uint32_t breadcrumb_id; - uint64_t activity_id; - uint64_t timestamp; - std::string name; - }; - - struct Activity - { - uint64_t activity_start; - uint64_t activity_id; - uint64_t parent_id; - std::string activity_name; - std::string reason; - }; - - struct Message - { - uint64_t timestamp; - uint64_t activity_id; - uint64_t trace_id; - uint64_t thread; - uint8_t type; // OS_TRACE_TYPE_RELEASE, OS_TRACE_TYPE_DEBUG, OS_TRACE_TYPE_ERROR, OS_TRACE_TYPE_FAULT - uint32_t process_info_index; // index # of the image uuid/file path, 0 means unknown - std::string message; - }; - - typedef std::vector<Message> MessageList; - typedef std::vector<Breadcrumb> BreadcrumbList; - typedef std::vector<Activity> ActivityList; - - struct ThreadActivity - { - Activity current_activity; - MessageList messages; - BreadcrumbList breadcrumbs; // should be 0 or 1 breadcrumbs; no more than 1 BC for any given activity - }; - - typedef std::shared_ptr<ThreadActivity> ThreadActivitySP; - - ThreadActivitySP - GetGenealogyInfoForThread (pid_t pid, nub_thread_t tid, const MachThreadList &thread_list, task_t task, bool &timed_out); - - struct ProcessExecutableInfo - { - std::string image_path; - uuid_t image_uuid; - }; - - typedef std::shared_ptr<ProcessExecutableInfo> ProcessExecutableInfoSP; - - ProcessExecutableInfoSP - GetProcessExecutableInfosAtIndex(size_t idx); - - uint32_t - AddProcessExecutableInfo(ProcessExecutableInfoSP process_exe_info); + Genealogy(); + + ~Genealogy() {} + + void Clear(); + + struct Breadcrumb { + uint32_t breadcrumb_id; + uint64_t activity_id; + uint64_t timestamp; + std::string name; + }; + + struct Activity { + uint64_t activity_start; + uint64_t activity_id; + uint64_t parent_id; + std::string activity_name; + std::string reason; + }; + + struct Message { + uint64_t timestamp; + uint64_t activity_id; + uint64_t trace_id; + uint64_t thread; + uint8_t type; // OS_TRACE_TYPE_RELEASE, OS_TRACE_TYPE_DEBUG, + // OS_TRACE_TYPE_ERROR, OS_TRACE_TYPE_FAULT + uint32_t process_info_index; // index # of the image uuid/file path, 0 means + // unknown + std::string message; + }; + + typedef std::vector<Message> MessageList; + typedef std::vector<Breadcrumb> BreadcrumbList; + typedef std::vector<Activity> ActivityList; + + struct ThreadActivity { + Activity current_activity; + MessageList messages; + BreadcrumbList breadcrumbs; // should be 0 or 1 breadcrumbs; no more than 1 + // BC for any given activity + }; + + typedef std::shared_ptr<ThreadActivity> ThreadActivitySP; + + ThreadActivitySP GetGenealogyInfoForThread(pid_t pid, nub_thread_t tid, + const MachThreadList &thread_list, + task_t task, bool &timed_out); + + struct ProcessExecutableInfo { + std::string image_path; + uuid_t image_uuid; + }; + + typedef std::shared_ptr<ProcessExecutableInfo> ProcessExecutableInfoSP; + + ProcessExecutableInfoSP GetProcessExecutableInfosAtIndex(size_t idx); + + uint32_t AddProcessExecutableInfo(ProcessExecutableInfoSP process_exe_info); private: - - void - GetActivities(pid_t pid, const MachThreadList &thread_list, task_t task); - - // the spi we need to call into libtrace - look them up via dlsym at runtime - bool (*m_os_activity_diagnostic_for_pid) (pid_t pid, os_activity_t activity, uint32_t flags, os_diagnostic_block_t block); - void (*m_os_activity_iterate_processes) (os_activity_process_list_t processes, bool (^iterator)(os_activity_process_t process_info)); - void (*m_os_activity_iterate_breadcrumbs) (os_activity_process_t process_info, bool (^iterator)(os_activity_breadcrumb_t breadcrumb)); - void (*m_os_activity_iterate_messages) (os_trace_message_list_t messages, os_activity_process_t process_info, bool (^iterator)(os_trace_message_t tracemsg)); - void (*m_os_activity_iterate_activities) (os_activity_list_t activities, os_activity_process_t process_info, bool (^iterator)(os_activity_entry_t activity)); - uint8_t (*m_os_trace_get_type) (os_trace_message_t trace_msg); - char * (*m_os_trace_copy_formatted_message) (os_trace_message_t trace_msg); - os_activity_t (*m_os_activity_for_thread) (os_activity_process_t process, uint64_t thread_id); - os_activity_t (*m_os_activity_for_task_thread) (task_t target, uint64_t thread_id); - os_trace_message_list_t (*m_os_activity_messages_for_thread) (os_activity_process_t process, os_activity_t activity, uint64_t thread_id); - - - std::map<nub_thread_t, ThreadActivitySP> m_thread_activities; - std::vector<ProcessExecutableInfoSP> m_process_executable_infos; - bool m_diagnosticd_call_timed_out; + void GetActivities(pid_t pid, const MachThreadList &thread_list, task_t task); + + // the spi we need to call into libtrace - look them up via dlsym at runtime + bool (*m_os_activity_diagnostic_for_pid)(pid_t pid, os_activity_t activity, + uint32_t flags, + os_diagnostic_block_t block); + void (*m_os_activity_iterate_processes)( + os_activity_process_list_t processes, + bool (^iterator)(os_activity_process_t process_info)); + void (*m_os_activity_iterate_breadcrumbs)( + os_activity_process_t process_info, + bool (^iterator)(os_activity_breadcrumb_t breadcrumb)); + void (*m_os_activity_iterate_messages)( + os_trace_message_list_t messages, os_activity_process_t process_info, + bool (^iterator)(os_trace_message_t tracemsg)); + void (*m_os_activity_iterate_activities)( + os_activity_list_t activities, os_activity_process_t process_info, + bool (^iterator)(os_activity_entry_t activity)); + uint8_t (*m_os_trace_get_type)(os_trace_message_t trace_msg); + char *(*m_os_trace_copy_formatted_message)(os_trace_message_t trace_msg); + os_activity_t (*m_os_activity_for_thread)(os_activity_process_t process, + uint64_t thread_id); + os_activity_t (*m_os_activity_for_task_thread)(task_t target, + uint64_t thread_id); + os_trace_message_list_t (*m_os_activity_messages_for_thread)( + os_activity_process_t process, os_activity_t activity, + uint64_t thread_id); + + std::map<nub_thread_t, ThreadActivitySP> m_thread_activities; + std::vector<ProcessExecutableInfoSP> m_process_executable_infos; + bool m_diagnosticd_call_timed_out; }; #endif // __Genealogy_h__ diff --git a/lldb/tools/debugserver/source/MacOSX/GenealogySPI.h b/lldb/tools/debugserver/source/MacOSX/GenealogySPI.h index f84e930e872..de9db2d2e64 100644 --- a/lldb/tools/debugserver/source/MacOSX/GenealogySPI.h +++ b/lldb/tools/debugserver/source/MacOSX/GenealogySPI.h @@ -18,67 +18,65 @@ typedef struct os_activity_watch_s *os_activity_watch_t; typedef uint64_t os_activity_t; struct os_activity_breadcrumb_s { - uint32_t breadcrumb_id; - uint64_t activity_id; - uint64_t timestamp; - const char *name; + uint32_t breadcrumb_id; + uint64_t activity_id; + uint64_t timestamp; + const char *name; }; typedef struct os_activity_breadcrumb_s *os_activity_breadcrumb_t; typedef struct os_trace_message_s { - uint64_t trace_id; - uint64_t thread; - uint64_t timestamp; - uint32_t offset; - xpc_object_t __unsafe_unretained payload; - const uint8_t *image_uuid; - const char *image_path; - const char *format; - const void *buffer; - size_t bufferLen; -} *os_trace_message_t; + uint64_t trace_id; + uint64_t thread; + uint64_t timestamp; + uint32_t offset; + xpc_object_t __unsafe_unretained payload; + const uint8_t *image_uuid; + const char *image_path; + const char *format; + const void *buffer; + size_t bufferLen; +} * os_trace_message_t; typedef struct os_activity_process_s { - os_activity_process_list_t child_procs; - os_trace_message_list_t messages; - os_activity_list_t activities; - void *breadcrumbs; - uint64_t proc_id; - const uint8_t *image_uuid; - const char *image_path; - pid_t pid; -} *os_activity_process_t; + os_activity_process_list_t child_procs; + os_trace_message_list_t messages; + os_activity_list_t activities; + void *breadcrumbs; + uint64_t proc_id; + const uint8_t *image_uuid; + const char *image_path; + pid_t pid; +} * os_activity_process_t; typedef struct os_activity_entry_s { - uint64_t activity_start; - os_activity_t activity_id; - os_activity_t parent_id; - const char *activity_name; - const char *reason; - os_trace_message_list_t messages; -} *os_activity_entry_t; + uint64_t activity_start; + os_activity_t activity_id; + os_activity_t parent_id; + const char *activity_name; + const char *reason; + os_trace_message_list_t messages; +} * os_activity_entry_t; -enum -{ - OS_ACTIVITY_DIAGNOSTIC_DEFAULT = 0x00000000, - OS_ACTIVITY_DIAGNOSTIC_PROCESS_ONLY = 0x00000001, - OS_ACTIVITY_DIAGNOSTIC_SKIP_DECODE = 0x00000002, - OS_ACTIVITY_DIAGNOSTIC_FLATTENED = 0x00000004, - OS_ACTIVITY_DIAGNOSTIC_ALL_ACTIVITIES = 0x00000008, - OS_ACTIVITY_DIAGNOSTIC_MAX = 0x0000000f +enum { + OS_ACTIVITY_DIAGNOSTIC_DEFAULT = 0x00000000, + OS_ACTIVITY_DIAGNOSTIC_PROCESS_ONLY = 0x00000001, + OS_ACTIVITY_DIAGNOSTIC_SKIP_DECODE = 0x00000002, + OS_ACTIVITY_DIAGNOSTIC_FLATTENED = 0x00000004, + OS_ACTIVITY_DIAGNOSTIC_ALL_ACTIVITIES = 0x00000008, + OS_ACTIVITY_DIAGNOSTIC_MAX = 0x0000000f }; typedef uint32_t os_activity_diagnostic_flag_t; -enum -{ - OS_ACTIVITY_WATCH_DEFAULT = 0x00000000, - OS_ACTIVITY_WATCH_PROCESS_ONLY = 0x00000001, - OS_ACTIVITY_WATCH_SKIP_DECODE = 0x00000002, - OS_ACTIVITY_WATCH_PAYLOAD = 0x00000004, - OS_ACTIVITY_WATCH_ERRORS = 0x00000008, - OS_ACTIVITY_WATCH_FAULTS = 0x00000010, - OS_ACTIVITY_WATCH_MAX = 0x0000001f +enum { + OS_ACTIVITY_WATCH_DEFAULT = 0x00000000, + OS_ACTIVITY_WATCH_PROCESS_ONLY = 0x00000001, + OS_ACTIVITY_WATCH_SKIP_DECODE = 0x00000002, + OS_ACTIVITY_WATCH_PAYLOAD = 0x00000004, + OS_ACTIVITY_WATCH_ERRORS = 0x00000008, + OS_ACTIVITY_WATCH_FAULTS = 0x00000010, + OS_ACTIVITY_WATCH_MAX = 0x0000001f }; typedef uint32_t os_activity_watch_flag_t; @@ -88,9 +86,10 @@ typedef uint32_t os_activity_watch_flag_t; #define OS_TRACE_TYPE_ERROR ((1u << 6) | (1u << 0)) #define OS_TRACE_TYPE_FAULT ((1u << 7) | (1u << 6) | (1u << 0)) - -typedef void (^os_activity_watch_block_t)(os_activity_watch_t watch, os_activity_process_t process_info, bool canceled); -typedef void (^os_diagnostic_block_t)(os_activity_process_list_t processes, int error); +typedef void (^os_activity_watch_block_t)(os_activity_watch_t watch, + os_activity_process_t process_info, + bool canceled); +typedef void (^os_diagnostic_block_t)(os_activity_process_list_t processes, + int error); #endif - diff --git a/lldb/tools/debugserver/source/MacOSX/HasAVX.h b/lldb/tools/debugserver/source/MacOSX/HasAVX.h index c7a50fa20b3..43fbd5e514e 100644 --- a/lldb/tools/debugserver/source/MacOSX/HasAVX.h +++ b/lldb/tools/debugserver/source/MacOSX/HasAVX.h @@ -10,18 +10,18 @@ #ifndef HasAVX_h #define HasAVX_h -#if defined (__i386__) || defined (__x86_64__) +#if defined(__i386__) || defined(__x86_64__) #ifdef __cplusplus extern "C" { #endif -int HasAVX (); +int HasAVX(); #ifdef __cplusplus } #endif #endif - + #endif diff --git a/lldb/tools/debugserver/source/MacOSX/MachException.cpp b/lldb/tools/debugserver/source/MacOSX/MachException.cpp index 0b5459e3a18..09849312fbb 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachException.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachException.cpp @@ -12,62 +12,40 @@ //===----------------------------------------------------------------------===// #include "MachException.h" -#include "MachProcess.h" #include "DNB.h" #include "DNBError.h" -#include <sys/types.h> #include "DNBLog.h" +#include "MachProcess.h" #include "PThreadMutex.h" #include "SysSignal.h" #include <errno.h> #include <sys/ptrace.h> +#include <sys/types.h> // Routine mach_exception_raise -extern "C" -kern_return_t catch_mach_exception_raise -( - mach_port_t exception_port, - mach_port_t thread, - mach_port_t task, - exception_type_t exception, - mach_exception_data_t code, - mach_msg_type_number_t codeCnt -); - -extern "C" -kern_return_t catch_mach_exception_raise_state -( - mach_port_t exception_port, - exception_type_t exception, - const mach_exception_data_t code, - mach_msg_type_number_t codeCnt, - int *flavor, - const thread_state_t old_state, - mach_msg_type_number_t old_stateCnt, - thread_state_t new_state, - mach_msg_type_number_t *new_stateCnt -); +extern "C" kern_return_t +catch_mach_exception_raise(mach_port_t exception_port, mach_port_t thread, + mach_port_t task, exception_type_t exception, + mach_exception_data_t code, + mach_msg_type_number_t codeCnt); + +extern "C" kern_return_t catch_mach_exception_raise_state( + mach_port_t exception_port, exception_type_t exception, + const mach_exception_data_t code, mach_msg_type_number_t codeCnt, + int *flavor, const thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt); // Routine mach_exception_raise_state_identity -extern "C" -kern_return_t catch_mach_exception_raise_state_identity -( - mach_port_t exception_port, - mach_port_t thread, - mach_port_t task, - exception_type_t exception, - mach_exception_data_t code, - mach_msg_type_number_t codeCnt, - int *flavor, - thread_state_t old_state, - mach_msg_type_number_t old_stateCnt, - thread_state_t new_state, - mach_msg_type_number_t *new_stateCnt -); - -extern "C" boolean_t mach_exc_server( - mach_msg_header_t *InHeadP, - mach_msg_header_t *OutHeadP); +extern "C" kern_return_t catch_mach_exception_raise_state_identity( + mach_port_t exception_port, mach_port_t thread, mach_port_t task, + exception_type_t exception, mach_exception_data_t code, + mach_msg_type_number_t codeCnt, int *flavor, thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt); + +extern "C" boolean_t mach_exc_server(mach_msg_header_t *InHeadP, + mach_msg_header_t *OutHeadP); // Any access to the g_message variable should be done by locking the // g_message_mutex first, using the g_message variable, then unlocking @@ -75,417 +53,339 @@ extern "C" boolean_t mach_exc_server( // for sample code. static MachException::Data *g_message = NULL; -//static pthread_mutex_t g_message_mutex = PTHREAD_MUTEX_INITIALIZER; - - -extern "C" -kern_return_t -catch_mach_exception_raise_state -( - mach_port_t exc_port, - exception_type_t exc_type, - const mach_exception_data_t exc_data, - mach_msg_type_number_t exc_data_count, - int * flavor, - const thread_state_t old_state, - mach_msg_type_number_t old_stateCnt, - thread_state_t new_state, - mach_msg_type_number_t * new_stateCnt -) -{ - if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) - { - DNBLogThreaded ("::%s ( exc_port = 0x%4.4x, exc_type = %d ( %s ), exc_data = 0x%llx, exc_data_count = %d)", - __FUNCTION__, - exc_port, - exc_type, MachException::Name(exc_type), - (uint64_t)exc_data, - exc_data_count); - } - return KERN_FAILURE; +// static pthread_mutex_t g_message_mutex = PTHREAD_MUTEX_INITIALIZER; + +extern "C" kern_return_t catch_mach_exception_raise_state( + mach_port_t exc_port, exception_type_t exc_type, + const mach_exception_data_t exc_data, mach_msg_type_number_t exc_data_count, + int *flavor, const thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt) { + if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) { + DNBLogThreaded("::%s ( exc_port = 0x%4.4x, exc_type = %d ( %s ), exc_data " + "= 0x%llx, exc_data_count = %d)", + __FUNCTION__, exc_port, exc_type, + MachException::Name(exc_type), (uint64_t)exc_data, + exc_data_count); + } + return KERN_FAILURE; } -extern "C" -kern_return_t -catch_mach_exception_raise_state_identity -( - mach_port_t exc_port, - mach_port_t thread_port, - mach_port_t task_port, - exception_type_t exc_type, - mach_exception_data_t exc_data, - mach_msg_type_number_t exc_data_count, - int * flavor, - thread_state_t old_state, - mach_msg_type_number_t old_stateCnt, - thread_state_t new_state, - mach_msg_type_number_t *new_stateCnt -) -{ - if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) - { - DNBLogThreaded("::%s ( exc_port = 0x%4.4x, thd_port = 0x%4.4x, tsk_port = 0x%4.4x, exc_type = %d ( %s ), exc_data[%d] = { 0x%llx, 0x%llx })", - __FUNCTION__, - exc_port, - thread_port, - task_port, - exc_type, MachException::Name(exc_type), - exc_data_count, - (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD), - (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD)); - } - mach_port_deallocate (mach_task_self (), task_port); - mach_port_deallocate (mach_task_self (), thread_port); - - return KERN_FAILURE; +extern "C" kern_return_t catch_mach_exception_raise_state_identity( + mach_port_t exc_port, mach_port_t thread_port, mach_port_t task_port, + exception_type_t exc_type, mach_exception_data_t exc_data, + mach_msg_type_number_t exc_data_count, int *flavor, + thread_state_t old_state, mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, mach_msg_type_number_t *new_stateCnt) { + if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) { + DNBLogThreaded("::%s ( exc_port = 0x%4.4x, thd_port = 0x%4.4x, tsk_port = " + "0x%4.4x, exc_type = %d ( %s ), exc_data[%d] = { 0x%llx, " + "0x%llx })", + __FUNCTION__, exc_port, thread_port, task_port, exc_type, + MachException::Name(exc_type), exc_data_count, + (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD), + (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD)); + } + mach_port_deallocate(mach_task_self(), task_port); + mach_port_deallocate(mach_task_self(), thread_port); + + return KERN_FAILURE; } -extern "C" -kern_return_t -catch_mach_exception_raise -( - mach_port_t exc_port, - mach_port_t thread_port, - mach_port_t task_port, - exception_type_t exc_type, - mach_exception_data_t exc_data, - mach_msg_type_number_t exc_data_count) -{ - if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) - { - DNBLogThreaded ("::%s ( exc_port = 0x%4.4x, thd_port = 0x%4.4x, tsk_port = 0x%4.4x, exc_type = %d ( %s ), exc_data[%d] = { 0x%llx, 0x%llx })", - __FUNCTION__, - exc_port, - thread_port, - task_port, - exc_type, MachException::Name(exc_type), - exc_data_count, - (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD), - (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD)); - } - - if (task_port == g_message->task_port) - { - g_message->task_port = task_port; - g_message->thread_port = thread_port; - g_message->exc_type = exc_type; - g_message->exc_data.resize(exc_data_count); - ::memcpy (&g_message->exc_data[0], exc_data, g_message->exc_data.size() * sizeof (mach_exception_data_type_t)); - return KERN_SUCCESS; - } - return KERN_FAILURE; +extern "C" kern_return_t +catch_mach_exception_raise(mach_port_t exc_port, mach_port_t thread_port, + mach_port_t task_port, exception_type_t exc_type, + mach_exception_data_t exc_data, + mach_msg_type_number_t exc_data_count) { + if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) { + DNBLogThreaded("::%s ( exc_port = 0x%4.4x, thd_port = 0x%4.4x, tsk_port = " + "0x%4.4x, exc_type = %d ( %s ), exc_data[%d] = { 0x%llx, " + "0x%llx })", + __FUNCTION__, exc_port, thread_port, task_port, exc_type, + MachException::Name(exc_type), exc_data_count, + (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD), + (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD)); + } + + if (task_port == g_message->task_port) { + g_message->task_port = task_port; + g_message->thread_port = thread_port; + g_message->exc_type = exc_type; + g_message->exc_data.resize(exc_data_count); + ::memcpy(&g_message->exc_data[0], exc_data, + g_message->exc_data.size() * sizeof(mach_exception_data_type_t)); + return KERN_SUCCESS; + } + return KERN_FAILURE; } - -void -MachException::Message::Dump() const -{ - DNBLogThreadedIf(LOG_EXCEPTIONS, - " exc_msg { bits = 0x%8.8x size = 0x%8.8x remote-port = 0x%8.8x local-port = 0x%8.8x reserved = 0x%8.8x id = 0x%8.8x } ", - exc_msg.hdr.msgh_bits, - exc_msg.hdr.msgh_size, - exc_msg.hdr.msgh_remote_port, - exc_msg.hdr.msgh_local_port, - exc_msg.hdr.msgh_reserved, - exc_msg.hdr.msgh_id); - - DNBLogThreadedIf(LOG_EXCEPTIONS, - "reply_msg { bits = 0x%8.8x size = 0x%8.8x remote-port = 0x%8.8x local-port = 0x%8.8x reserved = 0x%8.8x id = 0x%8.8x }", - reply_msg.hdr.msgh_bits, - reply_msg.hdr.msgh_size, - reply_msg.hdr.msgh_remote_port, - reply_msg.hdr.msgh_local_port, - reply_msg.hdr.msgh_reserved, - reply_msg.hdr.msgh_id); - - state.Dump(); +void MachException::Message::Dump() const { + DNBLogThreadedIf(LOG_EXCEPTIONS, " exc_msg { bits = 0x%8.8x size = 0x%8.8x " + "remote-port = 0x%8.8x local-port = 0x%8.8x " + "reserved = 0x%8.8x id = 0x%8.8x } ", + exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size, + exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port, + exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id); + + DNBLogThreadedIf(LOG_EXCEPTIONS, "reply_msg { bits = 0x%8.8x size = 0x%8.8x " + "remote-port = 0x%8.8x local-port = 0x%8.8x " + "reserved = 0x%8.8x id = 0x%8.8x }", + reply_msg.hdr.msgh_bits, reply_msg.hdr.msgh_size, + reply_msg.hdr.msgh_remote_port, + reply_msg.hdr.msgh_local_port, reply_msg.hdr.msgh_reserved, + reply_msg.hdr.msgh_id); + + state.Dump(); } -bool -MachException::Data::GetStopInfo(struct DNBThreadStopInfo *stop_info) const -{ - // Zero out the structure. - memset(stop_info, 0, sizeof(struct DNBThreadStopInfo)); - - if (exc_type == 0) - { - stop_info->reason = eStopTypeInvalid; - return true; - } +bool MachException::Data::GetStopInfo( + struct DNBThreadStopInfo *stop_info) const { + // Zero out the structure. + memset(stop_info, 0, sizeof(struct DNBThreadStopInfo)); - // We always stop with a mach exceptions - stop_info->reason = eStopTypeException; - // Save the EXC_XXXX exception type - stop_info->details.exception.type = exc_type; - - // Fill in a text description - const char * exc_name = MachException::Name(exc_type); - char *desc = stop_info->description; - const char *end_desc = desc + DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH; - if (exc_name) - desc += snprintf(desc, DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH, "%s", exc_name); - else - desc += snprintf(desc, DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH, "%i", exc_type); - - stop_info->details.exception.data_count = exc_data.size(); - - int soft_signal = SoftSignal(); - if (soft_signal) - { - if (desc < end_desc) - { - const char *sig_str = SysSignal::Name(soft_signal); - snprintf(desc, end_desc - desc, " EXC_SOFT_SIGNAL( %i ( %s ))", soft_signal, sig_str ? sig_str : "unknown signal"); - } + if (exc_type == 0) { + stop_info->reason = eStopTypeInvalid; + return true; + } + + // We always stop with a mach exceptions + stop_info->reason = eStopTypeException; + // Save the EXC_XXXX exception type + stop_info->details.exception.type = exc_type; + + // Fill in a text description + const char *exc_name = MachException::Name(exc_type); + char *desc = stop_info->description; + const char *end_desc = desc + DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH; + if (exc_name) + desc += + snprintf(desc, DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH, "%s", exc_name); + else + desc += + snprintf(desc, DNB_THREAD_STOP_INFO_MAX_DESC_LENGTH, "%i", exc_type); + + stop_info->details.exception.data_count = exc_data.size(); + + int soft_signal = SoftSignal(); + if (soft_signal) { + if (desc < end_desc) { + const char *sig_str = SysSignal::Name(soft_signal); + snprintf(desc, end_desc - desc, " EXC_SOFT_SIGNAL( %i ( %s ))", + soft_signal, sig_str ? sig_str : "unknown signal"); } - else - { - // No special disassembly for exception data, just - size_t idx; - if (desc < end_desc) - { - desc += snprintf(desc, end_desc - desc, " data[%llu] = {", (uint64_t)stop_info->details.exception.data_count); - - for (idx = 0; desc < end_desc && idx < stop_info->details.exception.data_count; ++idx) - desc += snprintf(desc, end_desc - desc, "0x%llx%c", (uint64_t)exc_data[idx], ((idx + 1 == stop_info->details.exception.data_count) ? '}' : ',')); - } + } else { + // No special disassembly for exception data, just + size_t idx; + if (desc < end_desc) { + desc += snprintf(desc, end_desc - desc, " data[%llu] = {", + (uint64_t)stop_info->details.exception.data_count); + + for (idx = 0; + desc < end_desc && idx < stop_info->details.exception.data_count; + ++idx) + desc += snprintf( + desc, end_desc - desc, "0x%llx%c", (uint64_t)exc_data[idx], + ((idx + 1 == stop_info->details.exception.data_count) ? '}' : ',')); } + } - // Copy the exception data - size_t i; - for (i=0; i<stop_info->details.exception.data_count; i++) - stop_info->details.exception.data[i] = exc_data[i]; + // Copy the exception data + size_t i; + for (i = 0; i < stop_info->details.exception.data_count; i++) + stop_info->details.exception.data[i] = exc_data[i]; - return true; + return true; } - -void -MachException::Data::DumpStopReason() const -{ - int soft_signal = SoftSignal(); - if (soft_signal) - { - const char *signal_str = SysSignal::Name(soft_signal); - if (signal_str) - DNBLog("signal(%s)", signal_str); - else - DNBLog("signal(%i)", soft_signal); - return; - } - DNBLog("%s", Name(exc_type)); +void MachException::Data::DumpStopReason() const { + int soft_signal = SoftSignal(); + if (soft_signal) { + const char *signal_str = SysSignal::Name(soft_signal); + if (signal_str) + DNBLog("signal(%s)", signal_str); + else + DNBLog("signal(%i)", soft_signal); + return; + } + DNBLog("%s", Name(exc_type)); } -kern_return_t -MachException::Message::Receive(mach_port_t port, mach_msg_option_t options, mach_msg_timeout_t timeout, mach_port_t notify_port) -{ - DNBError err; - const bool log_exceptions = DNBLogCheckLogBit(LOG_EXCEPTIONS); - mach_msg_timeout_t mach_msg_timeout = options & MACH_RCV_TIMEOUT ? timeout : 0; - if (log_exceptions && ((options & MACH_RCV_TIMEOUT) == 0)) - { - // Dump this log message if we have no timeout in case it never returns - DNBLogThreaded ("::mach_msg ( msg->{bits = %#x, size = %u remote_port = %#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, option = %#x, send_size = 0, rcv_size = %llu, rcv_name = %#x, timeout = %u, notify = %#x)", - exc_msg.hdr.msgh_bits, - exc_msg.hdr.msgh_size, - exc_msg.hdr.msgh_remote_port, - exc_msg.hdr.msgh_local_port, - exc_msg.hdr.msgh_reserved, - exc_msg.hdr.msgh_id, - options, - (uint64_t)sizeof (exc_msg.data), - port, - mach_msg_timeout, - notify_port); - } - - err = ::mach_msg (&exc_msg.hdr, - options, // options - 0, // Send size - sizeof (exc_msg.data), // Receive size - port, // exception port to watch for exception on - mach_msg_timeout, // timeout in msec (obeyed only if MACH_RCV_TIMEOUT is ORed into the options parameter) - notify_port); - - // Dump any errors we get - if (log_exceptions) - { - err.LogThreaded("::mach_msg ( msg->{bits = %#x, size = %u remote_port = %#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, option = %#x, send_size = %u, rcv_size = %u, rcv_name = %#x, timeout = %u, notify = %#x)", - exc_msg.hdr.msgh_bits, - exc_msg.hdr.msgh_size, - exc_msg.hdr.msgh_remote_port, - exc_msg.hdr.msgh_local_port, - exc_msg.hdr.msgh_reserved, - exc_msg.hdr.msgh_id, - options, - 0, - sizeof (exc_msg.data), - port, - mach_msg_timeout, - notify_port); - } - return err.Error(); +kern_return_t MachException::Message::Receive(mach_port_t port, + mach_msg_option_t options, + mach_msg_timeout_t timeout, + mach_port_t notify_port) { + DNBError err; + const bool log_exceptions = DNBLogCheckLogBit(LOG_EXCEPTIONS); + mach_msg_timeout_t mach_msg_timeout = + options & MACH_RCV_TIMEOUT ? timeout : 0; + if (log_exceptions && ((options & MACH_RCV_TIMEOUT) == 0)) { + // Dump this log message if we have no timeout in case it never returns + DNBLogThreaded("::mach_msg ( msg->{bits = %#x, size = %u remote_port = " + "%#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, option " + "= %#x, send_size = 0, rcv_size = %llu, rcv_name = %#x, " + "timeout = %u, notify = %#x)", + exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size, + exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port, + exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options, + (uint64_t)sizeof(exc_msg.data), port, mach_msg_timeout, + notify_port); + } + + err = ::mach_msg(&exc_msg.hdr, + options, // options + 0, // Send size + sizeof(exc_msg.data), // Receive size + port, // exception port to watch for exception on + mach_msg_timeout, // timeout in msec (obeyed only if + // MACH_RCV_TIMEOUT is ORed into the + // options parameter) + notify_port); + + // Dump any errors we get + if (log_exceptions) { + err.LogThreaded("::mach_msg ( msg->{bits = %#x, size = %u remote_port = " + "%#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, " + "option = %#x, send_size = %u, rcv_size = %u, rcv_name = " + "%#x, timeout = %u, notify = %#x)", + exc_msg.hdr.msgh_bits, exc_msg.hdr.msgh_size, + exc_msg.hdr.msgh_remote_port, exc_msg.hdr.msgh_local_port, + exc_msg.hdr.msgh_reserved, exc_msg.hdr.msgh_id, options, 0, + sizeof(exc_msg.data), port, mach_msg_timeout, notify_port); + } + return err.Error(); } -bool -MachException::Message::CatchExceptionRaise(task_t task) -{ - bool success = false; - // locker will keep a mutex locked until it goes out of scope -// PThreadMutex::Locker locker(&g_message_mutex); - // DNBLogThreaded("calling mach_exc_server"); - state.task_port = task; - g_message = &state; - // The exc_server function is the MIG generated server handling function - // to handle messages from the kernel relating to the occurrence of an - // exception in a thread. Such messages are delivered to the exception port - // set via thread_set_exception_ports or task_set_exception_ports. When an - // exception occurs in a thread, the thread sends an exception message to - // its exception port, blocking in the kernel waiting for the receipt of a - // reply. The exc_server function performs all necessary argument handling - // for this kernel message and calls catch_exception_raise, - // catch_exception_raise_state or catch_exception_raise_state_identity, - // which should handle the exception. If the called routine returns - // KERN_SUCCESS, a reply message will be sent, allowing the thread to - // continue from the point of the exception; otherwise, no reply message - // is sent and the called routine must have dealt with the exception - // thread directly. - if (mach_exc_server (&exc_msg.hdr, &reply_msg.hdr)) - { - success = true; - } - else if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) - { - DNBLogThreaded("mach_exc_server returned zero..."); - } - g_message = NULL; - return success; +bool MachException::Message::CatchExceptionRaise(task_t task) { + bool success = false; + // locker will keep a mutex locked until it goes out of scope + // PThreadMutex::Locker locker(&g_message_mutex); + // DNBLogThreaded("calling mach_exc_server"); + state.task_port = task; + g_message = &state; + // The exc_server function is the MIG generated server handling function + // to handle messages from the kernel relating to the occurrence of an + // exception in a thread. Such messages are delivered to the exception port + // set via thread_set_exception_ports or task_set_exception_ports. When an + // exception occurs in a thread, the thread sends an exception message to + // its exception port, blocking in the kernel waiting for the receipt of a + // reply. The exc_server function performs all necessary argument handling + // for this kernel message and calls catch_exception_raise, + // catch_exception_raise_state or catch_exception_raise_state_identity, + // which should handle the exception. If the called routine returns + // KERN_SUCCESS, a reply message will be sent, allowing the thread to + // continue from the point of the exception; otherwise, no reply message + // is sent and the called routine must have dealt with the exception + // thread directly. + if (mach_exc_server(&exc_msg.hdr, &reply_msg.hdr)) { + success = true; + } else if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) { + DNBLogThreaded("mach_exc_server returned zero..."); + } + g_message = NULL; + return success; } - - -kern_return_t -MachException::Message::Reply(MachProcess *process, int signal) -{ - // Reply to the exception... - DNBError err; - - // If we had a soft signal, we need to update the thread first so it can - // continue without signaling - int soft_signal = state.SoftSignal(); - if (soft_signal) - { - int state_pid = -1; - if (process->Task().TaskPort() == state.task_port) - { - // This is our task, so we can update the signal to send to it - state_pid = process->ProcessID(); - soft_signal = signal; - } - else - { - err = ::pid_for_task(state.task_port, &state_pid); - } - - assert (state_pid != -1); - if (state_pid != -1) - { - errno = 0; - if (::ptrace (PT_THUPDATE, state_pid, (caddr_t)((uintptr_t)state.thread_port), soft_signal) != 0) - err.SetError(errno, DNBError::POSIX); - else - err.Clear(); - - if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail()) - err.LogThreaded("::ptrace (request = PT_THUPDATE, pid = 0x%4.4x, tid = 0x%4.4x, signal = %i)", state_pid, state.thread_port, soft_signal); - } +kern_return_t MachException::Message::Reply(MachProcess *process, int signal) { + // Reply to the exception... + DNBError err; + + // If we had a soft signal, we need to update the thread first so it can + // continue without signaling + int soft_signal = state.SoftSignal(); + if (soft_signal) { + int state_pid = -1; + if (process->Task().TaskPort() == state.task_port) { + // This is our task, so we can update the signal to send to it + state_pid = process->ProcessID(); + soft_signal = signal; + } else { + err = ::pid_for_task(state.task_port, &state_pid); } - DNBLogThreadedIf(LOG_EXCEPTIONS, "::mach_msg ( msg->{bits = %#x, size = %u, remote_port = %#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, option = %#x, send_size = %u, rcv_size = %u, rcv_name = %#x, timeout = %u, notify = %#x)", - reply_msg.hdr.msgh_bits, - reply_msg.hdr.msgh_size, - reply_msg.hdr.msgh_remote_port, - reply_msg.hdr.msgh_local_port, - reply_msg.hdr.msgh_reserved, - reply_msg.hdr.msgh_id, - MACH_SEND_MSG | MACH_SEND_INTERRUPT, - reply_msg.hdr.msgh_size, - 0, - MACH_PORT_NULL, - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL); - - err = ::mach_msg ( &reply_msg.hdr, - MACH_SEND_MSG | MACH_SEND_INTERRUPT, - reply_msg.hdr.msgh_size, - 0, - MACH_PORT_NULL, - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL); - - if (err.Fail()) - { - if (err.Error() == MACH_SEND_INTERRUPTED) - { - if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) - err.LogThreaded("::mach_msg() - send interrupted"); - // TODO: keep retrying to reply??? - } - else - { - if (state.task_port == process->Task().TaskPort()) - { - DNBLogThreaded("error: mach_msg() returned an error when replying to a mach exception: error = %u", err.Error()); - } - else - { - if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) - err.LogThreaded("::mach_msg() - failed (child of task)"); - } - } + assert(state_pid != -1); + if (state_pid != -1) { + errno = 0; + if (::ptrace(PT_THUPDATE, state_pid, + (caddr_t)((uintptr_t)state.thread_port), soft_signal) != 0) + err.SetError(errno, DNBError::POSIX); + else + err.Clear(); + + if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail()) + err.LogThreaded("::ptrace (request = PT_THUPDATE, pid = 0x%4.4x, tid = " + "0x%4.4x, signal = %i)", + state_pid, state.thread_port, soft_signal); } + } + + DNBLogThreadedIf( + LOG_EXCEPTIONS, "::mach_msg ( msg->{bits = %#x, size = %u, remote_port = " + "%#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, " + "option = %#x, send_size = %u, rcv_size = %u, rcv_name = " + "%#x, timeout = %u, notify = %#x)", + reply_msg.hdr.msgh_bits, reply_msg.hdr.msgh_size, + reply_msg.hdr.msgh_remote_port, reply_msg.hdr.msgh_local_port, + reply_msg.hdr.msgh_reserved, reply_msg.hdr.msgh_id, + MACH_SEND_MSG | MACH_SEND_INTERRUPT, reply_msg.hdr.msgh_size, 0, + MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + + err = ::mach_msg(&reply_msg.hdr, MACH_SEND_MSG | MACH_SEND_INTERRUPT, + reply_msg.hdr.msgh_size, 0, MACH_PORT_NULL, + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + + if (err.Fail()) { + if (err.Error() == MACH_SEND_INTERRUPTED) { + if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) + err.LogThreaded("::mach_msg() - send interrupted"); + // TODO: keep retrying to reply??? + } else { + if (state.task_port == process->Task().TaskPort()) { + DNBLogThreaded("error: mach_msg() returned an error when replying to a " + "mach exception: error = %u", + err.Error()); + } else { + if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) + err.LogThreaded("::mach_msg() - failed (child of task)"); + } + } + } - return err.Error(); + return err.Error(); } - -void -MachException::Data::Dump() const -{ - const char *exc_type_name = MachException::Name(exc_type); - DNBLogThreadedIf(LOG_EXCEPTIONS, " state { task_port = 0x%4.4x, thread_port = 0x%4.4x, exc_type = %i (%s) ...", task_port, thread_port, exc_type, exc_type_name ? exc_type_name : "???"); - - const size_t exc_data_count = exc_data.size(); - // Dump any special exception data contents - int soft_signal = SoftSignal(); - if (soft_signal != 0) - { - const char *sig_str = SysSignal::Name(soft_signal); - DNBLogThreadedIf(LOG_EXCEPTIONS, " exc_data: EXC_SOFT_SIGNAL (%i (%s))", soft_signal, sig_str ? sig_str : "unknown signal"); - } - else - { - // No special disassembly for this data, just dump the data - size_t idx; - for (idx = 0; idx < exc_data_count; ++idx) - { - DNBLogThreadedIf(LOG_EXCEPTIONS, " exc_data[%llu]: 0x%llx", (uint64_t)idx, (uint64_t)exc_data[idx]); - } +void MachException::Data::Dump() const { + const char *exc_type_name = MachException::Name(exc_type); + DNBLogThreadedIf( + LOG_EXCEPTIONS, " state { task_port = 0x%4.4x, thread_port = " + "0x%4.4x, exc_type = %i (%s) ...", + task_port, thread_port, exc_type, exc_type_name ? exc_type_name : "???"); + + const size_t exc_data_count = exc_data.size(); + // Dump any special exception data contents + int soft_signal = SoftSignal(); + if (soft_signal != 0) { + const char *sig_str = SysSignal::Name(soft_signal); + DNBLogThreadedIf(LOG_EXCEPTIONS, + " exc_data: EXC_SOFT_SIGNAL (%i (%s))", + soft_signal, sig_str ? sig_str : "unknown signal"); + } else { + // No special disassembly for this data, just dump the data + size_t idx; + for (idx = 0; idx < exc_data_count; ++idx) { + DNBLogThreadedIf(LOG_EXCEPTIONS, " exc_data[%llu]: 0x%llx", + (uint64_t)idx, (uint64_t)exc_data[idx]); } + } } -#define PREV_EXC_MASK_ALL (EXC_MASK_BAD_ACCESS | \ - EXC_MASK_BAD_INSTRUCTION | \ - EXC_MASK_ARITHMETIC | \ - EXC_MASK_EMULATION | \ - EXC_MASK_SOFTWARE | \ - EXC_MASK_BREAKPOINT | \ - EXC_MASK_SYSCALL | \ - EXC_MASK_MACH_SYSCALL | \ - EXC_MASK_RPC_ALERT | \ - EXC_MASK_MACHINE) +#define PREV_EXC_MASK_ALL \ + (EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC | \ + EXC_MASK_EMULATION | EXC_MASK_SOFTWARE | EXC_MASK_BREAKPOINT | \ + EXC_MASK_SYSCALL | EXC_MASK_MACH_SYSCALL | EXC_MASK_RPC_ALERT | \ + EXC_MASK_MACHINE) -// Don't listen for EXC_RESOURCE, it should really get handled by the system handler. +// Don't listen for EXC_RESOURCE, it should really get handled by the system +// handler. #ifndef EXC_RESOURCE #define EXC_RESOURCE 11 @@ -497,85 +397,92 @@ MachException::Data::Dump() const #define LLDB_EXC_MASK (EXC_MASK_ALL & ~EXC_MASK_RESOURCE) -kern_return_t -MachException::PortInfo::Save (task_t task) -{ - DNBLogThreadedIf(LOG_EXCEPTIONS | LOG_VERBOSE, "MachException::PortInfo::Save ( task = 0x%4.4x )", task); - // Be careful to be able to have debugserver built on a newer OS than what - // it is currently running on by being able to start with all exceptions - // and back off to just what is supported on the current system - DNBError err; - - mask = LLDB_EXC_MASK; - - count = (sizeof (ports) / sizeof (ports[0])); - err = ::task_get_exception_ports (task, mask, masks, &count, ports, behaviors, flavors); +kern_return_t MachException::PortInfo::Save(task_t task) { + DNBLogThreadedIf(LOG_EXCEPTIONS | LOG_VERBOSE, + "MachException::PortInfo::Save ( task = 0x%4.4x )", task); + // Be careful to be able to have debugserver built on a newer OS than what + // it is currently running on by being able to start with all exceptions + // and back off to just what is supported on the current system + DNBError err; + + mask = LLDB_EXC_MASK; + + count = (sizeof(ports) / sizeof(ports[0])); + err = ::task_get_exception_ports(task, mask, masks, &count, ports, behaviors, + flavors); + if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail()) + err.LogThreaded("::task_get_exception_ports ( task = 0x%4.4x, mask = 0x%x, " + "maskCnt => %u, ports, behaviors, flavors )", + task, mask, count); + + if (err.Error() == KERN_INVALID_ARGUMENT && mask != PREV_EXC_MASK_ALL) { + mask = PREV_EXC_MASK_ALL; + count = (sizeof(ports) / sizeof(ports[0])); + err = ::task_get_exception_ports(task, mask, masks, &count, ports, + behaviors, flavors); if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail()) - err.LogThreaded("::task_get_exception_ports ( task = 0x%4.4x, mask = 0x%x, maskCnt => %u, ports, behaviors, flavors )", task, mask, count); - - if (err.Error() == KERN_INVALID_ARGUMENT && mask != PREV_EXC_MASK_ALL) - { - mask = PREV_EXC_MASK_ALL; - count = (sizeof (ports) / sizeof (ports[0])); - err = ::task_get_exception_ports (task, mask, masks, &count, ports, behaviors, flavors); - if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail()) - err.LogThreaded("::task_get_exception_ports ( task = 0x%4.4x, mask = 0x%x, maskCnt => %u, ports, behaviors, flavors )", task, mask, count); - } - if (err.Fail()) - { - mask = 0; - count = 0; - } - return err.Error(); + err.LogThreaded("::task_get_exception_ports ( task = 0x%4.4x, mask = " + "0x%x, maskCnt => %u, ports, behaviors, flavors )", + task, mask, count); + } + if (err.Fail()) { + mask = 0; + count = 0; + } + return err.Error(); } -kern_return_t -MachException::PortInfo::Restore (task_t task) -{ - DNBLogThreadedIf(LOG_EXCEPTIONS | LOG_VERBOSE, "MachException::PortInfo::Restore( task = 0x%4.4x )", task); - uint32_t i = 0; - DNBError err; - if (count > 0) - { - for (i = 0; i < count; i++) - { - err = ::task_set_exception_ports (task, masks[i], ports[i], behaviors[i], flavors[i]); - if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail()) - { - err.LogThreaded("::task_set_exception_ports ( task = 0x%4.4x, exception_mask = 0x%8.8x, new_port = 0x%4.4x, behavior = 0x%8.8x, new_flavor = 0x%8.8x )", task, masks[i], ports[i], behaviors[i], flavors[i]); - // Bail if we encounter any errors - } - - if (err.Fail()) - break; - } +kern_return_t MachException::PortInfo::Restore(task_t task) { + DNBLogThreadedIf(LOG_EXCEPTIONS | LOG_VERBOSE, + "MachException::PortInfo::Restore( task = 0x%4.4x )", task); + uint32_t i = 0; + DNBError err; + if (count > 0) { + for (i = 0; i < count; i++) { + err = ::task_set_exception_ports(task, masks[i], ports[i], behaviors[i], + flavors[i]); + if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail()) { + err.LogThreaded("::task_set_exception_ports ( task = 0x%4.4x, " + "exception_mask = 0x%8.8x, new_port = 0x%4.4x, " + "behavior = 0x%8.8x, new_flavor = 0x%8.8x )", + task, masks[i], ports[i], behaviors[i], flavors[i]); + // Bail if we encounter any errors + } + + if (err.Fail()) + break; } - count = 0; - return err.Error(); + } + count = 0; + return err.Error(); } -const char * -MachException::Name(exception_type_t exc_type) -{ - switch (exc_type) - { - case EXC_BAD_ACCESS: return "EXC_BAD_ACCESS"; - case EXC_BAD_INSTRUCTION: return "EXC_BAD_INSTRUCTION"; - case EXC_ARITHMETIC: return "EXC_ARITHMETIC"; - case EXC_EMULATION: return "EXC_EMULATION"; - case EXC_SOFTWARE: return "EXC_SOFTWARE"; - case EXC_BREAKPOINT: return "EXC_BREAKPOINT"; - case EXC_SYSCALL: return "EXC_SYSCALL"; - case EXC_MACH_SYSCALL: return "EXC_MACH_SYSCALL"; - case EXC_RPC_ALERT: return "EXC_RPC_ALERT"; +const char *MachException::Name(exception_type_t exc_type) { + switch (exc_type) { + case EXC_BAD_ACCESS: + return "EXC_BAD_ACCESS"; + case EXC_BAD_INSTRUCTION: + return "EXC_BAD_INSTRUCTION"; + case EXC_ARITHMETIC: + return "EXC_ARITHMETIC"; + case EXC_EMULATION: + return "EXC_EMULATION"; + case EXC_SOFTWARE: + return "EXC_SOFTWARE"; + case EXC_BREAKPOINT: + return "EXC_BREAKPOINT"; + case EXC_SYSCALL: + return "EXC_SYSCALL"; + case EXC_MACH_SYSCALL: + return "EXC_MACH_SYSCALL"; + case EXC_RPC_ALERT: + return "EXC_RPC_ALERT"; #ifdef EXC_CRASH - case EXC_CRASH: return "EXC_CRASH"; + case EXC_CRASH: + return "EXC_CRASH"; #endif - default: - break; - } - return NULL; + default: + break; + } + return NULL; } - - - diff --git a/lldb/tools/debugserver/source/MacOSX/MachException.h b/lldb/tools/debugserver/source/MacOSX/MachException.h index c831479f2b6..a45a41e01f4 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachException.h +++ b/lldb/tools/debugserver/source/MacOSX/MachException.h @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// - #ifndef __MachException_h__ #define __MachException_h__ @@ -21,113 +20,105 @@ class MachProcess; class PThreadMutex; -typedef union MachMessageTag -{ - mach_msg_header_t hdr; - char data[1024]; +typedef union MachMessageTag { + mach_msg_header_t hdr; + char data[1024]; } MachMessage; - -class MachException -{ +class MachException { public: - - struct PortInfo - { - exception_mask_t mask; // the exception mask for this device which may be a subset of EXC_MASK_ALL... - exception_mask_t masks[EXC_TYPES_COUNT]; - mach_port_t ports[EXC_TYPES_COUNT]; - exception_behavior_t behaviors[EXC_TYPES_COUNT]; - thread_state_flavor_t flavors[EXC_TYPES_COUNT]; - mach_msg_type_number_t count; - - kern_return_t Save(task_t task); - kern_return_t Restore(task_t task); - }; - - struct Data - { - task_t task_port; - thread_t thread_port; - exception_type_t exc_type; - std::vector<mach_exception_data_type_t> exc_data; - Data() : - task_port(TASK_NULL), - thread_port(THREAD_NULL), - exc_type(0), - exc_data() - { - } - - void Clear() - { - task_port = TASK_NULL; - thread_port = THREAD_NULL; - exc_type = 0; - exc_data.clear(); - } - bool IsValid() const - { - return task_port != TASK_NULL && - thread_port != THREAD_NULL && - exc_type != 0; - } - // Return the SoftSignal for this MachException data, or zero if there is none - int SoftSignal() const - { - if (exc_type == EXC_SOFTWARE && exc_data.size() == 2 && exc_data[0] == EXC_SOFT_SIGNAL) - return static_cast<int>(exc_data[1]); - return 0; - } - bool IsBreakpoint() const - { - return (exc_type == EXC_BREAKPOINT || ((exc_type == EXC_SOFTWARE) && exc_data[0] == 1)); - } - void Dump() const; - void DumpStopReason() const; - bool GetStopInfo(struct DNBThreadStopInfo *stop_info) const; - }; - - struct Message - { - MachMessage exc_msg; - MachMessage reply_msg; - Data state; - - Message() : - state() - { - memset(&exc_msg, 0, sizeof(exc_msg)); - memset(&reply_msg, 0, sizeof(reply_msg)); - } - bool CatchExceptionRaise(task_t task); - void Dump() const; - kern_return_t Reply (MachProcess *process, int signal); - kern_return_t Receive( mach_port_t receive_port, - mach_msg_option_t options, - mach_msg_timeout_t timeout, - mach_port_t notify_port = MACH_PORT_NULL); - - typedef std::vector<Message> collection; - typedef collection::iterator iterator; - typedef collection::const_iterator const_iterator; - }; - - enum - { - e_actionForward, // Forward signal to inferior process - e_actionStop, // Stop when this signal is received - }; - struct Action - { - task_t task_port; // Set to TASK_NULL for any TASK - thread_t thread_port; // Set to THREAD_NULL for any thread - exception_type_t exc_mask; // Mach exception mask to watch for - std::vector<mach_exception_data_type_t> exc_data_mask; // Mask to apply to exception data, or empty to ignore exc_data value for exception - std::vector<mach_exception_data_type_t> exc_data_value; // Value to compare to exception data after masking, or empty to ignore exc_data value for exception - uint8_t flags; // Action flags describing what to do with the exception - }; - static const char *Name(exception_type_t exc_type); + struct PortInfo { + exception_mask_t mask; // the exception mask for this device which may be a + // subset of EXC_MASK_ALL... + exception_mask_t masks[EXC_TYPES_COUNT]; + mach_port_t ports[EXC_TYPES_COUNT]; + exception_behavior_t behaviors[EXC_TYPES_COUNT]; + thread_state_flavor_t flavors[EXC_TYPES_COUNT]; + mach_msg_type_number_t count; + + kern_return_t Save(task_t task); + kern_return_t Restore(task_t task); + }; + + struct Data { + task_t task_port; + thread_t thread_port; + exception_type_t exc_type; + std::vector<mach_exception_data_type_t> exc_data; + Data() + : task_port(TASK_NULL), thread_port(THREAD_NULL), exc_type(0), + exc_data() {} + + void Clear() { + task_port = TASK_NULL; + thread_port = THREAD_NULL; + exc_type = 0; + exc_data.clear(); + } + bool IsValid() const { + return task_port != TASK_NULL && thread_port != THREAD_NULL && + exc_type != 0; + } + // Return the SoftSignal for this MachException data, or zero if there is + // none + int SoftSignal() const { + if (exc_type == EXC_SOFTWARE && exc_data.size() == 2 && + exc_data[0] == EXC_SOFT_SIGNAL) + return static_cast<int>(exc_data[1]); + return 0; + } + bool IsBreakpoint() const { + return (exc_type == EXC_BREAKPOINT || + ((exc_type == EXC_SOFTWARE) && exc_data[0] == 1)); + } + void Dump() const; + void DumpStopReason() const; + bool GetStopInfo(struct DNBThreadStopInfo *stop_info) const; + }; + + struct Message { + MachMessage exc_msg; + MachMessage reply_msg; + Data state; + + Message() : state() { + memset(&exc_msg, 0, sizeof(exc_msg)); + memset(&reply_msg, 0, sizeof(reply_msg)); + } + bool CatchExceptionRaise(task_t task); + void Dump() const; + kern_return_t Reply(MachProcess *process, int signal); + kern_return_t Receive(mach_port_t receive_port, mach_msg_option_t options, + mach_msg_timeout_t timeout, + mach_port_t notify_port = MACH_PORT_NULL); + + typedef std::vector<Message> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + }; + + enum { + e_actionForward, // Forward signal to inferior process + e_actionStop, // Stop when this signal is received + }; + struct Action { + task_t task_port; // Set to TASK_NULL for any TASK + thread_t thread_port; // Set to THREAD_NULL for any thread + exception_type_t exc_mask; // Mach exception mask to watch for + std::vector<mach_exception_data_type_t> exc_data_mask; // Mask to apply to + // exception data, or + // empty to ignore + // exc_data value for + // exception + std::vector<mach_exception_data_type_t> exc_data_value; // Value to compare + // to exception data + // after masking, or + // empty to ignore + // exc_data value + // for exception + uint8_t flags; // Action flags describing what to do with the exception + }; + static const char *Name(exception_type_t exc_type); }; #endif diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.h b/lldb/tools/debugserver/source/MacOSX/MachProcess.h index 094c13b8f0a..9ab06bcda9c 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachProcess.h +++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.h @@ -14,405 +14,432 @@ #ifndef __MachProcess_h__ #define __MachProcess_h__ -#include <mach/mach.h> +#include <CoreFoundation/CoreFoundation.h> #include <mach-o/loader.h> -#include <sys/signal.h> +#include <mach/mach.h> #include <pthread.h> +#include <sys/signal.h> #include <uuid/uuid.h> #include <vector> -#include <CoreFoundation/CoreFoundation.h> -#include "DNBDefs.h" #include "DNBBreakpoint.h" +#include "DNBDefs.h" #include "DNBError.h" #include "DNBThreadResumeActions.h" +#include "Genealogy.h" +#include "JSONGenerator.h" #include "MachException.h" -#include "MachVMMemory.h" #include "MachTask.h" #include "MachThreadList.h" +#include "MachVMMemory.h" #include "PThreadCondition.h" #include "PThreadEvent.h" #include "PThreadMutex.h" -#include "Genealogy.h" #include "ThreadInfo.h" -#include "JSONGenerator.h" class DNBThreadResumeActions; -class MachProcess -{ +class MachProcess { public: - //---------------------------------------------------------------------- - // Constructors and Destructors - //---------------------------------------------------------------------- - MachProcess (); - ~MachProcess (); - - // A structure that can hold everything debugserver needs to know from - // a binary's Mach-O header / load commands. - - struct mach_o_segment - { - std::string name; - uint64_t vmaddr; - uint64_t vmsize; - uint64_t fileoff; - uint64_t filesize; - uint64_t maxprot; - uint64_t initprot; - uint64_t nsects; - uint64_t flags; - }; - - struct mach_o_information - { - struct mach_header_64 mach_header; - std::vector<struct mach_o_segment> segments; - uuid_t uuid; - std::string min_version_os_name; - std::string min_version_os_version; - }; - - struct binary_image_information - { - std::string filename; - uint64_t load_address; - uint64_t mod_date; // may not be available - 0 if so - struct mach_o_information macho_info; - - binary_image_information () : - filename (), - load_address (INVALID_NUB_ADDRESS), - mod_date (0) - { } - }; - - //---------------------------------------------------------------------- - // Child process control - //---------------------------------------------------------------------- - pid_t AttachForDebug (pid_t pid, char *err_str, size_t err_len); - pid_t LaunchForDebug (const char *path, - char const *argv[], - char const *envp[], - const char *working_directory, - 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, - DNBError &err); - - static uint32_t GetCPUTypeForLocalProcess (pid_t pid); - static pid_t ForkChildForPTraceDebugging (const char *path, char const *argv[], char const *envp[], MachProcess* process, DNBError &err); - static pid_t PosixSpawnChildForPTraceDebugging (const char *path, - cpu_type_t cpu_type, - char const *argv[], - char const *envp[], - const char *working_directory, - const char *stdin_path, - const char *stdout_path, - const char *stderr_path, - bool no_stdio, - MachProcess* process, - int disable_aslr, - DNBError& err); - nub_addr_t GetDYLDAllImageInfosAddress (); - static const void * PrepareForAttach (const char *path, nub_launch_flavor_t launch_flavor, bool waitfor, DNBError &err_str); - static void CleanupAfterAttach (const void *attach_token, nub_launch_flavor_t launch_flavor, bool success, DNBError &err_str); - static nub_process_t CheckForProcess (const void *attach_token, nub_launch_flavor_t launch_flavor); + //---------------------------------------------------------------------- + // Constructors and Destructors + //---------------------------------------------------------------------- + MachProcess(); + ~MachProcess(); + + // A structure that can hold everything debugserver needs to know from + // a binary's Mach-O header / load commands. + + struct mach_o_segment { + std::string name; + uint64_t vmaddr; + uint64_t vmsize; + uint64_t fileoff; + uint64_t filesize; + uint64_t maxprot; + uint64_t initprot; + uint64_t nsects; + uint64_t flags; + }; + + struct mach_o_information { + struct mach_header_64 mach_header; + std::vector<struct mach_o_segment> segments; + uuid_t uuid; + std::string min_version_os_name; + std::string min_version_os_version; + }; + + struct binary_image_information { + std::string filename; + uint64_t load_address; + uint64_t mod_date; // may not be available - 0 if so + struct mach_o_information macho_info; + + binary_image_information() + : filename(), load_address(INVALID_NUB_ADDRESS), mod_date(0) {} + }; + + //---------------------------------------------------------------------- + // Child process control + //---------------------------------------------------------------------- + pid_t AttachForDebug(pid_t pid, char *err_str, size_t err_len); + pid_t LaunchForDebug(const char *path, char const *argv[], char const *envp[], + const char *working_directory, 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, DNBError &err); + + static uint32_t GetCPUTypeForLocalProcess(pid_t pid); + static pid_t ForkChildForPTraceDebugging(const char *path, char const *argv[], + char const *envp[], + MachProcess *process, DNBError &err); + static pid_t PosixSpawnChildForPTraceDebugging( + const char *path, cpu_type_t cpu_type, char const *argv[], + char const *envp[], const char *working_directory, const char *stdin_path, + const char *stdout_path, const char *stderr_path, bool no_stdio, + MachProcess *process, int disable_aslr, DNBError &err); + nub_addr_t GetDYLDAllImageInfosAddress(); + static const void *PrepareForAttach(const char *path, + nub_launch_flavor_t launch_flavor, + bool waitfor, DNBError &err_str); + static void CleanupAfterAttach(const void *attach_token, + nub_launch_flavor_t launch_flavor, + bool success, DNBError &err_str); + static nub_process_t CheckForProcess(const void *attach_token, + nub_launch_flavor_t launch_flavor); #if defined(WITH_BKS) || defined(WITH_FBS) - pid_t BoardServiceLaunchForDebug (const char *app_bundle_path, char const *argv[], char const *envp[], bool no_stdio, bool disable_aslr, const char *event_data, DNBError &launch_err); - pid_t BoardServiceForkChildForPTraceDebugging (const char *path, char const *argv[], char const *envp[], bool no_stdio, bool disable_aslr, const char *event_data, DNBError &launch_err); - bool BoardServiceSendEvent (const char *event, DNBError &error); + pid_t BoardServiceLaunchForDebug(const char *app_bundle_path, + char const *argv[], char const *envp[], + bool no_stdio, bool disable_aslr, + const char *event_data, + DNBError &launch_err); + pid_t BoardServiceForkChildForPTraceDebugging( + const char *path, char const *argv[], char const *envp[], bool no_stdio, + bool disable_aslr, const char *event_data, DNBError &launch_err); + bool BoardServiceSendEvent(const char *event, DNBError &error); #endif - static bool GetOSVersionNumbers (uint64_t *major, uint64_t *minor, uint64_t *patch); + static bool GetOSVersionNumbers(uint64_t *major, uint64_t *minor, + uint64_t *patch); #ifdef WITH_BKS - static void BKSCleanupAfterAttach (const void *attach_token, DNBError &err_str); + static void BKSCleanupAfterAttach(const void *attach_token, + DNBError &err_str); #endif // WITH_BKS #ifdef WITH_FBS - static void FBSCleanupAfterAttach (const void *attach_token, DNBError &err_str); -#endif // WITH_FBS + static void FBSCleanupAfterAttach(const void *attach_token, + DNBError &err_str); +#endif // WITH_FBS #ifdef WITH_SPRINGBOARD - pid_t SBLaunchForDebug (const char *app_bundle_path, char const *argv[], char const *envp[], bool no_stdio, bool disable_aslr, DNBError &launch_err); - static pid_t SBForkChildForPTraceDebugging (const char *path, char const *argv[], char const *envp[], bool no_stdio, MachProcess* process, DNBError &launch_err); -#endif // WITH_SPRINGBOARD - nub_addr_t LookupSymbol (const char *name, const char *shlib); - void SetNameToAddressCallback (DNBCallbackNameToAddress callback, void *baton) - { - m_name_to_addr_callback = callback; - m_name_to_addr_baton = baton; - } - void SetSharedLibraryInfoCallback (DNBCallbackCopyExecutableImageInfos callback, void *baton) - { - m_image_infos_callback = callback; - m_image_infos_baton = baton; - } - - bool Resume (const DNBThreadResumeActions& thread_actions); - bool Signal (int signal, const struct timespec *timeout_abstime = NULL); - bool Interrupt(); - bool SendEvent (const char *event, DNBError &send_err); - bool Kill (const struct timespec *timeout_abstime = NULL); - bool Detach (); - nub_size_t ReadMemory (nub_addr_t addr, nub_size_t size, void *buf); - nub_size_t WriteMemory (nub_addr_t addr, nub_size_t size, const void *buf); - - //---------------------------------------------------------------------- - // Path and arg accessors - //---------------------------------------------------------------------- - const char * Path () const { return m_path.c_str(); } - size_t ArgumentCount () const { return m_args.size(); } - const char * ArgumentAtIndex (size_t arg_idx) const - { - if (arg_idx < m_args.size()) - return m_args[arg_idx].c_str(); - return NULL; - } - - //---------------------------------------------------------------------- - // Breakpoint functions - //---------------------------------------------------------------------- - DNBBreakpoint * CreateBreakpoint (nub_addr_t addr, nub_size_t length, bool hardware); - bool DisableBreakpoint (nub_addr_t addr, bool remove); - void DisableAllBreakpoints (bool remove); - bool EnableBreakpoint (nub_addr_t addr); - DNBBreakpointList& Breakpoints() { return m_breakpoints; } - const DNBBreakpointList& Breakpoints() const { return m_breakpoints; } - - //---------------------------------------------------------------------- - // Watchpoint functions - //---------------------------------------------------------------------- - DNBBreakpoint * CreateWatchpoint (nub_addr_t addr, nub_size_t length, uint32_t watch_type, bool hardware); - bool DisableWatchpoint (nub_addr_t addr, bool remove); - void DisableAllWatchpoints (bool remove); - bool EnableWatchpoint (nub_addr_t addr); - uint32_t GetNumSupportedHardwareWatchpoints () const; - DNBBreakpointList& Watchpoints() { return m_watchpoints; } - const DNBBreakpointList& Watchpoints() const { return m_watchpoints; } - - //---------------------------------------------------------------------- - // Exception thread functions - //---------------------------------------------------------------------- - bool StartSTDIOThread (); - static void * STDIOThread (void *arg); - void ExceptionMessageReceived (const MachException::Message& exceptionMessage); - task_t ExceptionMessageBundleComplete (); - void SharedLibrariesUpdated (); - nub_size_t CopyImageInfos (struct DNBExecutableImageInfo **image_infos, bool only_changed); - - //---------------------------------------------------------------------- - // Profile functions - //---------------------------------------------------------------------- - void SetEnableAsyncProfiling (bool enable, uint64_t internal_usec, DNBProfileDataScanType scan_type); - bool IsProfilingEnabled () { return m_profile_enabled; } - useconds_t ProfileInterval () { return m_profile_interval_usec; } - bool StartProfileThread (); - static void * ProfileThread (void *arg); - void SignalAsyncProfileData (const char *info); - size_t GetAsyncProfileData (char *buf, size_t buf_size); - - //---------------------------------------------------------------------- - // Accessors - //---------------------------------------------------------------------- - pid_t ProcessID () const { return m_pid; } - bool ProcessIDIsValid () const { return m_pid > 0; } - pid_t SetProcessID (pid_t pid); - MachTask& Task() { return m_task; } - const MachTask& Task() const { return m_task; } - - PThreadEvent& Events() { return m_events; } - const DNBRegisterSetInfo * - GetRegisterSetInfo (nub_thread_t tid, nub_size_t *num_reg_sets) const; - bool GetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *reg_value) const; - bool SetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value) const; - nub_bool_t SyncThreadState (nub_thread_t tid); - const char * ThreadGetName (nub_thread_t tid); - nub_state_t ThreadGetState (nub_thread_t tid); - ThreadInfo::QoS GetRequestedQoS (nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index); - nub_addr_t GetPThreadT (nub_thread_t tid); - nub_addr_t GetDispatchQueueT (nub_thread_t tid); - nub_addr_t GetTSDAddressForThread (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); - - - bool GetMachOInformationFromMemory (nub_addr_t mach_o_header_addr, int wordsize, struct mach_o_information &inf); - JSONGenerator::ObjectSP FormatDynamicLibrariesIntoJSON (const std::vector<struct binary_image_information> &image_infos); - void GetAllLoadedBinariesViaDYLDSPI (std::vector<struct binary_image_information> &image_infos); - JSONGenerator::ObjectSP GetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count); - JSONGenerator::ObjectSP GetLibrariesInfoForAddresses (nub_process_t pid, std::vector<uint64_t> &macho_addresses); - JSONGenerator::ObjectSP GetAllLoadedLibrariesInfos (nub_process_t pid); - JSONGenerator::ObjectSP GetSharedCacheInfo (nub_process_t pid); - - nub_size_t GetNumThreads () const; - nub_thread_t GetThreadAtIndex (nub_size_t thread_idx) const; - nub_thread_t GetCurrentThread (); - nub_thread_t GetCurrentThreadMachPort (); - nub_thread_t SetCurrentThread (nub_thread_t tid); - MachThreadList & GetThreadList() { return m_thread_list; } - bool GetThreadStoppedReason(nub_thread_t tid, struct DNBThreadStopInfo *stop_info); - void DumpThreadStoppedReason(nub_thread_t tid) const; - const char * GetThreadInfo (nub_thread_t tid) const; - - nub_thread_t GetThreadIDForMachPortNumber (thread_t mach_port_number) const; - - uint32_t GetCPUType (); - nub_state_t GetState (); - void SetState (nub_state_t state); - bool IsRunning (nub_state_t state) - { - return state == eStateRunning || IsStepping(state); - } - bool IsStepping (nub_state_t state) - { - return state == eStateStepping; - } - bool CanResume (nub_state_t state) - { - return state == eStateStopped; - } - - bool GetExitStatus(int* status) - { - if (GetState() == eStateExited) - { - if (status) - *status = m_exit_status; - return true; - } - return false; - } - void SetExitStatus(int status) - { - m_exit_status = status; - SetState(eStateExited); - } - const char * GetExitInfo () - { - return m_exit_info.c_str(); - } - - void SetExitInfo (const char *info); - - uint32_t StopCount() const { return m_stop_count; } - void SetChildFileDescriptors (int stdin_fileno, int stdout_fileno, int stderr_fileno) - { - m_child_stdin = stdin_fileno; - m_child_stdout = stdout_fileno; - m_child_stderr = stderr_fileno; - } - - int GetStdinFileDescriptor () const { return m_child_stdin; } - int GetStdoutFileDescriptor () const { return m_child_stdout; } - int GetStderrFileDescriptor () const { return m_child_stderr; } - void AppendSTDOUT (char* s, size_t len); - size_t GetAvailableSTDOUT (char *buf, size_t buf_size); - size_t GetAvailableSTDERR (char *buf, size_t buf_size); - void CloseChildFileDescriptors () - { - if (m_child_stdin >= 0) - { - ::close (m_child_stdin); - m_child_stdin = -1; - } - if (m_child_stdout >= 0) - { - ::close (m_child_stdout); - m_child_stdout = -1; - } - if (m_child_stderr >= 0) - { - ::close (m_child_stderr); - m_child_stderr = -1; - } - } - - bool ProcessUsingSpringBoard() const { return (m_flags & eMachProcessFlagsUsingSBS) != 0; } - bool ProcessUsingBackBoard() const { return (m_flags & eMachProcessFlagsUsingBKS) != 0; } - - Genealogy::ThreadActivitySP GetGenealogyInfoForThread (nub_thread_t tid, bool &timed_out); - - Genealogy::ProcessExecutableInfoSP GetGenealogyImageInfo (size_t idx); - - DNBProfileDataScanType GetProfileScanType () { return m_profile_scan_type; } + pid_t SBLaunchForDebug(const char *app_bundle_path, char const *argv[], + char const *envp[], bool no_stdio, bool disable_aslr, + DNBError &launch_err); + static pid_t SBForkChildForPTraceDebugging(const char *path, + char const *argv[], + char const *envp[], bool no_stdio, + MachProcess *process, + DNBError &launch_err); +#endif // WITH_SPRINGBOARD + nub_addr_t LookupSymbol(const char *name, const char *shlib); + void SetNameToAddressCallback(DNBCallbackNameToAddress callback, + void *baton) { + m_name_to_addr_callback = callback; + m_name_to_addr_baton = baton; + } + void + SetSharedLibraryInfoCallback(DNBCallbackCopyExecutableImageInfos callback, + void *baton) { + m_image_infos_callback = callback; + m_image_infos_baton = baton; + } + + bool Resume(const DNBThreadResumeActions &thread_actions); + bool Signal(int signal, const struct timespec *timeout_abstime = NULL); + bool Interrupt(); + bool SendEvent(const char *event, DNBError &send_err); + bool Kill(const struct timespec *timeout_abstime = NULL); + bool Detach(); + nub_size_t ReadMemory(nub_addr_t addr, nub_size_t size, void *buf); + nub_size_t WriteMemory(nub_addr_t addr, nub_size_t size, const void *buf); + + //---------------------------------------------------------------------- + // Path and arg accessors + //---------------------------------------------------------------------- + const char *Path() const { return m_path.c_str(); } + size_t ArgumentCount() const { return m_args.size(); } + const char *ArgumentAtIndex(size_t arg_idx) const { + if (arg_idx < m_args.size()) + return m_args[arg_idx].c_str(); + return NULL; + } + + //---------------------------------------------------------------------- + // Breakpoint functions + //---------------------------------------------------------------------- + DNBBreakpoint *CreateBreakpoint(nub_addr_t addr, nub_size_t length, + bool hardware); + bool DisableBreakpoint(nub_addr_t addr, bool remove); + void DisableAllBreakpoints(bool remove); + bool EnableBreakpoint(nub_addr_t addr); + DNBBreakpointList &Breakpoints() { return m_breakpoints; } + const DNBBreakpointList &Breakpoints() const { return m_breakpoints; } + + //---------------------------------------------------------------------- + // Watchpoint functions + //---------------------------------------------------------------------- + DNBBreakpoint *CreateWatchpoint(nub_addr_t addr, nub_size_t length, + uint32_t watch_type, bool hardware); + bool DisableWatchpoint(nub_addr_t addr, bool remove); + void DisableAllWatchpoints(bool remove); + bool EnableWatchpoint(nub_addr_t addr); + uint32_t GetNumSupportedHardwareWatchpoints() const; + DNBBreakpointList &Watchpoints() { return m_watchpoints; } + const DNBBreakpointList &Watchpoints() const { return m_watchpoints; } + + //---------------------------------------------------------------------- + // Exception thread functions + //---------------------------------------------------------------------- + bool StartSTDIOThread(); + static void *STDIOThread(void *arg); + void ExceptionMessageReceived(const MachException::Message &exceptionMessage); + task_t ExceptionMessageBundleComplete(); + void SharedLibrariesUpdated(); + nub_size_t CopyImageInfos(struct DNBExecutableImageInfo **image_infos, + bool only_changed); + + //---------------------------------------------------------------------- + // Profile functions + //---------------------------------------------------------------------- + void SetEnableAsyncProfiling(bool enable, uint64_t internal_usec, + DNBProfileDataScanType scan_type); + bool IsProfilingEnabled() { return m_profile_enabled; } + useconds_t ProfileInterval() { return m_profile_interval_usec; } + bool StartProfileThread(); + static void *ProfileThread(void *arg); + void SignalAsyncProfileData(const char *info); + size_t GetAsyncProfileData(char *buf, size_t buf_size); + + //---------------------------------------------------------------------- + // Accessors + //---------------------------------------------------------------------- + pid_t ProcessID() const { return m_pid; } + bool ProcessIDIsValid() const { return m_pid > 0; } + pid_t SetProcessID(pid_t pid); + MachTask &Task() { return m_task; } + const MachTask &Task() const { return m_task; } + + PThreadEvent &Events() { return m_events; } + const DNBRegisterSetInfo *GetRegisterSetInfo(nub_thread_t tid, + nub_size_t *num_reg_sets) const; + bool GetRegisterValue(nub_thread_t tid, uint32_t set, uint32_t reg, + DNBRegisterValue *reg_value) const; + bool SetRegisterValue(nub_thread_t tid, uint32_t set, uint32_t reg, + const DNBRegisterValue *value) const; + nub_bool_t SyncThreadState(nub_thread_t tid); + const char *ThreadGetName(nub_thread_t tid); + nub_state_t ThreadGetState(nub_thread_t tid); + ThreadInfo::QoS GetRequestedQoS(nub_thread_t tid, nub_addr_t tsd, + uint64_t dti_qos_class_index); + nub_addr_t GetPThreadT(nub_thread_t tid); + nub_addr_t GetDispatchQueueT(nub_thread_t tid); + nub_addr_t + GetTSDAddressForThread(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); + + bool GetMachOInformationFromMemory(nub_addr_t mach_o_header_addr, + int wordsize, + struct mach_o_information &inf); + JSONGenerator::ObjectSP FormatDynamicLibrariesIntoJSON( + const std::vector<struct binary_image_information> &image_infos); + void GetAllLoadedBinariesViaDYLDSPI( + std::vector<struct binary_image_information> &image_infos); + JSONGenerator::ObjectSP GetLoadedDynamicLibrariesInfos( + nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count); + JSONGenerator::ObjectSP + GetLibrariesInfoForAddresses(nub_process_t pid, + std::vector<uint64_t> &macho_addresses); + JSONGenerator::ObjectSP GetAllLoadedLibrariesInfos(nub_process_t pid); + JSONGenerator::ObjectSP GetSharedCacheInfo(nub_process_t pid); + + nub_size_t GetNumThreads() const; + nub_thread_t GetThreadAtIndex(nub_size_t thread_idx) const; + nub_thread_t GetCurrentThread(); + nub_thread_t GetCurrentThreadMachPort(); + nub_thread_t SetCurrentThread(nub_thread_t tid); + MachThreadList &GetThreadList() { return m_thread_list; } + bool GetThreadStoppedReason(nub_thread_t tid, + struct DNBThreadStopInfo *stop_info); + void DumpThreadStoppedReason(nub_thread_t tid) const; + const char *GetThreadInfo(nub_thread_t tid) const; + + nub_thread_t GetThreadIDForMachPortNumber(thread_t mach_port_number) const; + + uint32_t GetCPUType(); + nub_state_t GetState(); + void SetState(nub_state_t state); + bool IsRunning(nub_state_t state) { + return state == eStateRunning || IsStepping(state); + } + bool IsStepping(nub_state_t state) { return state == eStateStepping; } + bool CanResume(nub_state_t state) { return state == eStateStopped; } + + bool GetExitStatus(int *status) { + if (GetState() == eStateExited) { + if (status) + *status = m_exit_status; + return true; + } + return false; + } + void SetExitStatus(int status) { + m_exit_status = status; + SetState(eStateExited); + } + const char *GetExitInfo() { return m_exit_info.c_str(); } + + void SetExitInfo(const char *info); + + uint32_t StopCount() const { return m_stop_count; } + void SetChildFileDescriptors(int stdin_fileno, int stdout_fileno, + int stderr_fileno) { + m_child_stdin = stdin_fileno; + m_child_stdout = stdout_fileno; + m_child_stderr = stderr_fileno; + } + + int GetStdinFileDescriptor() const { return m_child_stdin; } + int GetStdoutFileDescriptor() const { return m_child_stdout; } + int GetStderrFileDescriptor() const { return m_child_stderr; } + void AppendSTDOUT(char *s, size_t len); + size_t GetAvailableSTDOUT(char *buf, size_t buf_size); + size_t GetAvailableSTDERR(char *buf, size_t buf_size); + void CloseChildFileDescriptors() { + if (m_child_stdin >= 0) { + ::close(m_child_stdin); + m_child_stdin = -1; + } + if (m_child_stdout >= 0) { + ::close(m_child_stdout); + m_child_stdout = -1; + } + if (m_child_stderr >= 0) { + ::close(m_child_stderr); + m_child_stderr = -1; + } + } + + bool ProcessUsingSpringBoard() const { + return (m_flags & eMachProcessFlagsUsingSBS) != 0; + } + bool ProcessUsingBackBoard() const { + return (m_flags & eMachProcessFlagsUsingBKS) != 0; + } + + Genealogy::ThreadActivitySP GetGenealogyInfoForThread(nub_thread_t tid, + bool &timed_out); + + Genealogy::ProcessExecutableInfoSP GetGenealogyImageInfo(size_t idx); + + DNBProfileDataScanType GetProfileScanType() { return m_profile_scan_type; } private: - enum - { - eMachProcessFlagsNone = 0, - eMachProcessFlagsAttached = (1 << 0), - eMachProcessFlagsUsingSBS = (1 << 1), - eMachProcessFlagsUsingBKS = (1 << 2), - eMachProcessFlagsUsingFBS = (1 << 3) - }; - void Clear (bool detaching = false); - void ReplyToAllExceptions (); - void PrivateResume (); - - uint32_t Flags () const { return m_flags; } - nub_state_t DoSIGSTOP (bool clear_bps_and_wps, bool allow_running, uint32_t *thread_idx_ptr); - - pid_t m_pid; // Process ID of child process - cpu_type_t m_cpu_type; // The CPU type of this process - int m_child_stdin; - int m_child_stdout; - int m_child_stderr; - std::string m_path; // A path to the executable if we have one - std::vector<std::string> m_args; // The arguments with which the process was lauched - int m_exit_status; // The exit status for the process - std::string m_exit_info; // Any extra info that we may have about the exit - MachTask m_task; // The mach task for this process - uint32_t m_flags; // Process specific flags (see eMachProcessFlags enums) - uint32_t m_stop_count; // A count of many times have we stopped - pthread_t m_stdio_thread; // Thread ID for the thread that watches for child process stdio - PThreadMutex m_stdio_mutex; // Multithreaded protection for stdio - std::string m_stdout_data; - - bool m_profile_enabled; // A flag to indicate if profiling is enabled - useconds_t m_profile_interval_usec; // If enable, the profiling interval in microseconds - DNBProfileDataScanType m_profile_scan_type; // Indicates what needs to be profiled - pthread_t m_profile_thread; // Thread ID for the thread that profiles the inferior - PThreadMutex m_profile_data_mutex; // Multithreaded protection for profile info data - std::vector<std::string> m_profile_data; // Profile data, must be protected by m_profile_data_mutex - - DNBThreadResumeActions m_thread_actions; // The thread actions for the current MachProcess::Resume() call - MachException::Message::collection - m_exception_messages; // A collection of exception messages caught when listening to the exception port - PThreadMutex m_exception_messages_mutex; // Multithreaded protection for m_exception_messages - - MachThreadList m_thread_list; // A list of threads that is maintained/updated after each stop - Genealogy m_activities; // A list of activities that is updated after every stop lazily - nub_state_t m_state; // The state of our process - PThreadMutex m_state_mutex; // Multithreaded protection for m_state - PThreadEvent m_events; // Process related events in the child processes lifetime can be waited upon - PThreadEvent m_private_events; // Used to coordinate running and stopping the process without affecting m_events - DNBBreakpointList m_breakpoints; // Breakpoint list for this process - DNBBreakpointList m_watchpoints; // Watchpoint list for this process - DNBCallbackNameToAddress m_name_to_addr_callback; - void * m_name_to_addr_baton; - DNBCallbackCopyExecutableImageInfos - m_image_infos_callback; - void * m_image_infos_baton; - std::string m_bundle_id; // If we are a SB or BKS process, this will be our bundle ID. - int m_sent_interrupt_signo; // When we call MachProcess::Interrupt(), we want to send a single signal - // to the inferior and only send the signal if we aren't already stopped. - // If we end up sending a signal to stop the process we store it until we - // receive an exception with this signal. This helps us to verify we got - // the signal that interrupted the process. We might stop due to another - // reason after an interrupt signal is sent, so this helps us ensure that - // we don't report a spurious stop on the next resume. - int m_auto_resume_signo; // If we resume the process and still haven't received our interrupt signal - // acknownledgement, we will shortly after the next resume. We store the - // interrupt signal in this variable so when we get the interrupt signal - // as the sole reason for the process being stopped, we can auto resume - // the process. - bool m_did_exec; - - void * (*m_dyld_process_info_create) (task_t task, uint64_t timestamp, kern_return_t* kernelError); - void (*m_dyld_process_info_for_each_image) (void* info, void (^callback)(uint64_t machHeaderAddress, const uuid_t uuid, const char* path)); - void (*m_dyld_process_info_release) (void* info); - void (*m_dyld_process_info_get_cache) (void* info, void* cacheInfo); + enum { + eMachProcessFlagsNone = 0, + eMachProcessFlagsAttached = (1 << 0), + eMachProcessFlagsUsingSBS = (1 << 1), + eMachProcessFlagsUsingBKS = (1 << 2), + eMachProcessFlagsUsingFBS = (1 << 3) + }; + void Clear(bool detaching = false); + void ReplyToAllExceptions(); + void PrivateResume(); + + uint32_t Flags() const { return m_flags; } + nub_state_t DoSIGSTOP(bool clear_bps_and_wps, bool allow_running, + uint32_t *thread_idx_ptr); + + pid_t m_pid; // Process ID of child process + cpu_type_t m_cpu_type; // The CPU type of this process + int m_child_stdin; + int m_child_stdout; + int m_child_stderr; + std::string m_path; // A path to the executable if we have one + std::vector<std::string> + m_args; // The arguments with which the process was lauched + int m_exit_status; // The exit status for the process + std::string m_exit_info; // Any extra info that we may have about the exit + MachTask m_task; // The mach task for this process + uint32_t m_flags; // Process specific flags (see eMachProcessFlags enums) + uint32_t m_stop_count; // A count of many times have we stopped + pthread_t m_stdio_thread; // Thread ID for the thread that watches for child + // process stdio + PThreadMutex m_stdio_mutex; // Multithreaded protection for stdio + std::string m_stdout_data; + + bool m_profile_enabled; // A flag to indicate if profiling is enabled + useconds_t m_profile_interval_usec; // If enable, the profiling interval in + // microseconds + DNBProfileDataScanType + m_profile_scan_type; // Indicates what needs to be profiled + pthread_t + m_profile_thread; // Thread ID for the thread that profiles the inferior + PThreadMutex + m_profile_data_mutex; // Multithreaded protection for profile info data + std::vector<std::string> + m_profile_data; // Profile data, must be protected by m_profile_data_mutex + + DNBThreadResumeActions m_thread_actions; // The thread actions for the current + // MachProcess::Resume() call + MachException::Message::collection m_exception_messages; // A collection of + // exception messages + // caught when + // listening to the + // exception port + PThreadMutex m_exception_messages_mutex; // Multithreaded protection for + // m_exception_messages + + MachThreadList m_thread_list; // A list of threads that is maintained/updated + // after each stop + Genealogy m_activities; // A list of activities that is updated after every + // stop lazily + nub_state_t m_state; // The state of our process + PThreadMutex m_state_mutex; // Multithreaded protection for m_state + PThreadEvent m_events; // Process related events in the child processes + // lifetime can be waited upon + PThreadEvent m_private_events; // Used to coordinate running and stopping the + // process without affecting m_events + DNBBreakpointList m_breakpoints; // Breakpoint list for this process + DNBBreakpointList m_watchpoints; // Watchpoint list for this process + DNBCallbackNameToAddress m_name_to_addr_callback; + void *m_name_to_addr_baton; + DNBCallbackCopyExecutableImageInfos m_image_infos_callback; + void *m_image_infos_baton; + std::string + m_bundle_id; // If we are a SB or BKS process, this will be our bundle ID. + int m_sent_interrupt_signo; // When we call MachProcess::Interrupt(), we want + // to send a single signal + // to the inferior and only send the signal if we aren't already stopped. + // If we end up sending a signal to stop the process we store it until we + // receive an exception with this signal. This helps us to verify we got + // the signal that interrupted the process. We might stop due to another + // reason after an interrupt signal is sent, so this helps us ensure that + // we don't report a spurious stop on the next resume. + int m_auto_resume_signo; // If we resume the process and still haven't + // received our interrupt signal + // acknownledgement, we will shortly after the next resume. We store the + // interrupt signal in this variable so when we get the interrupt signal + // as the sole reason for the process being stopped, we can auto resume + // the process. + bool m_did_exec; + + void *(*m_dyld_process_info_create)(task_t task, uint64_t timestamp, + kern_return_t *kernelError); + void (*m_dyld_process_info_for_each_image)( + void *info, void (^callback)(uint64_t machHeaderAddress, + const uuid_t uuid, const char *path)); + void (*m_dyld_process_info_release)(void *info); + void (*m_dyld_process_info_get_cache)(void *info, void *cacheInfo); }; - #endif // __MachProcess_h__ diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.mm b/lldb/tools/debugserver/source/MacOSX/MachProcess.mm index cea1772d27d..e0f3290ff0d 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachProcess.mm +++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.mm @@ -12,23 +12,23 @@ //===----------------------------------------------------------------------===// #include "DNB.h" +#include "MacOSX/CFUtils.h" +#include "SysSignal.h" #include <dlfcn.h> #include <inttypes.h> +#include <mach-o/loader.h> #include <mach/mach.h> #include <mach/task.h> +#include <pthread.h> #include <signal.h> #include <spawn.h> #include <sys/fcntl.h> -#include <sys/types.h> #include <sys/ptrace.h> #include <sys/stat.h> #include <sys/sysctl.h> +#include <sys/types.h> #include <unistd.h> -#include <pthread.h> -#include <mach-o/loader.h> #include <uuid/uuid.h> -#include "MacOSX/CFUtils.h" -#include "SysSignal.h" #include <algorithm> #include <map> @@ -48,329 +48,359 @@ #ifdef WITH_SPRINGBOARD #include <CoreFoundation/CoreFoundation.h> -#include <SpringBoardServices/SpringBoardServer.h> #include <SpringBoardServices/SBSWatchdogAssertion.h> +#include <SpringBoardServices/SpringBoardServer.h> -static bool -IsSBProcess (nub_process_t pid) -{ - CFReleaser<CFArrayRef> appIdsForPID (::SBSCopyDisplayIdentifiersForProcessID(pid)); - return appIdsForPID.get() != NULL; +static bool IsSBProcess(nub_process_t pid) { + CFReleaser<CFArrayRef> appIdsForPID( + ::SBSCopyDisplayIdentifiersForProcessID(pid)); + return appIdsForPID.get() != NULL; } #endif // WITH_SPRINGBOARD -#if defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined (WITH_FBS) +#if defined(WITH_SPRINGBOARD) || defined(WITH_BKS) || defined(WITH_FBS) // This returns a CFRetained pointer to the Bundle ID for app_bundle_path, // or NULL if there was some problem getting the bundle id. -static CFStringRef CopyBundleIDForPath (const char *app_bundle_path, DNBError &err_str); +static CFStringRef CopyBundleIDForPath(const char *app_bundle_path, + DNBError &err_str); #endif #if defined(WITH_BKS) || defined(WITH_FBS) #import <Foundation/Foundation.h> static const int OPEN_APPLICATION_TIMEOUT_ERROR = 111; -typedef void (*SetErrorFunction) (NSInteger, DNBError &); -typedef bool (*CallOpenApplicationFunction) (NSString *bundleIDNSStr, NSDictionary *options, DNBError &error, pid_t *return_pid); -// This function runs the BKSSystemService (or FBSSystemService) method openApplication:options:clientPort:withResult, +typedef void (*SetErrorFunction)(NSInteger, DNBError &); +typedef bool (*CallOpenApplicationFunction)(NSString *bundleIDNSStr, + NSDictionary *options, + DNBError &error, pid_t *return_pid); +// This function runs the BKSSystemService (or FBSSystemService) method +// openApplication:options:clientPort:withResult, // messaging the app passed in bundleIDNSStr. // The function should be run inside of an NSAutoReleasePool. // -// It will use the "options" dictionary passed in, and fill the error passed in if there is an error. -// If return_pid is not NULL, we'll fetch the pid that was made for the bundleID. +// It will use the "options" dictionary passed in, and fill the error passed in +// if there is an error. +// If return_pid is not NULL, we'll fetch the pid that was made for the +// bundleID. // If bundleIDNSStr is NULL, then the system application will be messaged. -template <typename OpenFlavor, typename ErrorFlavor, ErrorFlavor no_error_enum_value, SetErrorFunction error_function> -static bool -CallBoardSystemServiceOpenApplication (NSString *bundleIDNSStr, NSDictionary *options, DNBError &error, pid_t *return_pid) -{ - // Now make our systemService: - OpenFlavor *system_service = [[OpenFlavor alloc] init]; - - if (bundleIDNSStr == nil) - { - bundleIDNSStr = [system_service systemApplicationBundleIdentifier]; - if (bundleIDNSStr == nil) - { - // Okay, no system app... - error.SetErrorString("No system application to message."); - return false; - } - } - - mach_port_t client_port = [system_service createClientPort]; - __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); - __block ErrorFlavor open_app_error = no_error_enum_value; - bool wants_pid = (return_pid != NULL); - __block pid_t pid_in_block; - - const char *cstr = [bundleIDNSStr UTF8String]; - if (!cstr) - cstr = "<Unknown Bundle ID>"; - - DNBLog ("About to launch process for bundle ID: %s", cstr); - [system_service openApplication: bundleIDNSStr - options: options - clientPort: client_port - withResult: ^(NSError *bks_error) - { - // The system service will cleanup the client port we created for us. - if (bks_error) - open_app_error = (ErrorFlavor)[bks_error code]; - - if (open_app_error == no_error_enum_value) - { - if (wants_pid) - { - pid_in_block = [system_service pidForApplication: bundleIDNSStr]; - DNBLog("In completion handler, got pid for bundle id, pid: %d.", pid_in_block); - DNBLogThreadedIf(LOG_PROCESS, "In completion handler, got pid for bundle id, pid: %d.", pid_in_block); - } - else - DNBLogThreadedIf (LOG_PROCESS, "In completion handler: success."); - } - else - { - const char *error_str = [(NSString *)[bks_error localizedDescription] UTF8String]; - DNBLogThreadedIf(LOG_PROCESS, "In completion handler for send event, got error \"%s\"(%ld).", - error_str ? error_str : "<unknown error>", - open_app_error); - // REMOVE ME - DNBLogError ("In completion handler for send event, got error \"%s\"(%ld).", - error_str ? error_str : "<unknown error>", - open_app_error); - } - - [system_service release]; - dispatch_semaphore_signal(semaphore); - } - - ]; - - const uint32_t timeout_secs = 9; - - dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, timeout_secs * NSEC_PER_SEC); - - long success = dispatch_semaphore_wait(semaphore, timeout) == 0; - - dispatch_release(semaphore); - - if (!success) -{ - DNBLogError("timed out trying to send openApplication to %s.", cstr); - error.SetError (OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic); - error.SetErrorString ("timed out trying to launch app"); - } - else if (open_app_error != no_error_enum_value) - { - error_function (open_app_error, error); - DNBLogError("unable to launch the application with CFBundleIdentifier '%s' bks_error = %u", cstr, open_app_error); - success = false; - } - else if (wants_pid) - { - *return_pid = pid_in_block; - DNBLogThreadedIf (LOG_PROCESS, "Out of completion handler, pid from block %d and passing out: %d", pid_in_block, *return_pid); -} - - - return success; +template <typename OpenFlavor, typename ErrorFlavor, + ErrorFlavor no_error_enum_value, SetErrorFunction error_function> +static bool CallBoardSystemServiceOpenApplication(NSString *bundleIDNSStr, + NSDictionary *options, + DNBError &error, + pid_t *return_pid) { + // Now make our systemService: + OpenFlavor *system_service = [[OpenFlavor alloc] init]; + + if (bundleIDNSStr == nil) { + bundleIDNSStr = [system_service systemApplicationBundleIdentifier]; + if (bundleIDNSStr == nil) { + // Okay, no system app... + error.SetErrorString("No system application to message."); + return false; + } + } + + mach_port_t client_port = [system_service createClientPort]; + __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + __block ErrorFlavor open_app_error = no_error_enum_value; + bool wants_pid = (return_pid != NULL); + __block pid_t pid_in_block; + + const char *cstr = [bundleIDNSStr UTF8String]; + if (!cstr) + cstr = "<Unknown Bundle ID>"; + + DNBLog("About to launch process for bundle ID: %s", cstr); + [system_service + openApplication:bundleIDNSStr + options:options + clientPort:client_port + withResult:^(NSError *bks_error) { + // The system service will cleanup the client port we created for + // us. + if (bks_error) + open_app_error = (ErrorFlavor)[bks_error code]; + + if (open_app_error == no_error_enum_value) { + if (wants_pid) { + pid_in_block = + [system_service pidForApplication:bundleIDNSStr]; + DNBLog( + "In completion handler, got pid for bundle id, pid: %d.", + pid_in_block); + DNBLogThreadedIf( + LOG_PROCESS, + "In completion handler, got pid for bundle id, pid: %d.", + pid_in_block); + } else + DNBLogThreadedIf(LOG_PROCESS, + "In completion handler: success."); + } else { + const char *error_str = + [(NSString *)[bks_error localizedDescription] UTF8String]; + DNBLogThreadedIf(LOG_PROCESS, "In completion handler for send " + "event, got error \"%s\"(%ld).", + error_str ? error_str : "<unknown error>", + open_app_error); + // REMOVE ME + DNBLogError("In completion handler for send event, got error " + "\"%s\"(%ld).", + error_str ? error_str : "<unknown error>", + open_app_error); + } + + [system_service release]; + dispatch_semaphore_signal(semaphore); + } + + ]; + + const uint32_t timeout_secs = 9; + + dispatch_time_t timeout = + dispatch_time(DISPATCH_TIME_NOW, timeout_secs * NSEC_PER_SEC); + + long success = dispatch_semaphore_wait(semaphore, timeout) == 0; + + dispatch_release(semaphore); + + if (!success) { + DNBLogError("timed out trying to send openApplication to %s.", cstr); + error.SetError(OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic); + error.SetErrorString("timed out trying to launch app"); + } else if (open_app_error != no_error_enum_value) { + error_function(open_app_error, error); + DNBLogError("unable to launch the application with CFBundleIdentifier '%s' " + "bks_error = %u", + cstr, open_app_error); + success = false; + } else if (wants_pid) { + *return_pid = pid_in_block; + DNBLogThreadedIf( + LOG_PROCESS, + "Out of completion handler, pid from block %d and passing out: %d", + pid_in_block, *return_pid); + } + + return success; } #endif #ifdef WITH_BKS #import <Foundation/Foundation.h> -extern "C" -{ -#import <BackBoardServices/BackBoardServices.h> -#import <BackBoardServices/BKSSystemService_LaunchServices.h> +extern "C" { #import <BackBoardServices/BKSOpenApplicationConstants_Private.h> +#import <BackBoardServices/BKSSystemService_LaunchServices.h> +#import <BackBoardServices/BackBoardServices.h> } -static bool -IsBKSProcess (nub_process_t pid) -{ - BKSApplicationStateMonitor *state_monitor = [[BKSApplicationStateMonitor alloc] init]; - BKSApplicationState app_state = [state_monitor mostElevatedApplicationStateForPID: pid]; - return app_state != BKSApplicationStateUnknown; -} - -static void -SetBKSError (NSInteger error_code, DNBError &error) -{ - error.SetError (error_code, DNBError::BackBoard); - NSString *err_nsstr = ::BKSOpenApplicationErrorCodeToString((BKSOpenApplicationErrorCode) error_code); - const char *err_str = NULL; - if (err_nsstr == NULL) - err_str = "unknown BKS error"; - else - { - err_str = [err_nsstr UTF8String]; - if (err_str == NULL) - err_str = "unknown BKS error"; - } - error.SetErrorString(err_str); -} - -static bool -BKSAddEventDataToOptions (NSMutableDictionary *options, const char *event_data, DNBError &option_error) -{ - if (strcmp (event_data, "BackgroundContentFetching") == 0) - { - DNBLog("Setting ActivateForEvent key in options dictionary."); - NSDictionary *event_details = [NSDictionary dictionary]; - NSDictionary *event_dictionary = [NSDictionary dictionaryWithObject:event_details forKey:BKSActivateForEventOptionTypeBackgroundContentFetching]; - [options setObject: event_dictionary forKey: BKSOpenApplicationOptionKeyActivateForEvent]; - return true; - } - else - { - DNBLogError ("Unrecognized event type: %s. Ignoring.", event_data); - option_error.SetErrorString("Unrecognized event data."); - return false; - } - -} - -static NSMutableDictionary * -BKSCreateOptionsDictionary(const char *app_bundle_path, NSMutableArray *launch_argv, NSMutableDictionary *launch_envp, NSString *stdio_path, bool disable_aslr, const char *event_data) -{ - NSMutableDictionary *debug_options = [NSMutableDictionary dictionary]; - if (launch_argv != nil) - [debug_options setObject: launch_argv forKey: BKSDebugOptionKeyArguments]; - if (launch_envp != nil) - [debug_options setObject: launch_envp forKey: BKSDebugOptionKeyEnvironment]; - - [debug_options setObject: stdio_path forKey: BKSDebugOptionKeyStandardOutPath]; - [debug_options setObject: stdio_path forKey: BKSDebugOptionKeyStandardErrorPath]; - [debug_options setObject: [NSNumber numberWithBool: YES] forKey: BKSDebugOptionKeyWaitForDebugger]; - if (disable_aslr) - [debug_options setObject: [NSNumber numberWithBool: YES] forKey: BKSDebugOptionKeyDisableASLR]; - - // That will go in the overall dictionary: - - NSMutableDictionary *options = [NSMutableDictionary dictionary]; - [options setObject: debug_options forKey: BKSOpenApplicationOptionKeyDebuggingOptions]; - // And there are some other options at the top level in this dictionary: - [options setObject: [NSNumber numberWithBool: YES] forKey: BKSOpenApplicationOptionKeyUnlockDevice]; - - DNBError error; - BKSAddEventDataToOptions (options, event_data, error); - - return options; -} - -static CallOpenApplicationFunction BKSCallOpenApplicationFunction = CallBoardSystemServiceOpenApplication<BKSSystemService, BKSOpenApplicationErrorCode, BKSOpenApplicationErrorCodeNone, SetBKSError>; +static bool IsBKSProcess(nub_process_t pid) { + BKSApplicationStateMonitor *state_monitor = + [[BKSApplicationStateMonitor alloc] init]; + BKSApplicationState app_state = + [state_monitor mostElevatedApplicationStateForPID:pid]; + return app_state != BKSApplicationStateUnknown; +} + +static void SetBKSError(NSInteger error_code, DNBError &error) { + error.SetError(error_code, DNBError::BackBoard); + NSString *err_nsstr = ::BKSOpenApplicationErrorCodeToString( + (BKSOpenApplicationErrorCode)error_code); + const char *err_str = NULL; + if (err_nsstr == NULL) + err_str = "unknown BKS error"; + else { + err_str = [err_nsstr UTF8String]; + if (err_str == NULL) + err_str = "unknown BKS error"; + } + error.SetErrorString(err_str); +} + +static bool BKSAddEventDataToOptions(NSMutableDictionary *options, + const char *event_data, + DNBError &option_error) { + if (strcmp(event_data, "BackgroundContentFetching") == 0) { + DNBLog("Setting ActivateForEvent key in options dictionary."); + NSDictionary *event_details = [NSDictionary dictionary]; + NSDictionary *event_dictionary = [NSDictionary + dictionaryWithObject:event_details + forKey: + BKSActivateForEventOptionTypeBackgroundContentFetching]; + [options setObject:event_dictionary + forKey:BKSOpenApplicationOptionKeyActivateForEvent]; + return true; + } else { + DNBLogError("Unrecognized event type: %s. Ignoring.", event_data); + option_error.SetErrorString("Unrecognized event data."); + return false; + } +} + +static NSMutableDictionary *BKSCreateOptionsDictionary( + const char *app_bundle_path, NSMutableArray *launch_argv, + NSMutableDictionary *launch_envp, NSString *stdio_path, bool disable_aslr, + const char *event_data) { + NSMutableDictionary *debug_options = [NSMutableDictionary dictionary]; + if (launch_argv != nil) + [debug_options setObject:launch_argv forKey:BKSDebugOptionKeyArguments]; + if (launch_envp != nil) + [debug_options setObject:launch_envp forKey:BKSDebugOptionKeyEnvironment]; + + [debug_options setObject:stdio_path forKey:BKSDebugOptionKeyStandardOutPath]; + [debug_options setObject:stdio_path + forKey:BKSDebugOptionKeyStandardErrorPath]; + [debug_options setObject:[NSNumber numberWithBool:YES] + forKey:BKSDebugOptionKeyWaitForDebugger]; + if (disable_aslr) + [debug_options setObject:[NSNumber numberWithBool:YES] + forKey:BKSDebugOptionKeyDisableASLR]; + + // That will go in the overall dictionary: + + NSMutableDictionary *options = [NSMutableDictionary dictionary]; + [options setObject:debug_options + forKey:BKSOpenApplicationOptionKeyDebuggingOptions]; + // And there are some other options at the top level in this dictionary: + [options setObject:[NSNumber numberWithBool:YES] + forKey:BKSOpenApplicationOptionKeyUnlockDevice]; + + DNBError error; + BKSAddEventDataToOptions(options, event_data, error); + + return options; +} + +static CallOpenApplicationFunction BKSCallOpenApplicationFunction = + CallBoardSystemServiceOpenApplication< + BKSSystemService, BKSOpenApplicationErrorCode, + BKSOpenApplicationErrorCodeNone, SetBKSError>; #endif // WITH_BKS #ifdef WITH_FBS #import <Foundation/Foundation.h> -extern "C" -{ -#import <FrontBoardServices/FrontBoardServices.h> -#import <FrontBoardServices/FBSSystemService_LaunchServices.h> +extern "C" { #import <FrontBoardServices/FBSOpenApplicationConstants_Private.h> -#import <MobileCoreServices/MobileCoreServices.h> +#import <FrontBoardServices/FBSSystemService_LaunchServices.h> +#import <FrontBoardServices/FrontBoardServices.h> #import <MobileCoreServices/LSResourceProxy.h> +#import <MobileCoreServices/MobileCoreServices.h> } #ifdef WITH_BKS -static bool -IsFBSProcess (nub_process_t pid) -{ - BKSApplicationStateMonitor *state_monitor = [[BKSApplicationStateMonitor alloc] init]; - BKSApplicationState app_state = [state_monitor mostElevatedApplicationStateForPID: pid]; - return app_state != BKSApplicationStateUnknown; +static bool IsFBSProcess(nub_process_t pid) { + BKSApplicationStateMonitor *state_monitor = + [[BKSApplicationStateMonitor alloc] init]; + BKSApplicationState app_state = + [state_monitor mostElevatedApplicationStateForPID:pid]; + return app_state != BKSApplicationStateUnknown; } #else -static bool -IsFBSProcess (nub_process_t pid) -{ - // FIXME: What is the FBS equivalent of BKSApplicationStateMonitor - return true; +static bool IsFBSProcess(nub_process_t pid) { + // FIXME: What is the FBS equivalent of BKSApplicationStateMonitor + return true; } #endif -static void -SetFBSError (NSInteger error_code, DNBError &error) -{ - error.SetError ((DNBError::ValueType) error_code, DNBError::FrontBoard); - NSString *err_nsstr = ::FBSOpenApplicationErrorCodeToString((FBSOpenApplicationErrorCode) error_code); - const char *err_str = NULL; - if (err_nsstr == NULL) - err_str = "unknown FBS error"; - else - { - err_str = [err_nsstr UTF8String]; - if (err_str == NULL) - err_str = "unknown FBS error"; - } - error.SetErrorString(err_str); -} - -static bool -FBSAddEventDataToOptions (NSMutableDictionary *options, const char *event_data, DNBError &option_error) -{ - if (strcmp (event_data, "BackgroundContentFetching") == 0) - { - DNBLog("Setting ActivateForEvent key in options dictionary."); - NSDictionary *event_details = [NSDictionary dictionary]; - NSDictionary *event_dictionary = [NSDictionary dictionaryWithObject:event_details forKey:FBSActivateForEventOptionTypeBackgroundContentFetching]; - [options setObject: event_dictionary forKey: FBSOpenApplicationOptionKeyActivateForEvent]; - return true; - } - else - { - DNBLogError ("Unrecognized event type: %s. Ignoring.", event_data); - option_error.SetErrorString("Unrecognized event data."); - return false; - } - +static void SetFBSError(NSInteger error_code, DNBError &error) { + error.SetError((DNBError::ValueType)error_code, DNBError::FrontBoard); + NSString *err_nsstr = ::FBSOpenApplicationErrorCodeToString( + (FBSOpenApplicationErrorCode)error_code); + const char *err_str = NULL; + if (err_nsstr == NULL) + err_str = "unknown FBS error"; + else { + err_str = [err_nsstr UTF8String]; + if (err_str == NULL) + err_str = "unknown FBS error"; + } + error.SetErrorString(err_str); +} + +static bool FBSAddEventDataToOptions(NSMutableDictionary *options, + const char *event_data, + DNBError &option_error) { + if (strcmp(event_data, "BackgroundContentFetching") == 0) { + DNBLog("Setting ActivateForEvent key in options dictionary."); + NSDictionary *event_details = [NSDictionary dictionary]; + NSDictionary *event_dictionary = [NSDictionary + dictionaryWithObject:event_details + forKey: + FBSActivateForEventOptionTypeBackgroundContentFetching]; + [options setObject:event_dictionary + forKey:FBSOpenApplicationOptionKeyActivateForEvent]; + return true; + } else { + DNBLogError("Unrecognized event type: %s. Ignoring.", event_data); + option_error.SetErrorString("Unrecognized event data."); + return false; + } } static NSMutableDictionary * -FBSCreateOptionsDictionary(const char *app_bundle_path, NSMutableArray *launch_argv, NSDictionary *launch_envp, NSString *stdio_path, bool disable_aslr, const char *event_data) -{ - NSMutableDictionary *debug_options = [NSMutableDictionary dictionary]; - - if (launch_argv != nil) - [debug_options setObject: launch_argv forKey: FBSDebugOptionKeyArguments]; - if (launch_envp != nil) - [debug_options setObject: launch_envp forKey: FBSDebugOptionKeyEnvironment]; - - [debug_options setObject: stdio_path forKey: FBSDebugOptionKeyStandardOutPath]; - [debug_options setObject: stdio_path forKey: FBSDebugOptionKeyStandardErrorPath]; - [debug_options setObject: [NSNumber numberWithBool: YES] forKey: FBSDebugOptionKeyWaitForDebugger]; - if (disable_aslr) - [debug_options setObject: [NSNumber numberWithBool: YES] forKey: FBSDebugOptionKeyDisableASLR]; - - // That will go in the overall dictionary: - - NSMutableDictionary *options = [NSMutableDictionary dictionary]; - [options setObject: debug_options forKey: FBSOpenApplicationOptionKeyDebuggingOptions]; - // And there are some other options at the top level in this dictionary: - [options setObject: [NSNumber numberWithBool: YES] forKey: FBSOpenApplicationOptionKeyUnlockDevice]; - - // We have to get the "sequence ID & UUID" for this app bundle path and send them to FBS: - - NSURL *app_bundle_url = [NSURL fileURLWithPath: [NSString stringWithUTF8String: app_bundle_path] isDirectory: YES]; - LSApplicationProxy *app_proxy = [LSApplicationProxy applicationProxyForBundleURL: app_bundle_url]; - if (app_proxy) - { - DNBLog("Sending AppProxy info: sequence no: %lu, GUID: %s.", app_proxy.sequenceNumber, [app_proxy.cacheGUID.UUIDString UTF8String]); - [options setObject: [NSNumber numberWithUnsignedInteger: app_proxy.sequenceNumber] forKey: FBSOpenApplicationOptionKeyLSSequenceNumber]; - [options setObject: app_proxy.cacheGUID.UUIDString forKey: FBSOpenApplicationOptionKeyLSCacheGUID]; - } - - DNBError error; - FBSAddEventDataToOptions (options, event_data, error); - - return options; -} -static CallOpenApplicationFunction FBSCallOpenApplicationFunction = CallBoardSystemServiceOpenApplication<FBSSystemService, FBSOpenApplicationErrorCode, FBSOpenApplicationErrorCodeNone, SetFBSError>; +FBSCreateOptionsDictionary(const char *app_bundle_path, + NSMutableArray *launch_argv, + NSDictionary *launch_envp, NSString *stdio_path, + bool disable_aslr, const char *event_data) { + NSMutableDictionary *debug_options = [NSMutableDictionary dictionary]; + + if (launch_argv != nil) + [debug_options setObject:launch_argv forKey:FBSDebugOptionKeyArguments]; + if (launch_envp != nil) + [debug_options setObject:launch_envp forKey:FBSDebugOptionKeyEnvironment]; + + [debug_options setObject:stdio_path forKey:FBSDebugOptionKeyStandardOutPath]; + [debug_options setObject:stdio_path + forKey:FBSDebugOptionKeyStandardErrorPath]; + [debug_options setObject:[NSNumber numberWithBool:YES] + forKey:FBSDebugOptionKeyWaitForDebugger]; + if (disable_aslr) + [debug_options setObject:[NSNumber numberWithBool:YES] + forKey:FBSDebugOptionKeyDisableASLR]; + + // That will go in the overall dictionary: + + NSMutableDictionary *options = [NSMutableDictionary dictionary]; + [options setObject:debug_options + forKey:FBSOpenApplicationOptionKeyDebuggingOptions]; + // And there are some other options at the top level in this dictionary: + [options setObject:[NSNumber numberWithBool:YES] + forKey:FBSOpenApplicationOptionKeyUnlockDevice]; + + // We have to get the "sequence ID & UUID" for this app bundle path and send + // them to FBS: + + NSURL *app_bundle_url = + [NSURL fileURLWithPath:[NSString stringWithUTF8String:app_bundle_path] + isDirectory:YES]; + LSApplicationProxy *app_proxy = + [LSApplicationProxy applicationProxyForBundleURL:app_bundle_url]; + if (app_proxy) { + DNBLog("Sending AppProxy info: sequence no: %lu, GUID: %s.", + app_proxy.sequenceNumber, + [app_proxy.cacheGUID.UUIDString UTF8String]); + [options + setObject:[NSNumber numberWithUnsignedInteger:app_proxy.sequenceNumber] + forKey:FBSOpenApplicationOptionKeyLSSequenceNumber]; + [options setObject:app_proxy.cacheGUID.UUIDString + forKey:FBSOpenApplicationOptionKeyLSCacheGUID]; + } + + DNBError error; + FBSAddEventDataToOptions(options, event_data, error); + + return options; +} +static CallOpenApplicationFunction FBSCallOpenApplicationFunction = + CallBoardSystemServiceOpenApplication< + FBSSystemService, FBSOpenApplicationErrorCode, + FBSOpenApplicationErrorCodeNone, SetFBSError>; #endif // WITH_FBS #if 0 -#define DEBUG_LOG(fmt, ...) printf(fmt, ## __VA_ARGS__) +#define DEBUG_LOG(fmt, ...) printf(fmt, ##__VA_ARGS__) #else #define DEBUG_LOG(fmt, ...) #endif @@ -380,1055 +410,1015 @@ static CallOpenApplicationFunction FBSCallOpenApplicationFunction = CallBoardSys #endif #ifndef _POSIX_SPAWN_DISABLE_ASLR -#define _POSIX_SPAWN_DISABLE_ASLR 0x0100 +#define _POSIX_SPAWN_DISABLE_ASLR 0x0100 #endif -MachProcess::MachProcess() : - m_pid (0), - m_cpu_type (0), - m_child_stdin (-1), - m_child_stdout (-1), - m_child_stderr (-1), - m_path (), - m_args (), - m_task (this), - m_flags (eMachProcessFlagsNone), - m_stdio_thread (0), - m_stdio_mutex (PTHREAD_MUTEX_RECURSIVE), - m_stdout_data (), - m_profile_enabled (false), - m_profile_interval_usec (0), - m_profile_thread (0), - m_profile_data_mutex(PTHREAD_MUTEX_RECURSIVE), - m_profile_data (), - m_thread_actions (), - m_exception_messages (), - m_exception_messages_mutex (PTHREAD_MUTEX_RECURSIVE), - m_thread_list (), - m_activities (), - m_state (eStateUnloaded), - m_state_mutex (PTHREAD_MUTEX_RECURSIVE), - m_events (0, kAllEventsMask), - m_private_events (0, kAllEventsMask), - m_breakpoints (), - m_watchpoints (), - m_name_to_addr_callback(NULL), - m_name_to_addr_baton(NULL), - m_image_infos_callback(NULL), - m_image_infos_baton(NULL), - m_sent_interrupt_signo (0), - m_auto_resume_signo (0), - m_did_exec (false), - m_dyld_process_info_create (nullptr), - m_dyld_process_info_for_each_image (nullptr), - m_dyld_process_info_release (nullptr), - m_dyld_process_info_get_cache (nullptr) -{ - m_dyld_process_info_create = (void * (*) (task_t task, uint64_t timestamp, kern_return_t* kernelError)) dlsym (RTLD_DEFAULT, "_dyld_process_info_create"); - m_dyld_process_info_for_each_image = (void (*)(void *info, void (^)(uint64_t machHeaderAddress, const uuid_t uuid, const char* path))) dlsym (RTLD_DEFAULT, "_dyld_process_info_for_each_image"); - m_dyld_process_info_release = (void (*) (void* info)) dlsym (RTLD_DEFAULT, "_dyld_process_info_release"); - m_dyld_process_info_get_cache = (void (*) (void* info, void* cacheInfo)) dlsym (RTLD_DEFAULT, "_dyld_process_info_get_cache"); - - DNBLogThreadedIf(LOG_PROCESS | LOG_VERBOSE, "%s", __PRETTY_FUNCTION__); -} - -MachProcess::~MachProcess() -{ - DNBLogThreadedIf(LOG_PROCESS | LOG_VERBOSE, "%s", __PRETTY_FUNCTION__); - Clear(); -} - -pid_t -MachProcess::SetProcessID(pid_t pid) -{ - // Free any previous process specific data or resources - Clear(); - // Set the current PID appropriately - if (pid == 0) - m_pid = ::getpid (); - else - m_pid = pid; - return m_pid; // Return actually PID in case a zero pid was passed in +MachProcess::MachProcess() + : m_pid(0), m_cpu_type(0), m_child_stdin(-1), m_child_stdout(-1), + m_child_stderr(-1), m_path(), m_args(), m_task(this), + m_flags(eMachProcessFlagsNone), m_stdio_thread(0), + m_stdio_mutex(PTHREAD_MUTEX_RECURSIVE), m_stdout_data(), + m_profile_enabled(false), m_profile_interval_usec(0), m_profile_thread(0), + m_profile_data_mutex(PTHREAD_MUTEX_RECURSIVE), m_profile_data(), + m_thread_actions(), m_exception_messages(), + m_exception_messages_mutex(PTHREAD_MUTEX_RECURSIVE), m_thread_list(), + m_activities(), m_state(eStateUnloaded), + m_state_mutex(PTHREAD_MUTEX_RECURSIVE), m_events(0, kAllEventsMask), + m_private_events(0, kAllEventsMask), m_breakpoints(), m_watchpoints(), + m_name_to_addr_callback(NULL), m_name_to_addr_baton(NULL), + m_image_infos_callback(NULL), m_image_infos_baton(NULL), + m_sent_interrupt_signo(0), m_auto_resume_signo(0), m_did_exec(false), + m_dyld_process_info_create(nullptr), + m_dyld_process_info_for_each_image(nullptr), + m_dyld_process_info_release(nullptr), + m_dyld_process_info_get_cache(nullptr) { + m_dyld_process_info_create = + (void *(*)(task_t task, uint64_t timestamp, kern_return_t * kernelError)) + dlsym(RTLD_DEFAULT, "_dyld_process_info_create"); + m_dyld_process_info_for_each_image = + (void (*)(void *info, void (^)(uint64_t machHeaderAddress, + const uuid_t uuid, const char *path))) + dlsym(RTLD_DEFAULT, "_dyld_process_info_for_each_image"); + m_dyld_process_info_release = + (void (*)(void *info))dlsym(RTLD_DEFAULT, "_dyld_process_info_release"); + m_dyld_process_info_get_cache = (void (*)(void *info, void *cacheInfo))dlsym( + RTLD_DEFAULT, "_dyld_process_info_get_cache"); + + DNBLogThreadedIf(LOG_PROCESS | LOG_VERBOSE, "%s", __PRETTY_FUNCTION__); } -nub_state_t -MachProcess::GetState() -{ - // If any other threads access this we will need a mutex for it - PTHREAD_MUTEX_LOCKER(locker, m_state_mutex); - return m_state; +MachProcess::~MachProcess() { + DNBLogThreadedIf(LOG_PROCESS | LOG_VERBOSE, "%s", __PRETTY_FUNCTION__); + Clear(); } -const char * -MachProcess::ThreadGetName(nub_thread_t tid) -{ - return m_thread_list.GetName(tid); +pid_t MachProcess::SetProcessID(pid_t pid) { + // Free any previous process specific data or resources + Clear(); + // Set the current PID appropriately + if (pid == 0) + m_pid = ::getpid(); + else + m_pid = pid; + return m_pid; // Return actually PID in case a zero pid was passed in } -nub_state_t -MachProcess::ThreadGetState(nub_thread_t tid) -{ - return m_thread_list.GetState(tid); +nub_state_t MachProcess::GetState() { + // If any other threads access this we will need a mutex for it + PTHREAD_MUTEX_LOCKER(locker, m_state_mutex); + return m_state; } +const char *MachProcess::ThreadGetName(nub_thread_t tid) { + return m_thread_list.GetName(tid); +} -nub_size_t -MachProcess::GetNumThreads () const -{ - return m_thread_list.NumThreads(); +nub_state_t MachProcess::ThreadGetState(nub_thread_t tid) { + return m_thread_list.GetState(tid); } -nub_thread_t -MachProcess::GetThreadAtIndex (nub_size_t thread_idx) const -{ - return m_thread_list.ThreadIDAtIndex(thread_idx); +nub_size_t MachProcess::GetNumThreads() const { + return m_thread_list.NumThreads(); } -nub_thread_t -MachProcess::GetThreadIDForMachPortNumber (thread_t mach_port_number) const -{ - return m_thread_list.GetThreadIDByMachPortNumber (mach_port_number); +nub_thread_t MachProcess::GetThreadAtIndex(nub_size_t thread_idx) const { + return m_thread_list.ThreadIDAtIndex(thread_idx); } -nub_bool_t -MachProcess::SyncThreadState (nub_thread_t tid) -{ - MachThreadSP thread_sp(m_thread_list.GetThreadByID(tid)); - if (!thread_sp) - return false; - kern_return_t kret = ::thread_abort_safely(thread_sp->MachPortNumber()); - DNBLogThreadedIf (LOG_THREAD, "thread = 0x%8.8" PRIx32 " calling thread_abort_safely (tid) => %u (GetGPRState() for stop_count = %u)", thread_sp->MachPortNumber(), kret, thread_sp->Process()->StopCount()); +nub_thread_t +MachProcess::GetThreadIDForMachPortNumber(thread_t mach_port_number) const { + return m_thread_list.GetThreadIDByMachPortNumber(mach_port_number); +} - if (kret == KERN_SUCCESS) - return true; - else - return false; - +nub_bool_t MachProcess::SyncThreadState(nub_thread_t tid) { + MachThreadSP thread_sp(m_thread_list.GetThreadByID(tid)); + if (!thread_sp) + return false; + kern_return_t kret = ::thread_abort_safely(thread_sp->MachPortNumber()); + DNBLogThreadedIf(LOG_THREAD, "thread = 0x%8.8" PRIx32 + " calling thread_abort_safely (tid) => %u " + "(GetGPRState() for stop_count = %u)", + thread_sp->MachPortNumber(), kret, + thread_sp->Process()->StopCount()); + + if (kret == KERN_SUCCESS) + return true; + else + return false; } -ThreadInfo::QoS -MachProcess::GetRequestedQoS (nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index) -{ - return m_thread_list.GetRequestedQoS (tid, tsd, dti_qos_class_index); +ThreadInfo::QoS MachProcess::GetRequestedQoS(nub_thread_t tid, nub_addr_t tsd, + uint64_t dti_qos_class_index) { + return m_thread_list.GetRequestedQoS(tid, tsd, dti_qos_class_index); } -nub_addr_t -MachProcess::GetPThreadT (nub_thread_t tid) -{ - return m_thread_list.GetPThreadT (tid); +nub_addr_t MachProcess::GetPThreadT(nub_thread_t tid) { + return m_thread_list.GetPThreadT(tid); } -nub_addr_t -MachProcess::GetDispatchQueueT (nub_thread_t tid) -{ - return m_thread_list.GetDispatchQueueT (tid); +nub_addr_t MachProcess::GetDispatchQueueT(nub_thread_t tid) { + return m_thread_list.GetDispatchQueueT(tid); } -nub_addr_t -MachProcess::GetTSDAddressForThread (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) -{ - return m_thread_list.GetTSDAddressForThread (tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size); +nub_addr_t MachProcess::GetTSDAddressForThread( + 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) { + return m_thread_list.GetTSDAddressForThread( + tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, + plo_pthread_tsd_entry_size); } -// Given an address, read the mach-o header and load commands out of memory to fill in +// Given an address, read the mach-o header and load commands out of memory to +// fill in // the mach_o_information "inf" object. // -// Returns false if there was an error in reading this mach-o file header/load commands. - -bool -MachProcess::GetMachOInformationFromMemory (nub_addr_t mach_o_header_addr, int wordsize, struct mach_o_information &inf) -{ - uint64_t load_cmds_p; - if (wordsize == 4) - { - struct mach_header header; - if (ReadMemory (mach_o_header_addr, sizeof (struct mach_header), &header) != sizeof (struct mach_header)) - { - return false; - } - load_cmds_p = mach_o_header_addr + sizeof (struct mach_header); - inf.mach_header.magic = header.magic; - inf.mach_header.cputype = header.cputype; - // high byte of cpusubtype is used for "capability bits", v. CPU_SUBTYPE_MASK, CPU_SUBTYPE_LIB64 in machine.h - inf.mach_header.cpusubtype = header.cpusubtype & 0x00ffffff; - inf.mach_header.filetype = header.filetype; - inf.mach_header.ncmds = header.ncmds; - inf.mach_header.sizeofcmds = header.sizeofcmds; - inf.mach_header.flags = header.flags; - } - else - { - struct mach_header_64 header; - if (ReadMemory (mach_o_header_addr, sizeof (struct mach_header_64), &header) != sizeof (struct mach_header_64)) - { - return false; - } - load_cmds_p = mach_o_header_addr + sizeof (struct mach_header_64); - inf.mach_header.magic = header.magic; - inf.mach_header.cputype = header.cputype; - // high byte of cpusubtype is used for "capability bits", v. CPU_SUBTYPE_MASK, CPU_SUBTYPE_LIB64 in machine.h - inf.mach_header.cpusubtype = header.cpusubtype & 0x00ffffff; - inf.mach_header.filetype = header.filetype; - inf.mach_header.ncmds = header.ncmds; - inf.mach_header.sizeofcmds = header.sizeofcmds; - inf.mach_header.flags = header.flags; - } - for (uint32_t j = 0; j < inf.mach_header.ncmds; j++) - { - struct load_command lc; - if (ReadMemory (load_cmds_p, sizeof (struct load_command), &lc) != sizeof (struct load_command)) - { - return false; - } - if (lc.cmd == LC_SEGMENT) - { - struct segment_command seg; - if (ReadMemory (load_cmds_p, sizeof (struct segment_command), &seg) != sizeof (struct segment_command)) - { - return false; - } - struct mach_o_segment this_seg; - char name[17]; - ::memset (name, 0, sizeof (name)); - memcpy (name, seg.segname, sizeof (seg.segname)); - this_seg.name = name; - this_seg.vmaddr = seg.vmaddr; - this_seg.vmsize = seg.vmsize; - this_seg.fileoff = seg.fileoff; - this_seg.filesize = seg.filesize; - this_seg.maxprot = seg.maxprot; - this_seg.initprot = seg.initprot; - this_seg.nsects = seg.nsects; - this_seg.flags = seg.flags; - inf.segments.push_back(this_seg); - } - if (lc.cmd == LC_SEGMENT_64) - { - struct segment_command_64 seg; - if (ReadMemory (load_cmds_p, sizeof (struct segment_command_64), &seg) != sizeof (struct segment_command_64)) - { - return false; - } - struct mach_o_segment this_seg; - char name[17]; - ::memset (name, 0, sizeof (name)); - memcpy (name, seg.segname, sizeof (seg.segname)); - this_seg.name = name; - this_seg.vmaddr = seg.vmaddr; - this_seg.vmsize = seg.vmsize; - this_seg.fileoff = seg.fileoff; - this_seg.filesize = seg.filesize; - this_seg.maxprot = seg.maxprot; - this_seg.initprot = seg.initprot; - this_seg.nsects = seg.nsects; - this_seg.flags = seg.flags; - inf.segments.push_back(this_seg); - } - if (lc.cmd == LC_UUID) - { - struct uuid_command uuidcmd; - if (ReadMemory (load_cmds_p, sizeof (struct uuid_command), &uuidcmd) == sizeof (struct uuid_command)) - uuid_copy (inf.uuid, uuidcmd.uuid); - } - bool lc_cmd_known = lc.cmd == LC_VERSION_MIN_IPHONEOS || lc.cmd == LC_VERSION_MIN_MACOSX; +// Returns false if there was an error in reading this mach-o file header/load +// commands. + +bool MachProcess::GetMachOInformationFromMemory( + nub_addr_t mach_o_header_addr, int wordsize, + struct mach_o_information &inf) { + uint64_t load_cmds_p; + if (wordsize == 4) { + struct mach_header header; + if (ReadMemory(mach_o_header_addr, sizeof(struct mach_header), &header) != + sizeof(struct mach_header)) { + return false; + } + load_cmds_p = mach_o_header_addr + sizeof(struct mach_header); + inf.mach_header.magic = header.magic; + inf.mach_header.cputype = header.cputype; + // high byte of cpusubtype is used for "capability bits", v. + // CPU_SUBTYPE_MASK, CPU_SUBTYPE_LIB64 in machine.h + inf.mach_header.cpusubtype = header.cpusubtype & 0x00ffffff; + inf.mach_header.filetype = header.filetype; + inf.mach_header.ncmds = header.ncmds; + inf.mach_header.sizeofcmds = header.sizeofcmds; + inf.mach_header.flags = header.flags; + } else { + struct mach_header_64 header; + if (ReadMemory(mach_o_header_addr, sizeof(struct mach_header_64), + &header) != sizeof(struct mach_header_64)) { + return false; + } + load_cmds_p = mach_o_header_addr + sizeof(struct mach_header_64); + inf.mach_header.magic = header.magic; + inf.mach_header.cputype = header.cputype; + // high byte of cpusubtype is used for "capability bits", v. + // CPU_SUBTYPE_MASK, CPU_SUBTYPE_LIB64 in machine.h + inf.mach_header.cpusubtype = header.cpusubtype & 0x00ffffff; + inf.mach_header.filetype = header.filetype; + inf.mach_header.ncmds = header.ncmds; + inf.mach_header.sizeofcmds = header.sizeofcmds; + inf.mach_header.flags = header.flags; + } + for (uint32_t j = 0; j < inf.mach_header.ncmds; j++) { + struct load_command lc; + if (ReadMemory(load_cmds_p, sizeof(struct load_command), &lc) != + sizeof(struct load_command)) { + return false; + } + if (lc.cmd == LC_SEGMENT) { + struct segment_command seg; + if (ReadMemory(load_cmds_p, sizeof(struct segment_command), &seg) != + sizeof(struct segment_command)) { + return false; + } + struct mach_o_segment this_seg; + char name[17]; + ::memset(name, 0, sizeof(name)); + memcpy(name, seg.segname, sizeof(seg.segname)); + this_seg.name = name; + this_seg.vmaddr = seg.vmaddr; + this_seg.vmsize = seg.vmsize; + this_seg.fileoff = seg.fileoff; + this_seg.filesize = seg.filesize; + this_seg.maxprot = seg.maxprot; + this_seg.initprot = seg.initprot; + this_seg.nsects = seg.nsects; + this_seg.flags = seg.flags; + inf.segments.push_back(this_seg); + } + if (lc.cmd == LC_SEGMENT_64) { + struct segment_command_64 seg; + if (ReadMemory(load_cmds_p, sizeof(struct segment_command_64), &seg) != + sizeof(struct segment_command_64)) { + return false; + } + struct mach_o_segment this_seg; + char name[17]; + ::memset(name, 0, sizeof(name)); + memcpy(name, seg.segname, sizeof(seg.segname)); + this_seg.name = name; + this_seg.vmaddr = seg.vmaddr; + this_seg.vmsize = seg.vmsize; + this_seg.fileoff = seg.fileoff; + this_seg.filesize = seg.filesize; + this_seg.maxprot = seg.maxprot; + this_seg.initprot = seg.initprot; + this_seg.nsects = seg.nsects; + this_seg.flags = seg.flags; + inf.segments.push_back(this_seg); + } + if (lc.cmd == LC_UUID) { + struct uuid_command uuidcmd; + if (ReadMemory(load_cmds_p, sizeof(struct uuid_command), &uuidcmd) == + sizeof(struct uuid_command)) + uuid_copy(inf.uuid, uuidcmd.uuid); + } + bool lc_cmd_known = + lc.cmd == LC_VERSION_MIN_IPHONEOS || lc.cmd == LC_VERSION_MIN_MACOSX; #if defined(LC_VERSION_MIN_TVOS) - lc_cmd_known |= lc.cmd == LC_VERSION_MIN_TVOS; + lc_cmd_known |= lc.cmd == LC_VERSION_MIN_TVOS; #endif #if defined(LC_VERSION_MIN_WATCHOS) - lc_cmd_known |= lc.cmd == LC_VERSION_MIN_WATCHOS; + lc_cmd_known |= lc.cmd == LC_VERSION_MIN_WATCHOS; #endif - if (lc_cmd_known) - { - struct version_min_command vers_cmd; - if (ReadMemory (load_cmds_p, sizeof (struct version_min_command), &vers_cmd) != sizeof (struct version_min_command)) - { - return false; - } - switch (lc.cmd) - { - case LC_VERSION_MIN_IPHONEOS: - inf.min_version_os_name = "iphoneos"; - break; - case LC_VERSION_MIN_MACOSX: - inf.min_version_os_name = "macosx"; - break; + if (lc_cmd_known) { + struct version_min_command vers_cmd; + if (ReadMemory(load_cmds_p, sizeof(struct version_min_command), + &vers_cmd) != sizeof(struct version_min_command)) { + return false; + } + switch (lc.cmd) { + case LC_VERSION_MIN_IPHONEOS: + inf.min_version_os_name = "iphoneos"; + break; + case LC_VERSION_MIN_MACOSX: + inf.min_version_os_name = "macosx"; + break; #if defined(LC_VERSION_MIN_TVOS) - case LC_VERSION_MIN_TVOS: - inf.min_version_os_name = "tvos"; - break; + case LC_VERSION_MIN_TVOS: + inf.min_version_os_name = "tvos"; + break; #endif #if defined(LC_VERSION_MIN_WATCHOS) - case LC_VERSION_MIN_WATCHOS: - inf.min_version_os_name = "watchos"; - break; + case LC_VERSION_MIN_WATCHOS: + inf.min_version_os_name = "watchos"; + break; #endif - default: - return false; - } - uint32_t xxxx = vers_cmd.sdk >> 16; - uint32_t yy = (vers_cmd.sdk >> 8) & 0xffu; - uint32_t zz = vers_cmd.sdk & 0xffu; - inf.min_version_os_version = ""; - inf.min_version_os_version += std::to_string(xxxx); - inf.min_version_os_version += "."; - inf.min_version_os_version += std::to_string(yy); - if (zz != 0) - { - inf.min_version_os_version += "."; - inf.min_version_os_version += std::to_string(zz); - } - } - load_cmds_p += lc.cmdsize; - } - return true; -} - -// Given completely filled in array of binary_image_information structures, create a JSONGenerator object + default: + return false; + } + uint32_t xxxx = vers_cmd.sdk >> 16; + uint32_t yy = (vers_cmd.sdk >> 8) & 0xffu; + uint32_t zz = vers_cmd.sdk & 0xffu; + inf.min_version_os_version = ""; + inf.min_version_os_version += std::to_string(xxxx); + inf.min_version_os_version += "."; + inf.min_version_os_version += std::to_string(yy); + if (zz != 0) { + inf.min_version_os_version += "."; + inf.min_version_os_version += std::to_string(zz); + } + } + load_cmds_p += lc.cmdsize; + } + return true; +} + +// Given completely filled in array of binary_image_information structures, +// create a JSONGenerator object // with all the details we want to send to lldb. -JSONGenerator::ObjectSP -MachProcess::FormatDynamicLibrariesIntoJSON (const std::vector<struct binary_image_information> &image_infos) -{ - - JSONGenerator::ArraySP image_infos_array_sp (new JSONGenerator::Array()); - - const size_t image_count = image_infos.size(); - - for (size_t i = 0; i < image_count; i++) - { - JSONGenerator::DictionarySP image_info_dict_sp (new JSONGenerator::Dictionary()); - image_info_dict_sp->AddIntegerItem ("load_address", image_infos[i].load_address); - image_info_dict_sp->AddIntegerItem ("mod_date", image_infos[i].mod_date); - image_info_dict_sp->AddStringItem ("pathname", image_infos[i].filename); - - uuid_string_t uuidstr; - uuid_unparse_upper (image_infos[i].macho_info.uuid, uuidstr); - image_info_dict_sp->AddStringItem ("uuid", uuidstr); - - if (image_infos[i].macho_info.min_version_os_name.empty() == false - && image_infos[i].macho_info.min_version_os_version.empty() == false) - { - image_info_dict_sp->AddStringItem ("min_version_os_name", image_infos[i].macho_info.min_version_os_name); - image_info_dict_sp->AddStringItem ("min_version_os_sdk", image_infos[i].macho_info.min_version_os_version); - } - - JSONGenerator::DictionarySP mach_header_dict_sp (new JSONGenerator::Dictionary()); - mach_header_dict_sp->AddIntegerItem ("magic", image_infos[i].macho_info.mach_header.magic); - mach_header_dict_sp->AddIntegerItem ("cputype", (uint32_t) image_infos[i].macho_info.mach_header.cputype); - mach_header_dict_sp->AddIntegerItem ("cpusubtype", (uint32_t) image_infos[i].macho_info.mach_header.cpusubtype); - mach_header_dict_sp->AddIntegerItem ("filetype", image_infos[i].macho_info.mach_header.filetype); - -// DynamicLoaderMacOSX doesn't currently need these fields, so don't send them. -// mach_header_dict_sp->AddIntegerItem ("ncmds", image_infos[i].macho_info.mach_header.ncmds); -// mach_header_dict_sp->AddIntegerItem ("sizeofcmds", image_infos[i].macho_info.mach_header.sizeofcmds); -// mach_header_dict_sp->AddIntegerItem ("flags", image_infos[i].macho_info.mach_header.flags); - image_info_dict_sp->AddItem ("mach_header", mach_header_dict_sp); - - JSONGenerator::ArraySP segments_sp (new JSONGenerator::Array()); - for (size_t j = 0; j < image_infos[i].macho_info.segments.size(); j++) - { - JSONGenerator::DictionarySP segment_sp (new JSONGenerator::Dictionary()); - segment_sp->AddStringItem ("name", image_infos[i].macho_info.segments[j].name); - segment_sp->AddIntegerItem ("vmaddr", image_infos[i].macho_info.segments[j].vmaddr); - segment_sp->AddIntegerItem ("vmsize", image_infos[i].macho_info.segments[j].vmsize); - segment_sp->AddIntegerItem ("fileoff", image_infos[i].macho_info.segments[j].fileoff); - segment_sp->AddIntegerItem ("filesize", image_infos[i].macho_info.segments[j].filesize); - segment_sp->AddIntegerItem ("maxprot", image_infos[i].macho_info.segments[j].maxprot); - -// DynamicLoaderMacOSX doesn't currently need these fields, so don't send them. -// segment_sp->AddIntegerItem ("initprot", image_infos[i].macho_info.segments[j].initprot); -// segment_sp->AddIntegerItem ("nsects", image_infos[i].macho_info.segments[j].nsects); -// segment_sp->AddIntegerItem ("flags", image_infos[i].macho_info.segments[j].flags); - segments_sp->AddItem (segment_sp); - } - image_info_dict_sp->AddItem ("segments", segments_sp); - - image_infos_array_sp->AddItem (image_info_dict_sp); - } - - JSONGenerator::DictionarySP reply_sp (new JSONGenerator::Dictionary());; - reply_sp->AddItem ("images", image_infos_array_sp); - - return reply_sp; -} - -// Get the shared library information using the old (pre-macOS 10.12, pre-iOS 10, pre-tvOS 10, pre-watchOS 3) +JSONGenerator::ObjectSP MachProcess::FormatDynamicLibrariesIntoJSON( + const std::vector<struct binary_image_information> &image_infos) { + + JSONGenerator::ArraySP image_infos_array_sp(new JSONGenerator::Array()); + + const size_t image_count = image_infos.size(); + + for (size_t i = 0; i < image_count; i++) { + JSONGenerator::DictionarySP image_info_dict_sp( + new JSONGenerator::Dictionary()); + image_info_dict_sp->AddIntegerItem("load_address", + image_infos[i].load_address); + image_info_dict_sp->AddIntegerItem("mod_date", image_infos[i].mod_date); + image_info_dict_sp->AddStringItem("pathname", image_infos[i].filename); + + uuid_string_t uuidstr; + uuid_unparse_upper(image_infos[i].macho_info.uuid, uuidstr); + image_info_dict_sp->AddStringItem("uuid", uuidstr); + + if (image_infos[i].macho_info.min_version_os_name.empty() == false && + image_infos[i].macho_info.min_version_os_version.empty() == false) { + image_info_dict_sp->AddStringItem( + "min_version_os_name", image_infos[i].macho_info.min_version_os_name); + image_info_dict_sp->AddStringItem( + "min_version_os_sdk", + image_infos[i].macho_info.min_version_os_version); + } + + JSONGenerator::DictionarySP mach_header_dict_sp( + new JSONGenerator::Dictionary()); + mach_header_dict_sp->AddIntegerItem( + "magic", image_infos[i].macho_info.mach_header.magic); + mach_header_dict_sp->AddIntegerItem( + "cputype", (uint32_t)image_infos[i].macho_info.mach_header.cputype); + mach_header_dict_sp->AddIntegerItem( + "cpusubtype", + (uint32_t)image_infos[i].macho_info.mach_header.cpusubtype); + mach_header_dict_sp->AddIntegerItem( + "filetype", image_infos[i].macho_info.mach_header.filetype); + + // DynamicLoaderMacOSX doesn't currently need these fields, so + // don't send them. + // mach_header_dict_sp->AddIntegerItem ("ncmds", + // image_infos[i].macho_info.mach_header.ncmds); + // mach_header_dict_sp->AddIntegerItem ("sizeofcmds", + // image_infos[i].macho_info.mach_header.sizeofcmds); + // mach_header_dict_sp->AddIntegerItem ("flags", + // image_infos[i].macho_info.mach_header.flags); + image_info_dict_sp->AddItem("mach_header", mach_header_dict_sp); + + JSONGenerator::ArraySP segments_sp(new JSONGenerator::Array()); + for (size_t j = 0; j < image_infos[i].macho_info.segments.size(); j++) { + JSONGenerator::DictionarySP segment_sp(new JSONGenerator::Dictionary()); + segment_sp->AddStringItem("name", + image_infos[i].macho_info.segments[j].name); + segment_sp->AddIntegerItem("vmaddr", + image_infos[i].macho_info.segments[j].vmaddr); + segment_sp->AddIntegerItem("vmsize", + image_infos[i].macho_info.segments[j].vmsize); + segment_sp->AddIntegerItem("fileoff", + image_infos[i].macho_info.segments[j].fileoff); + segment_sp->AddIntegerItem( + "filesize", image_infos[i].macho_info.segments[j].filesize); + segment_sp->AddIntegerItem("maxprot", + image_infos[i].macho_info.segments[j].maxprot); + + // DynamicLoaderMacOSX doesn't currently need these fields, + // so don't send them. + // segment_sp->AddIntegerItem ("initprot", + // image_infos[i].macho_info.segments[j].initprot); + // segment_sp->AddIntegerItem ("nsects", + // image_infos[i].macho_info.segments[j].nsects); + // segment_sp->AddIntegerItem ("flags", + // image_infos[i].macho_info.segments[j].flags); + segments_sp->AddItem(segment_sp); + } + image_info_dict_sp->AddItem("segments", segments_sp); + + image_infos_array_sp->AddItem(image_info_dict_sp); + } + + JSONGenerator::DictionarySP reply_sp(new JSONGenerator::Dictionary()); + ; + reply_sp->AddItem("images", image_infos_array_sp); + + return reply_sp; +} + +// Get the shared library information using the old (pre-macOS 10.12, pre-iOS +// 10, pre-tvOS 10, pre-watchOS 3) // code path. We'll be given the address of an array of structures in the form -// {void* load_addr, void* mod_date, void* pathname} +// {void* load_addr, void* mod_date, void* pathname} // -// In macOS 10.12 etc and newer, we'll use SPI calls into dyld to gather this information. -JSONGenerator::ObjectSP -MachProcess::GetLoadedDynamicLibrariesInfos (nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count) -{ - JSONGenerator::DictionarySP reply_sp; - - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; - struct kinfo_proc processInfo; - size_t bufsize = sizeof(processInfo); - if (sysctl(mib, (unsigned)(sizeof(mib)/sizeof(int)), &processInfo, &bufsize, NULL, 0) == 0 && bufsize > 0) - { - uint32_t pointer_size = 4; - if (processInfo.kp_proc.p_flag & P_LP64) - pointer_size = 8; - - std::vector<struct binary_image_information> image_infos; - size_t image_infos_size = image_count * 3 * pointer_size; - - uint8_t *image_info_buf = (uint8_t *) malloc (image_infos_size); - if (image_info_buf == NULL) - { - return reply_sp; - } - if (ReadMemory (image_list_address, image_infos_size, image_info_buf) != image_infos_size) - { - return reply_sp; - } - - - //// First the image_infos array with (load addr, pathname, mod date) tuples - - - for (size_t i = 0; i < image_count; i++) - { - struct binary_image_information info; - nub_addr_t pathname_address; - if (pointer_size == 4) - { - uint32_t load_address_32; - uint32_t pathname_address_32; - uint32_t mod_date_32; - ::memcpy (&load_address_32, image_info_buf + (i * 3 * pointer_size), 4); - ::memcpy (&pathname_address_32, image_info_buf + (i * 3 * pointer_size) + pointer_size, 4); - ::memcpy (&mod_date_32, image_info_buf + (i * 3 * pointer_size) + pointer_size + pointer_size, 4); - info.load_address = load_address_32; - info.mod_date = mod_date_32; - pathname_address = pathname_address_32; - } - else - { - uint64_t load_address_64; - uint64_t pathname_address_64; - uint64_t mod_date_64; - ::memcpy (&load_address_64, image_info_buf + (i * 3 * pointer_size), 8); - ::memcpy (&pathname_address_64, image_info_buf + (i * 3 * pointer_size) + pointer_size, 8); - ::memcpy (&mod_date_64, image_info_buf + (i * 3 * pointer_size) + pointer_size + pointer_size, 8); - info.load_address = load_address_64; - info.mod_date = mod_date_64; - pathname_address = pathname_address_64; - } - char strbuf[17]; - info.filename = ""; - uint64_t pathname_ptr = pathname_address; - bool still_reading = true; - while (still_reading && ReadMemory (pathname_ptr, sizeof (strbuf) - 1, strbuf) == sizeof (strbuf) - 1) - { - strbuf[sizeof(strbuf) - 1] = '\0'; - info.filename += strbuf; - pathname_ptr += sizeof (strbuf) - 1; - // Stop if we found nul byte indicating the end of the string - for (size_t i = 0; i < sizeof(strbuf) - 1; i++) - { - if (strbuf[i] == '\0') - { - still_reading = false; - break; - } - } - } - uuid_clear (info.macho_info.uuid); - image_infos.push_back (info); - } - if (image_infos.size() == 0) - { - return reply_sp; +// In macOS 10.12 etc and newer, we'll use SPI calls into dyld to gather this +// information. +JSONGenerator::ObjectSP MachProcess::GetLoadedDynamicLibrariesInfos( + nub_process_t pid, nub_addr_t image_list_address, nub_addr_t image_count) { + JSONGenerator::DictionarySP reply_sp; + + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; + struct kinfo_proc processInfo; + size_t bufsize = sizeof(processInfo); + if (sysctl(mib, (unsigned)(sizeof(mib) / sizeof(int)), &processInfo, &bufsize, + NULL, 0) == 0 && + bufsize > 0) { + uint32_t pointer_size = 4; + if (processInfo.kp_proc.p_flag & P_LP64) + pointer_size = 8; + + std::vector<struct binary_image_information> image_infos; + size_t image_infos_size = image_count * 3 * pointer_size; + + uint8_t *image_info_buf = (uint8_t *)malloc(image_infos_size); + if (image_info_buf == NULL) { + return reply_sp; + } + if (ReadMemory(image_list_address, image_infos_size, image_info_buf) != + image_infos_size) { + return reply_sp; + } + + //// First the image_infos array with (load addr, pathname, mod date) + ///tuples + + for (size_t i = 0; i < image_count; i++) { + struct binary_image_information info; + nub_addr_t pathname_address; + if (pointer_size == 4) { + uint32_t load_address_32; + uint32_t pathname_address_32; + uint32_t mod_date_32; + ::memcpy(&load_address_32, image_info_buf + (i * 3 * pointer_size), 4); + ::memcpy(&pathname_address_32, + image_info_buf + (i * 3 * pointer_size) + pointer_size, 4); + ::memcpy(&mod_date_32, image_info_buf + (i * 3 * pointer_size) + + pointer_size + pointer_size, + 4); + info.load_address = load_address_32; + info.mod_date = mod_date_32; + pathname_address = pathname_address_32; + } else { + uint64_t load_address_64; + uint64_t pathname_address_64; + uint64_t mod_date_64; + ::memcpy(&load_address_64, image_info_buf + (i * 3 * pointer_size), 8); + ::memcpy(&pathname_address_64, + image_info_buf + (i * 3 * pointer_size) + pointer_size, 8); + ::memcpy(&mod_date_64, image_info_buf + (i * 3 * pointer_size) + + pointer_size + pointer_size, + 8); + info.load_address = load_address_64; + info.mod_date = mod_date_64; + pathname_address = pathname_address_64; + } + char strbuf[17]; + info.filename = ""; + uint64_t pathname_ptr = pathname_address; + bool still_reading = true; + while (still_reading && + ReadMemory(pathname_ptr, sizeof(strbuf) - 1, strbuf) == + sizeof(strbuf) - 1) { + strbuf[sizeof(strbuf) - 1] = '\0'; + info.filename += strbuf; + pathname_ptr += sizeof(strbuf) - 1; + // Stop if we found nul byte indicating the end of the string + for (size_t i = 0; i < sizeof(strbuf) - 1; i++) { + if (strbuf[i] == '\0') { + still_reading = false; + break; + } } + } + uuid_clear(info.macho_info.uuid); + image_infos.push_back(info); + } + if (image_infos.size() == 0) { + return reply_sp; + } - free (image_info_buf); - - //// Second, read the mach header / load commands for all the dylibs + free(image_info_buf); - for (size_t i = 0; i < image_count; i++) - { - if (!GetMachOInformationFromMemory (image_infos[i].load_address, pointer_size, image_infos[i].macho_info)) - { - return reply_sp; - } - } + //// Second, read the mach header / load commands for all the dylibs + for (size_t i = 0; i < image_count; i++) { + if (!GetMachOInformationFromMemory(image_infos[i].load_address, + pointer_size, + image_infos[i].macho_info)) { + return reply_sp; + } + } - //// Third, format all of the above in the JSONGenerator object. + //// Third, format all of the above in the JSONGenerator object. + return FormatDynamicLibrariesIntoJSON(image_infos); + } - return FormatDynamicLibrariesIntoJSON (image_infos); - } - - return reply_sp; + return reply_sp; } // From dyld SPI header dyld_process_info.h -typedef void* dyld_process_info; -struct dyld_process_cache_info -{ - uuid_t cacheUUID; // UUID of cache used by process - uint64_t cacheBaseAddress; // load address of dyld shared cache - bool noCache; // process is running without a dyld cache - bool privateCache; // process is using a private copy of its dyld cache +typedef void *dyld_process_info; +struct dyld_process_cache_info { + uuid_t cacheUUID; // UUID of cache used by process + uint64_t cacheBaseAddress; // load address of dyld shared cache + bool noCache; // process is running without a dyld cache + bool privateCache; // process is using a private copy of its dyld cache }; - -// Use the dyld SPI present in macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer to get +// Use the dyld SPI present in macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer +// to get // the load address, uuid, and filenames of all the libraries. -// This only fills in those three fields in the 'struct binary_image_information' - call -// GetMachOInformationFromMemory to fill in the mach-o header/load command details. -void -MachProcess::GetAllLoadedBinariesViaDYLDSPI (std::vector<struct binary_image_information> &image_infos) -{ - kern_return_t kern_ret; - if (m_dyld_process_info_create) - { - dyld_process_info info = m_dyld_process_info_create (m_task.TaskPort(), 0, &kern_ret); - if (info) - { - m_dyld_process_info_for_each_image (info, ^(uint64_t mach_header_addr, const uuid_t uuid, const char *path) { - struct binary_image_information image; - image.filename = path; - uuid_copy (image.macho_info.uuid, uuid); - image.load_address = mach_header_addr; - image_infos.push_back (image); - }); - m_dyld_process_info_release (info); - } - } -} - -// Fetch information about all shared libraries using the dyld SPIs that exist in +// This only fills in those three fields in the 'struct +// binary_image_information' - call +// GetMachOInformationFromMemory to fill in the mach-o header/load command +// details. +void MachProcess::GetAllLoadedBinariesViaDYLDSPI( + std::vector<struct binary_image_information> &image_infos) { + kern_return_t kern_ret; + if (m_dyld_process_info_create) { + dyld_process_info info = + m_dyld_process_info_create(m_task.TaskPort(), 0, &kern_ret); + if (info) { + m_dyld_process_info_for_each_image( + info, + ^(uint64_t mach_header_addr, const uuid_t uuid, const char *path) { + struct binary_image_information image; + image.filename = path; + uuid_copy(image.macho_info.uuid, uuid); + image.load_address = mach_header_addr; + image_infos.push_back(image); + }); + m_dyld_process_info_release(info); + } + } +} + +// Fetch information about all shared libraries using the dyld SPIs that exist +// in // macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer. -JSONGenerator::ObjectSP -MachProcess::GetAllLoadedLibrariesInfos (nub_process_t pid) -{ - JSONGenerator::DictionarySP reply_sp; - - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid }; - struct kinfo_proc processInfo; - size_t bufsize = sizeof(processInfo); - if (sysctl(mib, (unsigned)(sizeof(mib)/sizeof(int)), &processInfo, &bufsize, NULL, 0) == 0 && bufsize > 0) - { - uint32_t pointer_size = 4; - if (processInfo.kp_proc.p_flag & P_LP64) - pointer_size = 8; - - std::vector<struct binary_image_information> image_infos; - GetAllLoadedBinariesViaDYLDSPI (image_infos); - const size_t image_count = image_infos.size(); - for (size_t i = 0; i < image_count; i++) - { - GetMachOInformationFromMemory (image_infos[i].load_address, pointer_size, image_infos[i].macho_info); - } - return FormatDynamicLibrariesIntoJSON (image_infos); +JSONGenerator::ObjectSP +MachProcess::GetAllLoadedLibrariesInfos(nub_process_t pid) { + JSONGenerator::DictionarySP reply_sp; + + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; + struct kinfo_proc processInfo; + size_t bufsize = sizeof(processInfo); + if (sysctl(mib, (unsigned)(sizeof(mib) / sizeof(int)), &processInfo, &bufsize, + NULL, 0) == 0 && + bufsize > 0) { + uint32_t pointer_size = 4; + if (processInfo.kp_proc.p_flag & P_LP64) + pointer_size = 8; + + std::vector<struct binary_image_information> image_infos; + GetAllLoadedBinariesViaDYLDSPI(image_infos); + const size_t image_count = image_infos.size(); + for (size_t i = 0; i < image_count; i++) { + GetMachOInformationFromMemory(image_infos[i].load_address, pointer_size, + image_infos[i].macho_info); } - return reply_sp; + return FormatDynamicLibrariesIntoJSON(image_infos); + } + return reply_sp; } -// Fetch information about the shared libraries at the given load addresses using the +// Fetch information about the shared libraries at the given load addresses +// using the // dyld SPIs that exist in macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer. -JSONGenerator::ObjectSP -MachProcess::GetLibrariesInfoForAddresses (nub_process_t pid, std::vector<uint64_t> &macho_addresses) -{ - JSONGenerator::DictionarySP reply_sp; - - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid }; - struct kinfo_proc processInfo; - size_t bufsize = sizeof(processInfo); - if (sysctl(mib, (unsigned)(sizeof(mib)/sizeof(int)), &processInfo, &bufsize, NULL, 0) == 0 && bufsize > 0) - { - uint32_t pointer_size = 4; - if (processInfo.kp_proc.p_flag & P_LP64) - pointer_size = 8; - - std::vector<struct binary_image_information> all_image_infos; - GetAllLoadedBinariesViaDYLDSPI (all_image_infos); - - std::vector<struct binary_image_information> image_infos; - const size_t macho_addresses_count = macho_addresses.size(); - const size_t all_image_infos_count = all_image_infos.size(); - for (size_t i = 0; i < macho_addresses_count; i++) - { - for (size_t j = 0; j < all_image_infos_count; j++) - { - if (all_image_infos[j].load_address == macho_addresses[i]) - { - image_infos.push_back (all_image_infos[j]); - } - } - } +JSONGenerator::ObjectSP MachProcess::GetLibrariesInfoForAddresses( + nub_process_t pid, std::vector<uint64_t> &macho_addresses) { + JSONGenerator::DictionarySP reply_sp; + + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; + struct kinfo_proc processInfo; + size_t bufsize = sizeof(processInfo); + if (sysctl(mib, (unsigned)(sizeof(mib) / sizeof(int)), &processInfo, &bufsize, + NULL, 0) == 0 && + bufsize > 0) { + uint32_t pointer_size = 4; + if (processInfo.kp_proc.p_flag & P_LP64) + pointer_size = 8; + + std::vector<struct binary_image_information> all_image_infos; + GetAllLoadedBinariesViaDYLDSPI(all_image_infos); - const size_t image_infos_count = image_infos.size(); - for (size_t i = 0; i < image_infos_count; i++) - { - GetMachOInformationFromMemory (image_infos[i].load_address, pointer_size, image_infos[i].macho_info); + std::vector<struct binary_image_information> image_infos; + const size_t macho_addresses_count = macho_addresses.size(); + const size_t all_image_infos_count = all_image_infos.size(); + for (size_t i = 0; i < macho_addresses_count; i++) { + for (size_t j = 0; j < all_image_infos_count; j++) { + if (all_image_infos[j].load_address == macho_addresses[i]) { + image_infos.push_back(all_image_infos[j]); } - return FormatDynamicLibrariesIntoJSON (image_infos); + } + } + + const size_t image_infos_count = image_infos.size(); + for (size_t i = 0; i < image_infos_count; i++) { + GetMachOInformationFromMemory(image_infos[i].load_address, pointer_size, + image_infos[i].macho_info); } - return reply_sp; + return FormatDynamicLibrariesIntoJSON(image_infos); + } + return reply_sp; } // From dyld's internal podyld_process_info.h: -JSONGenerator::ObjectSP -MachProcess::GetSharedCacheInfo (nub_process_t pid) -{ - JSONGenerator::DictionarySP reply_sp (new JSONGenerator::Dictionary());; - kern_return_t kern_ret; - if (m_dyld_process_info_create && m_dyld_process_info_get_cache) - { - dyld_process_info info = m_dyld_process_info_create (m_task.TaskPort(), 0, &kern_ret); - if (info) - { - struct dyld_process_cache_info shared_cache_info; - m_dyld_process_info_get_cache (info, &shared_cache_info); - - reply_sp->AddIntegerItem ("shared_cache_base_address", shared_cache_info.cacheBaseAddress); - - uuid_string_t uuidstr; - uuid_unparse_upper (shared_cache_info.cacheUUID, uuidstr); - reply_sp->AddStringItem ("shared_cache_uuid", uuidstr); - - reply_sp->AddBooleanItem ("no_shared_cache", shared_cache_info.noCache); - reply_sp->AddBooleanItem ("shared_cache_private_cache", shared_cache_info.privateCache); - - m_dyld_process_info_release (info); - } - } - return reply_sp; -} +JSONGenerator::ObjectSP MachProcess::GetSharedCacheInfo(nub_process_t pid) { + JSONGenerator::DictionarySP reply_sp(new JSONGenerator::Dictionary()); + ; + kern_return_t kern_ret; + if (m_dyld_process_info_create && m_dyld_process_info_get_cache) { + dyld_process_info info = + m_dyld_process_info_create(m_task.TaskPort(), 0, &kern_ret); + if (info) { + struct dyld_process_cache_info shared_cache_info; + m_dyld_process_info_get_cache(info, &shared_cache_info); -nub_thread_t -MachProcess::GetCurrentThread () -{ - return m_thread_list.CurrentThreadID(); -} + reply_sp->AddIntegerItem("shared_cache_base_address", + shared_cache_info.cacheBaseAddress); -nub_thread_t -MachProcess::GetCurrentThreadMachPort () -{ - return m_thread_list.GetMachPortNumberByThreadID(m_thread_list.CurrentThreadID()); -} + uuid_string_t uuidstr; + uuid_unparse_upper(shared_cache_info.cacheUUID, uuidstr); + reply_sp->AddStringItem("shared_cache_uuid", uuidstr); -nub_thread_t -MachProcess::SetCurrentThread(nub_thread_t tid) -{ - return m_thread_list.SetCurrentThread(tid); -} - -bool -MachProcess::GetThreadStoppedReason(nub_thread_t tid, struct DNBThreadStopInfo *stop_info) -{ - if (m_thread_list.GetThreadStoppedReason(tid, stop_info)) - { - if (m_did_exec) - stop_info->reason = eStopTypeExec; - return true; + reply_sp->AddBooleanItem("no_shared_cache", shared_cache_info.noCache); + reply_sp->AddBooleanItem("shared_cache_private_cache", + shared_cache_info.privateCache); + + m_dyld_process_info_release(info); } - return false; + } + return reply_sp; } -void -MachProcess::DumpThreadStoppedReason(nub_thread_t tid) const -{ - return m_thread_list.DumpThreadStoppedReason(tid); +nub_thread_t MachProcess::GetCurrentThread() { + return m_thread_list.CurrentThreadID(); } -const char * -MachProcess::GetThreadInfo(nub_thread_t tid) const -{ - return m_thread_list.GetThreadInfo(tid); +nub_thread_t MachProcess::GetCurrentThreadMachPort() { + return m_thread_list.GetMachPortNumberByThreadID( + m_thread_list.CurrentThreadID()); } -uint32_t -MachProcess::GetCPUType () -{ - if (m_cpu_type == 0 && m_pid != 0) - m_cpu_type = MachProcess::GetCPUTypeForLocalProcess (m_pid); - return m_cpu_type; +nub_thread_t MachProcess::SetCurrentThread(nub_thread_t tid) { + return m_thread_list.SetCurrentThread(tid); } -const DNBRegisterSetInfo * -MachProcess::GetRegisterSetInfo (nub_thread_t tid, nub_size_t *num_reg_sets) const -{ - MachThreadSP thread_sp (m_thread_list.GetThreadByID (tid)); - if (thread_sp) - { - DNBArchProtocol *arch = thread_sp->GetArchProtocol(); - if (arch) - return arch->GetRegisterSetInfo (num_reg_sets); - } - *num_reg_sets = 0; - return NULL; +bool MachProcess::GetThreadStoppedReason(nub_thread_t tid, + struct DNBThreadStopInfo *stop_info) { + if (m_thread_list.GetThreadStoppedReason(tid, stop_info)) { + if (m_did_exec) + stop_info->reason = eStopTypeExec; + return true; + } + return false; } -bool -MachProcess::GetRegisterValue ( nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *value ) const -{ - return m_thread_list.GetRegisterValue(tid, set, reg, value); +void MachProcess::DumpThreadStoppedReason(nub_thread_t tid) const { + return m_thread_list.DumpThreadStoppedReason(tid); } -bool -MachProcess::SetRegisterValue ( nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *value ) const -{ - return m_thread_list.SetRegisterValue(tid, set, reg, value); +const char *MachProcess::GetThreadInfo(nub_thread_t tid) const { + return m_thread_list.GetThreadInfo(tid); } -void -MachProcess::SetState(nub_state_t new_state) -{ - // If any other threads access this we will need a mutex for it - uint32_t event_mask = 0; - - // Scope for mutex locker - { - PTHREAD_MUTEX_LOCKER(locker, m_state_mutex); - const nub_state_t old_state = m_state; - - if (old_state == eStateExited) - { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::SetState(%s) ignoring new state since current state is exited", DNBStateAsString(new_state)); - } - else if (old_state == new_state) - { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::SetState(%s) ignoring redundant state change...", DNBStateAsString(new_state)); - } - else - { - if (NUB_STATE_IS_STOPPED(new_state)) - event_mask = eEventProcessStoppedStateChanged; - else - event_mask = eEventProcessRunningStateChanged; - - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::SetState(%s) upating state (previous state was %s), event_mask = 0x%8.8x", DNBStateAsString(new_state), DNBStateAsString(old_state), event_mask); - - m_state = new_state; - if (new_state == eStateStopped) - m_stop_count++; - } - } - - if (event_mask != 0) - { - m_events.SetEvents (event_mask); - m_private_events.SetEvents (event_mask); - if (event_mask == eEventProcessStoppedStateChanged) - m_private_events.ResetEvents (eEventProcessRunningStateChanged); - else - m_private_events.ResetEvents (eEventProcessStoppedStateChanged); - - // Wait for the event bit to reset if a reset ACK is requested - m_events.WaitForResetAck(event_mask); - } +uint32_t MachProcess::GetCPUType() { + if (m_cpu_type == 0 && m_pid != 0) + m_cpu_type = MachProcess::GetCPUTypeForLocalProcess(m_pid); + return m_cpu_type; +} +const DNBRegisterSetInfo * +MachProcess::GetRegisterSetInfo(nub_thread_t tid, + nub_size_t *num_reg_sets) const { + MachThreadSP thread_sp(m_thread_list.GetThreadByID(tid)); + if (thread_sp) { + DNBArchProtocol *arch = thread_sp->GetArchProtocol(); + if (arch) + return arch->GetRegisterSetInfo(num_reg_sets); + } + *num_reg_sets = 0; + return NULL; } -void -MachProcess::Clear(bool detaching) -{ - // Clear any cached thread list while the pid and task are still valid +bool MachProcess::GetRegisterValue(nub_thread_t tid, uint32_t set, uint32_t reg, + DNBRegisterValue *value) const { + return m_thread_list.GetRegisterValue(tid, set, reg, value); +} - m_task.Clear(); - // Now clear out all member variables - m_pid = INVALID_NUB_PROCESS; - if (!detaching) - CloseChildFileDescriptors(); - - m_path.clear(); - m_args.clear(); - SetState(eStateUnloaded); - m_flags = eMachProcessFlagsNone; - m_stop_count = 0; - m_thread_list.Clear(); - { - PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex); - m_exception_messages.clear(); - } - m_activities.Clear(); - if (m_profile_thread) - { - pthread_join(m_profile_thread, NULL); - m_profile_thread = NULL; - } +bool MachProcess::SetRegisterValue(nub_thread_t tid, uint32_t set, uint32_t reg, + const DNBRegisterValue *value) const { + return m_thread_list.SetRegisterValue(tid, set, reg, value); } +void MachProcess::SetState(nub_state_t new_state) { + // If any other threads access this we will need a mutex for it + uint32_t event_mask = 0; -bool -MachProcess::StartSTDIOThread() -{ - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s ( )", __FUNCTION__); - // Create the thread that watches for the child STDIO - return ::pthread_create (&m_stdio_thread, NULL, MachProcess::STDIOThread, this) == 0; -} + // Scope for mutex locker + { + PTHREAD_MUTEX_LOCKER(locker, m_state_mutex); + const nub_state_t old_state = m_state; + + if (old_state == eStateExited) { + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::SetState(%s) ignoring new " + "state since current state is exited", + DNBStateAsString(new_state)); + } else if (old_state == new_state) { + DNBLogThreadedIf( + LOG_PROCESS, + "MachProcess::SetState(%s) ignoring redundant state change...", + DNBStateAsString(new_state)); + } else { + if (NUB_STATE_IS_STOPPED(new_state)) + event_mask = eEventProcessStoppedStateChanged; + else + event_mask = eEventProcessRunningStateChanged; + + DNBLogThreadedIf( + LOG_PROCESS, "MachProcess::SetState(%s) upating state (previous " + "state was %s), event_mask = 0x%8.8x", + DNBStateAsString(new_state), DNBStateAsString(old_state), event_mask); + + m_state = new_state; + if (new_state == eStateStopped) + m_stop_count++; + } + } + + if (event_mask != 0) { + m_events.SetEvents(event_mask); + m_private_events.SetEvents(event_mask); + if (event_mask == eEventProcessStoppedStateChanged) + m_private_events.ResetEvents(eEventProcessRunningStateChanged); + else + m_private_events.ResetEvents(eEventProcessStoppedStateChanged); -void -MachProcess::SetEnableAsyncProfiling(bool enable, uint64_t interval_usec, DNBProfileDataScanType scan_type) -{ - m_profile_enabled = enable; - m_profile_interval_usec = static_cast<useconds_t>(interval_usec); - m_profile_scan_type = scan_type; - - if (m_profile_enabled && (m_profile_thread == NULL)) - { - StartProfileThread(); - } - else if (!m_profile_enabled && m_profile_thread) - { - pthread_join(m_profile_thread, NULL); - m_profile_thread = NULL; - } + // Wait for the event bit to reset if a reset ACK is requested + m_events.WaitForResetAck(event_mask); + } +} + +void MachProcess::Clear(bool detaching) { + // Clear any cached thread list while the pid and task are still valid + + m_task.Clear(); + // Now clear out all member variables + m_pid = INVALID_NUB_PROCESS; + if (!detaching) + CloseChildFileDescriptors(); + + m_path.clear(); + m_args.clear(); + SetState(eStateUnloaded); + m_flags = eMachProcessFlagsNone; + m_stop_count = 0; + m_thread_list.Clear(); + { + PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex); + m_exception_messages.clear(); + } + m_activities.Clear(); + if (m_profile_thread) { + pthread_join(m_profile_thread, NULL); + m_profile_thread = NULL; + } } -bool -MachProcess::StartProfileThread() -{ - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s ( )", __FUNCTION__); - // Create the thread that profiles the inferior and reports back if enabled - return ::pthread_create (&m_profile_thread, NULL, MachProcess::ProfileThread, this) == 0; +bool MachProcess::StartSTDIOThread() { + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s ( )", __FUNCTION__); + // Create the thread that watches for the child STDIO + return ::pthread_create(&m_stdio_thread, NULL, MachProcess::STDIOThread, + this) == 0; } +void MachProcess::SetEnableAsyncProfiling(bool enable, uint64_t interval_usec, + DNBProfileDataScanType scan_type) { + m_profile_enabled = enable; + m_profile_interval_usec = static_cast<useconds_t>(interval_usec); + m_profile_scan_type = scan_type; -nub_addr_t -MachProcess::LookupSymbol(const char *name, const char *shlib) -{ - if (m_name_to_addr_callback != NULL && name && name[0]) - return m_name_to_addr_callback(ProcessID(), name, shlib, m_name_to_addr_baton); - return INVALID_NUB_ADDRESS; + if (m_profile_enabled && (m_profile_thread == NULL)) { + StartProfileThread(); + } else if (!m_profile_enabled && m_profile_thread) { + pthread_join(m_profile_thread, NULL); + m_profile_thread = NULL; + } } -bool -MachProcess::Resume (const DNBThreadResumeActions& thread_actions) -{ - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Resume ()"); - nub_state_t state = GetState(); - - if (CanResume(state)) - { - m_thread_actions = thread_actions; - PrivateResume(); - return true; - } - else if (state == eStateRunning) - { - DNBLog("Resume() - task 0x%x is already running, ignoring...", m_task.TaskPort()); - return true; - } - DNBLog("Resume() - task 0x%x has state %s, can't continue...", m_task.TaskPort(), DNBStateAsString(state)); - return false; +bool MachProcess::StartProfileThread() { + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s ( )", __FUNCTION__); + // Create the thread that profiles the inferior and reports back if enabled + return ::pthread_create(&m_profile_thread, NULL, MachProcess::ProfileThread, + this) == 0; } -bool -MachProcess::Kill (const struct timespec *timeout_abstime) -{ - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Kill ()"); - nub_state_t state = DoSIGSTOP(true, false, NULL); - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Kill() DoSIGSTOP() state = %s", DNBStateAsString(state)); - errno = 0; - DNBLog ("Sending ptrace PT_KILL to terminate inferior process."); - ::ptrace (PT_KILL, m_pid, 0, 0); - DNBError err; - err.SetErrorToErrno(); - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Kill() DoSIGSTOP() ::ptrace (PT_KILL, pid=%u, 0, 0) => 0x%8.8x (%s)", m_pid, err.Error(), err.AsString()); - m_thread_actions = DNBThreadResumeActions (eStateRunning, 0); - PrivateResume (); - - // Try and reap the process without touching our m_events since - // we want the code above this to still get the eStateExited event - const uint32_t reap_timeout_usec = 1000000; // Wait 1 second and try to reap the process - const uint32_t reap_interval_usec = 10000; // - uint32_t reap_time_elapsed; - for (reap_time_elapsed = 0; - reap_time_elapsed < reap_timeout_usec; - reap_time_elapsed += reap_interval_usec) - { - if (GetState() == eStateExited) - break; - usleep(reap_interval_usec); - } - DNBLog ("Waited %u ms for process to be reaped (state = %s)", reap_time_elapsed/1000, DNBStateAsString(GetState())); - return true; +nub_addr_t MachProcess::LookupSymbol(const char *name, const char *shlib) { + if (m_name_to_addr_callback != NULL && name && name[0]) + return m_name_to_addr_callback(ProcessID(), name, shlib, + m_name_to_addr_baton); + return INVALID_NUB_ADDRESS; } -bool -MachProcess::Interrupt() -{ - nub_state_t state = GetState(); - if (IsRunning(state)) - { - if (m_sent_interrupt_signo == 0) - { - m_sent_interrupt_signo = SIGSTOP; - if (Signal (m_sent_interrupt_signo)) - { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Interrupt() - sent %i signal to interrupt process", m_sent_interrupt_signo); - return true; - } - else - { - m_sent_interrupt_signo = 0; - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Interrupt() - failed to send %i signal to interrupt process", m_sent_interrupt_signo); - } - } - else - { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Interrupt() - previously sent an interrupt signal %i that hasn't been received yet, interrupt aborted", m_sent_interrupt_signo); - } - } - else - { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Interrupt() - process already stopped, no interrupt sent"); - } - return false; -} +bool MachProcess::Resume(const DNBThreadResumeActions &thread_actions) { + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Resume ()"); + nub_state_t state = GetState(); -bool -MachProcess::Signal (int signal, const struct timespec *timeout_abstime) -{ - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Signal (signal = %d, timeout = %p)", signal, timeout_abstime); - nub_state_t state = GetState(); - if (::kill (ProcessID(), signal) == 0) - { - // If we were running and we have a timeout, wait for the signal to stop - if (IsRunning(state) && timeout_abstime) - { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Signal (signal = %d, timeout = %p) waiting for signal to stop process...", signal, timeout_abstime); - m_private_events.WaitForSetEvents(eEventProcessStoppedStateChanged, timeout_abstime); - state = GetState(); - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Signal (signal = %d, timeout = %p) state = %s", signal, timeout_abstime, DNBStateAsString(state)); - return !IsRunning (state); - } - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Signal (signal = %d, timeout = %p) not waiting...", signal, timeout_abstime); + if (CanResume(state)) { + m_thread_actions = thread_actions; + PrivateResume(); + return true; + } else if (state == eStateRunning) { + DNBLog("Resume() - task 0x%x is already running, ignoring...", + m_task.TaskPort()); + return true; + } + DNBLog("Resume() - task 0x%x has state %s, can't continue...", + m_task.TaskPort(), DNBStateAsString(state)); + return false; +} + +bool MachProcess::Kill(const struct timespec *timeout_abstime) { + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Kill ()"); + nub_state_t state = DoSIGSTOP(true, false, NULL); + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Kill() DoSIGSTOP() state = %s", + DNBStateAsString(state)); + errno = 0; + DNBLog("Sending ptrace PT_KILL to terminate inferior process."); + ::ptrace(PT_KILL, m_pid, 0, 0); + DNBError err; + err.SetErrorToErrno(); + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Kill() DoSIGSTOP() ::ptrace " + "(PT_KILL, pid=%u, 0, 0) => 0x%8.8x (%s)", + m_pid, err.Error(), err.AsString()); + m_thread_actions = DNBThreadResumeActions(eStateRunning, 0); + PrivateResume(); + + // Try and reap the process without touching our m_events since + // we want the code above this to still get the eStateExited event + const uint32_t reap_timeout_usec = + 1000000; // Wait 1 second and try to reap the process + const uint32_t reap_interval_usec = 10000; // + uint32_t reap_time_elapsed; + for (reap_time_elapsed = 0; reap_time_elapsed < reap_timeout_usec; + reap_time_elapsed += reap_interval_usec) { + if (GetState() == eStateExited) + break; + usleep(reap_interval_usec); + } + DNBLog("Waited %u ms for process to be reaped (state = %s)", + reap_time_elapsed / 1000, DNBStateAsString(GetState())); + return true; +} + +bool MachProcess::Interrupt() { + nub_state_t state = GetState(); + if (IsRunning(state)) { + if (m_sent_interrupt_signo == 0) { + m_sent_interrupt_signo = SIGSTOP; + if (Signal(m_sent_interrupt_signo)) { + DNBLogThreadedIf( + LOG_PROCESS, + "MachProcess::Interrupt() - sent %i signal to interrupt process", + m_sent_interrupt_signo); return true; - } - DNBError err(errno, DNBError::POSIX); - err.LogThreadedIfError("kill (pid = %d, signo = %i)", ProcessID(), signal); - return false; - + } else { + m_sent_interrupt_signo = 0; + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Interrupt() - failed to " + "send %i signal to interrupt process", + m_sent_interrupt_signo); + } + } else { + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Interrupt() - previously " + "sent an interrupt signal %i that hasn't " + "been received yet, interrupt aborted", + m_sent_interrupt_signo); + } + } else { + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Interrupt() - process already " + "stopped, no interrupt sent"); + } + return false; +} + +bool MachProcess::Signal(int signal, const struct timespec *timeout_abstime) { + DNBLogThreadedIf(LOG_PROCESS, + "MachProcess::Signal (signal = %d, timeout = %p)", signal, + timeout_abstime); + nub_state_t state = GetState(); + if (::kill(ProcessID(), signal) == 0) { + // If we were running and we have a timeout, wait for the signal to stop + if (IsRunning(state) && timeout_abstime) { + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Signal (signal = %d, timeout " + "= %p) waiting for signal to stop " + "process...", + signal, timeout_abstime); + m_private_events.WaitForSetEvents(eEventProcessStoppedStateChanged, + timeout_abstime); + state = GetState(); + DNBLogThreadedIf( + LOG_PROCESS, + "MachProcess::Signal (signal = %d, timeout = %p) state = %s", signal, + timeout_abstime, DNBStateAsString(state)); + return !IsRunning(state); + } + DNBLogThreadedIf( + LOG_PROCESS, + "MachProcess::Signal (signal = %d, timeout = %p) not waiting...", + signal, timeout_abstime); + return true; + } + DNBError err(errno, DNBError::POSIX); + err.LogThreadedIfError("kill (pid = %d, signo = %i)", ProcessID(), signal); + return false; } -bool -MachProcess::SendEvent (const char *event, DNBError &send_err) -{ - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::SendEvent (event = %s) to pid: %d", event, m_pid); - if (m_pid == INVALID_NUB_PROCESS) - return false; - // FIXME: Shouldn't we use the launch flavor we were started with? +bool MachProcess::SendEvent(const char *event, DNBError &send_err) { + DNBLogThreadedIf(LOG_PROCESS, + "MachProcess::SendEvent (event = %s) to pid: %d", event, + m_pid); + if (m_pid == INVALID_NUB_PROCESS) + return false; +// FIXME: Shouldn't we use the launch flavor we were started with? #if defined(WITH_FBS) || defined(WITH_BKS) - return BoardServiceSendEvent (event, send_err); + return BoardServiceSendEvent(event, send_err); #endif - return true; + return true; } -nub_state_t -MachProcess::DoSIGSTOP (bool clear_bps_and_wps, bool allow_running, uint32_t *thread_idx_ptr) -{ - nub_state_t state = GetState(); - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::DoSIGSTOP() state = %s", DNBStateAsString (state)); +nub_state_t MachProcess::DoSIGSTOP(bool clear_bps_and_wps, bool allow_running, + uint32_t *thread_idx_ptr) { + nub_state_t state = GetState(); + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::DoSIGSTOP() state = %s", + DNBStateAsString(state)); - if (!IsRunning(state)) - { - if (clear_bps_and_wps) - { - DisableAllBreakpoints (true); - DisableAllWatchpoints (true); - clear_bps_and_wps = false; - } + if (!IsRunning(state)) { + if (clear_bps_and_wps) { + DisableAllBreakpoints(true); + DisableAllWatchpoints(true); + clear_bps_and_wps = false; + } - // If we already have a thread stopped due to a SIGSTOP, we don't have - // to do anything... - uint32_t thread_idx = m_thread_list.GetThreadIndexForThreadStoppedWithSignal (SIGSTOP); - if (thread_idx_ptr) - *thread_idx_ptr = thread_idx; - if (thread_idx != UINT32_MAX) - return GetState(); - - // No threads were stopped with a SIGSTOP, we need to run and halt the - // process with a signal - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::DoSIGSTOP() state = %s -- resuming process", DNBStateAsString (state)); - if (allow_running) - m_thread_actions = DNBThreadResumeActions (eStateRunning, 0); - else - m_thread_actions = DNBThreadResumeActions (eStateSuspended, 0); - - PrivateResume (); - - // Reset the event that says we were indeed running - m_events.ResetEvents(eEventProcessRunningStateChanged); - state = GetState(); - } - - // We need to be stopped in order to be able to detach, so we need - // to send ourselves a SIGSTOP - - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::DoSIGSTOP() state = %s -- sending SIGSTOP", DNBStateAsString (state)); - struct timespec sigstop_timeout; - DNBTimer::OffsetTimeOfDay(&sigstop_timeout, 2, 0); - Signal (SIGSTOP, &sigstop_timeout); - if (clear_bps_and_wps) - { - DisableAllBreakpoints (true); - DisableAllWatchpoints (true); - //clear_bps_and_wps = false; - } - uint32_t thread_idx = m_thread_list.GetThreadIndexForThreadStoppedWithSignal (SIGSTOP); + // If we already have a thread stopped due to a SIGSTOP, we don't have + // to do anything... + uint32_t thread_idx = + m_thread_list.GetThreadIndexForThreadStoppedWithSignal(SIGSTOP); if (thread_idx_ptr) - *thread_idx_ptr = thread_idx; - return GetState(); -} - -bool -MachProcess::Detach() -{ - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Detach()"); + *thread_idx_ptr = thread_idx; + if (thread_idx != UINT32_MAX) + return GetState(); - uint32_t thread_idx = UINT32_MAX; - nub_state_t state = DoSIGSTOP(true, true, &thread_idx); - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Detach() DoSIGSTOP() returned %s", DNBStateAsString(state)); + // No threads were stopped with a SIGSTOP, we need to run and halt the + // process with a signal + DNBLogThreadedIf(LOG_PROCESS, + "MachProcess::DoSIGSTOP() state = %s -- resuming process", + DNBStateAsString(state)); + if (allow_running) + m_thread_actions = DNBThreadResumeActions(eStateRunning, 0); + else + m_thread_actions = DNBThreadResumeActions(eStateSuspended, 0); + + PrivateResume(); + + // Reset the event that says we were indeed running + m_events.ResetEvents(eEventProcessRunningStateChanged); + state = GetState(); + } + + // We need to be stopped in order to be able to detach, so we need + // to send ourselves a SIGSTOP + + DNBLogThreadedIf(LOG_PROCESS, + "MachProcess::DoSIGSTOP() state = %s -- sending SIGSTOP", + DNBStateAsString(state)); + struct timespec sigstop_timeout; + DNBTimer::OffsetTimeOfDay(&sigstop_timeout, 2, 0); + Signal(SIGSTOP, &sigstop_timeout); + if (clear_bps_and_wps) { + DisableAllBreakpoints(true); + DisableAllWatchpoints(true); + // clear_bps_and_wps = false; + } + uint32_t thread_idx = + m_thread_list.GetThreadIndexForThreadStoppedWithSignal(SIGSTOP); + if (thread_idx_ptr) + *thread_idx_ptr = thread_idx; + return GetState(); +} + +bool MachProcess::Detach() { + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Detach()"); + + uint32_t thread_idx = UINT32_MAX; + nub_state_t state = DoSIGSTOP(true, true, &thread_idx); + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Detach() DoSIGSTOP() returned %s", + DNBStateAsString(state)); + + { + m_thread_actions.Clear(); + m_activities.Clear(); + DNBThreadResumeAction thread_action; + thread_action.tid = m_thread_list.ThreadIDAtIndex(thread_idx); + thread_action.state = eStateRunning; + thread_action.signal = -1; + thread_action.addr = INVALID_NUB_ADDRESS; - { - m_thread_actions.Clear(); - m_activities.Clear(); - DNBThreadResumeAction thread_action; - thread_action.tid = m_thread_list.ThreadIDAtIndex (thread_idx); - thread_action.state = eStateRunning; - thread_action.signal = -1; - thread_action.addr = INVALID_NUB_ADDRESS; - - m_thread_actions.Append (thread_action); - m_thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, 0); - - PTHREAD_MUTEX_LOCKER (locker, m_exception_messages_mutex); + m_thread_actions.Append(thread_action); + m_thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0); - ReplyToAllExceptions (); + PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex); - } + ReplyToAllExceptions(); + } - m_task.ShutDownExcecptionThread(); + m_task.ShutDownExcecptionThread(); - // Detach from our process - errno = 0; - nub_process_t pid = m_pid; - int ret = ::ptrace (PT_DETACH, pid, (caddr_t)1, 0); - DNBError err(errno, DNBError::POSIX); - if (DNBLogCheckLogBit(LOG_PROCESS) || err.Fail() || (ret != 0)) - err.LogThreaded("::ptrace (PT_DETACH, %u, (caddr_t)1, 0)", pid); + // Detach from our process + errno = 0; + nub_process_t pid = m_pid; + int ret = ::ptrace(PT_DETACH, pid, (caddr_t)1, 0); + DNBError err(errno, DNBError::POSIX); + if (DNBLogCheckLogBit(LOG_PROCESS) || err.Fail() || (ret != 0)) + err.LogThreaded("::ptrace (PT_DETACH, %u, (caddr_t)1, 0)", pid); - // Resume our task - m_task.Resume(); + // Resume our task + m_task.Resume(); - // NULL our task out as we have already retored all exception ports - m_task.Clear(); + // NULL our task out as we have already retored all exception ports + m_task.Clear(); - // Clear out any notion of the process we once were - const bool detaching = true; - Clear(detaching); + // Clear out any notion of the process we once were + const bool detaching = true; + Clear(detaching); - SetState(eStateDetached); + SetState(eStateDetached); - return true; + return true; } //---------------------------------------------------------------------- @@ -1438,20 +1428,19 @@ MachProcess::Detach() // (m_task.ReadMemory()) as that version will give you what is actually // in inferior memory. //---------------------------------------------------------------------- -nub_size_t -MachProcess::ReadMemory (nub_addr_t addr, nub_size_t size, void *buf) -{ - // We need to remove any current software traps (enabled software - // breakpoints) that we may have placed in our tasks memory. +nub_size_t MachProcess::ReadMemory(nub_addr_t addr, nub_size_t size, + void *buf) { + // We need to remove any current software traps (enabled software + // breakpoints) that we may have placed in our tasks memory. - // First just read the memory as is - nub_size_t bytes_read = m_task.ReadMemory(addr, size, buf); + // First just read the memory as is + nub_size_t bytes_read = m_task.ReadMemory(addr, size, buf); - // Then place any opcodes that fall into this range back into the buffer - // before we return this to callers. - if (bytes_read > 0) - m_breakpoints.RemoveTrapsFromBuffer (addr, bytes_read, buf); - return bytes_read; + // Then place any opcodes that fall into this range back into the buffer + // before we return this to callers. + if (bytes_read > 0) + m_breakpoints.RemoveTrapsFromBuffer(addr, bytes_read, buf); + return bytes_read; } //---------------------------------------------------------------------- @@ -1463,1288 +1452,1275 @@ MachProcess::ReadMemory (nub_addr_t addr, nub_size_t size, void *buf) // (m_task.WriteMemory()) as that version will always modify inferior // memory. //---------------------------------------------------------------------- -nub_size_t -MachProcess::WriteMemory (nub_addr_t addr, nub_size_t size, const void *buf) -{ - // We need to write any data that would go where any current software traps - // (enabled software breakpoints) any software traps (breakpoints) that we - // may have placed in our tasks memory. - - std::vector<DNBBreakpoint *> bps; - - const size_t num_bps = m_breakpoints.FindBreakpointsThatOverlapRange(addr, size, bps); - if (num_bps == 0) - return m_task.WriteMemory(addr, size, buf); - - nub_size_t bytes_written = 0; - nub_addr_t intersect_addr; - nub_size_t intersect_size; - nub_size_t opcode_offset; - const uint8_t *ubuf = (const uint8_t *)buf; - - for (size_t i=0; i<num_bps; ++i) - { - DNBBreakpoint *bp = bps[i]; - - const bool intersects = bp->IntersectsRange(addr, size, &intersect_addr, &intersect_size, &opcode_offset); - UNUSED_IF_ASSERT_DISABLED(intersects); - assert(intersects); - 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()); - - // Check for bytes before this breakpoint - const nub_addr_t curr_addr = addr + bytes_written; - if (intersect_addr > curr_addr) - { - // There are some bytes before this breakpoint that we need to - // just write to memory - nub_size_t curr_size = intersect_addr - curr_addr; - nub_size_t curr_bytes_written = m_task.WriteMemory(curr_addr, curr_size, ubuf + bytes_written); - bytes_written += curr_bytes_written; - if (curr_bytes_written != curr_size) - { - // We weren't able to write all of the requested bytes, we - // are done looping and will return the number of bytes that - // we have written so far. - break; - } - } - - // Now write any bytes that would cover up any software breakpoints - // directly into the breakpoint opcode buffer - ::memcpy(bp->SavedOpcodeBytes() + opcode_offset, ubuf + bytes_written, intersect_size); - bytes_written += intersect_size; - } - - // Write any remaining bytes after the last breakpoint if we have any left - if (bytes_written < size) - bytes_written += m_task.WriteMemory(addr + bytes_written, size - bytes_written, ubuf + bytes_written); - - return bytes_written; -} - -void -MachProcess::ReplyToAllExceptions () -{ - PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex); - if (m_exception_messages.empty() == false) - { - MachException::Message::iterator pos; - MachException::Message::iterator begin = m_exception_messages.begin(); - MachException::Message::iterator end = m_exception_messages.end(); - for (pos = begin; pos != end; ++pos) - { - DNBLogThreadedIf(LOG_EXCEPTIONS, "Replying to exception %u...", (uint32_t)std::distance(begin, pos)); - int thread_reply_signal = 0; - - nub_thread_t tid = m_thread_list.GetThreadIDByMachPortNumber (pos->state.thread_port); - const DNBThreadResumeAction *action = NULL; - if (tid != INVALID_NUB_THREAD) - { - action = m_thread_actions.GetActionForThread (tid, false); - } - - if (action) - { - thread_reply_signal = action->signal; - if (thread_reply_signal) - m_thread_actions.SetSignalHandledForThread (tid); - } - - DNBError err (pos->Reply(this, thread_reply_signal)); - if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) - err.LogThreadedIfError("Error replying to exception"); - } - - // Erase all exception message as we should have used and replied - // to them all already. - m_exception_messages.clear(); - } +nub_size_t MachProcess::WriteMemory(nub_addr_t addr, nub_size_t size, + const void *buf) { + // We need to write any data that would go where any current software traps + // (enabled software breakpoints) any software traps (breakpoints) that we + // may have placed in our tasks memory. + + std::vector<DNBBreakpoint *> bps; + + const size_t num_bps = + m_breakpoints.FindBreakpointsThatOverlapRange(addr, size, bps); + if (num_bps == 0) + return m_task.WriteMemory(addr, size, buf); + + nub_size_t bytes_written = 0; + nub_addr_t intersect_addr; + nub_size_t intersect_size; + nub_size_t opcode_offset; + const uint8_t *ubuf = (const uint8_t *)buf; + + for (size_t i = 0; i < num_bps; ++i) { + DNBBreakpoint *bp = bps[i]; + + const bool intersects = bp->IntersectsRange( + addr, size, &intersect_addr, &intersect_size, &opcode_offset); + UNUSED_IF_ASSERT_DISABLED(intersects); + assert(intersects); + 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()); + + // Check for bytes before this breakpoint + const nub_addr_t curr_addr = addr + bytes_written; + if (intersect_addr > curr_addr) { + // There are some bytes before this breakpoint that we need to + // just write to memory + nub_size_t curr_size = intersect_addr - curr_addr; + nub_size_t curr_bytes_written = + m_task.WriteMemory(curr_addr, curr_size, ubuf + bytes_written); + bytes_written += curr_bytes_written; + if (curr_bytes_written != curr_size) { + // We weren't able to write all of the requested bytes, we + // are done looping and will return the number of bytes that + // we have written so far. + break; + } + } + + // Now write any bytes that would cover up any software breakpoints + // directly into the breakpoint opcode buffer + ::memcpy(bp->SavedOpcodeBytes() + opcode_offset, ubuf + bytes_written, + intersect_size); + bytes_written += intersect_size; + } + + // Write any remaining bytes after the last breakpoint if we have any left + if (bytes_written < size) + bytes_written += m_task.WriteMemory( + addr + bytes_written, size - bytes_written, ubuf + bytes_written); + + return bytes_written; +} + +void MachProcess::ReplyToAllExceptions() { + PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex); + if (m_exception_messages.empty() == false) { + MachException::Message::iterator pos; + MachException::Message::iterator begin = m_exception_messages.begin(); + MachException::Message::iterator end = m_exception_messages.end(); + for (pos = begin; pos != end; ++pos) { + DNBLogThreadedIf(LOG_EXCEPTIONS, "Replying to exception %u...", + (uint32_t)std::distance(begin, pos)); + int thread_reply_signal = 0; + + nub_thread_t tid = + m_thread_list.GetThreadIDByMachPortNumber(pos->state.thread_port); + const DNBThreadResumeAction *action = NULL; + if (tid != INVALID_NUB_THREAD) { + action = m_thread_actions.GetActionForThread(tid, false); + } + + if (action) { + thread_reply_signal = action->signal; + if (thread_reply_signal) + m_thread_actions.SetSignalHandledForThread(tid); + } + + DNBError err(pos->Reply(this, thread_reply_signal)); + if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) + err.LogThreadedIfError("Error replying to exception"); + } + + // Erase all exception message as we should have used and replied + // to them all already. + m_exception_messages.clear(); + } +} +void MachProcess::PrivateResume() { + PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex); + + m_auto_resume_signo = m_sent_interrupt_signo; + if (m_auto_resume_signo) + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::PrivateResume() - task 0x%x " + "resuming (with unhandled interrupt signal " + "%i)...", + m_task.TaskPort(), m_auto_resume_signo); + else + DNBLogThreadedIf(LOG_PROCESS, + "MachProcess::PrivateResume() - task 0x%x resuming...", + m_task.TaskPort()); + + ReplyToAllExceptions(); + // bool stepOverBreakInstruction = step; + + // Let the thread prepare to resume and see if any threads want us to + // step over a breakpoint instruction (ProcessWillResume will modify + // the value of stepOverBreakInstruction). + m_thread_list.ProcessWillResume(this, m_thread_actions); + + // Set our state accordingly + if (m_thread_actions.NumActionsWithState(eStateStepping)) + SetState(eStateStepping); + else + SetState(eStateRunning); + + // Now resume our task. + m_task.Resume(); +} + +DNBBreakpoint *MachProcess::CreateBreakpoint(nub_addr_t addr, nub_size_t length, + bool hardware) { + DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::CreateBreakpoint ( addr = " + "0x%8.8llx, length = %llu, hardware = %i)", + (uint64_t)addr, (uint64_t)length, hardware); + + DNBBreakpoint *bp = m_breakpoints.FindByAddress(addr); + if (bp) + bp->Retain(); + else + bp = m_breakpoints.Add(addr, length, hardware); + + if (EnableBreakpoint(addr)) { + DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::CreateBreakpoint ( addr = " + "0x%8.8llx, length = %llu) => %p", + (uint64_t)addr, (uint64_t)length, bp); + return bp; + } else if (bp->Release() == 0) { + m_breakpoints.Remove(addr); + } + // We failed to enable the breakpoint + return NULL; } -void -MachProcess::PrivateResume () -{ - PTHREAD_MUTEX_LOCKER (locker, m_exception_messages_mutex); - - m_auto_resume_signo = m_sent_interrupt_signo; - if (m_auto_resume_signo) - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::PrivateResume() - task 0x%x resuming (with unhandled interrupt signal %i)...", m_task.TaskPort(), m_auto_resume_signo); - else - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::PrivateResume() - task 0x%x resuming...", m_task.TaskPort()); - - ReplyToAllExceptions (); -// bool stepOverBreakInstruction = step; - - // Let the thread prepare to resume and see if any threads want us to - // step over a breakpoint instruction (ProcessWillResume will modify - // the value of stepOverBreakInstruction). - m_thread_list.ProcessWillResume (this, m_thread_actions); - - // Set our state accordingly - if (m_thread_actions.NumActionsWithState(eStateStepping)) - SetState (eStateStepping); - else - SetState (eStateRunning); - // Now resume our task. - m_task.Resume(); +DNBBreakpoint *MachProcess::CreateWatchpoint(nub_addr_t addr, nub_size_t length, + uint32_t watch_flags, + bool hardware) { + DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = " + "0x%8.8llx, length = %llu, flags = " + "0x%8.8x, hardware = %i)", + (uint64_t)addr, (uint64_t)length, watch_flags, hardware); + + DNBBreakpoint *wp = m_watchpoints.FindByAddress(addr); + // since the Z packets only send an address, we can only have one watchpoint + // at + // an address. If there is already one, we must refuse to create another + // watchpoint + if (wp) + return NULL; + + wp = m_watchpoints.Add(addr, length, hardware); + wp->SetIsWatchpoint(watch_flags); + + if (EnableWatchpoint(addr)) { + DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = " + "0x%8.8llx, length = %llu) => %p", + (uint64_t)addr, (uint64_t)length, wp); + return wp; + } else { + DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = " + "0x%8.8llx, length = %llu) => FAILED", + (uint64_t)addr, (uint64_t)length); + m_watchpoints.Remove(addr); + } + // We failed to enable the watchpoint + return NULL; } -DNBBreakpoint * -MachProcess::CreateBreakpoint(nub_addr_t addr, nub_size_t length, bool hardware) -{ - DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::CreateBreakpoint ( addr = 0x%8.8llx, length = %llu, hardware = %i)", (uint64_t)addr, (uint64_t)length, hardware); +void MachProcess::DisableAllBreakpoints(bool remove) { + DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::%s (remove = %d )", + __FUNCTION__, remove); - DNBBreakpoint *bp = m_breakpoints.FindByAddress(addr); - if (bp) - bp->Retain(); - else - bp = m_breakpoints.Add(addr, length, hardware); + m_breakpoints.DisableAllBreakpoints(this); - if (EnableBreakpoint(addr)) - { - DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::CreateBreakpoint ( addr = 0x%8.8llx, length = %llu) => %p", (uint64_t)addr, (uint64_t)length, bp); - return bp; - } - else if (bp->Release() == 0) - { - m_breakpoints.Remove(addr); - } - // We failed to enable the breakpoint - return NULL; + if (remove) + m_breakpoints.RemoveDisabled(); } -DNBBreakpoint * -MachProcess::CreateWatchpoint(nub_addr_t addr, nub_size_t length, uint32_t watch_flags, bool hardware) -{ - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = 0x%8.8llx, length = %llu, flags = 0x%8.8x, hardware = %i)", (uint64_t)addr, (uint64_t)length, watch_flags, hardware); +void MachProcess::DisableAllWatchpoints(bool remove) { + DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::%s (remove = %d )", + __FUNCTION__, remove); - DNBBreakpoint *wp = m_watchpoints.FindByAddress(addr); - // since the Z packets only send an address, we can only have one watchpoint at - // an address. If there is already one, we must refuse to create another watchpoint - if (wp) - return NULL; - - wp = m_watchpoints.Add(addr, length, hardware); - wp->SetIsWatchpoint(watch_flags); + m_watchpoints.DisableAllWatchpoints(this); - if (EnableWatchpoint(addr)) - { - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = 0x%8.8llx, length = %llu) => %p", (uint64_t)addr, (uint64_t)length, wp); - return wp; - } - else - { - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::CreateWatchpoint ( addr = 0x%8.8llx, length = %llu) => FAILED", (uint64_t)addr, (uint64_t)length); - m_watchpoints.Remove(addr); - } - // We failed to enable the watchpoint - return NULL; + if (remove) + m_watchpoints.RemoveDisabled(); } -void -MachProcess::DisableAllBreakpoints (bool remove) -{ - DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::%s (remove = %d )", __FUNCTION__, remove); - - m_breakpoints.DisableAllBreakpoints (this); - - if (remove) - m_breakpoints.RemoveDisabled(); -} - -void -MachProcess::DisableAllWatchpoints(bool remove) -{ - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::%s (remove = %d )", __FUNCTION__, remove); - - m_watchpoints.DisableAllWatchpoints(this); - - if (remove) - m_watchpoints.RemoveDisabled(); -} - -bool -MachProcess::DisableBreakpoint(nub_addr_t addr, bool remove) -{ - DNBBreakpoint *bp = m_breakpoints.FindByAddress(addr); - if (bp) - { - // After "exec" we might end up with a bunch of breakpoints that were disabled - // manually, just ignore them - if (!bp->IsEnabled()) - { - // Breakpoint might have been disabled by an exec - if (remove && bp->Release() == 0) - { +bool MachProcess::DisableBreakpoint(nub_addr_t addr, bool remove) { + DNBBreakpoint *bp = m_breakpoints.FindByAddress(addr); + if (bp) { + // After "exec" we might end up with a bunch of breakpoints that were + // disabled + // manually, just ignore them + if (!bp->IsEnabled()) { + // Breakpoint might have been disabled by an exec + if (remove && bp->Release() == 0) { + m_thread_list.NotifyBreakpointChanged(bp); + m_breakpoints.Remove(addr); + } + return true; + } + + // We have multiple references to this breakpoint, decrement the ref count + // and if it isn't zero, then return true; + if (remove && bp->Release() > 0) + return true; + + DNBLogThreadedIf( + LOG_BREAKPOINTS | LOG_VERBOSE, + "MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d )", + (uint64_t)addr, remove); + + if (bp->IsHardware()) { + bool hw_disable_result = m_thread_list.DisableHardwareBreakpoint(bp); + + if (hw_disable_result == true) { + bp->SetEnabled(false); + // Let the thread list know that a breakpoint has been modified + if (remove) { + m_thread_list.NotifyBreakpointChanged(bp); + m_breakpoints.Remove(addr); + } + DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::DisableBreakpoint ( " + "addr = 0x%8.8llx, remove = %d ) " + "(hardware) => success", + (uint64_t)addr, remove); + return true; + } + + return false; + } + + const nub_size_t break_op_size = bp->ByteSize(); + assert(break_op_size > 0); + const uint8_t *const break_op = + DNBArchProtocol::GetBreakpointOpcode(bp->ByteSize()); + if (break_op_size > 0) { + // Clear a software breakpoint instruction + uint8_t curr_break_op[break_op_size]; + bool break_op_found = false; + + // Read the breakpoint opcode + if (m_task.ReadMemory(addr, break_op_size, curr_break_op) == + break_op_size) { + bool verify = false; + if (bp->IsEnabled()) { + // Make sure we have the a breakpoint opcode exists at this address + if (memcmp(curr_break_op, break_op, break_op_size) == 0) { + break_op_found = true; + // We found a valid breakpoint opcode at this address, now restore + // the saved opcode. + if (m_task.WriteMemory(addr, break_op_size, + bp->SavedOpcodeBytes()) == break_op_size) { + verify = true; + } else { + DNBLogError("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, " + "remove = %d ) memory write failed when restoring " + "original opcode", + (uint64_t)addr, remove); + } + } else { + DNBLogWarning("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, " + "remove = %d ) expected a breakpoint opcode but " + "didn't find one.", + (uint64_t)addr, remove); + // Set verify to true and so we can check if the original opcode has + // already been restored + verify = true; + } + } else { + DNBLogThreadedIf(LOG_BREAKPOINTS | LOG_VERBOSE, + "MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, " + "remove = %d ) is not enabled", + (uint64_t)addr, remove); + // Set verify to true and so we can check if the original opcode is + // there + verify = true; + } + + if (verify) { + uint8_t verify_opcode[break_op_size]; + // Verify that our original opcode made it back to the inferior + if (m_task.ReadMemory(addr, break_op_size, verify_opcode) == + break_op_size) { + // compare the memory we just read with the original opcode + if (memcmp(bp->SavedOpcodeBytes(), verify_opcode, break_op_size) == + 0) { + // SUCCESS + bp->SetEnabled(false); + // Let the thread list know that a breakpoint has been modified + if (remove && bp->Release() == 0) { m_thread_list.NotifyBreakpointChanged(bp); m_breakpoints.Remove(addr); + } + DNBLogThreadedIf(LOG_BREAKPOINTS, + "MachProcess::DisableBreakpoint ( addr = " + "0x%8.8llx, remove = %d ) => success", + (uint64_t)addr, remove); + return true; + } else { + if (break_op_found) + DNBLogError("MachProcess::DisableBreakpoint ( addr = " + "0x%8.8llx, remove = %d ) : failed to restore " + "original opcode", + (uint64_t)addr, remove); + else + DNBLogError("MachProcess::DisableBreakpoint ( addr = " + "0x%8.8llx, remove = %d ) : opcode changed", + (uint64_t)addr, remove); } - return true; - } - - // We have multiple references to this breakpoint, decrement the ref count - // and if it isn't zero, then return true; - if (remove && bp->Release() > 0) - return true; - - DNBLogThreadedIf(LOG_BREAKPOINTS | LOG_VERBOSE, "MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d )", (uint64_t)addr, remove); - - if (bp->IsHardware()) - { - bool hw_disable_result = m_thread_list.DisableHardwareBreakpoint (bp); - - if (hw_disable_result == true) - { - bp->SetEnabled(false); + } else { + DNBLogWarning("MachProcess::DisableBreakpoint: unable to disable " + "breakpoint 0x%8.8llx", + (uint64_t)addr); + } + } + } else { + DNBLogWarning("MachProcess::DisableBreakpoint: unable to read memory " + "at 0x%8.8llx", + (uint64_t)addr); + } + } + } else { + DNBLogError("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = " + "%d ) invalid breakpoint address", + (uint64_t)addr, remove); + } + return false; +} + +bool MachProcess::DisableWatchpoint(nub_addr_t addr, bool remove) { + DNBLogThreadedIf(LOG_WATCHPOINTS, + "MachProcess::%s(addr = 0x%8.8llx, remove = %d)", + __FUNCTION__, (uint64_t)addr, remove); + DNBBreakpoint *wp = m_watchpoints.FindByAddress(addr); + if (wp) { + // If we have multiple references to a watchpoint, removing the watchpoint + // shouldn't clear it + if (remove && wp->Release() > 0) + return true; + + nub_addr_t addr = wp->Address(); + DNBLogThreadedIf( + LOG_WATCHPOINTS, + "MachProcess::DisableWatchpoint ( addr = 0x%8.8llx, remove = %d )", + (uint64_t)addr, remove); + + if (wp->IsHardware()) { + bool hw_disable_result = m_thread_list.DisableHardwareWatchpoint(wp); + + if (hw_disable_result == true) { + wp->SetEnabled(false); + if (remove) + m_watchpoints.Remove(addr); + DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::Disablewatchpoint ( " + "addr = 0x%8.8llx, remove = %d ) " + "(hardware) => success", + (uint64_t)addr, remove); + return true; + } + } + + // TODO: clear software watchpoints if we implement them + } else { + DNBLogError("MachProcess::DisableWatchpoint ( addr = 0x%8.8llx, remove = " + "%d ) invalid watchpoint ID", + (uint64_t)addr, remove); + } + return false; +} + +uint32_t MachProcess::GetNumSupportedHardwareWatchpoints() const { + return m_thread_list.NumSupportedHardwareWatchpoints(); +} + +bool MachProcess::EnableBreakpoint(nub_addr_t addr) { + DNBLogThreadedIf(LOG_BREAKPOINTS, + "MachProcess::EnableBreakpoint ( addr = 0x%8.8llx )", + (uint64_t)addr); + DNBBreakpoint *bp = m_breakpoints.FindByAddress(addr); + if (bp) { + if (bp->IsEnabled()) { + DNBLogWarning("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): " + "breakpoint already enabled.", + (uint64_t)addr); + return true; + } else { + if (bp->HardwarePreferred()) { + bp->SetHardwareIndex(m_thread_list.EnableHardwareBreakpoint(bp)); + if (bp->IsHardware()) { + bp->SetEnabled(true); + return true; + } + } + + const nub_size_t break_op_size = bp->ByteSize(); + assert(break_op_size != 0); + const uint8_t *const break_op = + DNBArchProtocol::GetBreakpointOpcode(break_op_size); + if (break_op_size > 0) { + // Save the original opcode by reading it + if (m_task.ReadMemory(addr, break_op_size, bp->SavedOpcodeBytes()) == + break_op_size) { + // Write a software breakpoint in place of the original opcode + if (m_task.WriteMemory(addr, break_op_size, break_op) == + break_op_size) { + uint8_t verify_break_op[4]; + if (m_task.ReadMemory(addr, break_op_size, verify_break_op) == + break_op_size) { + if (memcmp(break_op, verify_break_op, break_op_size) == 0) { + bp->SetEnabled(true); // Let the thread list know that a breakpoint has been modified - if (remove) - { - m_thread_list.NotifyBreakpointChanged(bp); - m_breakpoints.Remove(addr); - } - DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) (hardware) => success", (uint64_t)addr, remove); + m_thread_list.NotifyBreakpointChanged(bp); + DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::" + "EnableBreakpoint ( addr = " + "0x%8.8llx ) : SUCCESS.", + (uint64_t)addr); return true; + } else { + DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx " + "): breakpoint opcode verification failed.", + (uint64_t)addr); + } + } else { + DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): " + "unable to read memory to verify breakpoint opcode.", + (uint64_t)addr); } + } else { + DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): " + "unable to write breakpoint opcode to memory.", + (uint64_t)addr); + } + } else { + DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): " + "unable to read memory at breakpoint address.", + (uint64_t)addr); + } + } else { + DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ) no " + "software breakpoint opcode for current architecture.", + (uint64_t)addr); + } + } + } + return false; +} + +bool MachProcess::EnableWatchpoint(nub_addr_t addr) { + DNBLogThreadedIf(LOG_WATCHPOINTS, + "MachProcess::EnableWatchpoint(addr = 0x%8.8llx)", + (uint64_t)addr); + DNBBreakpoint *wp = m_watchpoints.FindByAddress(addr); + if (wp) { + nub_addr_t addr = wp->Address(); + if (wp->IsEnabled()) { + DNBLogWarning("MachProcess::EnableWatchpoint(addr = 0x%8.8llx): " + "watchpoint already enabled.", + (uint64_t)addr); + return true; + } else { + // Currently only try and set hardware watchpoints. + wp->SetHardwareIndex(m_thread_list.EnableHardwareWatchpoint(wp)); + if (wp->IsHardware()) { + wp->SetEnabled(true); + return true; + } + // TODO: Add software watchpoints by doing page protection tricks. + } + } + return false; +} - return false; - } - - const nub_size_t break_op_size = bp->ByteSize(); - assert (break_op_size > 0); - const uint8_t * const break_op = DNBArchProtocol::GetBreakpointOpcode (bp->ByteSize()); - if (break_op_size > 0) - { - // Clear a software breakpoint instruction - uint8_t curr_break_op[break_op_size]; - bool break_op_found = false; - - // Read the breakpoint opcode - if (m_task.ReadMemory(addr, break_op_size, curr_break_op) == break_op_size) - { - bool verify = false; - if (bp->IsEnabled()) - { - // Make sure we have the a breakpoint opcode exists at this address - if (memcmp(curr_break_op, break_op, break_op_size) == 0) - { - break_op_found = true; - // We found a valid breakpoint opcode at this address, now restore - // the saved opcode. - if (m_task.WriteMemory(addr, break_op_size, bp->SavedOpcodeBytes()) == break_op_size) - { - verify = true; - } - else - { - DNBLogError("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) memory write failed when restoring original opcode", (uint64_t)addr, remove); - } - } - else - { - DNBLogWarning("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) expected a breakpoint opcode but didn't find one.", (uint64_t)addr, remove); - // Set verify to true and so we can check if the original opcode has already been restored - verify = true; - } - } - else - { - DNBLogThreadedIf(LOG_BREAKPOINTS | LOG_VERBOSE, "MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) is not enabled", (uint64_t)addr, remove); - // Set verify to true and so we can check if the original opcode is there - verify = true; - } - - if (verify) - { - uint8_t verify_opcode[break_op_size]; - // Verify that our original opcode made it back to the inferior - if (m_task.ReadMemory(addr, break_op_size, verify_opcode) == break_op_size) - { - // compare the memory we just read with the original opcode - if (memcmp(bp->SavedOpcodeBytes(), verify_opcode, break_op_size) == 0) - { - // SUCCESS - bp->SetEnabled(false); - // Let the thread list know that a breakpoint has been modified - if (remove && bp->Release() == 0) - { - m_thread_list.NotifyBreakpointChanged(bp); - m_breakpoints.Remove(addr); - } - DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) => success", (uint64_t)addr, remove); - return true; - } - else - { - if (break_op_found) - DNBLogError("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) : failed to restore original opcode", (uint64_t)addr, remove); - else - DNBLogError("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) : opcode changed", (uint64_t)addr, remove); - } - } - else - { - DNBLogWarning("MachProcess::DisableBreakpoint: unable to disable breakpoint 0x%8.8llx", (uint64_t)addr); - } +// Called by the exception thread when an exception has been received from +// our process. The exception message is completely filled and the exception +// data has already been copied. +void MachProcess::ExceptionMessageReceived( + const MachException::Message &exceptionMessage) { + PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex); + + if (m_exception_messages.empty()) + m_task.Suspend(); + + DNBLogThreadedIf(LOG_EXCEPTIONS, "MachProcess::ExceptionMessageReceived ( )"); + + // Use a locker to automatically unlock our mutex in case of exceptions + // Add the exception to our internal exception stack + m_exception_messages.push_back(exceptionMessage); +} + +task_t MachProcess::ExceptionMessageBundleComplete() { + // We have a complete bundle of exceptions for our child process. + PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex); + DNBLogThreadedIf(LOG_EXCEPTIONS, "%s: %llu exception messages.", + __PRETTY_FUNCTION__, (uint64_t)m_exception_messages.size()); + bool auto_resume = false; + if (!m_exception_messages.empty()) { + m_did_exec = false; + // First check for any SIGTRAP and make sure we didn't exec + const task_t task = m_task.TaskPort(); + size_t i; + if (m_pid != 0) { + bool received_interrupt = false; + uint32_t num_task_exceptions = 0; + for (i = 0; i < m_exception_messages.size(); ++i) { + if (m_exception_messages[i].state.task_port == task) { + ++num_task_exceptions; + const int signo = m_exception_messages[i].state.SoftSignal(); + if (signo == SIGTRAP) { + // SIGTRAP could mean that we exec'ed. We need to check the + // dyld all_image_infos.infoArray to see if it is NULL and if + // so, say that we exec'ed. + const nub_addr_t aii_addr = GetDYLDAllImageInfosAddress(); + if (aii_addr != INVALID_NUB_ADDRESS) { + const nub_addr_t info_array_count_addr = aii_addr + 4; + uint32_t info_array_count = 0; + if (m_task.ReadMemory(info_array_count_addr, 4, + &info_array_count) == 4) { + if (info_array_count == 0) { + m_did_exec = true; + // Force the task port to update itself in case the task port + // changed after exec + DNBError err; + const task_t old_task = m_task.TaskPort(); + const task_t new_task = + m_task.TaskPortForProcessID(err, true); + if (old_task != new_task) + DNBLogThreadedIf( + LOG_PROCESS, + "exec: task changed from 0x%4.4x to 0x%4.4x", old_task, + new_task); } + } else { + DNBLog("error: failed to read all_image_infos.infoArrayCount " + "from 0x%8.8llx", + (uint64_t)info_array_count_addr); + } } - else - { - DNBLogWarning("MachProcess::DisableBreakpoint: unable to read memory at 0x%8.8llx", (uint64_t)addr); + break; + } else if (m_sent_interrupt_signo != 0 && + signo == m_sent_interrupt_signo) { + received_interrupt = true; + } + } + } + + if (m_did_exec) { + cpu_type_t process_cpu_type = + MachProcess::GetCPUTypeForLocalProcess(m_pid); + if (m_cpu_type != process_cpu_type) { + DNBLog("arch changed from 0x%8.8x to 0x%8.8x", m_cpu_type, + process_cpu_type); + m_cpu_type = process_cpu_type; + DNBArchProtocol::SetArchitecture(process_cpu_type); + } + m_thread_list.Clear(); + m_activities.Clear(); + m_breakpoints.DisableAll(); + } + + if (m_sent_interrupt_signo != 0) { + if (received_interrupt) { + DNBLogThreadedIf(LOG_PROCESS, + "MachProcess::ExceptionMessageBundleComplete(): " + "process successfully interrupted with signal %i", + m_sent_interrupt_signo); + + // Mark that we received the interrupt signal + m_sent_interrupt_signo = 0; + // Not check if we had a case where: + // 1 - We called MachProcess::Interrupt() but we stopped for another + // reason + // 2 - We called MachProcess::Resume() (but still haven't gotten the + // interrupt signal) + // 3 - We are now incorrectly stopped because we are handling the + // interrupt signal we missed + // 4 - We might need to resume if we stopped only with the interrupt + // signal that we never handled + if (m_auto_resume_signo != 0) { + // Only auto_resume if we stopped with _only_ the interrupt signal + if (num_task_exceptions == 1) { + auto_resume = true; + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::" + "ExceptionMessageBundleComplete(): " + "auto resuming due to unhandled " + "interrupt signal %i", + m_auto_resume_signo); } + m_auto_resume_signo = 0; + } + } else { + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::" + "ExceptionMessageBundleComplete(): " + "didn't get signal %i after " + "MachProcess::Interrupt()", + m_sent_interrupt_signo); } + } } - else - { - DNBLogError("MachProcess::DisableBreakpoint ( addr = 0x%8.8llx, remove = %d ) invalid breakpoint address", (uint64_t)addr, remove); - } - return false; -} -bool -MachProcess::DisableWatchpoint(nub_addr_t addr, bool remove) -{ - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::%s(addr = 0x%8.8llx, remove = %d)", __FUNCTION__, (uint64_t)addr, remove); - DNBBreakpoint *wp = m_watchpoints.FindByAddress(addr); - if (wp) - { - // If we have multiple references to a watchpoint, removing the watchpoint shouldn't clear it - if (remove && wp->Release() > 0) - return true; - - nub_addr_t addr = wp->Address(); - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::DisableWatchpoint ( addr = 0x%8.8llx, remove = %d )", (uint64_t)addr, remove); - - if (wp->IsHardware()) - { - bool hw_disable_result = m_thread_list.DisableHardwareWatchpoint (wp); - - if (hw_disable_result == true) - { - wp->SetEnabled(false); - if (remove) - m_watchpoints.Remove(addr); - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::Disablewatchpoint ( addr = 0x%8.8llx, remove = %d ) (hardware) => success", (uint64_t)addr, remove); - return true; - } - } + // Let all threads recover from stopping and do any clean up based + // on the previous thread state (if any). + m_thread_list.ProcessDidStop(this); + m_activities.Clear(); - // TODO: clear software watchpoints if we implement them - } - else - { - DNBLogError("MachProcess::DisableWatchpoint ( addr = 0x%8.8llx, remove = %d ) invalid watchpoint ID", (uint64_t)addr, remove); - } - return false; + // Let each thread know of any exceptions + for (i = 0; i < m_exception_messages.size(); ++i) { + // Let the thread list figure use the MachProcess to forward all + // exceptions + // on down to each thread. + if (m_exception_messages[i].state.task_port == task) + m_thread_list.NotifyException(m_exception_messages[i].state); + if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) + m_exception_messages[i].Dump(); + } + + if (DNBLogCheckLogBit(LOG_THREAD)) + m_thread_list.Dump(); + + bool step_more = false; + if (m_thread_list.ShouldStop(step_more) && auto_resume == false) { + // Wait for the eEventProcessRunningStateChanged event to be reset + // before changing state to stopped to avoid race condition with + // very fast start/stops + struct timespec timeout; + // DNBTimer::OffsetTimeOfDay(&timeout, 0, 250 * 1000); // Wait for 250 + // ms + DNBTimer::OffsetTimeOfDay(&timeout, 1, 0); // Wait for 250 ms + m_events.WaitForEventsToReset(eEventProcessRunningStateChanged, &timeout); + SetState(eStateStopped); + } else { + // Resume without checking our current state. + PrivateResume(); + } + } else { + DNBLogThreadedIf( + LOG_EXCEPTIONS, "%s empty exception messages bundle (%llu exceptions).", + __PRETTY_FUNCTION__, (uint64_t)m_exception_messages.size()); + } + return m_task.TaskPort(); } +nub_size_t +MachProcess::CopyImageInfos(struct DNBExecutableImageInfo **image_infos, + bool only_changed) { + if (m_image_infos_callback != NULL) + return m_image_infos_callback(ProcessID(), image_infos, only_changed, + m_image_infos_baton); + return 0; +} + +void MachProcess::SharedLibrariesUpdated() { + uint32_t event_bits = eEventSharedLibsStateChange; + // Set the shared library event bit to let clients know of shared library + // changes + m_events.SetEvents(event_bits); + // Wait for the event bit to reset if a reset ACK is requested + m_events.WaitForResetAck(event_bits); +} + +void MachProcess::SetExitInfo(const char *info) { + if (info && info[0]) { + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s(\"%s\")", __FUNCTION__, + info); + m_exit_info.assign(info); + } else { + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s(NULL)", __FUNCTION__); + m_exit_info.clear(); + } +} + +void MachProcess::AppendSTDOUT(char *s, size_t len) { + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (<%llu> %s) ...", __FUNCTION__, + (uint64_t)len, s); + PTHREAD_MUTEX_LOCKER(locker, m_stdio_mutex); + m_stdout_data.append(s, len); + m_events.SetEvents(eEventStdioAvailable); + + // Wait for the event bit to reset if a reset ACK is requested + m_events.WaitForResetAck(eEventStdioAvailable); +} + +size_t MachProcess::GetAvailableSTDOUT(char *buf, size_t buf_size) { + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (&%p[%llu]) ...", __FUNCTION__, + buf, (uint64_t)buf_size); + PTHREAD_MUTEX_LOCKER(locker, m_stdio_mutex); + size_t bytes_available = m_stdout_data.size(); + if (bytes_available > 0) { + if (bytes_available > buf_size) { + memcpy(buf, m_stdout_data.data(), buf_size); + m_stdout_data.erase(0, buf_size); + bytes_available = buf_size; + } else { + memcpy(buf, m_stdout_data.data(), bytes_available); + m_stdout_data.clear(); + } + } + return bytes_available; +} + +nub_addr_t MachProcess::GetDYLDAllImageInfosAddress() { + DNBError err; + return m_task.GetDYLDAllImageInfosAddress(err); +} + +size_t MachProcess::GetAvailableSTDERR(char *buf, size_t buf_size) { return 0; } + +void *MachProcess::STDIOThread(void *arg) { + MachProcess *proc = (MachProcess *)arg; + DNBLogThreadedIf(LOG_PROCESS, + "MachProcess::%s ( arg = %p ) thread starting...", + __FUNCTION__, arg); + +#if defined(__APPLE__) + pthread_setname_np("stdio monitoring thread"); +#endif -uint32_t -MachProcess::GetNumSupportedHardwareWatchpoints () const -{ - return m_thread_list.NumSupportedHardwareWatchpoints(); + // We start use a base and more options so we can control if we + // are currently using a timeout on the mach_msg. We do this to get a + // bunch of related exceptions on our exception port so we can process + // then together. When we have multiple threads, we can get an exception + // per thread and they will come in consecutively. The main thread loop + // will start by calling mach_msg to without having the MACH_RCV_TIMEOUT + // flag set in the options, so we will wait forever for an exception on + // our exception port. After we get one exception, we then will use the + // MACH_RCV_TIMEOUT option with a zero timeout to grab all other current + // exceptions for our process. After we have received the last pending + // exception, we will get a timeout which enables us to then notify + // our main thread that we have an exception bundle available. We then wait + // for the main thread to tell this exception thread to start trying to get + // exceptions messages again and we start again with a mach_msg read with + // infinite timeout. + DNBError err; + int stdout_fd = proc->GetStdoutFileDescriptor(); + int stderr_fd = proc->GetStderrFileDescriptor(); + if (stdout_fd == stderr_fd) + stderr_fd = -1; + + while (stdout_fd >= 0 || stderr_fd >= 0) { + ::pthread_testcancel(); + + fd_set read_fds; + FD_ZERO(&read_fds); + if (stdout_fd >= 0) + FD_SET(stdout_fd, &read_fds); + if (stderr_fd >= 0) + FD_SET(stderr_fd, &read_fds); + int nfds = std::max<int>(stdout_fd, stderr_fd) + 1; + + int num_set_fds = select(nfds, &read_fds, NULL, NULL, NULL); + DNBLogThreadedIf(LOG_PROCESS, + "select (nfds, &read_fds, NULL, NULL, NULL) => %d", + num_set_fds); + + if (num_set_fds < 0) { + int select_errno = errno; + if (DNBLogCheckLogBit(LOG_PROCESS)) { + err.SetError(select_errno, DNBError::POSIX); + err.LogThreadedIfError( + "select (nfds, &read_fds, NULL, NULL, NULL) => %d", num_set_fds); + } + + switch (select_errno) { + case EAGAIN: // The kernel was (perhaps temporarily) unable to allocate + // the requested number of file descriptors, or we have + // non-blocking IO + break; + case EBADF: // One of the descriptor sets specified an invalid descriptor. + return NULL; + break; + case EINTR: // A signal was delivered before the time limit expired and + // before any of the selected events occurred. + case EINVAL: // The specified time limit is invalid. One of its components + // is negative or too large. + default: // Other unknown error + break; + } + } else if (num_set_fds == 0) { + } else { + char s[1024]; + s[sizeof(s) - 1] = '\0'; // Ensure we have NULL termination + ssize_t bytes_read = 0; + if (stdout_fd >= 0 && FD_ISSET(stdout_fd, &read_fds)) { + do { + bytes_read = ::read(stdout_fd, s, sizeof(s) - 1); + if (bytes_read < 0) { + int read_errno = errno; + DNBLogThreadedIf(LOG_PROCESS, + "read (stdout_fd, ) => %zd errno: %d (%s)", + bytes_read, read_errno, strerror(read_errno)); + } else if (bytes_read == 0) { + // EOF... + DNBLogThreadedIf( + LOG_PROCESS, + "read (stdout_fd, ) => %zd (reached EOF for child STDOUT)", + bytes_read); + stdout_fd = -1; + } else if (bytes_read > 0) { + proc->AppendSTDOUT(s, bytes_read); + } + + } while (bytes_read > 0); + } + + if (stderr_fd >= 0 && FD_ISSET(stderr_fd, &read_fds)) { + do { + bytes_read = ::read(stderr_fd, s, sizeof(s) - 1); + if (bytes_read < 0) { + int read_errno = errno; + DNBLogThreadedIf(LOG_PROCESS, + "read (stderr_fd, ) => %zd errno: %d (%s)", + bytes_read, read_errno, strerror(read_errno)); + } else if (bytes_read == 0) { + // EOF... + DNBLogThreadedIf( + LOG_PROCESS, + "read (stderr_fd, ) => %zd (reached EOF for child STDERR)", + bytes_read); + stderr_fd = -1; + } else if (bytes_read > 0) { + proc->AppendSTDOUT(s, bytes_read); + } + + } while (bytes_read > 0); + } + } + } + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (%p): thread exiting...", + __FUNCTION__, arg); + return NULL; } -bool -MachProcess::EnableBreakpoint(nub_addr_t addr) -{ - DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::EnableBreakpoint ( addr = 0x%8.8llx )", (uint64_t)addr); - DNBBreakpoint *bp = m_breakpoints.FindByAddress(addr); - if (bp) - { - if (bp->IsEnabled()) - { - DNBLogWarning("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): breakpoint already enabled.", (uint64_t)addr); - return true; - } - else - { - if (bp->HardwarePreferred()) - { - bp->SetHardwareIndex(m_thread_list.EnableHardwareBreakpoint(bp)); - if (bp->IsHardware()) - { - bp->SetEnabled(true); - return true; - } - } +void MachProcess::SignalAsyncProfileData(const char *info) { + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (%s) ...", __FUNCTION__, info); + PTHREAD_MUTEX_LOCKER(locker, m_profile_data_mutex); + m_profile_data.push_back(info); + m_events.SetEvents(eEventProfileDataAvailable); - const nub_size_t break_op_size = bp->ByteSize(); - assert (break_op_size != 0); - const uint8_t * const break_op = DNBArchProtocol::GetBreakpointOpcode (break_op_size); - if (break_op_size > 0) - { - // Save the original opcode by reading it - if (m_task.ReadMemory(addr, break_op_size, bp->SavedOpcodeBytes()) == break_op_size) - { - // Write a software breakpoint in place of the original opcode - if (m_task.WriteMemory(addr, break_op_size, break_op) == break_op_size) - { - uint8_t verify_break_op[4]; - if (m_task.ReadMemory(addr, break_op_size, verify_break_op) == break_op_size) - { - if (memcmp(break_op, verify_break_op, break_op_size) == 0) - { - bp->SetEnabled(true); - // Let the thread list know that a breakpoint has been modified - m_thread_list.NotifyBreakpointChanged(bp); - DNBLogThreadedIf(LOG_BREAKPOINTS, "MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ) : SUCCESS.", (uint64_t)addr); - return true; - } - else - { - DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): breakpoint opcode verification failed.", (uint64_t)addr); - } - } - else - { - DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): unable to read memory to verify breakpoint opcode.", (uint64_t)addr); - } - } - else - { - DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): unable to write breakpoint opcode to memory.", (uint64_t)addr); - } - } - else - { - DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ): unable to read memory at breakpoint address.", (uint64_t)addr); - } - } - else - { - DNBLogError("MachProcess::EnableBreakpoint ( addr = 0x%8.8llx ) no software breakpoint opcode for current architecture.", (uint64_t)addr); - } - } - } - return false; + // Wait for the event bit to reset if a reset ACK is requested + m_events.WaitForResetAck(eEventProfileDataAvailable); } -bool -MachProcess::EnableWatchpoint(nub_addr_t addr) -{ - DNBLogThreadedIf(LOG_WATCHPOINTS, "MachProcess::EnableWatchpoint(addr = 0x%8.8llx)", (uint64_t)addr); - DNBBreakpoint *wp = m_watchpoints.FindByAddress(addr); - if (wp) - { - nub_addr_t addr = wp->Address(); - if (wp->IsEnabled()) - { - DNBLogWarning("MachProcess::EnableWatchpoint(addr = 0x%8.8llx): watchpoint already enabled.", (uint64_t)addr); - return true; - } - else - { - // Currently only try and set hardware watchpoints. - wp->SetHardwareIndex(m_thread_list.EnableHardwareWatchpoint(wp)); - if (wp->IsHardware()) - { - wp->SetEnabled(true); - return true; - } - // TODO: Add software watchpoints by doing page protection tricks. - } +size_t MachProcess::GetAsyncProfileData(char *buf, size_t buf_size) { + DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (&%p[%llu]) ...", __FUNCTION__, + buf, (uint64_t)buf_size); + PTHREAD_MUTEX_LOCKER(locker, m_profile_data_mutex); + if (m_profile_data.empty()) + return 0; + + size_t bytes_available = m_profile_data.front().size(); + if (bytes_available > 0) { + if (bytes_available > buf_size) { + memcpy(buf, m_profile_data.front().data(), buf_size); + m_profile_data.front().erase(0, buf_size); + bytes_available = buf_size; + } else { + memcpy(buf, m_profile_data.front().data(), bytes_available); + m_profile_data.erase(m_profile_data.begin()); } - return false; + } + return bytes_available; } -// Called by the exception thread when an exception has been received from -// our process. The exception message is completely filled and the exception -// data has already been copied. -void -MachProcess::ExceptionMessageReceived (const MachException::Message& exceptionMessage) -{ - PTHREAD_MUTEX_LOCKER (locker, m_exception_messages_mutex); - - if (m_exception_messages.empty()) - m_task.Suspend(); - - DNBLogThreadedIf(LOG_EXCEPTIONS, "MachProcess::ExceptionMessageReceived ( )"); - - // Use a locker to automatically unlock our mutex in case of exceptions - // Add the exception to our internal exception stack - m_exception_messages.push_back(exceptionMessage); -} - -task_t -MachProcess::ExceptionMessageBundleComplete() -{ - // We have a complete bundle of exceptions for our child process. - PTHREAD_MUTEX_LOCKER (locker, m_exception_messages_mutex); - DNBLogThreadedIf(LOG_EXCEPTIONS, "%s: %llu exception messages.", __PRETTY_FUNCTION__, (uint64_t)m_exception_messages.size()); - bool auto_resume = false; - if (!m_exception_messages.empty()) - { - m_did_exec = false; - // First check for any SIGTRAP and make sure we didn't exec - const task_t task = m_task.TaskPort(); - size_t i; - if (m_pid != 0) - { - bool received_interrupt = false; - uint32_t num_task_exceptions = 0; - for (i=0; i<m_exception_messages.size(); ++i) - { - if (m_exception_messages[i].state.task_port == task) - { - ++num_task_exceptions; - const int signo = m_exception_messages[i].state.SoftSignal(); - if (signo == SIGTRAP) - { - // SIGTRAP could mean that we exec'ed. We need to check the - // dyld all_image_infos.infoArray to see if it is NULL and if - // so, say that we exec'ed. - const nub_addr_t aii_addr = GetDYLDAllImageInfosAddress(); - if (aii_addr != INVALID_NUB_ADDRESS) - { - const nub_addr_t info_array_count_addr = aii_addr + 4; - uint32_t info_array_count = 0; - if (m_task.ReadMemory(info_array_count_addr, 4, &info_array_count) == 4) - { - if (info_array_count == 0) - { - m_did_exec = true; - // Force the task port to update itself in case the task port changed after exec - DNBError err; - const task_t old_task = m_task.TaskPort(); - const task_t new_task = m_task.TaskPortForProcessID (err, true); - if (old_task != new_task) - DNBLogThreadedIf(LOG_PROCESS, "exec: task changed from 0x%4.4x to 0x%4.4x", old_task, new_task); - } - } - else - { - DNBLog ("error: failed to read all_image_infos.infoArrayCount from 0x%8.8llx", (uint64_t)info_array_count_addr); - } - } - break; - } - else if (m_sent_interrupt_signo != 0 && signo == m_sent_interrupt_signo) - { - received_interrupt = true; - } - } - } - - if (m_did_exec) - { - cpu_type_t process_cpu_type = MachProcess::GetCPUTypeForLocalProcess (m_pid); - if (m_cpu_type != process_cpu_type) - { - DNBLog ("arch changed from 0x%8.8x to 0x%8.8x", m_cpu_type, process_cpu_type); - m_cpu_type = process_cpu_type; - DNBArchProtocol::SetArchitecture (process_cpu_type); - } - m_thread_list.Clear(); - m_activities.Clear(); - m_breakpoints.DisableAll(); - } - - if (m_sent_interrupt_signo != 0) - { - if (received_interrupt) - { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::ExceptionMessageBundleComplete(): process successfully interrupted with signal %i", m_sent_interrupt_signo); - - // Mark that we received the interrupt signal - m_sent_interrupt_signo = 0; - // Not check if we had a case where: - // 1 - We called MachProcess::Interrupt() but we stopped for another reason - // 2 - We called MachProcess::Resume() (but still haven't gotten the interrupt signal) - // 3 - We are now incorrectly stopped because we are handling the interrupt signal we missed - // 4 - We might need to resume if we stopped only with the interrupt signal that we never handled - if (m_auto_resume_signo != 0) - { - // Only auto_resume if we stopped with _only_ the interrupt signal - if (num_task_exceptions == 1) - { - auto_resume = true; - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::ExceptionMessageBundleComplete(): auto resuming due to unhandled interrupt signal %i", m_auto_resume_signo); - } - m_auto_resume_signo = 0; - } - } - else - { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::ExceptionMessageBundleComplete(): didn't get signal %i after MachProcess::Interrupt()", - m_sent_interrupt_signo); - } - } - } +void *MachProcess::ProfileThread(void *arg) { + MachProcess *proc = (MachProcess *)arg; + DNBLogThreadedIf(LOG_PROCESS, + "MachProcess::%s ( arg = %p ) thread starting...", + __FUNCTION__, arg); - // Let all threads recover from stopping and do any clean up based - // on the previous thread state (if any). - m_thread_list.ProcessDidStop(this); - m_activities.Clear(); +#if defined(__APPLE__) + pthread_setname_np("performance profiling thread"); +#endif - // Let each thread know of any exceptions - for (i=0; i<m_exception_messages.size(); ++i) - { - // Let the thread list figure use the MachProcess to forward all exceptions - // on down to each thread. - if (m_exception_messages[i].state.task_port == task) - m_thread_list.NotifyException(m_exception_messages[i].state); - if (DNBLogCheckLogBit(LOG_EXCEPTIONS)) - m_exception_messages[i].Dump(); - } + while (proc->IsProfilingEnabled()) { + nub_state_t state = proc->GetState(); + if (state == eStateRunning) { + std::string data = + proc->Task().GetProfileData(proc->GetProfileScanType()); + if (!data.empty()) { + proc->SignalAsyncProfileData(data.c_str()); + } + } else if ((state == eStateUnloaded) || (state == eStateDetached) || + (state == eStateUnloaded)) { + // Done. Get out of this thread. + break; + } + + // A simple way to set up the profile interval. We can also use select() or + // dispatch timer source if necessary. + usleep(proc->ProfileInterval()); + } + return NULL; +} - if (DNBLogCheckLogBit(LOG_THREAD)) - m_thread_list.Dump(); - - bool step_more = false; - if (m_thread_list.ShouldStop(step_more) && auto_resume == false) - { - // Wait for the eEventProcessRunningStateChanged event to be reset - // before changing state to stopped to avoid race condition with - // very fast start/stops - struct timespec timeout; - //DNBTimer::OffsetTimeOfDay(&timeout, 0, 250 * 1000); // Wait for 250 ms - DNBTimer::OffsetTimeOfDay(&timeout, 1, 0); // Wait for 250 ms - m_events.WaitForEventsToReset(eEventProcessRunningStateChanged, &timeout); - SetState(eStateStopped); - } - else - { - // Resume without checking our current state. - PrivateResume (); - } +pid_t MachProcess::AttachForDebug(pid_t pid, char *err_str, size_t err_len) { + // Clear out and clean up from any current state + Clear(); + if (pid != 0) { + DNBError err; + // Make sure the process exists... + if (::getpgid(pid) < 0) { + err.SetErrorToErrno(); + const char *err_cstr = err.AsString(); + ::snprintf(err_str, err_len, "%s", + err_cstr ? err_cstr : "No such process"); + return INVALID_NUB_PROCESS; + } + + SetState(eStateAttaching); + m_pid = pid; +// Let ourselves know we are going to be using SBS or BKS if the correct flag +// bit is set... +#if defined(WITH_FBS) || defined(WITH_BKS) + bool found_app_flavor = false; +#endif + +#if defined(WITH_FBS) + if (!found_app_flavor && IsFBSProcess(pid)) { + found_app_flavor = true; + m_flags |= eMachProcessFlagsUsingFBS; + } +#elif defined(WITH_BKS) + if (!found_app_flavor && IsBKSProcess(pid)) { + found_app_flavor = true; + m_flags |= eMachProcessFlagsUsingBKS; } +#elif defined(WITH_SPRINGBOARD) + if (IsSBProcess(pid)) + m_flags |= eMachProcessFlagsUsingSBS; +#endif + if (!m_task.StartExceptionThread(err)) { + const char *err_cstr = err.AsString(); + ::snprintf(err_str, err_len, "%s", + err_cstr ? err_cstr : "unable to start the exception thread"); + DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", pid); + m_pid = INVALID_NUB_PROCESS; + return INVALID_NUB_PROCESS; + } + + errno = 0; + if (::ptrace(PT_ATTACHEXC, pid, 0, 0)) + err.SetError(errno); else - { - DNBLogThreadedIf(LOG_EXCEPTIONS, "%s empty exception messages bundle (%llu exceptions).", __PRETTY_FUNCTION__, (uint64_t)m_exception_messages.size()); + err.Clear(); + + if (err.Success()) { + m_flags |= eMachProcessFlagsAttached; + // Sleep a bit to let the exception get received and set our process + // status + // to stopped. + ::usleep(250000); + DNBLogThreadedIf(LOG_PROCESS, "successfully attached to pid %d", pid); + return m_pid; + } else { + ::snprintf(err_str, err_len, "%s", err.AsString()); + DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", pid); } - return m_task.TaskPort(); + } + return INVALID_NUB_PROCESS; } -nub_size_t -MachProcess::CopyImageInfos ( struct DNBExecutableImageInfo **image_infos, bool only_changed) -{ - if (m_image_infos_callback != NULL) - return m_image_infos_callback(ProcessID(), image_infos, only_changed, m_image_infos_baton); - return 0; +Genealogy::ThreadActivitySP +MachProcess::GetGenealogyInfoForThread(nub_thread_t tid, bool &timed_out) { + return m_activities.GetGenealogyInfoForThread(m_pid, tid, m_thread_list, + m_task.TaskPort(), timed_out); } -void -MachProcess::SharedLibrariesUpdated ( ) -{ - uint32_t event_bits = eEventSharedLibsStateChange; - // Set the shared library event bit to let clients know of shared library - // changes - m_events.SetEvents(event_bits); - // Wait for the event bit to reset if a reset ACK is requested - m_events.WaitForResetAck(event_bits); +Genealogy::ProcessExecutableInfoSP +MachProcess::GetGenealogyImageInfo(size_t idx) { + return m_activities.GetProcessExecutableInfosAtIndex(idx); } -void -MachProcess::SetExitInfo (const char *info) -{ - if (info && info[0]) - { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s(\"%s\")", __FUNCTION__, info); - m_exit_info.assign(info); - } - else - { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s(NULL)", __FUNCTION__); - m_exit_info.clear(); - } -} +bool MachProcess::GetOSVersionNumbers(uint64_t *major, uint64_t *minor, + uint64_t *patch) { +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \ + (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101000) + return false; +#else + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; -void -MachProcess::AppendSTDOUT (char* s, size_t len) -{ - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (<%llu> %s) ...", __FUNCTION__, (uint64_t)len, s); - PTHREAD_MUTEX_LOCKER (locker, m_stdio_mutex); - m_stdout_data.append(s, len); - m_events.SetEvents(eEventStdioAvailable); + NSOperatingSystemVersion vers = + [[NSProcessInfo processInfo] operatingSystemVersion]; + if (major) + *major = vers.majorVersion; + if (minor) + *minor = vers.minorVersion; + if (patch) + *patch = vers.patchVersion; - // Wait for the event bit to reset if a reset ACK is requested - m_events.WaitForResetAck(eEventStdioAvailable); -} - -size_t -MachProcess::GetAvailableSTDOUT (char *buf, size_t buf_size) -{ - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (&%p[%llu]) ...", __FUNCTION__, buf, (uint64_t)buf_size); - PTHREAD_MUTEX_LOCKER (locker, m_stdio_mutex); - size_t bytes_available = m_stdout_data.size(); - if (bytes_available > 0) - { - if (bytes_available > buf_size) - { - memcpy(buf, m_stdout_data.data(), buf_size); - m_stdout_data.erase(0, buf_size); - bytes_available = buf_size; - } - else - { - memcpy(buf, m_stdout_data.data(), bytes_available); - m_stdout_data.clear(); - } - } - return bytes_available; -} + [pool drain]; -nub_addr_t -MachProcess::GetDYLDAllImageInfosAddress () -{ - DNBError err; - return m_task.GetDYLDAllImageInfosAddress(err); + return true; +#endif } -size_t -MachProcess::GetAvailableSTDERR (char *buf, size_t buf_size) -{ - return 0; -} +// Do the process specific setup for attach. If this returns NULL, then there's +// no +// platform specific stuff to be done to wait for the attach. If you get +// non-null, +// pass that token to the CheckForProcess method, and then to +// CleanupAfterAttach. -void * -MachProcess::STDIOThread(void *arg) -{ - MachProcess *proc = (MachProcess*) arg; - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s ( arg = %p ) thread starting...", __FUNCTION__, arg); +// Call PrepareForAttach before attaching to a process that has not yet +// launched +// This returns a token that can be passed to CheckForProcess, and to +// CleanupAfterAttach. +// You should call CleanupAfterAttach to free the token, and do whatever other +// cleanup seems good. -#if defined (__APPLE__) - pthread_setname_np ("stdio monitoring thread"); +const void *MachProcess::PrepareForAttach(const char *path, + nub_launch_flavor_t launch_flavor, + bool waitfor, DNBError &attach_err) { +#if defined(WITH_SPRINGBOARD) || defined(WITH_BKS) || defined(WITH_FBS) + // Tell SpringBoard to halt the next launch of this application on startup. + + if (!waitfor) + return NULL; + + const char *app_ext = strstr(path, ".app"); + const bool is_app = + app_ext != NULL && (app_ext[4] == '\0' || app_ext[4] == '/'); + if (!is_app) { + DNBLogThreadedIf( + LOG_PROCESS, + "MachProcess::PrepareForAttach(): path '%s' doesn't contain .app, " + "we can't tell springboard to wait for launch...", + path); + return NULL; + } + +#if defined(WITH_FBS) + if (launch_flavor == eLaunchFlavorDefault) + launch_flavor = eLaunchFlavorFBS; + if (launch_flavor != eLaunchFlavorFBS) + return NULL; +#elif defined(WITH_BKS) + if (launch_flavor == eLaunchFlavorDefault) + launch_flavor = eLaunchFlavorBKS; + if (launch_flavor != eLaunchFlavorBKS) + return NULL; +#elif defined(WITH_SPRINGBOARD) + if (launch_flavor == eLaunchFlavorDefault) + launch_flavor = eLaunchFlavorSpringBoard; + if (launch_flavor != eLaunchFlavorSpringBoard) + return NULL; #endif - // We start use a base and more options so we can control if we - // are currently using a timeout on the mach_msg. We do this to get a - // bunch of related exceptions on our exception port so we can process - // then together. When we have multiple threads, we can get an exception - // per thread and they will come in consecutively. The main thread loop - // will start by calling mach_msg to without having the MACH_RCV_TIMEOUT - // flag set in the options, so we will wait forever for an exception on - // our exception port. After we get one exception, we then will use the - // MACH_RCV_TIMEOUT option with a zero timeout to grab all other current - // exceptions for our process. After we have received the last pending - // exception, we will get a timeout which enables us to then notify - // our main thread that we have an exception bundle available. We then wait - // for the main thread to tell this exception thread to start trying to get - // exceptions messages again and we start again with a mach_msg read with - // infinite timeout. - DNBError err; - int stdout_fd = proc->GetStdoutFileDescriptor(); - int stderr_fd = proc->GetStderrFileDescriptor(); - if (stdout_fd == stderr_fd) - stderr_fd = -1; - - while (stdout_fd >= 0 || stderr_fd >= 0) - { - ::pthread_testcancel (); - - fd_set read_fds; - FD_ZERO (&read_fds); - if (stdout_fd >= 0) - FD_SET (stdout_fd, &read_fds); - if (stderr_fd >= 0) - FD_SET (stderr_fd, &read_fds); - int nfds = std::max<int>(stdout_fd, stderr_fd) + 1; - - int num_set_fds = select (nfds, &read_fds, NULL, NULL, NULL); - DNBLogThreadedIf(LOG_PROCESS, "select (nfds, &read_fds, NULL, NULL, NULL) => %d", num_set_fds); - - if (num_set_fds < 0) - { - int select_errno = errno; - if (DNBLogCheckLogBit(LOG_PROCESS)) - { - err.SetError (select_errno, DNBError::POSIX); - err.LogThreadedIfError("select (nfds, &read_fds, NULL, NULL, NULL) => %d", num_set_fds); - } + std::string app_bundle_path(path, app_ext + strlen(".app")); - switch (select_errno) - { - case EAGAIN: // The kernel was (perhaps temporarily) unable to allocate the requested number of file descriptors, or we have non-blocking IO - break; - case EBADF: // One of the descriptor sets specified an invalid descriptor. - return NULL; - break; - case EINTR: // A signal was delivered before the time limit expired and before any of the selected events occurred. - case EINVAL: // The specified time limit is invalid. One of its components is negative or too large. - default: // Other unknown error - break; - } - } - else if (num_set_fds == 0) - { - } - else - { - char s[1024]; - s[sizeof(s)-1] = '\0'; // Ensure we have NULL termination - ssize_t bytes_read = 0; - if (stdout_fd >= 0 && FD_ISSET (stdout_fd, &read_fds)) - { - do - { - bytes_read = ::read (stdout_fd, s, sizeof(s)-1); - if (bytes_read < 0) - { - int read_errno = errno; - DNBLogThreadedIf(LOG_PROCESS, "read (stdout_fd, ) => %zd errno: %d (%s)", bytes_read, read_errno, strerror(read_errno)); - } - else if (bytes_read == 0) - { - // EOF... - DNBLogThreadedIf(LOG_PROCESS, "read (stdout_fd, ) => %zd (reached EOF for child STDOUT)", bytes_read); - stdout_fd = -1; - } - else if (bytes_read > 0) - { - proc->AppendSTDOUT(s, bytes_read); - } - - } while (bytes_read > 0); - } + CFStringRef bundleIDCFStr = + CopyBundleIDForPath(app_bundle_path.c_str(), attach_err); + std::string bundleIDStr; + CFString::UTF8(bundleIDCFStr, bundleIDStr); + DNBLogThreadedIf(LOG_PROCESS, + "CopyBundleIDForPath (%s, err_str) returned @\"%s\"", + app_bundle_path.c_str(), bundleIDStr.c_str()); - if (stderr_fd >= 0 && FD_ISSET (stderr_fd, &read_fds)) - { - do - { - bytes_read = ::read (stderr_fd, s, sizeof(s)-1); - if (bytes_read < 0) - { - int read_errno = errno; - DNBLogThreadedIf(LOG_PROCESS, "read (stderr_fd, ) => %zd errno: %d (%s)", bytes_read, read_errno, strerror(read_errno)); - } - else if (bytes_read == 0) - { - // EOF... - DNBLogThreadedIf(LOG_PROCESS, "read (stderr_fd, ) => %zd (reached EOF for child STDERR)", bytes_read); - stderr_fd = -1; - } - else if (bytes_read > 0) - { - proc->AppendSTDOUT(s, bytes_read); - } - - } while (bytes_read > 0); - } - } - } - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (%p): thread exiting...", __FUNCTION__, arg); + if (bundleIDCFStr == NULL) { return NULL; -} + } +#if defined(WITH_FBS) + if (launch_flavor == eLaunchFlavorFBS) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; -void -MachProcess::SignalAsyncProfileData (const char *info) -{ - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (%s) ...", __FUNCTION__, info); - PTHREAD_MUTEX_LOCKER (locker, m_profile_data_mutex); - m_profile_data.push_back(info); - m_events.SetEvents(eEventProfileDataAvailable); - - // Wait for the event bit to reset if a reset ACK is requested - m_events.WaitForResetAck(eEventProfileDataAvailable); -} - - -size_t -MachProcess::GetAsyncProfileData (char *buf, size_t buf_size) -{ - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s (&%p[%llu]) ...", __FUNCTION__, buf, (uint64_t)buf_size); - PTHREAD_MUTEX_LOCKER (locker, m_profile_data_mutex); - if (m_profile_data.empty()) - return 0; - - size_t bytes_available = m_profile_data.front().size(); - if (bytes_available > 0) - { - if (bytes_available > buf_size) - { - memcpy(buf, m_profile_data.front().data(), buf_size); - m_profile_data.front().erase(0, buf_size); - bytes_available = buf_size; - } - else - { - memcpy(buf, m_profile_data.front().data(), bytes_available); - m_profile_data.erase(m_profile_data.begin()); - } - } - return bytes_available; -} + NSString *stdio_path = nil; + NSFileManager *file_manager = [NSFileManager defaultManager]; + const char *null_path = "/dev/null"; + stdio_path = + [file_manager stringWithFileSystemRepresentation:null_path + length:strlen(null_path)]; + NSMutableDictionary *debug_options = [NSMutableDictionary dictionary]; + NSMutableDictionary *options = [NSMutableDictionary dictionary]; -void * -MachProcess::ProfileThread(void *arg) -{ - MachProcess *proc = (MachProcess*) arg; - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s ( arg = %p ) thread starting...", __FUNCTION__, arg); + DNBLogThreadedIf(LOG_PROCESS, "Calling BKSSystemService openApplication: " + "@\"%s\",options include stdio path: \"%s\", " + "BKSDebugOptionKeyDebugOnNextLaunch & " + "BKSDebugOptionKeyWaitForDebugger )", + bundleIDStr.c_str(), null_path); -#if defined (__APPLE__) - pthread_setname_np ("performance profiling thread"); -#endif + [debug_options setObject:stdio_path + forKey:FBSDebugOptionKeyStandardOutPath]; + [debug_options setObject:stdio_path + forKey:FBSDebugOptionKeyStandardErrorPath]; + [debug_options setObject:[NSNumber numberWithBool:YES] + forKey:FBSDebugOptionKeyWaitForDebugger]; + [debug_options setObject:[NSNumber numberWithBool:YES] + forKey:FBSDebugOptionKeyDebugOnNextLaunch]; - while (proc->IsProfilingEnabled()) - { - nub_state_t state = proc->GetState(); - if (state == eStateRunning) - { - std::string data = proc->Task().GetProfileData(proc->GetProfileScanType()); - if (!data.empty()) - { - proc->SignalAsyncProfileData(data.c_str()); - } - } - else if ((state == eStateUnloaded) || (state == eStateDetached) || (state == eStateUnloaded)) - { - // Done. Get out of this thread. - break; - } - - // A simple way to set up the profile interval. We can also use select() or dispatch timer source if necessary. - usleep(proc->ProfileInterval()); - } - return NULL; -} + [options setObject:debug_options + forKey:FBSOpenApplicationOptionKeyDebuggingOptions]; + FBSSystemService *system_service = [[FBSSystemService alloc] init]; -pid_t -MachProcess::AttachForDebug (pid_t pid, char *err_str, size_t err_len) -{ - // Clear out and clean up from any current state - Clear(); - if (pid != 0) - { - DNBError err; - // Make sure the process exists... - if (::getpgid (pid) < 0) - { - err.SetErrorToErrno(); - const char *err_cstr = err.AsString(); - ::snprintf (err_str, err_len, "%s", err_cstr ? err_cstr : "No such process"); - return INVALID_NUB_PROCESS; - } + mach_port_t client_port = [system_service createClientPort]; + __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + __block FBSOpenApplicationErrorCode attach_error_code = + FBSOpenApplicationErrorCodeNone; - SetState(eStateAttaching); - m_pid = pid; - // Let ourselves know we are going to be using SBS or BKS if the correct flag bit is set... -#if defined (WITH_FBS) || defined (WITH_BKS) - bool found_app_flavor = false; -#endif - -#if defined (WITH_FBS) - if (!found_app_flavor && IsFBSProcess (pid)) - { - found_app_flavor = true; - m_flags |= eMachProcessFlagsUsingFBS; - } -#elif defined (WITH_BKS) - if (!found_app_flavor && IsBKSProcess (pid)) - { - found_app_flavor = true; - m_flags |= eMachProcessFlagsUsingBKS; - } -#elif defined (WITH_SPRINGBOARD) - if (IsSBProcess(pid)) - m_flags |= eMachProcessFlagsUsingSBS; -#endif - if (!m_task.StartExceptionThread(err)) - { - const char *err_cstr = err.AsString(); - ::snprintf (err_str, err_len, "%s", err_cstr ? err_cstr : "unable to start the exception thread"); - DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", pid); - m_pid = INVALID_NUB_PROCESS; - return INVALID_NUB_PROCESS; - } + NSString *bundleIDNSStr = (NSString *)bundleIDCFStr; - errno = 0; - if (::ptrace (PT_ATTACHEXC, pid, 0, 0)) - err.SetError(errno); - else - err.Clear(); - - if (err.Success()) - { - m_flags |= eMachProcessFlagsAttached; - // Sleep a bit to let the exception get received and set our process status - // to stopped. - ::usleep(250000); - DNBLogThreadedIf(LOG_PROCESS, "successfully attached to pid %d", pid); - return m_pid; - } - else - { - ::snprintf (err_str, err_len, "%s", err.AsString()); - DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", pid); - } - } - return INVALID_NUB_PROCESS; -} + [system_service openApplication:bundleIDNSStr + options:options + clientPort:client_port + withResult:^(NSError *error) { + // The system service will cleanup the client port we + // created for us. + if (error) + attach_error_code = + (FBSOpenApplicationErrorCode)[error code]; -Genealogy::ThreadActivitySP -MachProcess::GetGenealogyInfoForThread (nub_thread_t tid, bool &timed_out) -{ - return m_activities.GetGenealogyInfoForThread (m_pid, tid, m_thread_list, m_task.TaskPort(), timed_out); -} + [system_service release]; + dispatch_semaphore_signal(semaphore); + }]; -Genealogy::ProcessExecutableInfoSP -MachProcess::GetGenealogyImageInfo (size_t idx) -{ - return m_activities.GetProcessExecutableInfosAtIndex (idx); -} + const uint32_t timeout_secs = 9; -bool -MachProcess::GetOSVersionNumbers (uint64_t *major, uint64_t *minor, uint64_t *patch) -{ -#if defined (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101000) - return false; -#else - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + dispatch_time_t timeout = + dispatch_time(DISPATCH_TIME_NOW, timeout_secs * NSEC_PER_SEC); - NSOperatingSystemVersion vers = [[NSProcessInfo processInfo] operatingSystemVersion]; - if (major) - *major = vers.majorVersion; - if (minor) - *minor = vers.minorVersion; - if (patch) - *patch = vers.patchVersion; + long success = dispatch_semaphore_wait(semaphore, timeout) == 0; + if (!success) { + DNBLogError("timed out trying to launch %s.", bundleIDStr.c_str()); + attach_err.SetErrorString( + "debugserver timed out waiting for openApplication to complete."); + attach_err.SetError(OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic); + } else if (attach_error_code != FBSOpenApplicationErrorCodeNone) { + SetFBSError(attach_error_code, attach_err); + DNBLogError("unable to launch the application with CFBundleIdentifier " + "'%s' bks_error = %ld", + bundleIDStr.c_str(), (NSInteger)attach_error_code); + } + dispatch_release(semaphore); [pool drain]; - - return true; + } #endif -} +#if defined(WITH_BKS) + if (launch_flavor == eLaunchFlavorBKS) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; -// Do the process specific setup for attach. If this returns NULL, then there's no -// platform specific stuff to be done to wait for the attach. If you get non-null, -// pass that token to the CheckForProcess method, and then to CleanupAfterAttach. + NSString *stdio_path = nil; + NSFileManager *file_manager = [NSFileManager defaultManager]; + const char *null_path = "/dev/null"; + stdio_path = + [file_manager stringWithFileSystemRepresentation:null_path + length:strlen(null_path)]; -// Call PrepareForAttach before attaching to a process that has not yet launched -// This returns a token that can be passed to CheckForProcess, and to CleanupAfterAttach. -// You should call CleanupAfterAttach to free the token, and do whatever other -// cleanup seems good. + NSMutableDictionary *debug_options = [NSMutableDictionary dictionary]; + NSMutableDictionary *options = [NSMutableDictionary dictionary]; -const void * -MachProcess::PrepareForAttach (const char *path, nub_launch_flavor_t launch_flavor, bool waitfor, DNBError &attach_err) -{ -#if defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined (WITH_FBS) - // Tell SpringBoard to halt the next launch of this application on startup. + DNBLogThreadedIf(LOG_PROCESS, "Calling BKSSystemService openApplication: " + "@\"%s\",options include stdio path: \"%s\", " + "BKSDebugOptionKeyDebugOnNextLaunch & " + "BKSDebugOptionKeyWaitForDebugger )", + bundleIDStr.c_str(), null_path); - if (!waitfor) - return NULL; + [debug_options setObject:stdio_path + forKey:BKSDebugOptionKeyStandardOutPath]; + [debug_options setObject:stdio_path + forKey:BKSDebugOptionKeyStandardErrorPath]; + [debug_options setObject:[NSNumber numberWithBool:YES] + forKey:BKSDebugOptionKeyWaitForDebugger]; + [debug_options setObject:[NSNumber numberWithBool:YES] + forKey:BKSDebugOptionKeyDebugOnNextLaunch]; - const char *app_ext = strstr(path, ".app"); - const bool is_app = app_ext != NULL && (app_ext[4] == '\0' || app_ext[4] == '/'); - if (!is_app) - { - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::PrepareForAttach(): path '%s' doesn't contain .app, " - "we can't tell springboard to wait for launch...", - path); - return NULL; - } + [options setObject:debug_options + forKey:BKSOpenApplicationOptionKeyDebuggingOptions]; -#if defined (WITH_FBS) - if (launch_flavor == eLaunchFlavorDefault) - launch_flavor = eLaunchFlavorFBS; - if (launch_flavor != eLaunchFlavorFBS) - return NULL; -#elif defined (WITH_BKS) - if (launch_flavor == eLaunchFlavorDefault) - launch_flavor = eLaunchFlavorBKS; - if (launch_flavor != eLaunchFlavorBKS) - return NULL; -#elif defined (WITH_SPRINGBOARD) - if (launch_flavor == eLaunchFlavorDefault) - launch_flavor = eLaunchFlavorSpringBoard; - if (launch_flavor != eLaunchFlavorSpringBoard) - return NULL; -#endif + BKSSystemService *system_service = [[BKSSystemService alloc] init]; - std::string app_bundle_path(path, app_ext + strlen(".app")); + mach_port_t client_port = [system_service createClientPort]; + __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + __block BKSOpenApplicationErrorCode attach_error_code = + BKSOpenApplicationErrorCodeNone; - CFStringRef bundleIDCFStr = CopyBundleIDForPath (app_bundle_path.c_str (), attach_err); - std::string bundleIDStr; - CFString::UTF8(bundleIDCFStr, bundleIDStr); - DNBLogThreadedIf(LOG_PROCESS, - "CopyBundleIDForPath (%s, err_str) returned @\"%s\"", - app_bundle_path.c_str (), - bundleIDStr.c_str()); + NSString *bundleIDNSStr = (NSString *)bundleIDCFStr; - if (bundleIDCFStr == NULL) - { - return NULL; - } + [system_service openApplication:bundleIDNSStr + options:options + clientPort:client_port + withResult:^(NSError *error) { + // The system service will cleanup the client port we + // created for us. + if (error) + attach_error_code = + (BKSOpenApplicationErrorCode)[error code]; -#if defined (WITH_FBS) - if (launch_flavor == eLaunchFlavorFBS) - { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSString *stdio_path = nil; - NSFileManager *file_manager = [NSFileManager defaultManager]; - const char *null_path = "/dev/null"; - stdio_path = [file_manager stringWithFileSystemRepresentation: null_path length: strlen(null_path)]; - - NSMutableDictionary *debug_options = [NSMutableDictionary dictionary]; - NSMutableDictionary *options = [NSMutableDictionary dictionary]; - - DNBLogThreadedIf(LOG_PROCESS, "Calling BKSSystemService openApplication: @\"%s\",options include stdio path: \"%s\", " - "BKSDebugOptionKeyDebugOnNextLaunch & BKSDebugOptionKeyWaitForDebugger )", - bundleIDStr.c_str(), - null_path); - - [debug_options setObject: stdio_path forKey: FBSDebugOptionKeyStandardOutPath]; - [debug_options setObject: stdio_path forKey: FBSDebugOptionKeyStandardErrorPath]; - [debug_options setObject: [NSNumber numberWithBool: YES] forKey: FBSDebugOptionKeyWaitForDebugger]; - [debug_options setObject: [NSNumber numberWithBool: YES] forKey: FBSDebugOptionKeyDebugOnNextLaunch]; - - [options setObject: debug_options forKey: FBSOpenApplicationOptionKeyDebuggingOptions]; - - FBSSystemService *system_service = [[FBSSystemService alloc] init]; - - mach_port_t client_port = [system_service createClientPort]; - __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); - __block FBSOpenApplicationErrorCode attach_error_code = FBSOpenApplicationErrorCodeNone; - - NSString *bundleIDNSStr = (NSString *) bundleIDCFStr; - - [system_service openApplication: bundleIDNSStr - options: options - clientPort: client_port - withResult: ^(NSError *error) - { - // The system service will cleanup the client port we created for us. - if (error) - attach_error_code = (FBSOpenApplicationErrorCode)[error code]; - - [system_service release]; - dispatch_semaphore_signal(semaphore); - } - ]; - - const uint32_t timeout_secs = 9; - - dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, timeout_secs * NSEC_PER_SEC); - - long success = dispatch_semaphore_wait(semaphore, timeout) == 0; - - if (!success) - { - DNBLogError("timed out trying to launch %s.", bundleIDStr.c_str()); - attach_err.SetErrorString("debugserver timed out waiting for openApplication to complete."); - attach_err.SetError (OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic); - } - else if (attach_error_code != FBSOpenApplicationErrorCodeNone) - { - SetFBSError (attach_error_code, attach_err); - DNBLogError("unable to launch the application with CFBundleIdentifier '%s' bks_error = %ld", - bundleIDStr.c_str(), - (NSInteger) attach_error_code); - } - dispatch_release(semaphore); - [pool drain]; - } -#endif -#if defined (WITH_BKS) - if (launch_flavor == eLaunchFlavorBKS) - { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSString *stdio_path = nil; - NSFileManager *file_manager = [NSFileManager defaultManager]; - const char *null_path = "/dev/null"; - stdio_path = [file_manager stringWithFileSystemRepresentation: null_path length: strlen(null_path)]; - - NSMutableDictionary *debug_options = [NSMutableDictionary dictionary]; - NSMutableDictionary *options = [NSMutableDictionary dictionary]; - - DNBLogThreadedIf(LOG_PROCESS, "Calling BKSSystemService openApplication: @\"%s\",options include stdio path: \"%s\", " - "BKSDebugOptionKeyDebugOnNextLaunch & BKSDebugOptionKeyWaitForDebugger )", - bundleIDStr.c_str(), - null_path); - - [debug_options setObject: stdio_path forKey: BKSDebugOptionKeyStandardOutPath]; - [debug_options setObject: stdio_path forKey: BKSDebugOptionKeyStandardErrorPath]; - [debug_options setObject: [NSNumber numberWithBool: YES] forKey: BKSDebugOptionKeyWaitForDebugger]; - [debug_options setObject: [NSNumber numberWithBool: YES] forKey: BKSDebugOptionKeyDebugOnNextLaunch]; - - [options setObject: debug_options forKey: BKSOpenApplicationOptionKeyDebuggingOptions]; - - BKSSystemService *system_service = [[BKSSystemService alloc] init]; - - mach_port_t client_port = [system_service createClientPort]; - __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); - __block BKSOpenApplicationErrorCode attach_error_code = BKSOpenApplicationErrorCodeNone; - - NSString *bundleIDNSStr = (NSString *) bundleIDCFStr; - - [system_service openApplication: bundleIDNSStr - options: options - clientPort: client_port - withResult: ^(NSError *error) - { - // The system service will cleanup the client port we created for us. - if (error) - attach_error_code = (BKSOpenApplicationErrorCode)[error code]; - - [system_service release]; - dispatch_semaphore_signal(semaphore); - } - ]; - - const uint32_t timeout_secs = 9; - - dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, timeout_secs * NSEC_PER_SEC); - - long success = dispatch_semaphore_wait(semaphore, timeout) == 0; - - if (!success) - { - DNBLogError("timed out trying to launch %s.", bundleIDStr.c_str()); - attach_err.SetErrorString("debugserver timed out waiting for openApplication to complete."); - attach_err.SetError (OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic); - } - else if (attach_error_code != BKSOpenApplicationErrorCodeNone) - { - SetBKSError (attach_error_code, attach_err); - DNBLogError("unable to launch the application with CFBundleIdentifier '%s' bks_error = %ld", - bundleIDStr.c_str(), - attach_error_code); - } - dispatch_release(semaphore); - [pool drain]; + [system_service release]; + dispatch_semaphore_signal(semaphore); + }]; + + const uint32_t timeout_secs = 9; + + dispatch_time_t timeout = + dispatch_time(DISPATCH_TIME_NOW, timeout_secs * NSEC_PER_SEC); + + long success = dispatch_semaphore_wait(semaphore, timeout) == 0; + + if (!success) { + DNBLogError("timed out trying to launch %s.", bundleIDStr.c_str()); + attach_err.SetErrorString( + "debugserver timed out waiting for openApplication to complete."); + attach_err.SetError(OPEN_APPLICATION_TIMEOUT_ERROR, DNBError::Generic); + } else if (attach_error_code != BKSOpenApplicationErrorCodeNone) { + SetBKSError(attach_error_code, attach_err); + DNBLogError("unable to launch the application with CFBundleIdentifier " + "'%s' bks_error = %ld", + bundleIDStr.c_str(), attach_error_code); } + dispatch_release(semaphore); + [pool drain]; + } #endif -#if defined (WITH_SPRINGBOARD) - if (launch_flavor == eLaunchFlavorSpringBoard) - { - SBSApplicationLaunchError sbs_error = 0; - - const char *stdout_err = "/dev/null"; - CFString stdio_path; - stdio_path.SetFileSystemRepresentation (stdout_err); - - DNBLogThreadedIf(LOG_PROCESS, "SBSLaunchApplicationForDebugging ( @\"%s\" , NULL, NULL, NULL, @\"%s\", @\"%s\", " - "SBSApplicationDebugOnNextLaunch | SBSApplicationLaunchWaitForDebugger )", - bundleIDStr.c_str(), - stdout_err, - stdout_err); - - sbs_error = SBSLaunchApplicationForDebugging (bundleIDCFStr, - (CFURLRef)NULL, // openURL - NULL, // launch_argv.get(), - NULL, // launch_envp.get(), // CFDictionaryRef environment - stdio_path.get(), - stdio_path.get(), - SBSApplicationDebugOnNextLaunch | SBSApplicationLaunchWaitForDebugger); - - if (sbs_error != SBSApplicationLaunchErrorSuccess) - { - attach_err.SetError(sbs_error, DNBError::SpringBoard); - return NULL; - } - } +#if defined(WITH_SPRINGBOARD) + if (launch_flavor == eLaunchFlavorSpringBoard) { + SBSApplicationLaunchError sbs_error = 0; + + const char *stdout_err = "/dev/null"; + CFString stdio_path; + stdio_path.SetFileSystemRepresentation(stdout_err); + + DNBLogThreadedIf(LOG_PROCESS, "SBSLaunchApplicationForDebugging ( @\"%s\" " + ", NULL, NULL, NULL, @\"%s\", @\"%s\", " + "SBSApplicationDebugOnNextLaunch | " + "SBSApplicationLaunchWaitForDebugger )", + bundleIDStr.c_str(), stdout_err, stdout_err); + + sbs_error = SBSLaunchApplicationForDebugging( + bundleIDCFStr, + (CFURLRef)NULL, // openURL + NULL, // launch_argv.get(), + NULL, // launch_envp.get(), // CFDictionaryRef environment + stdio_path.get(), stdio_path.get(), + SBSApplicationDebugOnNextLaunch | SBSApplicationLaunchWaitForDebugger); + + if (sbs_error != SBSApplicationLaunchErrorSuccess) { + attach_err.SetError(sbs_error, DNBError::SpringBoard); + return NULL; + } + } #endif // WITH_SPRINGBOARD - DNBLogThreadedIf(LOG_PROCESS, "Successfully set DebugOnNextLaunch."); - return bundleIDCFStr; -# else // !(defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined (WITH_FBS)) + DNBLogThreadedIf(LOG_PROCESS, "Successfully set DebugOnNextLaunch."); + return bundleIDCFStr; +#else // !(defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined + // (WITH_FBS)) return NULL; #endif } @@ -2753,1148 +2729,1097 @@ MachProcess::PrepareForAttach (const char *path, nub_launch_flavor_t launch_flav // for that token, then the pid will be returned, otherwise INVALID_NUB_PROCESS // will be returned. -nub_process_t -MachProcess::CheckForProcess (const void *attach_token, nub_launch_flavor_t launch_flavor) -{ - if (attach_token == NULL) - return INVALID_NUB_PROCESS; - -#if defined (WITH_FBS) - if (launch_flavor == eLaunchFlavorFBS) - { - NSString *bundleIDNSStr = (NSString *) attach_token; - FBSSystemService *systemService = [[FBSSystemService alloc] init]; - pid_t pid = [systemService pidForApplication: bundleIDNSStr]; - [systemService release]; - if (pid == 0) - return INVALID_NUB_PROCESS; - else - return pid; - } +nub_process_t MachProcess::CheckForProcess(const void *attach_token, + nub_launch_flavor_t launch_flavor) { + if (attach_token == NULL) + return INVALID_NUB_PROCESS; + +#if defined(WITH_FBS) + if (launch_flavor == eLaunchFlavorFBS) { + NSString *bundleIDNSStr = (NSString *)attach_token; + FBSSystemService *systemService = [[FBSSystemService alloc] init]; + pid_t pid = [systemService pidForApplication:bundleIDNSStr]; + [systemService release]; + if (pid == 0) + return INVALID_NUB_PROCESS; + else + return pid; + } #endif -#if defined (WITH_BKS) - if (launch_flavor == eLaunchFlavorBKS) - { - NSString *bundleIDNSStr = (NSString *) attach_token; +#if defined(WITH_BKS) + if (launch_flavor == eLaunchFlavorBKS) { + NSString *bundleIDNSStr = (NSString *)attach_token; BKSSystemService *systemService = [[BKSSystemService alloc] init]; - pid_t pid = [systemService pidForApplication: bundleIDNSStr]; + pid_t pid = [systemService pidForApplication:bundleIDNSStr]; [systemService release]; if (pid == 0) - return INVALID_NUB_PROCESS; + return INVALID_NUB_PROCESS; else - return pid; - } + return pid; + } #endif -#if defined (WITH_SPRINGBOARD) - if (launch_flavor == eLaunchFlavorSpringBoard) - { - CFStringRef bundleIDCFStr = (CFStringRef) attach_token; +#if defined(WITH_SPRINGBOARD) + if (launch_flavor == eLaunchFlavorSpringBoard) { + CFStringRef bundleIDCFStr = (CFStringRef)attach_token; Boolean got_it; nub_process_t attach_pid; got_it = SBSProcessIDForDisplayIdentifier(bundleIDCFStr, &attach_pid); if (got_it) - return attach_pid; + return attach_pid; else - return INVALID_NUB_PROCESS; - } + return INVALID_NUB_PROCESS; + } #endif - return INVALID_NUB_PROCESS; + return INVALID_NUB_PROCESS; } -// Call this to clean up after you have either attached or given up on the attach. +// Call this to clean up after you have either attached or given up on the +// attach. // Pass true for success if you have attached, false if you have not. // The token will also be freed at this point, so you can't use it after calling // this method. -void -MachProcess::CleanupAfterAttach (const void *attach_token, nub_launch_flavor_t launch_flavor, bool success, DNBError &err_str) -{ - if (attach_token == NULL) - return; +void MachProcess::CleanupAfterAttach(const void *attach_token, + nub_launch_flavor_t launch_flavor, + bool success, DNBError &err_str) { + if (attach_token == NULL) + return; -#if defined (WITH_FBS) - if (launch_flavor == eLaunchFlavorFBS) - { - if (!success) - { - FBSCleanupAfterAttach (attach_token, err_str); - } - CFRelease((CFStringRef) attach_token); +#if defined(WITH_FBS) + if (launch_flavor == eLaunchFlavorFBS) { + if (!success) { + FBSCleanupAfterAttach(attach_token, err_str); } + CFRelease((CFStringRef)attach_token); + } #endif -#if defined (WITH_BKS) +#if defined(WITH_BKS) - if (launch_flavor == eLaunchFlavorBKS) - { - if (!success) - { - BKSCleanupAfterAttach (attach_token, err_str); - } - CFRelease((CFStringRef) attach_token); + if (launch_flavor == eLaunchFlavorBKS) { + if (!success) { + BKSCleanupAfterAttach(attach_token, err_str); } + CFRelease((CFStringRef)attach_token); + } #endif - -#if defined (WITH_SPRINGBOARD) - // Tell SpringBoard to cancel the debug on next launch of this application - // if we failed to attach - if (launch_flavor == eMachProcessFlagsUsingSpringBoard) - { - if (!success) - { - SBSApplicationLaunchError sbs_error = 0; - CFStringRef bundleIDCFStr = (CFStringRef) attach_token; - - sbs_error = SBSLaunchApplicationForDebugging (bundleIDCFStr, - (CFURLRef)NULL, - NULL, - NULL, - NULL, - NULL, - SBSApplicationCancelDebugOnNextLaunch); - - if (sbs_error != SBSApplicationLaunchErrorSuccess) - { - err_str.SetError(sbs_error, DNBError::SpringBoard); - return; - } - } - CFRelease((CFStringRef) attach_token); +#if defined(WITH_SPRINGBOARD) + // Tell SpringBoard to cancel the debug on next launch of this application + // if we failed to attach + if (launch_flavor == eMachProcessFlagsUsingSpringBoard) { + if (!success) { + SBSApplicationLaunchError sbs_error = 0; + CFStringRef bundleIDCFStr = (CFStringRef)attach_token; + + sbs_error = SBSLaunchApplicationForDebugging( + bundleIDCFStr, (CFURLRef)NULL, NULL, NULL, NULL, NULL, + SBSApplicationCancelDebugOnNextLaunch); + + if (sbs_error != SBSApplicationLaunchErrorSuccess) { + err_str.SetError(sbs_error, DNBError::SpringBoard); + return; + } } + + CFRelease((CFStringRef)attach_token); + } #endif } -pid_t -MachProcess::LaunchForDebug -( - const char *path, - char const *argv[], - char const *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, - DNBError &launch_err -) -{ - // Clear out and clean up from any current state - Clear(); - - DNBLogThreadedIf(LOG_PROCESS, "%s( path = '%s', argv = %p, envp = %p, launch_flavor = %u, disable_aslr = %d )", __FUNCTION__, path, argv, envp, launch_flavor, disable_aslr); - - // Fork a child process for debugging - SetState(eStateLaunching); - - switch (launch_flavor) - { - case eLaunchFlavorForkExec: - m_pid = MachProcess::ForkChildForPTraceDebugging (path, argv, envp, this, launch_err); - break; +pid_t MachProcess::LaunchForDebug( + const char *path, char const *argv[], char const *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, DNBError &launch_err) { + // Clear out and clean up from any current state + Clear(); + + DNBLogThreadedIf(LOG_PROCESS, "%s( path = '%s', argv = %p, envp = %p, " + "launch_flavor = %u, disable_aslr = %d )", + __FUNCTION__, path, argv, envp, launch_flavor, disable_aslr); + + // Fork a child process for debugging + SetState(eStateLaunching); + + switch (launch_flavor) { + case eLaunchFlavorForkExec: + m_pid = MachProcess::ForkChildForPTraceDebugging(path, argv, envp, this, + launch_err); + break; #ifdef WITH_FBS - case eLaunchFlavorFBS: - { - const char *app_ext = strstr(path, ".app"); - if (app_ext && (app_ext[4] == '\0' || app_ext[4] == '/')) - { - std::string app_bundle_path(path, app_ext + strlen(".app")); - m_flags |= eMachProcessFlagsUsingFBS; - if (BoardServiceLaunchForDebug (app_bundle_path.c_str(), argv, envp, no_stdio, disable_aslr, event_data, launch_err) != 0) - return m_pid; // A successful SBLaunchForDebug() returns and assigns a non-zero m_pid. - else - break; // We tried a FBS launch, but didn't succeed lets get out - } - } - break; + case eLaunchFlavorFBS: { + const char *app_ext = strstr(path, ".app"); + if (app_ext && (app_ext[4] == '\0' || app_ext[4] == '/')) { + std::string app_bundle_path(path, app_ext + strlen(".app")); + m_flags |= eMachProcessFlagsUsingFBS; + if (BoardServiceLaunchForDebug(app_bundle_path.c_str(), argv, envp, + no_stdio, disable_aslr, event_data, + launch_err) != 0) + return m_pid; // A successful SBLaunchForDebug() returns and assigns a + // non-zero m_pid. + else + break; // We tried a FBS launch, but didn't succeed lets get out + } + } break; #endif #ifdef WITH_BKS - case eLaunchFlavorBKS: - { - const char *app_ext = strstr(path, ".app"); - if (app_ext && (app_ext[4] == '\0' || app_ext[4] == '/')) - { - std::string app_bundle_path(path, app_ext + strlen(".app")); - m_flags |= eMachProcessFlagsUsingBKS; - if (BoardServiceLaunchForDebug (app_bundle_path.c_str(), argv, envp, no_stdio, disable_aslr, event_data, launch_err) != 0) - return m_pid; // A successful SBLaunchForDebug() returns and assigns a non-zero m_pid. - else - break; // We tried a BKS launch, but didn't succeed lets get out - } - } - break; + case eLaunchFlavorBKS: { + const char *app_ext = strstr(path, ".app"); + if (app_ext && (app_ext[4] == '\0' || app_ext[4] == '/')) { + std::string app_bundle_path(path, app_ext + strlen(".app")); + m_flags |= eMachProcessFlagsUsingBKS; + if (BoardServiceLaunchForDebug(app_bundle_path.c_str(), argv, envp, + no_stdio, disable_aslr, event_data, + launch_err) != 0) + return m_pid; // A successful SBLaunchForDebug() returns and assigns a + // non-zero m_pid. + else + break; // We tried a BKS launch, but didn't succeed lets get out + } + } break; #endif #ifdef WITH_SPRINGBOARD - case eLaunchFlavorSpringBoard: - { - // .../whatever.app/whatever ? - // Or .../com.apple.whatever.app/whatever -- be careful of ".app" in "com.apple.whatever" here - const char *app_ext = strstr (path, ".app/"); - if (app_ext == NULL) - { - // .../whatever.app ? - int len = strlen (path); - if (len > 5) - { - if (strcmp (path + len - 4, ".app") == 0) - { - app_ext = path + len - 4; - } - } - } - if (app_ext) - { - std::string app_bundle_path(path, app_ext + strlen(".app")); - if (SBLaunchForDebug (app_bundle_path.c_str(), argv, envp, no_stdio, disable_aslr, launch_err) != 0) - return m_pid; // A successful SBLaunchForDebug() returns and assigns a non-zero m_pid. - else - break; // We tried a springboard launch, but didn't succeed lets get out - } - } - break; + case eLaunchFlavorSpringBoard: { + // .../whatever.app/whatever ? + // Or .../com.apple.whatever.app/whatever -- be careful of ".app" in + // "com.apple.whatever" here + const char *app_ext = strstr(path, ".app/"); + if (app_ext == NULL) { + // .../whatever.app ? + int len = strlen(path); + if (len > 5) { + if (strcmp(path + len - 4, ".app") == 0) { + app_ext = path + len - 4; + } + } + } + if (app_ext) { + std::string app_bundle_path(path, app_ext + strlen(".app")); + if (SBLaunchForDebug(app_bundle_path.c_str(), argv, envp, no_stdio, + disable_aslr, launch_err) != 0) + return m_pid; // A successful SBLaunchForDebug() returns and assigns a + // non-zero m_pid. + else + break; // We tried a springboard launch, but didn't succeed lets get out + } + } break; #endif - case eLaunchFlavorPosixSpawn: - m_pid = MachProcess::PosixSpawnChildForPTraceDebugging (path, - DNBArchProtocol::GetArchitecture (), - argv, - envp, - working_directory, - stdin_path, - stdout_path, - stderr_path, - no_stdio, - this, - disable_aslr, - launch_err); - break; + case eLaunchFlavorPosixSpawn: + m_pid = MachProcess::PosixSpawnChildForPTraceDebugging( + path, DNBArchProtocol::GetArchitecture(), argv, envp, working_directory, + stdin_path, stdout_path, stderr_path, no_stdio, this, disable_aslr, + launch_err); + break; - default: - // Invalid launch + default: + // Invalid launch + launch_err.SetError(NUB_GENERIC_ERROR, DNBError::Generic); + return INVALID_NUB_PROCESS; + } + + if (m_pid == INVALID_NUB_PROCESS) { + // If we don't have a valid process ID and no one has set the error, + // then return a generic error + if (launch_err.Success()) + launch_err.SetError(NUB_GENERIC_ERROR, DNBError::Generic); + } else { + m_path = path; + size_t i; + char const *arg; + for (i = 0; (arg = argv[i]) != NULL; i++) + m_args.push_back(arg); + + m_task.StartExceptionThread(launch_err); + if (launch_err.Fail()) { + if (launch_err.AsString() == NULL) + launch_err.SetErrorString("unable to start the exception thread"); + DNBLog("Could not get inferior's Mach exception port, sending ptrace " + "PT_KILL and exiting."); + ::ptrace(PT_KILL, m_pid, 0, 0); + m_pid = INVALID_NUB_PROCESS; + return INVALID_NUB_PROCESS; + } + + StartSTDIOThread(); + + if (launch_flavor == eLaunchFlavorPosixSpawn) { + + SetState(eStateAttaching); + errno = 0; + int err = ::ptrace(PT_ATTACHEXC, m_pid, 0, 0); + if (err == 0) { + m_flags |= eMachProcessFlagsAttached; + DNBLogThreadedIf(LOG_PROCESS, "successfully spawned pid %d", m_pid); + launch_err.Clear(); + } else { + SetState(eStateExited); + DNBError ptrace_err(errno, DNBError::POSIX); + DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to spawned pid " + "%d (err = %i, errno = %i (%s))", + m_pid, err, ptrace_err.Error(), ptrace_err.AsString()); launch_err.SetError(NUB_GENERIC_ERROR, DNBError::Generic); - return INVALID_NUB_PROCESS; - } + } + } else { + launch_err.Clear(); + } + } + return m_pid; +} + +pid_t MachProcess::PosixSpawnChildForPTraceDebugging( + const char *path, cpu_type_t cpu_type, char const *argv[], + char const *envp[], const char *working_directory, const char *stdin_path, + const char *stdout_path, const char *stderr_path, bool no_stdio, + MachProcess *process, int disable_aslr, DNBError &err) { + posix_spawnattr_t attr; + short flags; + DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv=%p, envp=%p, " + "working_dir=%s, stdin=%s, stdout=%s " + "stderr=%s, no-stdio=%i)", + __FUNCTION__, path, argv, envp, working_directory, + stdin_path, stdout_path, stderr_path, no_stdio); + + err.SetError(::posix_spawnattr_init(&attr), DNBError::POSIX); + if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) + err.LogThreaded("::posix_spawnattr_init ( &attr )"); + if (err.Fail()) + return INVALID_NUB_PROCESS; - if (m_pid == INVALID_NUB_PROCESS) - { - // If we don't have a valid process ID and no one has set the error, - // then return a generic error - if (launch_err.Success()) - launch_err.SetError(NUB_GENERIC_ERROR, DNBError::Generic); - } - else - { - m_path = path; - size_t i; - char const *arg; - for (i=0; (arg = argv[i]) != NULL; i++) - m_args.push_back(arg); - - m_task.StartExceptionThread(launch_err); - if (launch_err.Fail()) - { - if (launch_err.AsString() == NULL) - launch_err.SetErrorString("unable to start the exception thread"); - DNBLog ("Could not get inferior's Mach exception port, sending ptrace PT_KILL and exiting."); - ::ptrace (PT_KILL, m_pid, 0, 0); - m_pid = INVALID_NUB_PROCESS; - return INVALID_NUB_PROCESS; - } + flags = POSIX_SPAWN_START_SUSPENDED | POSIX_SPAWN_SETSIGDEF | + POSIX_SPAWN_SETSIGMASK; + 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); + + err.SetError(::posix_spawnattr_setflags(&attr, flags), DNBError::POSIX); + if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) + err.LogThreaded( + "::posix_spawnattr_setflags ( &attr, POSIX_SPAWN_START_SUSPENDED%s )", + flags & _POSIX_SPAWN_DISABLE_ASLR ? " | _POSIX_SPAWN_DISABLE_ASLR" + : ""); + if (err.Fail()) + return INVALID_NUB_PROCESS; - StartSTDIOThread(); +// Don't do this on SnowLeopard, _sometimes_ the TASK_BASIC_INFO will fail +// and we will fail to continue with our process... - if (launch_flavor == eLaunchFlavorPosixSpawn) - { +// On SnowLeopard we should set "DYLD_NO_PIE" in the inferior environment.... - SetState (eStateAttaching); - errno = 0; - int err = ::ptrace (PT_ATTACHEXC, m_pid, 0, 0); - if (err == 0) - { - m_flags |= eMachProcessFlagsAttached; - DNBLogThreadedIf(LOG_PROCESS, "successfully spawned pid %d", m_pid); - launch_err.Clear(); - } - else - { - SetState (eStateExited); - DNBError ptrace_err(errno, DNBError::POSIX); - DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to spawned pid %d (err = %i, errno = %i (%s))", m_pid, err, ptrace_err.Error(), ptrace_err.AsString()); - launch_err.SetError(NUB_GENERIC_ERROR, DNBError::Generic); - } - } - else - { - launch_err.Clear(); - } - } - return m_pid; -} - -pid_t -MachProcess::PosixSpawnChildForPTraceDebugging -( - const char *path, - cpu_type_t cpu_type, - char const *argv[], - char const *envp[], - const char *working_directory, - const char *stdin_path, - const char *stdout_path, - const char *stderr_path, - bool no_stdio, - MachProcess* process, - int disable_aslr, - DNBError& err -) -{ - posix_spawnattr_t attr; - short flags; - DNBLogThreadedIf(LOG_PROCESS, "%s ( path='%s', argv=%p, envp=%p, working_dir=%s, stdin=%s, stdout=%s stderr=%s, no-stdio=%i)", - __FUNCTION__, - path, - argv, - envp, - working_directory, - stdin_path, - stdout_path, - stderr_path, - no_stdio); - - err.SetError( ::posix_spawnattr_init (&attr), DNBError::POSIX); - if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) - err.LogThreaded("::posix_spawnattr_init ( &attr )"); - if (err.Fail()) - return INVALID_NUB_PROCESS; - - flags = POSIX_SPAWN_START_SUSPENDED | POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; - 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); - - err.SetError( ::posix_spawnattr_setflags (&attr, flags), DNBError::POSIX); - if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) - err.LogThreaded("::posix_spawnattr_setflags ( &attr, POSIX_SPAWN_START_SUSPENDED%s )", flags & _POSIX_SPAWN_DISABLE_ASLR ? " | _POSIX_SPAWN_DISABLE_ASLR" : ""); - if (err.Fail()) - return INVALID_NUB_PROCESS; - - // Don't do this on SnowLeopard, _sometimes_ the TASK_BASIC_INFO will fail - // and we will fail to continue with our process... - - // On SnowLeopard we should set "DYLD_NO_PIE" in the inferior environment.... - #if !defined(__arm__) - // We don't need to do this for ARM, and we really shouldn't now that we - // have multiple CPU subtypes and no posix_spawnattr call that allows us - // to set which CPU subtype to launch... - if (cpu_type != 0) - { - size_t ocount = 0; - err.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu_type, &ocount), DNBError::POSIX); - if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) - err.LogThreaded("::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %llu )", cpu_type, (uint64_t)ocount); + // We don't need to do this for ARM, and we really shouldn't now that we + // have multiple CPU subtypes and no posix_spawnattr call that allows us + // to set which CPU subtype to launch... + if (cpu_type != 0) { + size_t ocount = 0; + err.SetError(::posix_spawnattr_setbinpref_np(&attr, 1, &cpu_type, &ocount), + DNBError::POSIX); + if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) + err.LogThreaded("::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = " + "0x%8.8x, count => %llu )", + cpu_type, (uint64_t)ocount); - if (err.Fail() != 0 || ocount != 1) - return INVALID_NUB_PROCESS; - } + if (err.Fail() != 0 || ocount != 1) + return INVALID_NUB_PROCESS; + } #endif - PseudoTerminal pty; - - posix_spawn_file_actions_t file_actions; - err.SetError( ::posix_spawn_file_actions_init (&file_actions), DNBError::POSIX); - int file_actions_valid = err.Success(); - if (!file_actions_valid || DNBLogCheckLogBit(LOG_PROCESS)) - err.LogThreaded("::posix_spawn_file_actions_init ( &file_actions )"); - int pty_error = -1; - pid_t pid = INVALID_NUB_PROCESS; - if (file_actions_valid) - { - if (stdin_path == NULL && stdout_path == NULL && stderr_path == NULL && !no_stdio) - { - pty_error = pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY); - if (pty_error == PseudoTerminal::success) - { - stdin_path = stdout_path = stderr_path = pty.SlaveName(); - } - } - - // if no_stdio or std paths not supplied, then route to "/dev/null". - if (no_stdio || stdin_path == NULL || stdin_path[0] == '\0') - stdin_path = "/dev/null"; - if (no_stdio || stdout_path == NULL || stdout_path[0] == '\0') - stdout_path = "/dev/null"; - if (no_stdio || stderr_path == NULL || stderr_path[0] == '\0') - stderr_path = "/dev/null"; - - err.SetError( ::posix_spawn_file_actions_addopen (&file_actions, - STDIN_FILENO, - stdin_path, - O_RDONLY | O_NOCTTY, - 0), - DNBError::POSIX); - if (err.Fail() || DNBLogCheckLogBit (LOG_PROCESS)) - err.LogThreaded ("::posix_spawn_file_actions_addopen (&file_actions, filedes=STDIN_FILENO, path='%s')", stdin_path); - - err.SetError( ::posix_spawn_file_actions_addopen (&file_actions, - STDOUT_FILENO, - stdout_path, - O_WRONLY | O_NOCTTY | O_CREAT, - 0640), - DNBError::POSIX); - if (err.Fail() || DNBLogCheckLogBit (LOG_PROCESS)) - err.LogThreaded ("::posix_spawn_file_actions_addopen (&file_actions, filedes=STDOUT_FILENO, path='%s')", stdout_path); - - err.SetError( ::posix_spawn_file_actions_addopen (&file_actions, - STDERR_FILENO, - stderr_path, - O_WRONLY | O_NOCTTY | O_CREAT, - 0640), - DNBError::POSIX); - if (err.Fail() || DNBLogCheckLogBit (LOG_PROCESS)) - err.LogThreaded ("::posix_spawn_file_actions_addopen (&file_actions, filedes=STDERR_FILENO, path='%s')", stderr_path); - - // TODO: Verify if we can set the working directory back immediately - // after the posix_spawnp call without creating a race condition??? - if (working_directory) - ::chdir (working_directory); - - err.SetError( ::posix_spawnp (&pid, path, &file_actions, &attr, (char * const*)argv, (char * const*)envp), DNBError::POSIX); - if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) - err.LogThreaded("::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", pid, path, &file_actions, &attr, argv, envp); - } - else - { - // TODO: Verify if we can set the working directory back immediately - // after the posix_spawnp call without creating a race condition??? - if (working_directory) - ::chdir (working_directory); - - err.SetError( ::posix_spawnp (&pid, path, NULL, &attr, (char * const*)argv, (char * const*)envp), DNBError::POSIX); - if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) - err.LogThreaded("::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", pid, path, NULL, &attr, argv, envp); - } - - // We have seen some cases where posix_spawnp was returning a valid - // looking pid even when an error was returned, so clear it out - if (err.Fail()) - pid = INVALID_NUB_PROCESS; - - if (pty_error == 0) - { - if (process != NULL) - { - int master_fd = pty.ReleaseMasterFD(); - process->SetChildFileDescriptors(master_fd, master_fd, master_fd); - } - } - ::posix_spawnattr_destroy (&attr); - - if (pid != INVALID_NUB_PROCESS) - { - cpu_type_t pid_cpu_type = MachProcess::GetCPUTypeForLocalProcess (pid); - DNBLogThreadedIf(LOG_PROCESS, "MachProcess::%s ( ) pid=%i, cpu_type=0x%8.8x", __FUNCTION__, pid, pid_cpu_type); - if (pid_cpu_type) - DNBArchProtocol::SetArchitecture (pid_cpu_type); - } - - if (file_actions_valid) - { - DNBError err2; - err2.SetError( ::posix_spawn_file_actions_destroy (&file_actions), DNBError::POSIX); - if (err2.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) - err2.LogThreaded("::posix_spawn_file_actions_destroy ( &file_actions )"); - } - - return pid; -} + PseudoTerminal pty; + + posix_spawn_file_actions_t file_actions; + err.SetError(::posix_spawn_file_actions_init(&file_actions), DNBError::POSIX); + int file_actions_valid = err.Success(); + if (!file_actions_valid || DNBLogCheckLogBit(LOG_PROCESS)) + err.LogThreaded("::posix_spawn_file_actions_init ( &file_actions )"); + int pty_error = -1; + pid_t pid = INVALID_NUB_PROCESS; + if (file_actions_valid) { + if (stdin_path == NULL && stdout_path == NULL && stderr_path == NULL && + !no_stdio) { + pty_error = pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY); + if (pty_error == PseudoTerminal::success) { + stdin_path = stdout_path = stderr_path = pty.SlaveName(); + } + } + + // if no_stdio or std paths not supplied, then route to "/dev/null". + if (no_stdio || stdin_path == NULL || stdin_path[0] == '\0') + stdin_path = "/dev/null"; + if (no_stdio || stdout_path == NULL || stdout_path[0] == '\0') + stdout_path = "/dev/null"; + if (no_stdio || stderr_path == NULL || stderr_path[0] == '\0') + stderr_path = "/dev/null"; + + err.SetError(::posix_spawn_file_actions_addopen(&file_actions, STDIN_FILENO, + stdin_path, + O_RDONLY | O_NOCTTY, 0), + DNBError::POSIX); + if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) + err.LogThreaded("::posix_spawn_file_actions_addopen (&file_actions, " + "filedes=STDIN_FILENO, path='%s')", + stdin_path); + + err.SetError(::posix_spawn_file_actions_addopen( + &file_actions, STDOUT_FILENO, stdout_path, + O_WRONLY | O_NOCTTY | O_CREAT, 0640), + DNBError::POSIX); + if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) + err.LogThreaded("::posix_spawn_file_actions_addopen (&file_actions, " + "filedes=STDOUT_FILENO, path='%s')", + stdout_path); + + err.SetError(::posix_spawn_file_actions_addopen( + &file_actions, STDERR_FILENO, stderr_path, + O_WRONLY | O_NOCTTY | O_CREAT, 0640), + DNBError::POSIX); + if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) + err.LogThreaded("::posix_spawn_file_actions_addopen (&file_actions, " + "filedes=STDERR_FILENO, path='%s')", + stderr_path); + + // TODO: Verify if we can set the working directory back immediately + // after the posix_spawnp call without creating a race condition??? + if (working_directory) + ::chdir(working_directory); + + err.SetError(::posix_spawnp(&pid, path, &file_actions, &attr, + (char *const *)argv, (char *const *)envp), + DNBError::POSIX); + if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) + err.LogThreaded("::posix_spawnp ( pid => %i, path = '%s', file_actions = " + "%p, attr = %p, argv = %p, envp = %p )", + pid, path, &file_actions, &attr, argv, envp); + } else { + // TODO: Verify if we can set the working directory back immediately + // after the posix_spawnp call without creating a race condition??? + if (working_directory) + ::chdir(working_directory); + + err.SetError(::posix_spawnp(&pid, path, NULL, &attr, (char *const *)argv, + (char *const *)envp), + DNBError::POSIX); + if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) + err.LogThreaded("::posix_spawnp ( pid => %i, path = '%s', file_actions = " + "%p, attr = %p, argv = %p, envp = %p )", + pid, path, NULL, &attr, argv, envp); + } + + // We have seen some cases where posix_spawnp was returning a valid + // looking pid even when an error was returned, so clear it out + if (err.Fail()) + pid = INVALID_NUB_PROCESS; + + if (pty_error == 0) { + if (process != NULL) { + int master_fd = pty.ReleaseMasterFD(); + process->SetChildFileDescriptors(master_fd, master_fd, master_fd); + } + } + ::posix_spawnattr_destroy(&attr); + + if (pid != INVALID_NUB_PROCESS) { + cpu_type_t pid_cpu_type = MachProcess::GetCPUTypeForLocalProcess(pid); + DNBLogThreadedIf(LOG_PROCESS, + "MachProcess::%s ( ) pid=%i, cpu_type=0x%8.8x", + __FUNCTION__, pid, pid_cpu_type); + if (pid_cpu_type) + DNBArchProtocol::SetArchitecture(pid_cpu_type); + } + + if (file_actions_valid) { + DNBError err2; + err2.SetError(::posix_spawn_file_actions_destroy(&file_actions), + DNBError::POSIX); + if (err2.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) + err2.LogThreaded("::posix_spawn_file_actions_destroy ( &file_actions )"); + } + + return pid; +} + +uint32_t MachProcess::GetCPUTypeForLocalProcess(pid_t pid) { + int mib[CTL_MAXNAME] = { + 0, + }; + size_t len = CTL_MAXNAME; + if (::sysctlnametomib("sysctl.proc_cputype", mib, &len)) + return 0; -uint32_t -MachProcess::GetCPUTypeForLocalProcess (pid_t pid) -{ - int mib[CTL_MAXNAME]={0,}; - size_t len = CTL_MAXNAME; - if (::sysctlnametomib("sysctl.proc_cputype", mib, &len)) - return 0; - - mib[len] = pid; - len++; - - cpu_type_t cpu; - size_t cpu_len = sizeof(cpu); - if (::sysctl (mib, static_cast<u_int>(len), &cpu, &cpu_len, 0, 0)) - cpu = 0; - return cpu; -} - -pid_t -MachProcess::ForkChildForPTraceDebugging -( - const char *path, - char const *argv[], - char const *envp[], - MachProcess* process, - DNBError& launch_err -) -{ - PseudoTerminal::Error pty_error = PseudoTerminal::success; - - // Use a fork that ties the child process's stdin/out/err to a pseudo - // terminal so we can read it in our MachProcess::STDIOThread - // as unbuffered io. - PseudoTerminal pty; - pid_t pid = pty.Fork(pty_error); - - if (pid < 0) - { - //-------------------------------------------------------------- - // Error during fork. - //-------------------------------------------------------------- - return pid; - } - else if (pid == 0) - { - //-------------------------------------------------------------- - // Child process - //-------------------------------------------------------------- - ::ptrace (PT_TRACE_ME, 0, 0, 0); // Debug this process - ::ptrace (PT_SIGEXC, 0, 0, 0); // Get BSD signals as mach exceptions - - // If our parent is setgid, lets make sure we don't inherit those - // extra powers due to nepotism. - if (::setgid (getgid ()) == 0) - { - - // Let the child have its own process group. We need to execute - // this call in both the child and parent to avoid a race condition - // between the two processes. - ::setpgid (0, 0); // Set the child process group to match its pid - - // Sleep a bit to before the exec call - ::sleep (1); - - // Turn this process into - ::execv (path, (char * const *)argv); - } - // Exit with error code. Child process should have taken - // over in above exec call and if the exec fails it will - // exit the child process below. - ::exit (127); - } - else - { - //-------------------------------------------------------------- - // Parent process - //-------------------------------------------------------------- - // Let the child have its own process group. We need to execute - // this call in both the child and parent to avoid a race condition - // between the two processes. - ::setpgid (pid, pid); // Set the child process group to match its pid - - if (process != NULL) - { - // Release our master pty file descriptor so the pty class doesn't - // close it and so we can continue to use it in our STDIO thread - int master_fd = pty.ReleaseMasterFD(); - process->SetChildFileDescriptors(master_fd, master_fd, master_fd); - } - } + mib[len] = pid; + len++; + + cpu_type_t cpu; + size_t cpu_len = sizeof(cpu); + if (::sysctl(mib, static_cast<u_int>(len), &cpu, &cpu_len, 0, 0)) + cpu = 0; + return cpu; +} + +pid_t MachProcess::ForkChildForPTraceDebugging(const char *path, + char const *argv[], + char const *envp[], + MachProcess *process, + DNBError &launch_err) { + PseudoTerminal::Error pty_error = PseudoTerminal::success; + + // Use a fork that ties the child process's stdin/out/err to a pseudo + // terminal so we can read it in our MachProcess::STDIOThread + // as unbuffered io. + PseudoTerminal pty; + pid_t pid = pty.Fork(pty_error); + + if (pid < 0) { + //-------------------------------------------------------------- + // Error during fork. + //-------------------------------------------------------------- return pid; -} - -#if defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined (WITH_FBS) + } else if (pid == 0) { + //-------------------------------------------------------------- + // Child process + //-------------------------------------------------------------- + ::ptrace(PT_TRACE_ME, 0, 0, 0); // Debug this process + ::ptrace(PT_SIGEXC, 0, 0, 0); // Get BSD signals as mach exceptions + + // If our parent is setgid, lets make sure we don't inherit those + // extra powers due to nepotism. + if (::setgid(getgid()) == 0) { + + // Let the child have its own process group. We need to execute + // this call in both the child and parent to avoid a race condition + // between the two processes. + ::setpgid(0, 0); // Set the child process group to match its pid + + // Sleep a bit to before the exec call + ::sleep(1); + + // Turn this process into + ::execv(path, (char *const *)argv); + } + // Exit with error code. Child process should have taken + // over in above exec call and if the exec fails it will + // exit the child process below. + ::exit(127); + } else { + //-------------------------------------------------------------- + // Parent process + //-------------------------------------------------------------- + // Let the child have its own process group. We need to execute + // this call in both the child and parent to avoid a race condition + // between the two processes. + ::setpgid(pid, pid); // Set the child process group to match its pid + + if (process != NULL) { + // Release our master pty file descriptor so the pty class doesn't + // close it and so we can continue to use it in our STDIO thread + int master_fd = pty.ReleaseMasterFD(); + process->SetChildFileDescriptors(master_fd, master_fd, master_fd); + } + } + return pid; +} + +#if defined(WITH_SPRINGBOARD) || defined(WITH_BKS) || defined(WITH_FBS) // This returns a CFRetained pointer to the Bundle ID for app_bundle_path, // or NULL if there was some problem getting the bundle id. -static CFStringRef -CopyBundleIDForPath (const char *app_bundle_path, DNBError &err_str) -{ - CFBundle bundle(app_bundle_path); - CFStringRef bundleIDCFStr = bundle.GetIdentifier(); - std::string bundleID; - if (CFString::UTF8(bundleIDCFStr, bundleID) == NULL) - { - struct stat app_bundle_stat; - char err_msg[PATH_MAX]; - - if (::stat (app_bundle_path, &app_bundle_stat) < 0) - { - err_str.SetError(errno, DNBError::POSIX); - snprintf(err_msg, sizeof(err_msg), "%s: \"%s\"", err_str.AsString(), app_bundle_path); - err_str.SetErrorString(err_msg); - DNBLogThreadedIf(LOG_PROCESS, "%s() error: %s", __FUNCTION__, err_msg); - } - else - { - err_str.SetError(-1, DNBError::Generic); - snprintf(err_msg, sizeof(err_msg), "failed to extract CFBundleIdentifier from %s", app_bundle_path); - err_str.SetErrorString(err_msg); - DNBLogThreadedIf(LOG_PROCESS, "%s() error: failed to extract CFBundleIdentifier from '%s'", __FUNCTION__, app_bundle_path); - } - return NULL; +static CFStringRef CopyBundleIDForPath(const char *app_bundle_path, + DNBError &err_str) { + CFBundle bundle(app_bundle_path); + CFStringRef bundleIDCFStr = bundle.GetIdentifier(); + std::string bundleID; + if (CFString::UTF8(bundleIDCFStr, bundleID) == NULL) { + struct stat app_bundle_stat; + char err_msg[PATH_MAX]; + + if (::stat(app_bundle_path, &app_bundle_stat) < 0) { + err_str.SetError(errno, DNBError::POSIX); + snprintf(err_msg, sizeof(err_msg), "%s: \"%s\"", err_str.AsString(), + app_bundle_path); + err_str.SetErrorString(err_msg); + DNBLogThreadedIf(LOG_PROCESS, "%s() error: %s", __FUNCTION__, err_msg); + } else { + err_str.SetError(-1, DNBError::Generic); + snprintf(err_msg, sizeof(err_msg), + "failed to extract CFBundleIdentifier from %s", app_bundle_path); + err_str.SetErrorString(err_msg); + DNBLogThreadedIf( + LOG_PROCESS, + "%s() error: failed to extract CFBundleIdentifier from '%s'", + __FUNCTION__, app_bundle_path); } + return NULL; + } - DNBLogThreadedIf(LOG_PROCESS, "%s() extracted CFBundleIdentifier: %s", __FUNCTION__, bundleID.c_str()); - CFRetain (bundleIDCFStr); + DNBLogThreadedIf(LOG_PROCESS, "%s() extracted CFBundleIdentifier: %s", + __FUNCTION__, bundleID.c_str()); + CFRetain(bundleIDCFStr); - return bundleIDCFStr; + return bundleIDCFStr; } -#endif // #if defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined (WITH_FBS) +#endif // #if defined (WITH_SPRINGBOARD) || defined (WITH_BKS) || defined + // (WITH_FBS) #ifdef WITH_SPRINGBOARD -pid_t -MachProcess::SBLaunchForDebug (const char *path, char const *argv[], char const *envp[], bool no_stdio, bool disable_aslr, DNBError &launch_err) -{ - // Clear out and clean up from any current state - Clear(); - - DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv)", __FUNCTION__, path); - - // Fork a child process for debugging - SetState(eStateLaunching); - m_pid = MachProcess::SBForkChildForPTraceDebugging(path, argv, envp, no_stdio, this, launch_err); - if (m_pid != 0) - { - m_flags |= eMachProcessFlagsUsingSBS; - m_path = path; - size_t i; - char const *arg; - for (i=0; (arg = argv[i]) != NULL; i++) - m_args.push_back(arg); - m_task.StartExceptionThread(launch_err); - - if (launch_err.Fail()) - { - if (launch_err.AsString() == NULL) - launch_err.SetErrorString("unable to start the exception thread"); - DNBLog ("Could not get inferior's Mach exception port, sending ptrace PT_KILL and exiting."); - ::ptrace (PT_KILL, m_pid, 0, 0); - m_pid = INVALID_NUB_PROCESS; - return INVALID_NUB_PROCESS; - } - - StartSTDIOThread(); - SetState (eStateAttaching); - int err = ::ptrace (PT_ATTACHEXC, m_pid, 0, 0); - if (err == 0) - { - m_flags |= eMachProcessFlagsAttached; - DNBLogThreadedIf(LOG_PROCESS, "successfully attached to pid %d", m_pid); - } - else - { - SetState (eStateExited); - DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", m_pid); - } - } - return m_pid; +pid_t MachProcess::SBLaunchForDebug(const char *path, char const *argv[], + char const *envp[], bool no_stdio, + bool disable_aslr, DNBError &launch_err) { + // Clear out and clean up from any current state + Clear(); + + DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv)", __FUNCTION__, path); + + // Fork a child process for debugging + SetState(eStateLaunching); + m_pid = MachProcess::SBForkChildForPTraceDebugging(path, argv, envp, no_stdio, + this, launch_err); + if (m_pid != 0) { + m_flags |= eMachProcessFlagsUsingSBS; + m_path = path; + size_t i; + char const *arg; + for (i = 0; (arg = argv[i]) != NULL; i++) + m_args.push_back(arg); + m_task.StartExceptionThread(launch_err); + + if (launch_err.Fail()) { + if (launch_err.AsString() == NULL) + launch_err.SetErrorString("unable to start the exception thread"); + DNBLog("Could not get inferior's Mach exception port, sending ptrace " + "PT_KILL and exiting."); + ::ptrace(PT_KILL, m_pid, 0, 0); + m_pid = INVALID_NUB_PROCESS; + return INVALID_NUB_PROCESS; + } + + StartSTDIOThread(); + SetState(eStateAttaching); + int err = ::ptrace(PT_ATTACHEXC, m_pid, 0, 0); + if (err == 0) { + m_flags |= eMachProcessFlagsAttached; + DNBLogThreadedIf(LOG_PROCESS, "successfully attached to pid %d", m_pid); + } else { + SetState(eStateExited); + DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", m_pid); + } + } + return m_pid; } #include <servers/bootstrap.h> -pid_t -MachProcess::SBForkChildForPTraceDebugging (const char *app_bundle_path, char const *argv[], char const *envp[], bool no_stdio, MachProcess* process, DNBError &launch_err) -{ - DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv, %p)", __FUNCTION__, app_bundle_path, process); - CFAllocatorRef alloc = kCFAllocatorDefault; - - if (argv[0] == NULL) - return INVALID_NUB_PROCESS; - - size_t argc = 0; - // Count the number of arguments - while (argv[argc] != NULL) - argc++; - - // Enumerate the arguments - size_t first_launch_arg_idx = 1; - CFReleaser<CFMutableArrayRef> launch_argv; - - if (argv[first_launch_arg_idx]) - { - size_t launch_argc = argc > 0 ? argc - 1 : 0; - launch_argv.reset (::CFArrayCreateMutable (alloc, launch_argc, &kCFTypeArrayCallBacks)); - size_t i; - char const *arg; - CFString launch_arg; - for (i=first_launch_arg_idx; (i < argc) && ((arg = argv[i]) != NULL); i++) - { - launch_arg.reset(::CFStringCreateWithCString (alloc, arg, kCFStringEncodingUTF8)); - if (launch_arg.get() != NULL) - CFArrayAppendValue(launch_argv.get(), launch_arg.get()); - else - break; - } - } - - // Next fill in the arguments dictionary. Note, the envp array is of the form - // Variable=value but SpringBoard wants a CF dictionary. So we have to convert - // this here. - - CFReleaser<CFMutableDictionaryRef> launch_envp; - - if (envp[0]) - { - launch_envp.reset(::CFDictionaryCreateMutable(alloc, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); - const char *value; - int name_len; - CFString name_string, value_string; - - for (int i = 0; envp[i] != NULL; i++) - { - value = strstr (envp[i], "="); - - // If the name field is empty or there's no =, skip it. Somebody's messing with us. - if (value == NULL || value == envp[i]) - continue; - - name_len = value - envp[i]; +pid_t MachProcess::SBForkChildForPTraceDebugging( + const char *app_bundle_path, char const *argv[], char const *envp[], + bool no_stdio, MachProcess *process, DNBError &launch_err) { + DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv, %p)", __FUNCTION__, + app_bundle_path, process); + CFAllocatorRef alloc = kCFAllocatorDefault; - // Now move value over the "=" - value++; - - name_string.reset(::CFStringCreateWithBytes(alloc, (const UInt8 *) envp[i], name_len, kCFStringEncodingUTF8, false)); - value_string.reset(::CFStringCreateWithCString(alloc, value, kCFStringEncodingUTF8)); - CFDictionarySetValue (launch_envp.get(), name_string.get(), value_string.get()); - } - } - - CFString stdio_path; + if (argv[0] == NULL) + return INVALID_NUB_PROCESS; - PseudoTerminal pty; - if (!no_stdio) - { - PseudoTerminal::Error pty_err = pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY); - if (pty_err == PseudoTerminal::success) - { - const char* slave_name = pty.SlaveName(); - DNBLogThreadedIf(LOG_PROCESS, "%s() successfully opened master pty, slave is %s", __FUNCTION__, slave_name); - if (slave_name && slave_name[0]) - { - ::chmod (slave_name, S_IRWXU | S_IRWXG | S_IRWXO); - stdio_path.SetFileSystemRepresentation (slave_name); - } - } - } - - if (stdio_path.get() == NULL) - { - stdio_path.SetFileSystemRepresentation ("/dev/null"); + size_t argc = 0; + // Count the number of arguments + while (argv[argc] != NULL) + argc++; + + // Enumerate the arguments + size_t first_launch_arg_idx = 1; + CFReleaser<CFMutableArrayRef> launch_argv; + + if (argv[first_launch_arg_idx]) { + size_t launch_argc = argc > 0 ? argc - 1 : 0; + launch_argv.reset( + ::CFArrayCreateMutable(alloc, launch_argc, &kCFTypeArrayCallBacks)); + size_t i; + char const *arg; + CFString launch_arg; + for (i = first_launch_arg_idx; (i < argc) && ((arg = argv[i]) != NULL); + i++) { + launch_arg.reset( + ::CFStringCreateWithCString(alloc, arg, kCFStringEncodingUTF8)); + if (launch_arg.get() != NULL) + CFArrayAppendValue(launch_argv.get(), launch_arg.get()); + else + break; } + } + + // Next fill in the arguments dictionary. Note, the envp array is of the form + // Variable=value but SpringBoard wants a CF dictionary. So we have to + // convert + // this here. + + CFReleaser<CFMutableDictionaryRef> launch_envp; + + if (envp[0]) { + launch_envp.reset( + ::CFDictionaryCreateMutable(alloc, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + const char *value; + int name_len; + CFString name_string, value_string; + + for (int i = 0; envp[i] != NULL; i++) { + value = strstr(envp[i], "="); + + // If the name field is empty or there's no =, skip it. Somebody's + // messing with us. + if (value == NULL || value == envp[i]) + continue; + + name_len = value - envp[i]; + + // Now move value over the "=" + value++; + + name_string.reset( + ::CFStringCreateWithBytes(alloc, (const UInt8 *)envp[i], name_len, + kCFStringEncodingUTF8, false)); + value_string.reset( + ::CFStringCreateWithCString(alloc, value, kCFStringEncodingUTF8)); + CFDictionarySetValue(launch_envp.get(), name_string.get(), + value_string.get()); + } + } + + CFString stdio_path; + + PseudoTerminal pty; + if (!no_stdio) { + PseudoTerminal::Error pty_err = + pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY); + if (pty_err == PseudoTerminal::success) { + const char *slave_name = pty.SlaveName(); + DNBLogThreadedIf(LOG_PROCESS, + "%s() successfully opened master pty, slave is %s", + __FUNCTION__, slave_name); + if (slave_name && slave_name[0]) { + ::chmod(slave_name, S_IRWXU | S_IRWXG | S_IRWXO); + stdio_path.SetFileSystemRepresentation(slave_name); + } + } + } + + if (stdio_path.get() == NULL) { + stdio_path.SetFileSystemRepresentation("/dev/null"); + } + + CFStringRef bundleIDCFStr = CopyBundleIDForPath(app_bundle_path, launch_err); + if (bundleIDCFStr == NULL) + return INVALID_NUB_PROCESS; - CFStringRef bundleIDCFStr = CopyBundleIDForPath (app_bundle_path, launch_err); - if (bundleIDCFStr == NULL) - return INVALID_NUB_PROCESS; - - // This is just for logging: - std::string bundleID; - CFString::UTF8(bundleIDCFStr, bundleID); - - DNBLogThreadedIf(LOG_PROCESS, "%s() serialized launch arg array", __FUNCTION__); - - // Find SpringBoard - SBSApplicationLaunchError sbs_error = 0; - sbs_error = SBSLaunchApplicationForDebugging (bundleIDCFStr, - (CFURLRef)NULL, // openURL - launch_argv.get(), - launch_envp.get(), // CFDictionaryRef environment - stdio_path.get(), - stdio_path.get(), - SBSApplicationLaunchWaitForDebugger | SBSApplicationLaunchUnlockDevice); - - - launch_err.SetError(sbs_error, DNBError::SpringBoard); - - if (sbs_error == SBSApplicationLaunchErrorSuccess) - { - static const useconds_t pid_poll_interval = 200000; - static const useconds_t pid_poll_timeout = 30000000; - - useconds_t pid_poll_total = 0; - - nub_process_t pid = INVALID_NUB_PROCESS; - Boolean pid_found = SBSProcessIDForDisplayIdentifier(bundleIDCFStr, &pid); - // Poll until the process is running, as long as we are getting valid responses and the timeout hasn't expired - // A return PID of 0 means the process is not running, which may be because it hasn't been (asynchronously) started - // yet, or that it died very quickly (if you weren't using waitForDebugger). - while (!pid_found && pid_poll_total < pid_poll_timeout) - { - usleep (pid_poll_interval); - pid_poll_total += pid_poll_interval; - DNBLogThreadedIf(LOG_PROCESS, "%s() polling Springboard for pid for %s...", __FUNCTION__, bundleID.c_str()); - pid_found = SBSProcessIDForDisplayIdentifier(bundleIDCFStr, &pid); - } - - CFRelease (bundleIDCFStr); - if (pid_found) - { - if (process != NULL) - { - // Release our master pty file descriptor so the pty class doesn't - // close it and so we can continue to use it in our STDIO thread - int master_fd = pty.ReleaseMasterFD(); - process->SetChildFileDescriptors(master_fd, master_fd, master_fd); - } - DNBLogThreadedIf(LOG_PROCESS, "%s() => pid = %4.4x", __FUNCTION__, pid); - } - else - { - DNBLogError("failed to lookup the process ID for CFBundleIdentifier %s.", bundleID.c_str()); - } - return pid; + // This is just for logging: + std::string bundleID; + CFString::UTF8(bundleIDCFStr, bundleID); + + DNBLogThreadedIf(LOG_PROCESS, "%s() serialized launch arg array", + __FUNCTION__); + + // Find SpringBoard + SBSApplicationLaunchError sbs_error = 0; + sbs_error = SBSLaunchApplicationForDebugging( + bundleIDCFStr, + (CFURLRef)NULL, // openURL + launch_argv.get(), + launch_envp.get(), // CFDictionaryRef environment + stdio_path.get(), stdio_path.get(), + SBSApplicationLaunchWaitForDebugger | SBSApplicationLaunchUnlockDevice); + + launch_err.SetError(sbs_error, DNBError::SpringBoard); + + if (sbs_error == SBSApplicationLaunchErrorSuccess) { + static const useconds_t pid_poll_interval = 200000; + static const useconds_t pid_poll_timeout = 30000000; + + useconds_t pid_poll_total = 0; + + nub_process_t pid = INVALID_NUB_PROCESS; + Boolean pid_found = SBSProcessIDForDisplayIdentifier(bundleIDCFStr, &pid); + // Poll until the process is running, as long as we are getting valid + // responses and the timeout hasn't expired + // A return PID of 0 means the process is not running, which may be because + // it hasn't been (asynchronously) started + // yet, or that it died very quickly (if you weren't using waitForDebugger). + while (!pid_found && pid_poll_total < pid_poll_timeout) { + usleep(pid_poll_interval); + pid_poll_total += pid_poll_interval; + DNBLogThreadedIf(LOG_PROCESS, + "%s() polling Springboard for pid for %s...", + __FUNCTION__, bundleID.c_str()); + pid_found = SBSProcessIDForDisplayIdentifier(bundleIDCFStr, &pid); + } + + CFRelease(bundleIDCFStr); + if (pid_found) { + if (process != NULL) { + // Release our master pty file descriptor so the pty class doesn't + // close it and so we can continue to use it in our STDIO thread + int master_fd = pty.ReleaseMasterFD(); + process->SetChildFileDescriptors(master_fd, master_fd, master_fd); + } + DNBLogThreadedIf(LOG_PROCESS, "%s() => pid = %4.4x", __FUNCTION__, pid); + } else { + DNBLogError("failed to lookup the process ID for CFBundleIdentifier %s.", + bundleID.c_str()); } + return pid; + } - DNBLogError("unable to launch the application with CFBundleIdentifier '%s' sbs_error = %u", bundleID.c_str(), sbs_error); - return INVALID_NUB_PROCESS; + DNBLogError("unable to launch the application with CFBundleIdentifier '%s' " + "sbs_error = %u", + bundleID.c_str(), sbs_error); + return INVALID_NUB_PROCESS; } #endif // #ifdef WITH_SPRINGBOARD - - -#if defined (WITH_BKS) || defined (WITH_FBS) -pid_t -MachProcess::BoardServiceLaunchForDebug (const char *path, char const *argv[], char const *envp[], bool no_stdio, bool disable_aslr, const char *event_data, DNBError &launch_err) -{ - DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv)", __FUNCTION__, path); - - // Fork a child process for debugging - SetState(eStateLaunching); - m_pid = BoardServiceForkChildForPTraceDebugging(path, argv, envp, no_stdio, disable_aslr, event_data, launch_err); - if (m_pid != 0) - { - m_path = path; - size_t i; - char const *arg; - for (i=0; (arg = argv[i]) != NULL; i++) - m_args.push_back(arg); - m_task.StartExceptionThread(launch_err); - - if (launch_err.Fail()) - { - if (launch_err.AsString() == NULL) - launch_err.SetErrorString("unable to start the exception thread"); - DNBLog ("Could not get inferior's Mach exception port, sending ptrace PT_KILL and exiting."); - ::ptrace (PT_KILL, m_pid, 0, 0); - m_pid = INVALID_NUB_PROCESS; - return INVALID_NUB_PROCESS; - } +#if defined(WITH_BKS) || defined(WITH_FBS) +pid_t MachProcess::BoardServiceLaunchForDebug( + const char *path, char const *argv[], char const *envp[], bool no_stdio, + bool disable_aslr, const char *event_data, DNBError &launch_err) { + DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv)", __FUNCTION__, path); + + // Fork a child process for debugging + SetState(eStateLaunching); + m_pid = BoardServiceForkChildForPTraceDebugging( + path, argv, envp, no_stdio, disable_aslr, event_data, launch_err); + if (m_pid != 0) { + m_path = path; + size_t i; + char const *arg; + for (i = 0; (arg = argv[i]) != NULL; i++) + m_args.push_back(arg); + m_task.StartExceptionThread(launch_err); + + if (launch_err.Fail()) { + if (launch_err.AsString() == NULL) + launch_err.SetErrorString("unable to start the exception thread"); + DNBLog("Could not get inferior's Mach exception port, sending ptrace " + "PT_KILL and exiting."); + ::ptrace(PT_KILL, m_pid, 0, 0); + m_pid = INVALID_NUB_PROCESS; + return INVALID_NUB_PROCESS; + } + + StartSTDIOThread(); + SetState(eStateAttaching); + int err = ::ptrace(PT_ATTACHEXC, m_pid, 0, 0); + if (err == 0) { + m_flags |= eMachProcessFlagsAttached; + DNBLogThreadedIf(LOG_PROCESS, "successfully attached to pid %d", m_pid); + } else { + SetState(eStateExited); + DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", m_pid); + } + } + return m_pid; +} + +pid_t MachProcess::BoardServiceForkChildForPTraceDebugging( + const char *app_bundle_path, char const *argv[], char const *envp[], + bool no_stdio, bool disable_aslr, const char *event_data, + DNBError &launch_err) { + if (argv[0] == NULL) + return INVALID_NUB_PROCESS; - StartSTDIOThread(); - SetState (eStateAttaching); - int err = ::ptrace (PT_ATTACHEXC, m_pid, 0, 0); - if (err == 0) - { - m_flags |= eMachProcessFlagsAttached; - DNBLogThreadedIf(LOG_PROCESS, "successfully attached to pid %d", m_pid); - } - else - { - SetState (eStateExited); - DNBLogThreadedIf(LOG_PROCESS, "error: failed to attach to pid %d", m_pid); - } + DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv, %p)", __FUNCTION__, + app_bundle_path, this); + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + size_t argc = 0; + // Count the number of arguments + while (argv[argc] != NULL) + argc++; + + // Enumerate the arguments + size_t first_launch_arg_idx = 1; + + NSMutableArray *launch_argv = nil; + + if (argv[first_launch_arg_idx]) { + size_t launch_argc = argc > 0 ? argc - 1 : 0; + launch_argv = [NSMutableArray arrayWithCapacity:launch_argc]; + size_t i; + char const *arg; + NSString *launch_arg; + for (i = first_launch_arg_idx; (i < argc) && ((arg = argv[i]) != NULL); + i++) { + launch_arg = [NSString stringWithUTF8String:arg]; + // FIXME: Should we silently eat an argument that we can't convert into a + // UTF8 string? + if (launch_arg != nil) + [launch_argv addObject:launch_arg]; + else + break; } - return m_pid; -} - -pid_t -MachProcess::BoardServiceForkChildForPTraceDebugging (const char *app_bundle_path, - char const *argv[], - char const *envp[], - bool no_stdio, - bool disable_aslr, - const char *event_data, - DNBError &launch_err) -{ - if (argv[0] == NULL) - return INVALID_NUB_PROCESS; - - DNBLogThreadedIf(LOG_PROCESS, "%s( '%s', argv, %p)", __FUNCTION__, app_bundle_path, this); - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + } + + NSMutableDictionary *launch_envp = nil; + if (envp[0]) { + launch_envp = [[NSMutableDictionary alloc] init]; + const char *value; + int name_len; + NSString *name_string, *value_string; + + for (int i = 0; envp[i] != NULL; i++) { + value = strstr(envp[i], "="); + + // If the name field is empty or there's no =, skip it. Somebody's + // messing with us. + if (value == NULL || value == envp[i]) + continue; + + name_len = value - envp[i]; + + // Now move value over the "=" + value++; + name_string = [[NSString alloc] initWithBytes:envp[i] + length:name_len + encoding:NSUTF8StringEncoding]; + value_string = [NSString stringWithUTF8String:value]; + [launch_envp setObject:value_string forKey:name_string]; + } + } + + NSString *stdio_path = nil; + NSFileManager *file_manager = [NSFileManager defaultManager]; + + PseudoTerminal pty; + if (!no_stdio) { + PseudoTerminal::Error pty_err = + pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY); + if (pty_err == PseudoTerminal::success) { + const char *slave_name = pty.SlaveName(); + DNBLogThreadedIf(LOG_PROCESS, + "%s() successfully opened master pty, slave is %s", + __FUNCTION__, slave_name); + if (slave_name && slave_name[0]) { + ::chmod(slave_name, S_IRWXU | S_IRWXG | S_IRWXO); + stdio_path = [file_manager + stringWithFileSystemRepresentation:slave_name + length:strlen(slave_name)]; + } + } + } + + if (stdio_path == nil) { + const char *null_path = "/dev/null"; + stdio_path = + [file_manager stringWithFileSystemRepresentation:null_path + length:strlen(null_path)]; + } + + CFStringRef bundleIDCFStr = CopyBundleIDForPath(app_bundle_path, launch_err); + if (bundleIDCFStr == NULL) { + [pool drain]; + return INVALID_NUB_PROCESS; + } - size_t argc = 0; - // Count the number of arguments - while (argv[argc] != NULL) - argc++; - - // Enumerate the arguments - size_t first_launch_arg_idx = 1; - - NSMutableArray *launch_argv = nil; - - if (argv[first_launch_arg_idx]) - { - size_t launch_argc = argc > 0 ? argc - 1 : 0; - launch_argv = [NSMutableArray arrayWithCapacity: launch_argc]; - size_t i; - char const *arg; - NSString *launch_arg; - for (i=first_launch_arg_idx; (i < argc) && ((arg = argv[i]) != NULL); i++) - { - launch_arg = [NSString stringWithUTF8String: arg]; - // FIXME: Should we silently eat an argument that we can't convert into a UTF8 string? - if (launch_arg != nil) - [launch_argv addObject: launch_arg]; - else - break; - } - } + // Instead of rewriting CopyBundleIDForPath for NSStrings, we'll just use + // toll-free bridging here: + NSString *bundleIDNSStr = (NSString *)bundleIDCFStr; - NSMutableDictionary *launch_envp = nil; - if (envp[0]) - { - launch_envp = [[NSMutableDictionary alloc] init]; - const char *value; - int name_len; - NSString *name_string, *value_string; + // Okay, now let's assemble all these goodies into the BackBoardServices + // options mega-dictionary: - for (int i = 0; envp[i] != NULL; i++) - { - value = strstr (envp[i], "="); + NSMutableDictionary *options = nullptr; + pid_t return_pid = INVALID_NUB_PROCESS; + bool success = false; - // If the name field is empty or there's no =, skip it. Somebody's messing with us. - if (value == NULL || value == envp[i]) - continue; +#ifdef WITH_BKS + if (m_flags & eMachProcessFlagsUsingBKS) { + options = + BKSCreateOptionsDictionary(app_bundle_path, launch_argv, launch_envp, + stdio_path, disable_aslr, event_data); + success = BKSCallOpenApplicationFunction(bundleIDNSStr, options, launch_err, + &return_pid); + } +#endif +#ifdef WITH_FBS + if (m_flags & eMachProcessFlagsUsingFBS) { + options = + FBSCreateOptionsDictionary(app_bundle_path, launch_argv, launch_envp, + stdio_path, disable_aslr, event_data); + success = FBSCallOpenApplicationFunction(bundleIDNSStr, options, launch_err, + &return_pid); + } +#endif - name_len = value - envp[i]; + if (success) { + int master_fd = pty.ReleaseMasterFD(); + SetChildFileDescriptors(master_fd, master_fd, master_fd); + CFString::UTF8(bundleIDCFStr, m_bundle_id); + } - // Now move value over the "=" - value++; - name_string = [[NSString alloc] initWithBytes: envp[i] length: name_len encoding: NSUTF8StringEncoding]; - value_string = [NSString stringWithUTF8String: value]; - [launch_envp setObject: value_string forKey: name_string]; - } - } + [pool drain]; - NSString *stdio_path = nil; - NSFileManager *file_manager = [NSFileManager defaultManager]; + return return_pid; +} - PseudoTerminal pty; - if (!no_stdio) - { - PseudoTerminal::Error pty_err = pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY); - if (pty_err == PseudoTerminal::success) - { - const char* slave_name = pty.SlaveName(); - DNBLogThreadedIf(LOG_PROCESS, "%s() successfully opened master pty, slave is %s", __FUNCTION__, slave_name); - if (slave_name && slave_name[0]) - { - ::chmod (slave_name, S_IRWXU | S_IRWXG | S_IRWXO); - stdio_path = [file_manager stringWithFileSystemRepresentation: slave_name length: strlen(slave_name)]; - } - } - } - - if (stdio_path == nil) - { - const char *null_path = "/dev/null"; - stdio_path = [file_manager stringWithFileSystemRepresentation: null_path length: strlen(null_path)]; - } - - CFStringRef bundleIDCFStr = CopyBundleIDForPath (app_bundle_path, launch_err); - if (bundleIDCFStr == NULL) - { - [pool drain]; - return INVALID_NUB_PROCESS; - } +bool MachProcess::BoardServiceSendEvent(const char *event_data, + DNBError &send_err) { + bool return_value = true; - // Instead of rewriting CopyBundleIDForPath for NSStrings, we'll just use toll-free bridging here: - NSString *bundleIDNSStr = (NSString *) bundleIDCFStr; + if (event_data == NULL || *event_data == '\0') { + DNBLogError("SendEvent called with NULL event data."); + send_err.SetErrorString("SendEvent called with empty event data"); + return false; + } - // Okay, now let's assemble all these goodies into the BackBoardServices options mega-dictionary: - - NSMutableDictionary *options = nullptr; - pid_t return_pid = INVALID_NUB_PROCESS; - bool success = false; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + if (strcmp(event_data, "BackgroundApplication") == 0) { +// This is an event I cooked up. What you actually do is foreground the system +// app, so: #ifdef WITH_BKS - if (m_flags & eMachProcessFlagsUsingBKS) - { - options = BKSCreateOptionsDictionary(app_bundle_path, launch_argv, launch_envp, stdio_path, disable_aslr, event_data); - success = BKSCallOpenApplicationFunction (bundleIDNSStr, options, launch_err, &return_pid); - } + if (m_flags & eMachProcessFlagsUsingBKS) { + return_value = BKSCallOpenApplicationFunction(nil, nil, send_err, NULL); + } #endif #ifdef WITH_FBS - if (m_flags & eMachProcessFlagsUsingFBS) - { - options = FBSCreateOptionsDictionary(app_bundle_path, launch_argv, launch_envp, stdio_path, disable_aslr, event_data); - success = FBSCallOpenApplicationFunction (bundleIDNSStr, options, launch_err, &return_pid); + if (m_flags & eMachProcessFlagsUsingFBS) { + return_value = FBSCallOpenApplicationFunction(nil, nil, send_err, NULL); } #endif - - if (success) - { - int master_fd = pty.ReleaseMasterFD(); - SetChildFileDescriptors(master_fd, master_fd, master_fd); - CFString::UTF8(bundleIDCFStr, m_bundle_id); + if (!return_value) { + DNBLogError("Failed to background application, error: %s.", + send_err.AsString()); } - - [pool drain]; + } else { + if (m_bundle_id.empty()) { + // See if we can figure out the bundle ID for this PID: - return return_pid; -} + DNBLogError( + "Tried to send event \"%s\" to a process that has no bundle ID.", + event_data); + return false; + } + + NSString *bundleIDNSStr = + [NSString stringWithUTF8String:m_bundle_id.c_str()]; -bool -MachProcess::BoardServiceSendEvent (const char *event_data, DNBError &send_err) -{ - bool return_value = true; - - if (event_data == NULL || *event_data == '\0') - { - DNBLogError ("SendEvent called with NULL event data."); - send_err.SetErrorString("SendEvent called with empty event data"); + NSMutableDictionary *options = [NSMutableDictionary dictionary]; + +#ifdef WITH_BKS + if (m_flags & eMachProcessFlagsUsingBKS) { + if (!BKSAddEventDataToOptions(options, event_data, send_err)) { + [pool drain]; return false; + } + return_value = BKSCallOpenApplicationFunction(bundleIDNSStr, options, + send_err, NULL); + DNBLogThreadedIf(LOG_PROCESS, + "Called BKSCallOpenApplicationFunction to send event."); } - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - if (strcmp (event_data, "BackgroundApplication") == 0) - { - // This is an event I cooked up. What you actually do is foreground the system app, so: -#ifdef WITH_BKS - if (m_flags & eMachProcessFlagsUsingBKS) - { - return_value = BKSCallOpenApplicationFunction(nil, nil, send_err, NULL); - } #endif #ifdef WITH_FBS - if (m_flags & eMachProcessFlagsUsingFBS) - { - return_value = FBSCallOpenApplicationFunction(nil, nil, send_err, NULL); - } -#endif - if (!return_value) - { - DNBLogError ("Failed to background application, error: %s.", send_err.AsString()); - } + if (m_flags & eMachProcessFlagsUsingFBS) { + if (!FBSAddEventDataToOptions(options, event_data, send_err)) { + [pool drain]; + return false; + } + return_value = FBSCallOpenApplicationFunction(bundleIDNSStr, options, + send_err, NULL); + DNBLogThreadedIf(LOG_PROCESS, + "Called FBSCallOpenApplicationFunction to send event."); } - else - { - if (m_bundle_id.empty()) - { - // See if we can figure out the bundle ID for this PID: - - DNBLogError ("Tried to send event \"%s\" to a process that has no bundle ID.", event_data); - return false; - } - - NSString *bundleIDNSStr = [NSString stringWithUTF8String:m_bundle_id.c_str()]; - - NSMutableDictionary *options = [NSMutableDictionary dictionary]; - -#ifdef WITH_BKS - if (m_flags & eMachProcessFlagsUsingBKS) - { - if (!BKSAddEventDataToOptions(options, event_data, send_err)) - { - [pool drain]; - return false; - } - return_value = BKSCallOpenApplicationFunction (bundleIDNSStr, options, send_err, NULL); - DNBLogThreadedIf (LOG_PROCESS, "Called BKSCallOpenApplicationFunction to send event."); - - } #endif -#ifdef WITH_FBS - if (m_flags & eMachProcessFlagsUsingFBS) - { - if (!FBSAddEventDataToOptions(options, event_data, send_err)) - { - [pool drain]; - return false; - } - return_value = FBSCallOpenApplicationFunction (bundleIDNSStr, options, send_err, NULL); - DNBLogThreadedIf (LOG_PROCESS, "Called FBSCallOpenApplicationFunction to send event."); - } -#endif - - if (!return_value) - { - DNBLogError ("Failed to send event: %s, error: %s.", event_data, send_err.AsString()); - } + + if (!return_value) { + DNBLogError("Failed to send event: %s, error: %s.", event_data, + send_err.AsString()); } - - [pool drain]; - return return_value; + } + + [pool drain]; + return return_value; } #endif // defined(WITH_BKS) || defined (WITH_FBS) #ifdef WITH_BKS -void -MachProcess::BKSCleanupAfterAttach (const void *attach_token, DNBError &err_str) -{ - bool success; - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - // Instead of rewriting CopyBundleIDForPath for NSStrings, we'll just use toll-free bridging here: - NSString *bundleIDNSStr = (NSString *) attach_token; +void MachProcess::BKSCleanupAfterAttach(const void *attach_token, + DNBError &err_str) { + bool success; - // Okay, now let's assemble all these goodies into the BackBoardServices options mega-dictionary: - - // First we have the debug sub-dictionary: - NSMutableDictionary *debug_options = [NSMutableDictionary dictionary]; - [debug_options setObject: [NSNumber numberWithBool: YES] forKey: BKSDebugOptionKeyCancelDebugOnNextLaunch]; - - // That will go in the overall dictionary: - - NSMutableDictionary *options = [NSMutableDictionary dictionary]; - [options setObject: debug_options forKey: BKSOpenApplicationOptionKeyDebuggingOptions]; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - success = BKSCallOpenApplicationFunction (bundleIDNSStr, options, err_str, NULL); - - if (!success) - { - DNBLogError ("error trying to cancel debug on next launch for %s: %s", [bundleIDNSStr UTF8String], err_str.AsString()); - } + // Instead of rewriting CopyBundleIDForPath for NSStrings, we'll just use + // toll-free bridging here: + NSString *bundleIDNSStr = (NSString *)attach_token; - [pool drain]; + // Okay, now let's assemble all these goodies into the BackBoardServices + // options mega-dictionary: + + // First we have the debug sub-dictionary: + NSMutableDictionary *debug_options = [NSMutableDictionary dictionary]; + [debug_options setObject:[NSNumber numberWithBool:YES] + forKey:BKSDebugOptionKeyCancelDebugOnNextLaunch]; + + // That will go in the overall dictionary: + + NSMutableDictionary *options = [NSMutableDictionary dictionary]; + [options setObject:debug_options + forKey:BKSOpenApplicationOptionKeyDebuggingOptions]; + + success = + BKSCallOpenApplicationFunction(bundleIDNSStr, options, err_str, NULL); + + if (!success) { + DNBLogError("error trying to cancel debug on next launch for %s: %s", + [bundleIDNSStr UTF8String], err_str.AsString()); + } + + [pool drain]; } #endif // WITH_BKS #ifdef WITH_FBS -void -MachProcess::FBSCleanupAfterAttach (const void *attach_token, DNBError &err_str) -{ - bool success; - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - // Instead of rewriting CopyBundleIDForPath for NSStrings, we'll just use toll-free bridging here: - NSString *bundleIDNSStr = (NSString *) attach_token; +void MachProcess::FBSCleanupAfterAttach(const void *attach_token, + DNBError &err_str) { + bool success; - // Okay, now let's assemble all these goodies into the BackBoardServices options mega-dictionary: - - // First we have the debug sub-dictionary: - NSMutableDictionary *debug_options = [NSMutableDictionary dictionary]; - [debug_options setObject: [NSNumber numberWithBool: YES] forKey: FBSDebugOptionKeyCancelDebugOnNextLaunch]; - - // That will go in the overall dictionary: - - NSMutableDictionary *options = [NSMutableDictionary dictionary]; - [options setObject: debug_options forKey: FBSOpenApplicationOptionKeyDebuggingOptions]; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - success = FBSCallOpenApplicationFunction (bundleIDNSStr, options, err_str, NULL); + // Instead of rewriting CopyBundleIDForPath for NSStrings, we'll just use + // toll-free bridging here: + NSString *bundleIDNSStr = (NSString *)attach_token; - if (!success) - { - DNBLogError ("error trying to cancel debug on next launch for %s: %s", [bundleIDNSStr UTF8String], err_str.AsString()); - } + // Okay, now let's assemble all these goodies into the BackBoardServices + // options mega-dictionary: - [pool drain]; + // First we have the debug sub-dictionary: + NSMutableDictionary *debug_options = [NSMutableDictionary dictionary]; + [debug_options setObject:[NSNumber numberWithBool:YES] + forKey:FBSDebugOptionKeyCancelDebugOnNextLaunch]; + + // That will go in the overall dictionary: + + NSMutableDictionary *options = [NSMutableDictionary dictionary]; + [options setObject:debug_options + forKey:FBSOpenApplicationOptionKeyDebuggingOptions]; + + success = + FBSCallOpenApplicationFunction(bundleIDNSStr, options, err_str, NULL); + + if (!success) { + DNBLogError("error trying to cancel debug on next launch for %s: %s", + [bundleIDNSStr UTF8String], err_str.AsString()); + } + + [pool drain]; } #endif // WITH_FBS diff --git a/lldb/tools/debugserver/source/MacOSX/MachTask.h b/lldb/tools/debugserver/source/MacOSX/MachTask.h index d8021e8f7fe..2fdb22f8e56 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachTask.h +++ b/lldb/tools/debugserver/source/MacOSX/MachTask.h @@ -35,80 +35,82 @@ class MachProcess; typedef uint64_t MachMallocEventId; -enum MachMallocEventType -{ - eMachMallocEventTypeAlloc = 2, - eMachMallocEventTypeDealloc = 4, - eMachMallocEventTypeOther = 1 +enum MachMallocEventType { + eMachMallocEventTypeAlloc = 2, + eMachMallocEventTypeDealloc = 4, + eMachMallocEventTypeOther = 1 }; -struct MachMallocEvent -{ - mach_vm_address_t m_base_address; - uint64_t m_size; - MachMallocEventType m_event_type; - MachMallocEventId m_event_id; +struct MachMallocEvent { + mach_vm_address_t m_base_address; + uint64_t m_size; + MachMallocEventType m_event_type; + MachMallocEventId m_event_id; }; -class MachTask -{ +class MachTask { public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - MachTask (MachProcess *process); - virtual ~MachTask (); - - void Clear (); - - kern_return_t Suspend (); - kern_return_t Resume (); - - nub_size_t ReadMemory (nub_addr_t addr, nub_size_t size, void *buf); - nub_size_t WriteMemory (nub_addr_t addr, nub_size_t size, const void *buf); - int GetMemoryRegionInfo (nub_addr_t addr, DNBRegionInfo *region_info); - std::string GetProfileData (DNBProfileDataScanType scanType); - - nub_addr_t AllocateMemory (nub_size_t size, uint32_t permissions); - nub_bool_t DeallocateMemory (nub_addr_t addr); - - mach_port_t ExceptionPort () const; - bool ExceptionPortIsValid () const; - kern_return_t SaveExceptionPortInfo (); - kern_return_t RestoreExceptionPortInfo (); - kern_return_t ShutDownExcecptionThread (); - - bool StartExceptionThread (DNBError &err); - nub_addr_t GetDYLDAllImageInfosAddress (DNBError& err); - kern_return_t BasicInfo (struct task_basic_info *info); - static kern_return_t BasicInfo (task_t task, struct task_basic_info *info); - bool IsValid () const; - static bool IsValid (task_t task); - static void * ExceptionThread (void *arg); - task_t TaskPort () const { return m_task; } - task_t TaskPortForProcessID (DNBError &err, bool force = false); - static task_t TaskPortForProcessID (pid_t pid, DNBError &err, uint32_t num_retries = 10, uint32_t usec_interval = 10000); - - MachProcess * Process () { return m_process; } - const MachProcess * Process () const { return m_process; } - - nub_size_t PageSize (); + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + MachTask(MachProcess *process); + virtual ~MachTask(); + + void Clear(); + + kern_return_t Suspend(); + kern_return_t Resume(); + + nub_size_t ReadMemory(nub_addr_t addr, nub_size_t size, void *buf); + nub_size_t WriteMemory(nub_addr_t addr, nub_size_t size, const void *buf); + int GetMemoryRegionInfo(nub_addr_t addr, DNBRegionInfo *region_info); + std::string GetProfileData(DNBProfileDataScanType scanType); + + nub_addr_t AllocateMemory(nub_size_t size, uint32_t permissions); + nub_bool_t DeallocateMemory(nub_addr_t addr); + + mach_port_t ExceptionPort() const; + bool ExceptionPortIsValid() const; + kern_return_t SaveExceptionPortInfo(); + kern_return_t RestoreExceptionPortInfo(); + kern_return_t ShutDownExcecptionThread(); + + bool StartExceptionThread(DNBError &err); + nub_addr_t GetDYLDAllImageInfosAddress(DNBError &err); + kern_return_t BasicInfo(struct task_basic_info *info); + static kern_return_t BasicInfo(task_t task, struct task_basic_info *info); + bool IsValid() const; + static bool IsValid(task_t task); + static void *ExceptionThread(void *arg); + task_t TaskPort() const { return m_task; } + task_t TaskPortForProcessID(DNBError &err, bool force = false); + static task_t TaskPortForProcessID(pid_t pid, DNBError &err, + uint32_t num_retries = 10, + uint32_t usec_interval = 10000); + + MachProcess *Process() { return m_process; } + const MachProcess *Process() const { return m_process; } + + nub_size_t PageSize(); protected: - MachProcess * m_process; // The mach process that owns this MachTask - task_t m_task; - MachVMMemory m_vm_memory; // Special mach memory reading class that will take care of watching for page and region boundaries - MachException::PortInfo - m_exc_port_info; // Saved settings for all exception ports - pthread_t m_exception_thread; // Thread ID for the exception thread in case we need it - mach_port_t m_exception_port; // Exception port on which we will receive child exceptions - - typedef std::map <mach_vm_address_t, size_t> allocation_collection; - allocation_collection m_allocations; + MachProcess *m_process; // The mach process that owns this MachTask + task_t m_task; + MachVMMemory m_vm_memory; // Special mach memory reading class that will take + // care of watching for page and region boundaries + MachException::PortInfo + m_exc_port_info; // Saved settings for all exception ports + pthread_t m_exception_thread; // Thread ID for the exception thread in case we + // need it + mach_port_t m_exception_port; // Exception port on which we will receive child + // exceptions + + typedef std::map<mach_vm_address_t, size_t> allocation_collection; + allocation_collection m_allocations; private: - MachTask(const MachTask&); // Outlaw - MachTask& operator=(const MachTask& rhs);// Outlaw + MachTask(const MachTask &); // Outlaw + MachTask &operator=(const MachTask &rhs); // Outlaw }; -#endif // __MachTask_h__ +#endif // __MachTask_h__ diff --git a/lldb/tools/debugserver/source/MacOSX/MachTask.mm b/lldb/tools/debugserver/source/MacOSX/MachTask.mm index cc1d6a38ec0..f0f086ecbd9 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachTask.mm +++ b/lldb/tools/debugserver/source/MacOSX/MachTask.mm @@ -23,7 +23,7 @@ #include <mach/mach_vm.h> #import <sys/sysctl.h> -#if defined (__APPLE__) +#if defined(__APPLE__) #include <pthread.h> #include <sched.h> #endif @@ -36,25 +36,24 @@ // Project includes #include "CFUtils.h" #include "DNB.h" +#include "DNBDataRef.h" #include "DNBError.h" #include "DNBLog.h" #include "MachProcess.h" -#include "DNBDataRef.h" #ifdef WITH_SPRINGBOARD #include <CoreFoundation/CoreFoundation.h> -#include <SpringBoardServices/SpringBoardServer.h> #include <SpringBoardServices/SBSWatchdogAssertion.h> +#include <SpringBoardServices/SpringBoardServer.h> #endif #ifdef WITH_BKS -extern "C" -{ - #import <Foundation/Foundation.h> - #import <BackBoardServices/BackBoardServices.h> - #import <BackBoardServices/BKSWatchdogAssertion.h> +extern "C" { +#import <BackBoardServices/BKSWatchdogAssertion.h> +#import <BackBoardServices/BackBoardServices.h> +#import <Foundation/Foundation.h> } #endif @@ -66,994 +65,922 @@ extern "C" #include <pmsample.h> #endif - //---------------------------------------------------------------------- // MachTask constructor //---------------------------------------------------------------------- -MachTask::MachTask(MachProcess *process) : - m_process (process), - m_task (TASK_NULL), - m_vm_memory (), - m_exception_thread (0), - m_exception_port (MACH_PORT_NULL) -{ - memset(&m_exc_port_info, 0, sizeof(m_exc_port_info)); +MachTask::MachTask(MachProcess *process) + : m_process(process), m_task(TASK_NULL), m_vm_memory(), + m_exception_thread(0), m_exception_port(MACH_PORT_NULL) { + memset(&m_exc_port_info, 0, sizeof(m_exc_port_info)); } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -MachTask::~MachTask() -{ - Clear(); -} - +MachTask::~MachTask() { Clear(); } //---------------------------------------------------------------------- // MachTask::Suspend //---------------------------------------------------------------------- -kern_return_t -MachTask::Suspend() -{ - DNBError err; - task_t task = TaskPort(); - err = ::task_suspend (task); - if (DNBLogCheckLogBit(LOG_TASK) || err.Fail()) - err.LogThreaded("::task_suspend ( target_task = 0x%4.4x )", task); - return err.Error(); +kern_return_t MachTask::Suspend() { + DNBError err; + task_t task = TaskPort(); + err = ::task_suspend(task); + if (DNBLogCheckLogBit(LOG_TASK) || err.Fail()) + err.LogThreaded("::task_suspend ( target_task = 0x%4.4x )", task); + return err.Error(); } - //---------------------------------------------------------------------- // MachTask::Resume //---------------------------------------------------------------------- -kern_return_t -MachTask::Resume() -{ - struct task_basic_info task_info; - task_t task = TaskPort(); - if (task == TASK_NULL) - return KERN_INVALID_ARGUMENT; - - DNBError err; - err = BasicInfo(task, &task_info); - - if (err.Success()) - { - // task_resume isn't counted like task_suspend calls are, are, so if the - // task is not suspended, don't try and resume it since it is already - // running - if (task_info.suspend_count > 0) - { - err = ::task_resume (task); - if (DNBLogCheckLogBit(LOG_TASK) || err.Fail()) - err.LogThreaded("::task_resume ( target_task = 0x%4.4x )", task); - } +kern_return_t MachTask::Resume() { + struct task_basic_info task_info; + task_t task = TaskPort(); + if (task == TASK_NULL) + return KERN_INVALID_ARGUMENT; + + DNBError err; + err = BasicInfo(task, &task_info); + + if (err.Success()) { + // task_resume isn't counted like task_suspend calls are, are, so if the + // task is not suspended, don't try and resume it since it is already + // running + if (task_info.suspend_count > 0) { + err = ::task_resume(task); + if (DNBLogCheckLogBit(LOG_TASK) || err.Fail()) + err.LogThreaded("::task_resume ( target_task = 0x%4.4x )", task); } - return err.Error(); + } + return err.Error(); } //---------------------------------------------------------------------- // MachTask::ExceptionPort //---------------------------------------------------------------------- -mach_port_t -MachTask::ExceptionPort() const -{ - return m_exception_port; -} +mach_port_t MachTask::ExceptionPort() const { return m_exception_port; } //---------------------------------------------------------------------- // MachTask::ExceptionPortIsValid //---------------------------------------------------------------------- -bool -MachTask::ExceptionPortIsValid() const -{ - return MACH_PORT_VALID(m_exception_port); +bool MachTask::ExceptionPortIsValid() const { + return MACH_PORT_VALID(m_exception_port); } - //---------------------------------------------------------------------- // MachTask::Clear //---------------------------------------------------------------------- -void -MachTask::Clear() -{ - // Do any cleanup needed for this task - m_task = TASK_NULL; - m_exception_thread = 0; - m_exception_port = MACH_PORT_NULL; - +void MachTask::Clear() { + // Do any cleanup needed for this task + m_task = TASK_NULL; + m_exception_thread = 0; + m_exception_port = MACH_PORT_NULL; } - //---------------------------------------------------------------------- // MachTask::SaveExceptionPortInfo //---------------------------------------------------------------------- -kern_return_t -MachTask::SaveExceptionPortInfo() -{ - return m_exc_port_info.Save(TaskPort()); +kern_return_t MachTask::SaveExceptionPortInfo() { + return m_exc_port_info.Save(TaskPort()); } //---------------------------------------------------------------------- // MachTask::RestoreExceptionPortInfo //---------------------------------------------------------------------- -kern_return_t -MachTask::RestoreExceptionPortInfo() -{ - return m_exc_port_info.Restore(TaskPort()); +kern_return_t MachTask::RestoreExceptionPortInfo() { + return m_exc_port_info.Restore(TaskPort()); } - //---------------------------------------------------------------------- // MachTask::ReadMemory //---------------------------------------------------------------------- -nub_size_t -MachTask::ReadMemory (nub_addr_t addr, nub_size_t size, void *buf) -{ - nub_size_t n = 0; - task_t task = TaskPort(); - if (task != TASK_NULL) - { - n = m_vm_memory.Read(task, addr, buf, size); - - DNBLogThreadedIf(LOG_MEMORY, "MachTask::ReadMemory ( addr = 0x%8.8llx, size = %llu, buf = %p) => %llu bytes read", (uint64_t)addr, (uint64_t)size, buf, (uint64_t)n); - if (DNBLogCheckLogBit(LOG_MEMORY_DATA_LONG) || (DNBLogCheckLogBit(LOG_MEMORY_DATA_SHORT) && size <= 8)) - { - DNBDataRef data((uint8_t*)buf, n, false); - data.Dump(0, static_cast<DNBDataRef::offset_t>(n), addr, DNBDataRef::TypeUInt8, 16); - } +nub_size_t MachTask::ReadMemory(nub_addr_t addr, nub_size_t size, void *buf) { + nub_size_t n = 0; + task_t task = TaskPort(); + if (task != TASK_NULL) { + n = m_vm_memory.Read(task, addr, buf, size); + + DNBLogThreadedIf(LOG_MEMORY, "MachTask::ReadMemory ( addr = 0x%8.8llx, " + "size = %llu, buf = %p) => %llu bytes read", + (uint64_t)addr, (uint64_t)size, buf, (uint64_t)n); + if (DNBLogCheckLogBit(LOG_MEMORY_DATA_LONG) || + (DNBLogCheckLogBit(LOG_MEMORY_DATA_SHORT) && size <= 8)) { + DNBDataRef data((uint8_t *)buf, n, false); + data.Dump(0, static_cast<DNBDataRef::offset_t>(n), addr, + DNBDataRef::TypeUInt8, 16); } - return n; + } + return n; } - //---------------------------------------------------------------------- // MachTask::WriteMemory //---------------------------------------------------------------------- -nub_size_t -MachTask::WriteMemory (nub_addr_t addr, nub_size_t size, const void *buf) -{ - nub_size_t n = 0; - task_t task = TaskPort(); - if (task != TASK_NULL) - { - n = m_vm_memory.Write(task, addr, buf, size); - DNBLogThreadedIf(LOG_MEMORY, "MachTask::WriteMemory ( addr = 0x%8.8llx, size = %llu, buf = %p) => %llu bytes written", (uint64_t)addr, (uint64_t)size, buf, (uint64_t)n); - if (DNBLogCheckLogBit(LOG_MEMORY_DATA_LONG) || (DNBLogCheckLogBit(LOG_MEMORY_DATA_SHORT) && size <= 8)) - { - DNBDataRef data((uint8_t*)buf, n, false); - data.Dump(0, static_cast<DNBDataRef::offset_t>(n), addr, DNBDataRef::TypeUInt8, 16); - } +nub_size_t MachTask::WriteMemory(nub_addr_t addr, nub_size_t size, + const void *buf) { + nub_size_t n = 0; + task_t task = TaskPort(); + if (task != TASK_NULL) { + n = m_vm_memory.Write(task, addr, buf, size); + DNBLogThreadedIf(LOG_MEMORY, "MachTask::WriteMemory ( addr = 0x%8.8llx, " + "size = %llu, buf = %p) => %llu bytes written", + (uint64_t)addr, (uint64_t)size, buf, (uint64_t)n); + if (DNBLogCheckLogBit(LOG_MEMORY_DATA_LONG) || + (DNBLogCheckLogBit(LOG_MEMORY_DATA_SHORT) && size <= 8)) { + DNBDataRef data((uint8_t *)buf, n, false); + data.Dump(0, static_cast<DNBDataRef::offset_t>(n), addr, + DNBDataRef::TypeUInt8, 16); } - return n; + } + return n; } //---------------------------------------------------------------------- // MachTask::MemoryRegionInfo //---------------------------------------------------------------------- -int -MachTask::GetMemoryRegionInfo (nub_addr_t addr, DNBRegionInfo *region_info) -{ - task_t task = TaskPort(); - if (task == TASK_NULL) - return -1; - - int ret = m_vm_memory.GetMemoryRegionInfo(task, addr, region_info); - DNBLogThreadedIf(LOG_MEMORY, "MachTask::MemoryRegionInfo ( addr = 0x%8.8llx ) => %i (start = 0x%8.8llx, size = 0x%8.8llx, permissions = %u)", - (uint64_t)addr, - ret, - (uint64_t)region_info->addr, - (uint64_t)region_info->size, - region_info->permissions); - return ret; +int MachTask::GetMemoryRegionInfo(nub_addr_t addr, DNBRegionInfo *region_info) { + task_t task = TaskPort(); + if (task == TASK_NULL) + return -1; + + int ret = m_vm_memory.GetMemoryRegionInfo(task, addr, region_info); + DNBLogThreadedIf(LOG_MEMORY, "MachTask::MemoryRegionInfo ( addr = 0x%8.8llx " + ") => %i (start = 0x%8.8llx, size = 0x%8.8llx, " + "permissions = %u)", + (uint64_t)addr, ret, (uint64_t)region_info->addr, + (uint64_t)region_info->size, region_info->permissions); + return ret; } -#define TIME_VALUE_TO_TIMEVAL(a, r) do { \ -(r)->tv_sec = (a)->seconds; \ -(r)->tv_usec = (a)->microseconds; \ -} while (0) +#define TIME_VALUE_TO_TIMEVAL(a, r) \ + do { \ + (r)->tv_sec = (a)->seconds; \ + (r)->tv_usec = (a)->microseconds; \ + } while (0) // We should consider moving this into each MacThread. -static void get_threads_profile_data(DNBProfileDataScanType scanType, task_t task, nub_process_t pid, std::vector<uint64_t> &threads_id, std::vector<std::string> &threads_name, std::vector<uint64_t> &threads_used_usec) -{ - kern_return_t kr; - thread_act_array_t threads; - mach_msg_type_number_t tcnt; - - kr = task_threads(task, &threads, &tcnt); +static void get_threads_profile_data(DNBProfileDataScanType scanType, + task_t task, nub_process_t pid, + std::vector<uint64_t> &threads_id, + std::vector<std::string> &threads_name, + std::vector<uint64_t> &threads_used_usec) { + kern_return_t kr; + thread_act_array_t threads; + mach_msg_type_number_t tcnt; + + kr = task_threads(task, &threads, &tcnt); + if (kr != KERN_SUCCESS) + return; + + for (mach_msg_type_number_t i = 0; i < tcnt; i++) { + thread_identifier_info_data_t identifier_info; + mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; + kr = ::thread_info(threads[i], THREAD_IDENTIFIER_INFO, + (thread_info_t)&identifier_info, &count); if (kr != KERN_SUCCESS) - return; - - for (mach_msg_type_number_t i = 0; i < tcnt; i++) - { - thread_identifier_info_data_t identifier_info; - mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; - kr = ::thread_info(threads[i], THREAD_IDENTIFIER_INFO, (thread_info_t)&identifier_info, &count); - if (kr != KERN_SUCCESS) continue; - - thread_basic_info_data_t basic_info; - count = THREAD_BASIC_INFO_COUNT; - kr = ::thread_info(threads[i], THREAD_BASIC_INFO, (thread_info_t)&basic_info, &count); - if (kr != KERN_SUCCESS) continue; - - if ((basic_info.flags & TH_FLAGS_IDLE) == 0) - { - nub_thread_t tid = MachThread::GetGloballyUniqueThreadIDForMachPortID (threads[i]); - threads_id.push_back(tid); - - if ((scanType & eProfileThreadName) && (identifier_info.thread_handle != 0)) - { - struct proc_threadinfo proc_threadinfo; - int len = ::proc_pidinfo(pid, PROC_PIDTHREADINFO, identifier_info.thread_handle, &proc_threadinfo, PROC_PIDTHREADINFO_SIZE); - if (len && proc_threadinfo.pth_name[0]) - { - threads_name.push_back(proc_threadinfo.pth_name); - } - else - { - threads_name.push_back(""); - } - } - else - { - threads_name.push_back(""); - } - struct timeval tv; - struct timeval thread_tv; - TIME_VALUE_TO_TIMEVAL(&basic_info.user_time, &thread_tv); - TIME_VALUE_TO_TIMEVAL(&basic_info.system_time, &tv); - timeradd(&thread_tv, &tv, &thread_tv); - uint64_t used_usec = thread_tv.tv_sec * 1000000ULL + thread_tv.tv_usec; - threads_used_usec.push_back(used_usec); + continue; + + thread_basic_info_data_t basic_info; + count = THREAD_BASIC_INFO_COUNT; + kr = ::thread_info(threads[i], THREAD_BASIC_INFO, + (thread_info_t)&basic_info, &count); + if (kr != KERN_SUCCESS) + continue; + + if ((basic_info.flags & TH_FLAGS_IDLE) == 0) { + nub_thread_t tid = + MachThread::GetGloballyUniqueThreadIDForMachPortID(threads[i]); + threads_id.push_back(tid); + + if ((scanType & eProfileThreadName) && + (identifier_info.thread_handle != 0)) { + struct proc_threadinfo proc_threadinfo; + int len = ::proc_pidinfo(pid, PROC_PIDTHREADINFO, + identifier_info.thread_handle, + &proc_threadinfo, PROC_PIDTHREADINFO_SIZE); + if (len && proc_threadinfo.pth_name[0]) { + threads_name.push_back(proc_threadinfo.pth_name); + } else { + threads_name.push_back(""); } - - mach_port_deallocate(mach_task_self(), threads[i]); + } else { + threads_name.push_back(""); + } + struct timeval tv; + struct timeval thread_tv; + TIME_VALUE_TO_TIMEVAL(&basic_info.user_time, &thread_tv); + TIME_VALUE_TO_TIMEVAL(&basic_info.system_time, &tv); + timeradd(&thread_tv, &tv, &thread_tv); + uint64_t used_usec = thread_tv.tv_sec * 1000000ULL + thread_tv.tv_usec; + threads_used_usec.push_back(used_usec); } - mach_vm_deallocate(mach_task_self(), (mach_vm_address_t)(uintptr_t)threads, tcnt * sizeof(*threads)); + + mach_port_deallocate(mach_task_self(), threads[i]); + } + mach_vm_deallocate(mach_task_self(), (mach_vm_address_t)(uintptr_t)threads, + tcnt * sizeof(*threads)); } -#define RAW_HEXBASE std::setfill('0') << std::hex << std::right -#define DECIMAL std::dec << std::setfill(' ') -std::string -MachTask::GetProfileData (DNBProfileDataScanType scanType) -{ - std::string result; - - static int32_t numCPU = -1; - struct host_cpu_load_info host_info; - if (scanType & eProfileHostCPU) - { - int32_t mib[] = {CTL_HW, HW_AVAILCPU}; - size_t len = sizeof(numCPU); - if (numCPU == -1) - { - if (sysctl(mib, sizeof(mib) / sizeof(int32_t), &numCPU, &len, NULL, 0) != 0) - return result; - } - - mach_port_t localHost = mach_host_self(); - mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT; - kern_return_t kr = host_statistics(localHost, HOST_CPU_LOAD_INFO, (host_info_t)&host_info, &count); - if (kr != KERN_SUCCESS) - return result; - } - - task_t task = TaskPort(); - if (task == TASK_NULL) +#define RAW_HEXBASE std::setfill('0') << std::hex << std::right +#define DECIMAL std::dec << std::setfill(' ') +std::string MachTask::GetProfileData(DNBProfileDataScanType scanType) { + std::string result; + + static int32_t numCPU = -1; + struct host_cpu_load_info host_info; + if (scanType & eProfileHostCPU) { + int32_t mib[] = {CTL_HW, HW_AVAILCPU}; + size_t len = sizeof(numCPU); + if (numCPU == -1) { + if (sysctl(mib, sizeof(mib) / sizeof(int32_t), &numCPU, &len, NULL, 0) != + 0) return result; - - pid_t pid = m_process->ProcessID(); - - struct task_basic_info task_info; - DNBError err; - err = BasicInfo(task, &task_info); - - if (!err.Success()) - return result; - - uint64_t elapsed_usec = 0; - uint64_t task_used_usec = 0; - if (scanType & eProfileCPU) - { - // Get current used time. - struct timeval current_used_time; - struct timeval tv; - TIME_VALUE_TO_TIMEVAL(&task_info.user_time, ¤t_used_time); - TIME_VALUE_TO_TIMEVAL(&task_info.system_time, &tv); - timeradd(¤t_used_time, &tv, ¤t_used_time); - task_used_usec = current_used_time.tv_sec * 1000000ULL + current_used_time.tv_usec; - - struct timeval current_elapsed_time; - int res = gettimeofday(¤t_elapsed_time, NULL); - if (res == 0) - { - elapsed_usec = current_elapsed_time.tv_sec * 1000000ULL + current_elapsed_time.tv_usec; - } } - - std::vector<uint64_t> threads_id; - std::vector<std::string> threads_name; - std::vector<uint64_t> threads_used_usec; - - if (scanType & eProfileThreadsCPU) - { - get_threads_profile_data(scanType, task, pid, threads_id, threads_name, threads_used_usec); + + mach_port_t localHost = mach_host_self(); + mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT; + kern_return_t kr = host_statistics(localHost, HOST_CPU_LOAD_INFO, + (host_info_t)&host_info, &count); + if (kr != KERN_SUCCESS) + return result; + } + + task_t task = TaskPort(); + if (task == TASK_NULL) + return result; + + pid_t pid = m_process->ProcessID(); + + struct task_basic_info task_info; + DNBError err; + err = BasicInfo(task, &task_info); + + if (!err.Success()) + return result; + + uint64_t elapsed_usec = 0; + uint64_t task_used_usec = 0; + if (scanType & eProfileCPU) { + // Get current used time. + struct timeval current_used_time; + struct timeval tv; + TIME_VALUE_TO_TIMEVAL(&task_info.user_time, ¤t_used_time); + TIME_VALUE_TO_TIMEVAL(&task_info.system_time, &tv); + timeradd(¤t_used_time, &tv, ¤t_used_time); + task_used_usec = + current_used_time.tv_sec * 1000000ULL + current_used_time.tv_usec; + + struct timeval current_elapsed_time; + int res = gettimeofday(¤t_elapsed_time, NULL); + if (res == 0) { + elapsed_usec = current_elapsed_time.tv_sec * 1000000ULL + + current_elapsed_time.tv_usec; } - -#if defined (HOST_VM_INFO64_COUNT) - vm_statistics64_data_t vminfo; + } + + std::vector<uint64_t> threads_id; + std::vector<std::string> threads_name; + std::vector<uint64_t> threads_used_usec; + + if (scanType & eProfileThreadsCPU) { + get_threads_profile_data(scanType, task, pid, threads_id, threads_name, + threads_used_usec); + } + +#if defined(HOST_VM_INFO64_COUNT) + vm_statistics64_data_t vminfo; #else - struct vm_statistics vminfo; + struct vm_statistics vminfo; #endif - uint64_t physical_memory; - mach_vm_size_t rprvt = 0; - mach_vm_size_t rsize = 0; - mach_vm_size_t vprvt = 0; - mach_vm_size_t vsize = 0; - mach_vm_size_t dirty_size = 0; - mach_vm_size_t purgeable = 0; - mach_vm_size_t anonymous = 0; - if (m_vm_memory.GetMemoryProfile(scanType, task, task_info, m_process->GetCPUType(), pid, vminfo, physical_memory, rprvt, rsize, vprvt, vsize, dirty_size, purgeable, anonymous)) - { - std::ostringstream profile_data_stream; - - if (scanType & eProfileHostCPU) - { - profile_data_stream << "num_cpu:" << numCPU << ';'; - profile_data_stream << "host_user_ticks:" << host_info.cpu_ticks[CPU_STATE_USER] << ';'; - profile_data_stream << "host_sys_ticks:" << host_info.cpu_ticks[CPU_STATE_SYSTEM] << ';'; - profile_data_stream << "host_idle_ticks:" << host_info.cpu_ticks[CPU_STATE_IDLE] << ';'; - } - - if (scanType & eProfileCPU) - { - profile_data_stream << "elapsed_usec:" << elapsed_usec << ';'; - profile_data_stream << "task_used_usec:" << task_used_usec << ';'; - } - - if (scanType & eProfileThreadsCPU) - { - const size_t num_threads = threads_id.size(); - for (size_t i=0; i<num_threads; i++) - { - profile_data_stream << "thread_used_id:" << std::hex << threads_id[i] << std::dec << ';'; - profile_data_stream << "thread_used_usec:" << threads_used_usec[i] << ';'; - - if (scanType & eProfileThreadName) - { - profile_data_stream << "thread_used_name:"; - const size_t len = threads_name[i].size(); - if (len) - { - const char *thread_name = threads_name[i].c_str(); - // Make sure that thread name doesn't interfere with our delimiter. - profile_data_stream << RAW_HEXBASE << std::setw(2); - const uint8_t *ubuf8 = (const uint8_t *)(thread_name); - for (size_t j=0; j<len; j++) - { - profile_data_stream << (uint32_t)(ubuf8[j]); - } - // Reset back to DECIMAL. - profile_data_stream << DECIMAL; - } - profile_data_stream << ';'; - } + uint64_t physical_memory; + mach_vm_size_t rprvt = 0; + mach_vm_size_t rsize = 0; + mach_vm_size_t vprvt = 0; + mach_vm_size_t vsize = 0; + mach_vm_size_t dirty_size = 0; + mach_vm_size_t purgeable = 0; + mach_vm_size_t anonymous = 0; + if (m_vm_memory.GetMemoryProfile(scanType, task, task_info, + m_process->GetCPUType(), pid, vminfo, + physical_memory, rprvt, rsize, vprvt, vsize, + dirty_size, purgeable, anonymous)) { + std::ostringstream profile_data_stream; + + if (scanType & eProfileHostCPU) { + profile_data_stream << "num_cpu:" << numCPU << ';'; + profile_data_stream << "host_user_ticks:" + << host_info.cpu_ticks[CPU_STATE_USER] << ';'; + profile_data_stream << "host_sys_ticks:" + << host_info.cpu_ticks[CPU_STATE_SYSTEM] << ';'; + profile_data_stream << "host_idle_ticks:" + << host_info.cpu_ticks[CPU_STATE_IDLE] << ';'; + } + + if (scanType & eProfileCPU) { + profile_data_stream << "elapsed_usec:" << elapsed_usec << ';'; + profile_data_stream << "task_used_usec:" << task_used_usec << ';'; + } + + if (scanType & eProfileThreadsCPU) { + const size_t num_threads = threads_id.size(); + for (size_t i = 0; i < num_threads; i++) { + profile_data_stream << "thread_used_id:" << std::hex << threads_id[i] + << std::dec << ';'; + profile_data_stream << "thread_used_usec:" << threads_used_usec[i] + << ';'; + + if (scanType & eProfileThreadName) { + profile_data_stream << "thread_used_name:"; + const size_t len = threads_name[i].size(); + if (len) { + const char *thread_name = threads_name[i].c_str(); + // Make sure that thread name doesn't interfere with our delimiter. + profile_data_stream << RAW_HEXBASE << std::setw(2); + const uint8_t *ubuf8 = (const uint8_t *)(thread_name); + for (size_t j = 0; j < len; j++) { + profile_data_stream << (uint32_t)(ubuf8[j]); } + // Reset back to DECIMAL. + profile_data_stream << DECIMAL; + } + profile_data_stream << ';'; } - - if (scanType & eProfileHostMemory) - profile_data_stream << "total:" << physical_memory << ';'; - - if (scanType & eProfileMemory) - { -#if defined (HOST_VM_INFO64_COUNT) && defined (_VM_PAGE_SIZE_H_) - static vm_size_t pagesize = vm_kernel_page_size; + } + } + + if (scanType & eProfileHostMemory) + profile_data_stream << "total:" << physical_memory << ';'; + + if (scanType & eProfileMemory) { +#if defined(HOST_VM_INFO64_COUNT) && defined(_VM_PAGE_SIZE_H_) + static vm_size_t pagesize = vm_kernel_page_size; #else - static vm_size_t pagesize; - static bool calculated = false; - if (!calculated) - { - calculated = true; - pagesize = PageSize(); - } + static vm_size_t pagesize; + static bool calculated = false; + if (!calculated) { + calculated = true; + pagesize = PageSize(); + } #endif - - /* Unused values. Optimized out for transfer performance. - profile_data_stream << "wired:" << vminfo.wire_count * pagesize << ';'; - profile_data_stream << "active:" << vminfo.active_count * pagesize << ';'; - profile_data_stream << "inactive:" << vminfo.inactive_count * pagesize << ';'; - */ -#if defined (HOST_VM_INFO64_COUNT) - // This mimicks Activity Monitor. - uint64_t total_used_count = (physical_memory / pagesize) - (vminfo.free_count - vminfo.speculative_count) - vminfo.external_page_count - vminfo.purgeable_count; + +/* Unused values. Optimized out for transfer performance. +profile_data_stream << "wired:" << vminfo.wire_count * pagesize << ';'; +profile_data_stream << "active:" << vminfo.active_count * pagesize << ';'; +profile_data_stream << "inactive:" << vminfo.inactive_count * pagesize << ';'; + */ +#if defined(HOST_VM_INFO64_COUNT) + // This mimicks Activity Monitor. + uint64_t total_used_count = + (physical_memory / pagesize) - + (vminfo.free_count - vminfo.speculative_count) - + vminfo.external_page_count - vminfo.purgeable_count; #else - uint64_t total_used_count = vminfo.wire_count + vminfo.inactive_count + vminfo.active_count; + uint64_t total_used_count = + vminfo.wire_count + vminfo.inactive_count + vminfo.active_count; #endif - profile_data_stream << "used:" << total_used_count * pagesize << ';'; - /* Unused values. Optimized out for transfer performance. - profile_data_stream << "free:" << vminfo.free_count * pagesize << ';'; - */ - - profile_data_stream << "rprvt:" << rprvt << ';'; - /* Unused values. Optimized out for transfer performance. - profile_data_stream << "rsize:" << rsize << ';'; - profile_data_stream << "vprvt:" << vprvt << ';'; - profile_data_stream << "vsize:" << vsize << ';'; - */ - - if (scanType & eProfileMemoryDirtyPage) - profile_data_stream << "dirty:" << dirty_size << ';'; - - if (scanType & eProfileMemoryAnonymous) - { - profile_data_stream << "purgeable:" << purgeable << ';'; - profile_data_stream << "anonymous:" << anonymous << ';'; - } - } - - // proc_pid_rusage pm_sample_task_and_pid pm_energy_impact needs to be tested for weakness in Cab + profile_data_stream << "used:" << total_used_count * pagesize << ';'; + /* Unused values. Optimized out for transfer performance. + profile_data_stream << "free:" << vminfo.free_count * pagesize << ';'; + */ + + profile_data_stream << "rprvt:" << rprvt << ';'; + /* Unused values. Optimized out for transfer performance. + profile_data_stream << "rsize:" << rsize << ';'; + profile_data_stream << "vprvt:" << vprvt << ';'; + profile_data_stream << "vsize:" << vsize << ';'; + */ + + if (scanType & eProfileMemoryDirtyPage) + profile_data_stream << "dirty:" << dirty_size << ';'; + + if (scanType & eProfileMemoryAnonymous) { + profile_data_stream << "purgeable:" << purgeable << ';'; + profile_data_stream << "anonymous:" << anonymous << ';'; + } + } + +// proc_pid_rusage pm_sample_task_and_pid pm_energy_impact needs to be tested +// for weakness in Cab #ifdef LLDB_ENERGY - if ((scanType & eProfileEnergy) && (pm_sample_task_and_pid != NULL)) - { - struct rusage_info_v2 info; - int rc = proc_pid_rusage(pid, RUSAGE_INFO_V2, (rusage_info_t *)&info); - if (rc == 0) - { - uint64_t now = mach_absolute_time(); - pm_task_energy_data_t pm_energy; - memset(&pm_energy, 0, sizeof(pm_energy)); - /* - * Disable most features of pm_sample_pid. It will gather - * network/GPU/WindowServer information; fill in the rest. - */ - pm_sample_task_and_pid(task, pid, &pm_energy, now, PM_SAMPLE_ALL & ~PM_SAMPLE_NAME & ~PM_SAMPLE_INTERVAL & ~PM_SAMPLE_CPU & ~PM_SAMPLE_DISK); - pm_energy.sti.total_user = info.ri_user_time; - pm_energy.sti.total_system = info.ri_system_time; - pm_energy.sti.task_interrupt_wakeups = info.ri_interrupt_wkups; - pm_energy.sti.task_platform_idle_wakeups = info.ri_pkg_idle_wkups; - pm_energy.diskio_bytesread = info.ri_diskio_bytesread; - pm_energy.diskio_byteswritten = info.ri_diskio_byteswritten; - pm_energy.pageins = info.ri_pageins; - - uint64_t total_energy = (uint64_t)(pm_energy_impact(&pm_energy) * NSEC_PER_SEC); - //uint64_t process_age = now - info.ri_proc_start_abstime; - //uint64_t avg_energy = 100.0 * (double)total_energy / (double)process_age; - - profile_data_stream << "energy:" << total_energy << ';'; - } - } -#endif - - profile_data_stream << "--end--;"; - - result = profile_data_stream.str(); + if ((scanType & eProfileEnergy) && (pm_sample_task_and_pid != NULL)) { + struct rusage_info_v2 info; + int rc = proc_pid_rusage(pid, RUSAGE_INFO_V2, (rusage_info_t *)&info); + if (rc == 0) { + uint64_t now = mach_absolute_time(); + pm_task_energy_data_t pm_energy; + memset(&pm_energy, 0, sizeof(pm_energy)); + /* + * Disable most features of pm_sample_pid. It will gather + * network/GPU/WindowServer information; fill in the rest. + */ + pm_sample_task_and_pid(task, pid, &pm_energy, now, + PM_SAMPLE_ALL & ~PM_SAMPLE_NAME & + ~PM_SAMPLE_INTERVAL & ~PM_SAMPLE_CPU & + ~PM_SAMPLE_DISK); + pm_energy.sti.total_user = info.ri_user_time; + pm_energy.sti.total_system = info.ri_system_time; + pm_energy.sti.task_interrupt_wakeups = info.ri_interrupt_wkups; + pm_energy.sti.task_platform_idle_wakeups = info.ri_pkg_idle_wkups; + pm_energy.diskio_bytesread = info.ri_diskio_bytesread; + pm_energy.diskio_byteswritten = info.ri_diskio_byteswritten; + pm_energy.pageins = info.ri_pageins; + + uint64_t total_energy = + (uint64_t)(pm_energy_impact(&pm_energy) * NSEC_PER_SEC); + // uint64_t process_age = now - info.ri_proc_start_abstime; + // uint64_t avg_energy = 100.0 * (double)total_energy / + // (double)process_age; + + profile_data_stream << "energy:" << total_energy << ';'; + } } - - return result; -} +#endif + + profile_data_stream << "--end--;"; + result = profile_data_stream.str(); + } + + return result; +} //---------------------------------------------------------------------- // MachTask::TaskPortForProcessID //---------------------------------------------------------------------- -task_t -MachTask::TaskPortForProcessID (DNBError &err, bool force) -{ - if (((m_task == TASK_NULL) || force) && m_process != NULL) - m_task = MachTask::TaskPortForProcessID(m_process->ProcessID(), err); - return m_task; +task_t MachTask::TaskPortForProcessID(DNBError &err, bool force) { + if (((m_task == TASK_NULL) || force) && m_process != NULL) + m_task = MachTask::TaskPortForProcessID(m_process->ProcessID(), err); + return m_task; } //---------------------------------------------------------------------- // MachTask::TaskPortForProcessID //---------------------------------------------------------------------- -task_t -MachTask::TaskPortForProcessID (pid_t pid, DNBError &err, uint32_t num_retries, uint32_t usec_interval) -{ - if (pid != INVALID_NUB_PROCESS) - { - DNBError err; - mach_port_t task_self = mach_task_self (); - task_t task = TASK_NULL; - for (uint32_t i=0; i<num_retries; i++) - { - err = ::task_for_pid ( task_self, pid, &task); - - if (DNBLogCheckLogBit(LOG_TASK) || err.Fail()) - { - char str[1024]; - ::snprintf (str, - sizeof(str), - "::task_for_pid ( target_tport = 0x%4.4x, pid = %d, &task ) => err = 0x%8.8x (%s)", - task_self, - pid, - err.Error(), - err.AsString() ? err.AsString() : "success"); - if (err.Fail()) - err.SetErrorString(str); - err.LogThreaded(str); - } +task_t MachTask::TaskPortForProcessID(pid_t pid, DNBError &err, + uint32_t num_retries, + uint32_t usec_interval) { + if (pid != INVALID_NUB_PROCESS) { + DNBError err; + mach_port_t task_self = mach_task_self(); + task_t task = TASK_NULL; + for (uint32_t i = 0; i < num_retries; i++) { + err = ::task_for_pid(task_self, pid, &task); + + if (DNBLogCheckLogBit(LOG_TASK) || err.Fail()) { + char str[1024]; + ::snprintf(str, sizeof(str), "::task_for_pid ( target_tport = 0x%4.4x, " + "pid = %d, &task ) => err = 0x%8.8x (%s)", + task_self, pid, err.Error(), + err.AsString() ? err.AsString() : "success"); + if (err.Fail()) + err.SetErrorString(str); + err.LogThreaded(str); + } - if (err.Success()) - return task; + if (err.Success()) + return task; - // Sleep a bit and try again - ::usleep (usec_interval); - } + // Sleep a bit and try again + ::usleep(usec_interval); } - return TASK_NULL; + } + return TASK_NULL; } - //---------------------------------------------------------------------- // MachTask::BasicInfo //---------------------------------------------------------------------- -kern_return_t -MachTask::BasicInfo(struct task_basic_info *info) -{ - return BasicInfo (TaskPort(), info); +kern_return_t MachTask::BasicInfo(struct task_basic_info *info) { + return BasicInfo(TaskPort(), info); } //---------------------------------------------------------------------- // MachTask::BasicInfo //---------------------------------------------------------------------- -kern_return_t -MachTask::BasicInfo(task_t task, struct task_basic_info *info) -{ - if (info == NULL) - return KERN_INVALID_ARGUMENT; - - DNBError err; - mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT; - err = ::task_info (task, TASK_BASIC_INFO, (task_info_t)info, &count); - const bool log_process = DNBLogCheckLogBit(LOG_TASK); - if (log_process || err.Fail()) - err.LogThreaded("::task_info ( target_task = 0x%4.4x, flavor = TASK_BASIC_INFO, task_info_out => %p, task_info_outCnt => %u )", task, info, count); - if (DNBLogCheckLogBit(LOG_TASK) && DNBLogCheckLogBit(LOG_VERBOSE) && err.Success()) - { - float user = (float)info->user_time.seconds + (float)info->user_time.microseconds / 1000000.0f; - float system = (float)info->user_time.seconds + (float)info->user_time.microseconds / 1000000.0f; - DNBLogThreaded ("task_basic_info = { suspend_count = %i, virtual_size = 0x%8.8llx, resident_size = 0x%8.8llx, user_time = %f, system_time = %f }", - info->suspend_count, - (uint64_t)info->virtual_size, - (uint64_t)info->resident_size, - user, - system); - } - return err.Error(); +kern_return_t MachTask::BasicInfo(task_t task, struct task_basic_info *info) { + if (info == NULL) + return KERN_INVALID_ARGUMENT; + + DNBError err; + mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT; + err = ::task_info(task, TASK_BASIC_INFO, (task_info_t)info, &count); + const bool log_process = DNBLogCheckLogBit(LOG_TASK); + if (log_process || err.Fail()) + err.LogThreaded("::task_info ( target_task = 0x%4.4x, flavor = " + "TASK_BASIC_INFO, task_info_out => %p, task_info_outCnt => " + "%u )", + task, info, count); + if (DNBLogCheckLogBit(LOG_TASK) && DNBLogCheckLogBit(LOG_VERBOSE) && + err.Success()) { + float user = (float)info->user_time.seconds + + (float)info->user_time.microseconds / 1000000.0f; + float system = (float)info->user_time.seconds + + (float)info->user_time.microseconds / 1000000.0f; + DNBLogThreaded("task_basic_info = { suspend_count = %i, virtual_size = " + "0x%8.8llx, resident_size = 0x%8.8llx, user_time = %f, " + "system_time = %f }", + info->suspend_count, (uint64_t)info->virtual_size, + (uint64_t)info->resident_size, user, system); + } + return err.Error(); } - //---------------------------------------------------------------------- // MachTask::IsValid // // Returns true if a task is a valid task port for a current process. //---------------------------------------------------------------------- -bool -MachTask::IsValid () const -{ - return MachTask::IsValid(TaskPort()); -} +bool MachTask::IsValid() const { return MachTask::IsValid(TaskPort()); } //---------------------------------------------------------------------- // MachTask::IsValid // // Returns true if a task is a valid task port for a current process. //---------------------------------------------------------------------- -bool -MachTask::IsValid (task_t task) -{ - if (task != TASK_NULL) - { - struct task_basic_info task_info; - return BasicInfo(task, &task_info) == KERN_SUCCESS; - } - return false; +bool MachTask::IsValid(task_t task) { + if (task != TASK_NULL) { + struct task_basic_info task_info; + return BasicInfo(task, &task_info) == KERN_SUCCESS; + } + return false; } - -bool -MachTask::StartExceptionThread(DNBError &err) -{ - DNBLogThreadedIf(LOG_EXCEPTIONS, "MachTask::%s ( )", __FUNCTION__); - - task_t task = TaskPortForProcessID(err); - if (MachTask::IsValid(task)) - { - // Got the mach port for the current process - mach_port_t task_self = mach_task_self (); - - // Allocate an exception port that we will use to track our child process - err = ::mach_port_allocate (task_self, MACH_PORT_RIGHT_RECEIVE, &m_exception_port); - if (err.Fail()) - return false; - - // Add the ability to send messages on the new exception port - err = ::mach_port_insert_right (task_self, m_exception_port, m_exception_port, MACH_MSG_TYPE_MAKE_SEND); - if (err.Fail()) - return false; - - // Save the original state of the exception ports for our child process - SaveExceptionPortInfo(); - - // We weren't able to save the info for our exception ports, we must stop... - if (m_exc_port_info.mask == 0) - { - err.SetErrorString("failed to get exception port info"); - return false; - } - - // Set the ability to get all exceptions on this port - err = ::task_set_exception_ports (task, m_exc_port_info.mask, m_exception_port, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE); - if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail()) - { - err.LogThreaded("::task_set_exception_ports ( task = 0x%4.4x, exception_mask = 0x%8.8x, new_port = 0x%4.4x, behavior = 0x%8.8x, new_flavor = 0x%8.8x )", - task, - m_exc_port_info.mask, - m_exception_port, - (EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES), - THREAD_STATE_NONE); - } - - if (err.Fail()) - return false; - - // Create the exception thread - err = ::pthread_create (&m_exception_thread, NULL, MachTask::ExceptionThread, this); - return err.Success(); +bool MachTask::StartExceptionThread(DNBError &err) { + DNBLogThreadedIf(LOG_EXCEPTIONS, "MachTask::%s ( )", __FUNCTION__); + + task_t task = TaskPortForProcessID(err); + if (MachTask::IsValid(task)) { + // Got the mach port for the current process + mach_port_t task_self = mach_task_self(); + + // Allocate an exception port that we will use to track our child process + err = ::mach_port_allocate(task_self, MACH_PORT_RIGHT_RECEIVE, + &m_exception_port); + if (err.Fail()) + return false; + + // Add the ability to send messages on the new exception port + err = ::mach_port_insert_right(task_self, m_exception_port, + m_exception_port, MACH_MSG_TYPE_MAKE_SEND); + if (err.Fail()) + return false; + + // Save the original state of the exception ports for our child process + SaveExceptionPortInfo(); + + // We weren't able to save the info for our exception ports, we must stop... + if (m_exc_port_info.mask == 0) { + err.SetErrorString("failed to get exception port info"); + return false; } - else - { - DNBLogError("MachTask::%s (): task invalid, exception thread start failed.", __FUNCTION__); + + // Set the ability to get all exceptions on this port + err = ::task_set_exception_ports( + task, m_exc_port_info.mask, m_exception_port, + EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE); + if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail()) { + err.LogThreaded("::task_set_exception_ports ( task = 0x%4.4x, " + "exception_mask = 0x%8.8x, new_port = 0x%4.4x, behavior " + "= 0x%8.8x, new_flavor = 0x%8.8x )", + task, m_exc_port_info.mask, m_exception_port, + (EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES), + THREAD_STATE_NONE); } - return false; + + if (err.Fail()) + return false; + + // Create the exception thread + err = ::pthread_create(&m_exception_thread, NULL, MachTask::ExceptionThread, + this); + return err.Success(); + } else { + DNBLogError("MachTask::%s (): task invalid, exception thread start failed.", + __FUNCTION__); + } + return false; } -kern_return_t -MachTask::ShutDownExcecptionThread() -{ - DNBError err; +kern_return_t MachTask::ShutDownExcecptionThread() { + DNBError err; - err = RestoreExceptionPortInfo(); + err = RestoreExceptionPortInfo(); - // NULL our our exception port and let our exception thread exit - mach_port_t exception_port = m_exception_port; - m_exception_port = 0; + // NULL our our exception port and let our exception thread exit + mach_port_t exception_port = m_exception_port; + m_exception_port = 0; - err.SetError(::pthread_cancel(m_exception_thread), DNBError::POSIX); - if (DNBLogCheckLogBit(LOG_TASK) || err.Fail()) - err.LogThreaded("::pthread_cancel ( thread = %p )", m_exception_thread); + err.SetError(::pthread_cancel(m_exception_thread), DNBError::POSIX); + if (DNBLogCheckLogBit(LOG_TASK) || err.Fail()) + err.LogThreaded("::pthread_cancel ( thread = %p )", m_exception_thread); - err.SetError(::pthread_join(m_exception_thread, NULL), DNBError::POSIX); - if (DNBLogCheckLogBit(LOG_TASK) || err.Fail()) - err.LogThreaded("::pthread_join ( thread = %p, value_ptr = NULL)", m_exception_thread); + err.SetError(::pthread_join(m_exception_thread, NULL), DNBError::POSIX); + if (DNBLogCheckLogBit(LOG_TASK) || err.Fail()) + err.LogThreaded("::pthread_join ( thread = %p, value_ptr = NULL)", + m_exception_thread); - // Deallocate our exception port that we used to track our child process - mach_port_t task_self = mach_task_self (); - err = ::mach_port_deallocate (task_self, exception_port); - if (DNBLogCheckLogBit(LOG_TASK) || err.Fail()) - err.LogThreaded("::mach_port_deallocate ( task = 0x%4.4x, name = 0x%4.4x )", task_self, exception_port); + // Deallocate our exception port that we used to track our child process + mach_port_t task_self = mach_task_self(); + err = ::mach_port_deallocate(task_self, exception_port); + if (DNBLogCheckLogBit(LOG_TASK) || err.Fail()) + err.LogThreaded("::mach_port_deallocate ( task = 0x%4.4x, name = 0x%4.4x )", + task_self, exception_port); - return err.Error(); + return err.Error(); } +void *MachTask::ExceptionThread(void *arg) { + if (arg == NULL) + return NULL; -void * -MachTask::ExceptionThread (void *arg) -{ - if (arg == NULL) - return NULL; - - MachTask *mach_task = (MachTask*) arg; - MachProcess *mach_proc = mach_task->Process(); - DNBLogThreadedIf(LOG_EXCEPTIONS, "MachTask::%s ( arg = %p ) starting thread...", __FUNCTION__, arg); - -#if defined (__APPLE__) - pthread_setname_np ("exception monitoring 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); - } + MachTask *mach_task = (MachTask *)arg; + MachProcess *mach_proc = mach_task->Process(); + DNBLogThreadedIf(LOG_EXCEPTIONS, + "MachTask::%s ( arg = %p ) starting thread...", __FUNCTION__, + arg); + +#if defined(__APPLE__) + pthread_setname_np("exception monitoring 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 - // We keep a count of the number of consecutive exceptions received so - // we know to grab all exceptions without a timeout. We do this to get a - // bunch of related exceptions on our exception port so we can process - // then together. When we have multiple threads, we can get an exception - // per thread and they will come in consecutively. The main loop in this - // thread can stop periodically if needed to service things related to this - // process. - // flag set in the options, so we will wait forever for an exception on - // our exception port. After we get one exception, we then will use the - // MACH_RCV_TIMEOUT option with a zero timeout to grab all other current - // exceptions for our process. After we have received the last pending - // exception, we will get a timeout which enables us to then notify - // our main thread that we have an exception bundle available. We then wait - // for the main thread to tell this exception thread to start trying to get - // exceptions messages again and we start again with a mach_msg read with - // infinite timeout. - uint32_t num_exceptions_received = 0; - DNBError err; - task_t task = mach_task->TaskPort(); - mach_msg_timeout_t periodic_timeout = 0; - -#if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS) - mach_msg_timeout_t watchdog_elapsed = 0; - mach_msg_timeout_t watchdog_timeout = 60 * 1000; - pid_t pid = mach_proc->ProcessID(); - CFReleaser<SBSWatchdogAssertionRef> watchdog; - - if (mach_proc->ProcessUsingSpringBoard()) - { - // Request a renewal for every 60 seconds if we attached using SpringBoard - watchdog.reset(::SBSWatchdogAssertionCreateForPID(NULL, pid, 60)); - DNBLogThreadedIf(LOG_TASK, "::SBSWatchdogAssertionCreateForPID (NULL, %4.4x, 60 ) => %p", pid, watchdog.get()); - - if (watchdog.get()) - { - ::SBSWatchdogAssertionRenew (watchdog.get()); - - CFTimeInterval watchdogRenewalInterval = ::SBSWatchdogAssertionGetRenewalInterval (watchdog.get()); - DNBLogThreadedIf(LOG_TASK, "::SBSWatchdogAssertionGetRenewalInterval ( %p ) => %g seconds", watchdog.get(), watchdogRenewalInterval); - if (watchdogRenewalInterval > 0.0) - { - watchdog_timeout = (mach_msg_timeout_t)watchdogRenewalInterval * 1000; - if (watchdog_timeout > 3000) - watchdog_timeout -= 1000; // Give us a second to renew our timeout - else if (watchdog_timeout > 1000) - watchdog_timeout -= 250; // Give us a quarter of a second to renew our timeout - } - } - if (periodic_timeout == 0 || periodic_timeout > watchdog_timeout) - periodic_timeout = watchdog_timeout; + // We keep a count of the number of consecutive exceptions received so + // we know to grab all exceptions without a timeout. We do this to get a + // bunch of related exceptions on our exception port so we can process + // then together. When we have multiple threads, we can get an exception + // per thread and they will come in consecutively. The main loop in this + // thread can stop periodically if needed to service things related to this + // process. + // flag set in the options, so we will wait forever for an exception on + // our exception port. After we get one exception, we then will use the + // MACH_RCV_TIMEOUT option with a zero timeout to grab all other current + // exceptions for our process. After we have received the last pending + // exception, we will get a timeout which enables us to then notify + // our main thread that we have an exception bundle available. We then wait + // for the main thread to tell this exception thread to start trying to get + // exceptions messages again and we start again with a mach_msg read with + // infinite timeout. + uint32_t num_exceptions_received = 0; + DNBError err; + task_t task = mach_task->TaskPort(); + mach_msg_timeout_t periodic_timeout = 0; + +#if defined(WITH_SPRINGBOARD) && !defined(WITH_BKS) + mach_msg_timeout_t watchdog_elapsed = 0; + mach_msg_timeout_t watchdog_timeout = 60 * 1000; + pid_t pid = mach_proc->ProcessID(); + CFReleaser<SBSWatchdogAssertionRef> watchdog; + + if (mach_proc->ProcessUsingSpringBoard()) { + // Request a renewal for every 60 seconds if we attached using SpringBoard + watchdog.reset(::SBSWatchdogAssertionCreateForPID(NULL, pid, 60)); + DNBLogThreadedIf( + LOG_TASK, "::SBSWatchdogAssertionCreateForPID (NULL, %4.4x, 60 ) => %p", + pid, watchdog.get()); + + if (watchdog.get()) { + ::SBSWatchdogAssertionRenew(watchdog.get()); + + CFTimeInterval watchdogRenewalInterval = + ::SBSWatchdogAssertionGetRenewalInterval(watchdog.get()); + DNBLogThreadedIf( + LOG_TASK, + "::SBSWatchdogAssertionGetRenewalInterval ( %p ) => %g seconds", + watchdog.get(), watchdogRenewalInterval); + if (watchdogRenewalInterval > 0.0) { + watchdog_timeout = (mach_msg_timeout_t)watchdogRenewalInterval * 1000; + if (watchdog_timeout > 3000) + watchdog_timeout -= 1000; // Give us a second to renew our timeout + else if (watchdog_timeout > 1000) + watchdog_timeout -= + 250; // Give us a quarter of a second to renew our timeout + } } -#endif // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS) + if (periodic_timeout == 0 || periodic_timeout > watchdog_timeout) + periodic_timeout = watchdog_timeout; + } +#endif // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS) #ifdef WITH_BKS - CFReleaser<BKSWatchdogAssertionRef> watchdog; - if (mach_proc->ProcessUsingBackBoard()) - { - pid_t pid = mach_proc->ProcessID(); - CFAllocatorRef alloc = kCFAllocatorDefault; - watchdog.reset(::BKSWatchdogAssertionCreateForPID(alloc, pid)); - } + CFReleaser<BKSWatchdogAssertionRef> watchdog; + if (mach_proc->ProcessUsingBackBoard()) { + pid_t pid = mach_proc->ProcessID(); + CFAllocatorRef alloc = kCFAllocatorDefault; + watchdog.reset(::BKSWatchdogAssertionCreateForPID(alloc, pid)); + } #endif // #ifdef WITH_BKS - while (mach_task->ExceptionPortIsValid()) - { - ::pthread_testcancel (); - - MachException::Message exception_message; - + while (mach_task->ExceptionPortIsValid()) { + ::pthread_testcancel(); + + MachException::Message exception_message; + + if (num_exceptions_received > 0) { + // No timeout, just receive as many exceptions as we can since we already + // have one and we want + // to get all currently available exceptions for this task + err = exception_message.Receive( + mach_task->ExceptionPort(), + MACH_RCV_MSG | MACH_RCV_INTERRUPT | MACH_RCV_TIMEOUT, 0); + } else if (periodic_timeout > 0) { + // We need to stop periodically in this loop, so try and get a mach + // message with a valid timeout (ms) + err = exception_message.Receive(mach_task->ExceptionPort(), + MACH_RCV_MSG | MACH_RCV_INTERRUPT | + MACH_RCV_TIMEOUT, + periodic_timeout); + } else { + // We don't need to parse all current exceptions or stop periodically, + // just wait for an exception forever. + err = exception_message.Receive(mach_task->ExceptionPort(), + MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0); + } - if (num_exceptions_received > 0) - { - // No timeout, just receive as many exceptions as we can since we already have one and we want - // to get all currently available exceptions for this task - err = exception_message.Receive(mach_task->ExceptionPort(), MACH_RCV_MSG | MACH_RCV_INTERRUPT | MACH_RCV_TIMEOUT, 0); - } - else if (periodic_timeout > 0) - { - // We need to stop periodically in this loop, so try and get a mach message with a valid timeout (ms) - err = exception_message.Receive(mach_task->ExceptionPort(), MACH_RCV_MSG | MACH_RCV_INTERRUPT | MACH_RCV_TIMEOUT, periodic_timeout); - } - else - { - // We don't need to parse all current exceptions or stop periodically, - // just wait for an exception forever. - err = exception_message.Receive(mach_task->ExceptionPort(), MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0); + if (err.Error() == MACH_RCV_INTERRUPTED) { + // If we have no task port we should exit this thread + if (!mach_task->ExceptionPortIsValid()) { + DNBLogThreadedIf(LOG_EXCEPTIONS, "thread cancelled..."); + break; + } + + // Make sure our task is still valid + if (MachTask::IsValid(task)) { + // Task is still ok + DNBLogThreadedIf(LOG_EXCEPTIONS, + "interrupted, but task still valid, continuing..."); + continue; + } else { + DNBLogThreadedIf(LOG_EXCEPTIONS, "task has exited..."); + mach_proc->SetState(eStateExited); + // Our task has died, exit the thread. + break; + } + } else if (err.Error() == MACH_RCV_TIMED_OUT) { + if (num_exceptions_received > 0) { + // We were receiving all current exceptions with a timeout of zero + // it is time to go back to our normal looping mode + num_exceptions_received = 0; + + // Notify our main thread we have a complete exception message + // bundle available and get the possibly updated task port back + // from the process in case we exec'ed and our task port changed + task = mach_proc->ExceptionMessageBundleComplete(); + + // in case we use a timeout value when getting exceptions... + // Make sure our task is still valid + if (MachTask::IsValid(task)) { + // Task is still ok + DNBLogThreadedIf(LOG_EXCEPTIONS, "got a timeout, continuing..."); + continue; + } else { + DNBLogThreadedIf(LOG_EXCEPTIONS, "task has exited..."); + mach_proc->SetState(eStateExited); + // Our task has died, exit the thread. + break; } - - if (err.Error() == MACH_RCV_INTERRUPTED) - { - // If we have no task port we should exit this thread - if (!mach_task->ExceptionPortIsValid()) - { - DNBLogThreadedIf(LOG_EXCEPTIONS, "thread cancelled..."); - break; - } - - // Make sure our task is still valid - if (MachTask::IsValid(task)) - { - // Task is still ok - DNBLogThreadedIf(LOG_EXCEPTIONS, "interrupted, but task still valid, continuing..."); - continue; - } - else - { - DNBLogThreadedIf(LOG_EXCEPTIONS, "task has exited..."); - mach_proc->SetState(eStateExited); - // Our task has died, exit the thread. - break; - } + } + +#if defined(WITH_SPRINGBOARD) && !defined(WITH_BKS) + if (watchdog.get()) { + watchdog_elapsed += periodic_timeout; + if (watchdog_elapsed >= watchdog_timeout) { + DNBLogThreadedIf(LOG_TASK, "SBSWatchdogAssertionRenew ( %p )", + watchdog.get()); + ::SBSWatchdogAssertionRenew(watchdog.get()); + watchdog_elapsed = 0; } - else if (err.Error() == MACH_RCV_TIMED_OUT) - { - if (num_exceptions_received > 0) - { - // We were receiving all current exceptions with a timeout of zero - // it is time to go back to our normal looping mode - num_exceptions_received = 0; - - // Notify our main thread we have a complete exception message - // bundle available and get the possibly updated task port back - // from the process in case we exec'ed and our task port changed - task = mach_proc->ExceptionMessageBundleComplete(); - - // in case we use a timeout value when getting exceptions... - // Make sure our task is still valid - if (MachTask::IsValid(task)) - { - // Task is still ok - DNBLogThreadedIf(LOG_EXCEPTIONS, "got a timeout, continuing..."); - continue; - } - else - { - DNBLogThreadedIf(LOG_EXCEPTIONS, "task has exited..."); - mach_proc->SetState(eStateExited); - // Our task has died, exit the thread. - break; - } - } - -#if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS) - if (watchdog.get()) - { - watchdog_elapsed += periodic_timeout; - if (watchdog_elapsed >= watchdog_timeout) - { - DNBLogThreadedIf(LOG_TASK, "SBSWatchdogAssertionRenew ( %p )", watchdog.get()); - ::SBSWatchdogAssertionRenew (watchdog.get()); - watchdog_elapsed = 0; - } - } + } #endif - } - else if (err.Error() != KERN_SUCCESS) - { - DNBLogThreadedIf(LOG_EXCEPTIONS, "got some other error, do something about it??? nah, continuing for now..."); - // TODO: notify of error? - } - else - { - if (exception_message.CatchExceptionRaise(task)) - { - ++num_exceptions_received; - mach_proc->ExceptionMessageReceived(exception_message); - } - } + } else if (err.Error() != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_EXCEPTIONS, "got some other error, do something " + "about it??? nah, continuing for " + "now..."); + // TODO: notify of error? + } else { + if (exception_message.CatchExceptionRaise(task)) { + ++num_exceptions_received; + mach_proc->ExceptionMessageReceived(exception_message); + } } - -#if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS) - if (watchdog.get()) - { - // TODO: change SBSWatchdogAssertionRelease to SBSWatchdogAssertionCancel when we - // all are up and running on systems that support it. The SBS framework has a #define - // that will forward SBSWatchdogAssertionRelease to SBSWatchdogAssertionCancel for now - // so it should still build either way. - DNBLogThreadedIf(LOG_TASK, "::SBSWatchdogAssertionRelease(%p)", watchdog.get()); - ::SBSWatchdogAssertionRelease (watchdog.get()); - } -#endif // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS) - - DNBLogThreadedIf(LOG_EXCEPTIONS, "MachTask::%s (%p): thread exiting...", __FUNCTION__, arg); - return NULL; + } + +#if defined(WITH_SPRINGBOARD) && !defined(WITH_BKS) + if (watchdog.get()) { + // TODO: change SBSWatchdogAssertionRelease to SBSWatchdogAssertionCancel + // when we + // all are up and running on systems that support it. The SBS framework has + // a #define + // that will forward SBSWatchdogAssertionRelease to + // SBSWatchdogAssertionCancel for now + // so it should still build either way. + DNBLogThreadedIf(LOG_TASK, "::SBSWatchdogAssertionRelease(%p)", + watchdog.get()); + ::SBSWatchdogAssertionRelease(watchdog.get()); + } +#endif // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS) + + DNBLogThreadedIf(LOG_EXCEPTIONS, "MachTask::%s (%p): thread exiting...", + __FUNCTION__, arg); + return NULL; } - // So the TASK_DYLD_INFO used to just return the address of the all image infos // as a single member called "all_image_info". Then someone decided it would be // a good idea to rename this first member to "all_image_info_addr" and add a // size member called "all_image_info_size". This of course can not be detected // using code or #defines. So to hack around this problem, we define our own -// version of the TASK_DYLD_INFO structure so we can guarantee what is inside it. +// version of the TASK_DYLD_INFO structure so we can guarantee what is inside +// it. struct hack_task_dyld_info { - mach_vm_address_t all_image_info_addr; - mach_vm_size_t all_image_info_size; + mach_vm_address_t all_image_info_addr; + mach_vm_size_t all_image_info_size; }; -nub_addr_t -MachTask::GetDYLDAllImageInfosAddress (DNBError& err) -{ - struct hack_task_dyld_info dyld_info; - mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; - // Make sure that COUNT isn't bigger than our hacked up struct hack_task_dyld_info. - // If it is, then make COUNT smaller to match. - if (count > (sizeof(struct hack_task_dyld_info) / sizeof(natural_t))) - count = (sizeof(struct hack_task_dyld_info) / sizeof(natural_t)); - - task_t task = TaskPortForProcessID (err); - if (err.Success()) - { - err = ::task_info (task, TASK_DYLD_INFO, (task_info_t)&dyld_info, &count); - if (err.Success()) - { - // We now have the address of the all image infos structure - return dyld_info.all_image_info_addr; - } +nub_addr_t MachTask::GetDYLDAllImageInfosAddress(DNBError &err) { + struct hack_task_dyld_info dyld_info; + mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; + // Make sure that COUNT isn't bigger than our hacked up struct + // hack_task_dyld_info. + // If it is, then make COUNT smaller to match. + if (count > (sizeof(struct hack_task_dyld_info) / sizeof(natural_t))) + count = (sizeof(struct hack_task_dyld_info) / sizeof(natural_t)); + + task_t task = TaskPortForProcessID(err); + if (err.Success()) { + err = ::task_info(task, TASK_DYLD_INFO, (task_info_t)&dyld_info, &count); + if (err.Success()) { + // We now have the address of the all image infos structure + return dyld_info.all_image_info_addr; } - return INVALID_NUB_ADDRESS; + } + return INVALID_NUB_ADDRESS; } - //---------------------------------------------------------------------- // MachTask::AllocateMemory //---------------------------------------------------------------------- -nub_addr_t -MachTask::AllocateMemory (size_t size, uint32_t permissions) -{ - mach_vm_address_t addr; - task_t task = TaskPort(); - if (task == TASK_NULL) - return INVALID_NUB_ADDRESS; +nub_addr_t MachTask::AllocateMemory(size_t size, uint32_t permissions) { + mach_vm_address_t addr; + task_t task = TaskPort(); + if (task == TASK_NULL) + return INVALID_NUB_ADDRESS; - DNBError err; - err = ::mach_vm_allocate (task, &addr, size, TRUE); - if (err.Error() == KERN_SUCCESS) - { - // Set the protections: - vm_prot_t mach_prot = VM_PROT_NONE; - if (permissions & eMemoryPermissionsReadable) - mach_prot |= VM_PROT_READ; - if (permissions & eMemoryPermissionsWritable) - mach_prot |= VM_PROT_WRITE; - if (permissions & eMemoryPermissionsExecutable) - mach_prot |= VM_PROT_EXECUTE; - - - err = ::mach_vm_protect (task, addr, size, 0, mach_prot); - if (err.Error() == KERN_SUCCESS) - { - m_allocations.insert (std::make_pair(addr, size)); - return addr; - } - ::mach_vm_deallocate (task, addr, size); + DNBError err; + err = ::mach_vm_allocate(task, &addr, size, TRUE); + if (err.Error() == KERN_SUCCESS) { + // Set the protections: + vm_prot_t mach_prot = VM_PROT_NONE; + if (permissions & eMemoryPermissionsReadable) + mach_prot |= VM_PROT_READ; + if (permissions & eMemoryPermissionsWritable) + mach_prot |= VM_PROT_WRITE; + if (permissions & eMemoryPermissionsExecutable) + mach_prot |= VM_PROT_EXECUTE; + + err = ::mach_vm_protect(task, addr, size, 0, mach_prot); + if (err.Error() == KERN_SUCCESS) { + m_allocations.insert(std::make_pair(addr, size)); + return addr; } - return INVALID_NUB_ADDRESS; + ::mach_vm_deallocate(task, addr, size); + } + return INVALID_NUB_ADDRESS; } //---------------------------------------------------------------------- // MachTask::DeallocateMemory //---------------------------------------------------------------------- -nub_bool_t -MachTask::DeallocateMemory (nub_addr_t addr) -{ - task_t task = TaskPort(); - if (task == TASK_NULL) - return false; - - // We have to stash away sizes for the allocations... - allocation_collection::iterator pos, end = m_allocations.end(); - for (pos = m_allocations.begin(); pos != end; pos++) - { - if ((*pos).first == addr) - { - m_allocations.erase(pos); +nub_bool_t MachTask::DeallocateMemory(nub_addr_t addr) { + task_t task = TaskPort(); + if (task == TASK_NULL) + return false; + + // We have to stash away sizes for the allocations... + allocation_collection::iterator pos, end = m_allocations.end(); + for (pos = m_allocations.begin(); pos != end; pos++) { + if ((*pos).first == addr) { + m_allocations.erase(pos); #define ALWAYS_ZOMBIE_ALLOCATIONS 0 - if (ALWAYS_ZOMBIE_ALLOCATIONS || getenv ("DEBUGSERVER_ZOMBIE_ALLOCATIONS")) - { - ::mach_vm_protect (task, (*pos).first, (*pos).second, 0, VM_PROT_NONE); - return true; - } - else - return ::mach_vm_deallocate (task, (*pos).first, (*pos).second) == KERN_SUCCESS; - } - + if (ALWAYS_ZOMBIE_ALLOCATIONS || + getenv("DEBUGSERVER_ZOMBIE_ALLOCATIONS")) { + ::mach_vm_protect(task, (*pos).first, (*pos).second, 0, VM_PROT_NONE); + return true; + } else + return ::mach_vm_deallocate(task, (*pos).first, (*pos).second) == + KERN_SUCCESS; } - return false; + } + return false; } -nub_size_t -MachTask::PageSize () -{ - return m_vm_memory.PageSize (m_task); -} +nub_size_t MachTask::PageSize() { return m_vm_memory.PageSize(m_task); } diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp index 89748415608..36aa8c04bf2 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp @@ -11,912 +11,773 @@ // //===----------------------------------------------------------------------===// -#include <inttypes.h> -#include <mach/thread_policy.h> -#include <dlfcn.h> #include "MachThread.h" -#include "MachProcess.h" -#include "DNBLog.h" #include "DNB.h" +#include "DNBLog.h" +#include "MachProcess.h" #include "ThreadInfo.h" +#include <dlfcn.h> +#include <inttypes.h> +#include <mach/thread_policy.h> -static uint32_t -GetSequenceID() -{ - static uint32_t g_nextID = 0; - return ++g_nextID; -} - -MachThread::MachThread (MachProcess *process, bool is_64_bit, uint64_t unique_thread_id, thread_t mach_port_num) : - m_process (process), - m_unique_id (unique_thread_id), - m_mach_port_number (mach_port_num), - m_seq_id (GetSequenceID()), - m_state (eStateUnloaded), - m_state_mutex (PTHREAD_MUTEX_RECURSIVE), - m_suspend_count (0), - m_stop_exception (), - m_arch_ap (DNBArchProtocol::Create (this)), - m_reg_sets (NULL), - m_num_reg_sets (0), - m_ident_info(), - m_proc_threadinfo(), - m_dispatch_queue_name(), - m_is_64_bit(is_64_bit), - m_pthread_qos_class_decode (nullptr) -{ - nub_size_t num_reg_sets = 0; - m_reg_sets = m_arch_ap->GetRegisterSetInfo (&num_reg_sets); - m_num_reg_sets = num_reg_sets; - - m_pthread_qos_class_decode = (unsigned int (*)(unsigned long, int*, unsigned long*)) dlsym (RTLD_DEFAULT, "_pthread_qos_class_decode"); - - // Get the thread state so we know if a thread is in a state where we can't - // muck with it and also so we get the suspend count correct in case it was - // already suspended - GetBasicInfo(); - DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::MachThread ( process = %p, tid = 0x%8.8" PRIx64 ", seq_id = %u )", &m_process, m_unique_id, m_seq_id); -} - -MachThread::~MachThread() -{ - DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::~MachThread() for tid = 0x%8.8" PRIx64 " (%u)", m_unique_id, m_seq_id); -} - - +static uint32_t GetSequenceID() { + static uint32_t g_nextID = 0; + return ++g_nextID; +} + +MachThread::MachThread(MachProcess *process, bool is_64_bit, + uint64_t unique_thread_id, thread_t mach_port_num) + : m_process(process), m_unique_id(unique_thread_id), + m_mach_port_number(mach_port_num), m_seq_id(GetSequenceID()), + m_state(eStateUnloaded), m_state_mutex(PTHREAD_MUTEX_RECURSIVE), + m_suspend_count(0), m_stop_exception(), + m_arch_ap(DNBArchProtocol::Create(this)), m_reg_sets(NULL), + m_num_reg_sets(0), m_ident_info(), m_proc_threadinfo(), + m_dispatch_queue_name(), m_is_64_bit(is_64_bit), + m_pthread_qos_class_decode(nullptr) { + nub_size_t num_reg_sets = 0; + m_reg_sets = m_arch_ap->GetRegisterSetInfo(&num_reg_sets); + m_num_reg_sets = num_reg_sets; + + m_pthread_qos_class_decode = + (unsigned int (*)(unsigned long, int *, unsigned long *))dlsym( + RTLD_DEFAULT, "_pthread_qos_class_decode"); + + // Get the thread state so we know if a thread is in a state where we can't + // muck with it and also so we get the suspend count correct in case it was + // already suspended + GetBasicInfo(); + DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, + "MachThread::MachThread ( process = %p, tid = 0x%8.8" PRIx64 + ", seq_id = %u )", + &m_process, m_unique_id, m_seq_id); +} + +MachThread::~MachThread() { + DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, + "MachThread::~MachThread() for tid = 0x%8.8" PRIx64 " (%u)", + m_unique_id, m_seq_id); +} + +void MachThread::Suspend() { + DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", + __FUNCTION__); + if (MachPortNumberIsValid(m_mach_port_number)) { + DNBError err(::thread_suspend(m_mach_port_number), DNBError::MachKernel); + if (err.Success()) + m_suspend_count++; + if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) + err.LogThreaded("::thread_suspend (%4.4" PRIx32 ")", m_mach_port_number); + } +} + +void MachThread::Resume(bool others_stopped) { + DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", + __FUNCTION__); + if (MachPortNumberIsValid(m_mach_port_number)) { + SetSuspendCountBeforeResume(others_stopped); + } +} + +bool MachThread::SetSuspendCountBeforeResume(bool others_stopped) { + DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", + __FUNCTION__); + DNBError err; + if (MachPortNumberIsValid(m_mach_port_number) == false) + return false; -void -MachThread::Suspend() -{ - DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); - if (MachPortNumberIsValid(m_mach_port_number)) - { - DNBError err(::thread_suspend (m_mach_port_number), DNBError::MachKernel); - if (err.Success()) - m_suspend_count++; - if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) - err.LogThreaded("::thread_suspend (%4.4" PRIx32 ")", m_mach_port_number); + integer_t times_to_resume; + + if (others_stopped) { + if (GetBasicInfo()) { + times_to_resume = m_basic_info.suspend_count; + m_suspend_count = -(times_to_resume - m_suspend_count); + } else + times_to_resume = 0; + } else { + times_to_resume = m_suspend_count; + m_suspend_count = 0; + } + + if (times_to_resume > 0) { + while (times_to_resume > 0) { + err = ::thread_resume(m_mach_port_number); + if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) + err.LogThreaded("::thread_resume (%4.4" PRIx32 ")", m_mach_port_number); + if (err.Success()) + --times_to_resume; + else { + if (GetBasicInfo()) + times_to_resume = m_basic_info.suspend_count; + else + times_to_resume = 0; + } } + } + return true; } -void -MachThread::Resume(bool others_stopped) -{ - DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); - if (MachPortNumberIsValid(m_mach_port_number)) - { - SetSuspendCountBeforeResume(others_stopped); - } -} +bool MachThread::RestoreSuspendCountAfterStop() { + DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", + __FUNCTION__); + DNBError err; + if (MachPortNumberIsValid(m_mach_port_number) == false) + return false; -bool -MachThread::SetSuspendCountBeforeResume(bool others_stopped) -{ - DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); - DNBError err; - if (MachPortNumberIsValid(m_mach_port_number) == false) - return false; - - integer_t times_to_resume; - - if (others_stopped) - { + if (m_suspend_count > 0) { + while (m_suspend_count > 0) { + err = ::thread_resume(m_mach_port_number); + if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) + err.LogThreaded("::thread_resume (%4.4" PRIx32 ")", m_mach_port_number); + if (err.Success()) + --m_suspend_count; + else { if (GetBasicInfo()) - { - times_to_resume = m_basic_info.suspend_count; - m_suspend_count = - (times_to_resume - m_suspend_count); - } + m_suspend_count = m_basic_info.suspend_count; else - times_to_resume = 0; + m_suspend_count = 0; + return false; // ??? + } } - else - { - times_to_resume = m_suspend_count; - m_suspend_count = 0; - } - - if (times_to_resume > 0) - { - while (times_to_resume > 0) - { - err = ::thread_resume (m_mach_port_number); - if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) - err.LogThreaded("::thread_resume (%4.4" PRIx32 ")", m_mach_port_number); - if (err.Success()) - --times_to_resume; - else - { - if (GetBasicInfo()) - times_to_resume = m_basic_info.suspend_count; - else - times_to_resume = 0; - } - } - } - return true; -} - -bool -MachThread::RestoreSuspendCountAfterStop () -{ - DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )", __FUNCTION__); - DNBError err; - if (MachPortNumberIsValid(m_mach_port_number) == false) + } else if (m_suspend_count < 0) { + while (m_suspend_count < 0) { + err = ::thread_suspend(m_mach_port_number); + if (err.Success()) + ++m_suspend_count; + if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) { + err.LogThreaded("::thread_suspend (%4.4" PRIx32 ")", + m_mach_port_number); return false; - - if (m_suspend_count > 0) - { - while (m_suspend_count > 0) - { - err = ::thread_resume (m_mach_port_number); - if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) - err.LogThreaded("::thread_resume (%4.4" PRIx32 ")", m_mach_port_number); - if (err.Success()) - --m_suspend_count; - else - { - if (GetBasicInfo()) - m_suspend_count = m_basic_info.suspend_count; - else - m_suspend_count = 0; - return false; // ??? - } - } + } } - else if (m_suspend_count < 0) - { - while (m_suspend_count < 0) - { - err = ::thread_suspend (m_mach_port_number); - if (err.Success()) - ++m_suspend_count; - if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) - { - err.LogThreaded("::thread_suspend (%4.4" PRIx32 ")", m_mach_port_number); - return false; - } + } + return true; +} + +const char *MachThread::GetBasicInfoAsString() const { + static char g_basic_info_string[1024]; + struct thread_basic_info basicInfo; + + if (GetBasicInfo(m_mach_port_number, &basicInfo)) { + + // char run_state_str[32]; + // size_t run_state_str_size = sizeof(run_state_str); + // switch (basicInfo.run_state) + // { + // case TH_STATE_RUNNING: strncpy(run_state_str, "running", + // run_state_str_size); break; + // case TH_STATE_STOPPED: strncpy(run_state_str, "stopped", + // run_state_str_size); break; + // case TH_STATE_WAITING: strncpy(run_state_str, "waiting", + // run_state_str_size); break; + // case TH_STATE_UNINTERRUPTIBLE: strncpy(run_state_str, + // "uninterruptible", run_state_str_size); break; + // case TH_STATE_HALTED: strncpy(run_state_str, "halted", + // run_state_str_size); break; + // default: snprintf(run_state_str, + // run_state_str_size, "%d", basicInfo.run_state); break; // ??? + // } + float user = (float)basicInfo.user_time.seconds + + (float)basicInfo.user_time.microseconds / 1000000.0f; + float system = (float)basicInfo.user_time.seconds + + (float)basicInfo.user_time.microseconds / 1000000.0f; + snprintf(g_basic_info_string, sizeof(g_basic_info_string), + "Thread 0x%8.8" PRIx64 ": user=%f system=%f cpu=%d sleep_time=%d", + m_unique_id, user, system, basicInfo.cpu_usage, + basicInfo.sleep_time); + + return g_basic_info_string; + } + return NULL; +} + +// Finds the Mach port number for a given thread in the inferior process' port +// namespace. +thread_t MachThread::InferiorThreadID() const { + mach_msg_type_number_t i; + mach_port_name_array_t names; + mach_port_type_array_t types; + mach_msg_type_number_t ncount, tcount; + thread_t inferior_tid = INVALID_NUB_THREAD; + task_t my_task = ::mach_task_self(); + task_t task = m_process->Task().TaskPort(); + + kern_return_t kret = + ::mach_port_names(task, &names, &ncount, &types, &tcount); + if (kret == KERN_SUCCESS) { + + for (i = 0; i < ncount; i++) { + mach_port_t my_name; + mach_msg_type_name_t my_type; + + kret = ::mach_port_extract_right(task, names[i], MACH_MSG_TYPE_COPY_SEND, + &my_name, &my_type); + if (kret == KERN_SUCCESS) { + ::mach_port_deallocate(my_task, my_name); + if (my_name == m_mach_port_number) { + inferior_tid = names[i]; + break; } + } } - return true; -} - - -const char * -MachThread::GetBasicInfoAsString () const -{ - static char g_basic_info_string[1024]; - struct thread_basic_info basicInfo; - - if (GetBasicInfo(m_mach_port_number, &basicInfo)) - { - -// char run_state_str[32]; -// size_t run_state_str_size = sizeof(run_state_str); -// switch (basicInfo.run_state) -// { -// case TH_STATE_RUNNING: strncpy(run_state_str, "running", run_state_str_size); break; -// case TH_STATE_STOPPED: strncpy(run_state_str, "stopped", run_state_str_size); break; -// case TH_STATE_WAITING: strncpy(run_state_str, "waiting", run_state_str_size); break; -// case TH_STATE_UNINTERRUPTIBLE: strncpy(run_state_str, "uninterruptible", run_state_str_size); break; -// case TH_STATE_HALTED: strncpy(run_state_str, "halted", run_state_str_size); break; -// default: snprintf(run_state_str, run_state_str_size, "%d", basicInfo.run_state); break; // ??? -// } - float user = (float)basicInfo.user_time.seconds + (float)basicInfo.user_time.microseconds / 1000000.0f; - float system = (float)basicInfo.user_time.seconds + (float)basicInfo.user_time.microseconds / 1000000.0f; - snprintf(g_basic_info_string, sizeof(g_basic_info_string), "Thread 0x%8.8" PRIx64 ": user=%f system=%f cpu=%d sleep_time=%d", - m_unique_id, - user, - system, - basicInfo.cpu_usage, - basicInfo.sleep_time); - - return g_basic_info_string; - } - return NULL; -} - -// Finds the Mach port number for a given thread in the inferior process' port namespace. -thread_t -MachThread::InferiorThreadID() const -{ - mach_msg_type_number_t i; - mach_port_name_array_t names; - mach_port_type_array_t types; - mach_msg_type_number_t ncount, tcount; - thread_t inferior_tid = INVALID_NUB_THREAD; - task_t my_task = ::mach_task_self(); - task_t task = m_process->Task().TaskPort(); - - kern_return_t kret = ::mach_port_names (task, &names, &ncount, &types, &tcount); - if (kret == KERN_SUCCESS) - { - - for (i = 0; i < ncount; i++) - { - mach_port_t my_name; - mach_msg_type_name_t my_type; - - kret = ::mach_port_extract_right (task, names[i], MACH_MSG_TYPE_COPY_SEND, &my_name, &my_type); - if (kret == KERN_SUCCESS) - { - ::mach_port_deallocate (my_task, my_name); - if (my_name == m_mach_port_number) - { - inferior_tid = names[i]; - break; - } - } - } - // Free up the names and types - ::vm_deallocate (my_task, (vm_address_t) names, ncount * sizeof (mach_port_name_t)); - ::vm_deallocate (my_task, (vm_address_t) types, tcount * sizeof (mach_port_type_t)); - } - return inferior_tid; -} - -bool -MachThread::IsUserReady() -{ - if (m_basic_info.run_state == 0) - GetBasicInfo (); - - switch (m_basic_info.run_state) - { - default: - case TH_STATE_UNINTERRUPTIBLE: - break; - - case TH_STATE_RUNNING: - case TH_STATE_STOPPED: - case TH_STATE_WAITING: - case TH_STATE_HALTED: - return true; - } - return false; -} - -struct thread_basic_info * -MachThread::GetBasicInfo () -{ - if (MachThread::GetBasicInfo(m_mach_port_number, &m_basic_info)) - return &m_basic_info; - return NULL; -} - - -bool -MachThread::GetBasicInfo(thread_t thread, struct thread_basic_info *basicInfoPtr) -{ - if (MachPortNumberIsValid(thread)) - { - unsigned int info_count = THREAD_BASIC_INFO_COUNT; - kern_return_t err = ::thread_info (thread, THREAD_BASIC_INFO, (thread_info_t) basicInfoPtr, &info_count); - if (err == KERN_SUCCESS) - return true; - } - ::memset (basicInfoPtr, 0, sizeof (struct thread_basic_info)); - return false; -} - - -bool -MachThread::ThreadIDIsValid(uint64_t thread) -{ - return thread != 0; -} - -bool -MachThread::MachPortNumberIsValid(thread_t thread) -{ - return thread != THREAD_NULL; -} - -bool -MachThread::GetRegisterState(int flavor, bool force) -{ - return m_arch_ap->GetRegisterState(flavor, force) == KERN_SUCCESS; + // Free up the names and types + ::vm_deallocate(my_task, (vm_address_t)names, + ncount * sizeof(mach_port_name_t)); + ::vm_deallocate(my_task, (vm_address_t)types, + tcount * sizeof(mach_port_type_t)); + } + return inferior_tid; } -bool -MachThread::SetRegisterState(int flavor) -{ - return m_arch_ap->SetRegisterState(flavor) == KERN_SUCCESS; -} +bool MachThread::IsUserReady() { + if (m_basic_info.run_state == 0) + GetBasicInfo(); -uint64_t -MachThread::GetPC(uint64_t failValue) -{ - // Get program counter - return m_arch_ap->GetPC(failValue); -} + switch (m_basic_info.run_state) { + default: + case TH_STATE_UNINTERRUPTIBLE: + break; -bool -MachThread::SetPC(uint64_t value) -{ - // Set program counter - return m_arch_ap->SetPC(value); + case TH_STATE_RUNNING: + case TH_STATE_STOPPED: + case TH_STATE_WAITING: + case TH_STATE_HALTED: + return true; + } + return false; } -uint64_t -MachThread::GetSP(uint64_t failValue) -{ - // Get stack pointer - return m_arch_ap->GetSP(failValue); -} - -nub_process_t -MachThread::ProcessID() const -{ - if (m_process) - return m_process->ProcessID(); - return INVALID_NUB_PROCESS; -} - -void -MachThread::Dump(uint32_t index) -{ - const char * thread_run_state = NULL; - - switch (m_basic_info.run_state) - { - case TH_STATE_RUNNING: thread_run_state = "running"; break; // 1 thread is running normally - case TH_STATE_STOPPED: thread_run_state = "stopped"; break; // 2 thread is stopped - case TH_STATE_WAITING: thread_run_state = "waiting"; break; // 3 thread is waiting normally - case TH_STATE_UNINTERRUPTIBLE: thread_run_state = "uninter"; break; // 4 thread is in an uninterruptible wait - case TH_STATE_HALTED: thread_run_state = "halted "; break; // 5 thread is halted at a - default: thread_run_state = "???"; break; - } +struct thread_basic_info *MachThread::GetBasicInfo() { + if (MachThread::GetBasicInfo(m_mach_port_number, &m_basic_info)) + return &m_basic_info; + return NULL; +} - DNBLogThreaded("[%3u] #%3u tid: 0x%8.8" PRIx64 ", pc: 0x%16.16" PRIx64 ", sp: 0x%16.16" PRIx64 ", user: %d.%6.6d, system: %d.%6.6d, cpu: %2d, policy: %2d, run_state: %2d (%s), flags: %2d, suspend_count: %2d (current %2d), sleep_time: %d", - index, - m_seq_id, - m_unique_id, - GetPC(INVALID_NUB_ADDRESS), - GetSP(INVALID_NUB_ADDRESS), - m_basic_info.user_time.seconds, m_basic_info.user_time.microseconds, - m_basic_info.system_time.seconds, m_basic_info.system_time.microseconds, - m_basic_info.cpu_usage, - m_basic_info.policy, - m_basic_info.run_state, - thread_run_state, - m_basic_info.flags, - m_basic_info.suspend_count, m_suspend_count, - m_basic_info.sleep_time); - //DumpRegisterState(0); -} - -void -MachThread::ThreadWillResume(const DNBThreadResumeAction *thread_action, bool others_stopped) -{ - if (thread_action->addr != INVALID_NUB_ADDRESS) - SetPC (thread_action->addr); - - SetState (thread_action->state); - switch (thread_action->state) - { - case eStateStopped: - case eStateSuspended: - assert (others_stopped == false); - Suspend(); - break; - - case eStateRunning: - case eStateStepping: - Resume(others_stopped); - break; - default: - break; - } - m_arch_ap->ThreadWillResume(); - m_stop_exception.Clear(); -} +bool MachThread::GetBasicInfo(thread_t thread, + struct thread_basic_info *basicInfoPtr) { + if (MachPortNumberIsValid(thread)) { + unsigned int info_count = THREAD_BASIC_INFO_COUNT; + kern_return_t err = ::thread_info(thread, THREAD_BASIC_INFO, + (thread_info_t)basicInfoPtr, &info_count); + if (err == KERN_SUCCESS) + return true; + } + ::memset(basicInfoPtr, 0, sizeof(struct thread_basic_info)); + return false; +} + +bool MachThread::ThreadIDIsValid(uint64_t thread) { return thread != 0; } -DNBBreakpoint * -MachThread::CurrentBreakpoint() -{ - return m_process->Breakpoints().FindByAddress(GetPC()); -} +bool MachThread::MachPortNumberIsValid(thread_t thread) { + return thread != THREAD_NULL; +} -bool -MachThread::ShouldStop(bool &step_more) -{ - // See if this thread is at a breakpoint? - DNBBreakpoint *bp = CurrentBreakpoint(); +bool MachThread::GetRegisterState(int flavor, bool force) { + return m_arch_ap->GetRegisterState(flavor, force) == KERN_SUCCESS; +} + +bool MachThread::SetRegisterState(int flavor) { + return m_arch_ap->SetRegisterState(flavor) == KERN_SUCCESS; +} + +uint64_t MachThread::GetPC(uint64_t failValue) { + // Get program counter + return m_arch_ap->GetPC(failValue); +} + +bool MachThread::SetPC(uint64_t value) { + // Set program counter + return m_arch_ap->SetPC(value); +} + +uint64_t MachThread::GetSP(uint64_t failValue) { + // Get stack pointer + return m_arch_ap->GetSP(failValue); +} + +nub_process_t MachThread::ProcessID() const { + if (m_process) + return m_process->ProcessID(); + return INVALID_NUB_PROCESS; +} + +void MachThread::Dump(uint32_t index) { + const char *thread_run_state = NULL; + + switch (m_basic_info.run_state) { + case TH_STATE_RUNNING: + thread_run_state = "running"; + break; // 1 thread is running normally + case TH_STATE_STOPPED: + thread_run_state = "stopped"; + break; // 2 thread is stopped + case TH_STATE_WAITING: + thread_run_state = "waiting"; + break; // 3 thread is waiting normally + case TH_STATE_UNINTERRUPTIBLE: + thread_run_state = "uninter"; + break; // 4 thread is in an uninterruptible wait + case TH_STATE_HALTED: + thread_run_state = "halted "; + break; // 5 thread is halted at a + default: + thread_run_state = "???"; + break; + } + + DNBLogThreaded( + "[%3u] #%3u tid: 0x%8.8" PRIx64 ", pc: 0x%16.16" PRIx64 + ", sp: 0x%16.16" PRIx64 + ", user: %d.%6.6d, system: %d.%6.6d, cpu: %2d, policy: %2d, run_state: " + "%2d (%s), flags: %2d, suspend_count: %2d (current %2d), sleep_time: %d", + index, m_seq_id, m_unique_id, GetPC(INVALID_NUB_ADDRESS), + GetSP(INVALID_NUB_ADDRESS), m_basic_info.user_time.seconds, + m_basic_info.user_time.microseconds, m_basic_info.system_time.seconds, + m_basic_info.system_time.microseconds, m_basic_info.cpu_usage, + m_basic_info.policy, m_basic_info.run_state, thread_run_state, + m_basic_info.flags, m_basic_info.suspend_count, m_suspend_count, + m_basic_info.sleep_time); + // DumpRegisterState(0); +} + +void MachThread::ThreadWillResume(const DNBThreadResumeAction *thread_action, + bool others_stopped) { + if (thread_action->addr != INVALID_NUB_ADDRESS) + SetPC(thread_action->addr); - if (bp) - { - // This thread is sitting at a breakpoint, ask the breakpoint - // if we should be stopping here. - return true; - } - else - { - if (m_arch_ap->StepNotComplete()) - { - step_more = true; - return false; - } - // The thread state is used to let us know what the thread was - // trying to do. MachThread::ThreadWillResume() will set the - // thread state to various values depending if the thread was - // the current thread and if it was to be single stepped, or - // resumed. - if (GetState() == eStateRunning) - { - // If our state is running, then we should continue as we are in - // the process of stepping over a breakpoint. - return false; - } - else - { - // Stop if we have any kind of valid exception for this - // thread. - if (GetStopException().IsValid()) - return true; - } - } - return false; + SetState(thread_action->state); + switch (thread_action->state) { + case eStateStopped: + case eStateSuspended: + assert(others_stopped == false); + Suspend(); + break; + + case eStateRunning: + case eStateStepping: + Resume(others_stopped); + break; + default: + break; + } + m_arch_ap->ThreadWillResume(); + m_stop_exception.Clear(); } -bool -MachThread::IsStepping() -{ - return GetState() == eStateStepping; -} - - -bool -MachThread::ThreadDidStop() -{ - // This thread has existed prior to resuming under debug nub control, - // and has just been stopped. Do any cleanup that needs to be done - // after running. - - // The thread state and breakpoint will still have the same values - // as they had prior to resuming the thread, so it makes it easy to check - // if we were trying to step a thread, or we tried to resume while being - // at a breakpoint. - - // When this method gets called, the process state is still in the - // state it was in while running so we can act accordingly. - m_arch_ap->ThreadDidStop(); - - // We may have suspended this thread so the primary thread could step - // without worrying about race conditions, so lets restore our suspend - // count. - RestoreSuspendCountAfterStop(); - - // Update the basic information for a thread - MachThread::GetBasicInfo(m_mach_port_number, &m_basic_info); - - if (m_basic_info.suspend_count > 0) - SetState(eStateSuspended); - else - SetState(eStateStopped); +DNBBreakpoint *MachThread::CurrentBreakpoint() { + return m_process->Breakpoints().FindByAddress(GetPC()); +} + +bool MachThread::ShouldStop(bool &step_more) { + // See if this thread is at a breakpoint? + DNBBreakpoint *bp = CurrentBreakpoint(); + + if (bp) { + // This thread is sitting at a breakpoint, ask the breakpoint + // if we should be stopping here. return true; -} - -bool -MachThread::NotifyException(MachException::Data& exc) -{ - // Allow the arch specific protocol to process (MachException::Data &)exc - // first before possible reassignment of m_stop_exception with exc. - // See also MachThread::GetStopException(). - bool handled = m_arch_ap->NotifyException(exc); - - if (m_stop_exception.IsValid()) - { - // We may have more than one exception for a thread, but we need to - // only remember the one that we will say is the reason we stopped. - // We may have been single stepping and also gotten a signal exception, - // so just remember the most pertinent one. - if (m_stop_exception.IsBreakpoint()) - m_stop_exception = exc; + } else { + if (m_arch_ap->StepNotComplete()) { + step_more = true; + return false; } - else - { - m_stop_exception = exc; - } - - return handled; -} - - -nub_state_t -MachThread::GetState() -{ - // If any other threads access this we will need a mutex for it - PTHREAD_MUTEX_LOCKER (locker, m_state_mutex); - return m_state; -} - -void -MachThread::SetState(nub_state_t state) -{ - PTHREAD_MUTEX_LOCKER (locker, m_state_mutex); - m_state = state; - DNBLogThreadedIf(LOG_THREAD, "MachThread::SetState ( %s ) for tid = 0x%8.8" PRIx64 "", DNBStateAsString(state), m_unique_id); -} - -nub_size_t -MachThread::GetNumRegistersInSet(nub_size_t regSet) const -{ - if (regSet < m_num_reg_sets) - return m_reg_sets[regSet].num_registers; - return 0; -} - -const char * -MachThread::GetRegisterSetName(nub_size_t regSet) const -{ - if (regSet < m_num_reg_sets) - return m_reg_sets[regSet].name; - return NULL; -} - -const DNBRegisterInfo * -MachThread::GetRegisterInfo(nub_size_t regSet, nub_size_t regIndex) const -{ - if (regSet < m_num_reg_sets) - if (regIndex < m_reg_sets[regSet].num_registers) - return &m_reg_sets[regSet].registers[regIndex]; - return NULL; -} -void -MachThread::DumpRegisterState(nub_size_t regSet) -{ - if (regSet == REGISTER_SET_ALL) - { - for (regSet = 1; regSet < m_num_reg_sets; regSet++) - DumpRegisterState(regSet); + // The thread state is used to let us know what the thread was + // trying to do. MachThread::ThreadWillResume() will set the + // thread state to various values depending if the thread was + // the current thread and if it was to be single stepped, or + // resumed. + if (GetState() == eStateRunning) { + // If our state is running, then we should continue as we are in + // the process of stepping over a breakpoint. + return false; + } else { + // Stop if we have any kind of valid exception for this + // thread. + if (GetStopException().IsValid()) + return true; } - else - { - if (m_arch_ap->RegisterSetStateIsValid((int)regSet)) - { - const size_t numRegisters = GetNumRegistersInSet(regSet); - uint32_t regIndex = 0; - DNBRegisterValueClass reg; - for (regIndex = 0; regIndex < numRegisters; ++regIndex) - { - if (m_arch_ap->GetRegisterValue((uint32_t)regSet, regIndex, ®)) - { - reg.Dump(NULL, NULL); - } - } - } - else - { - DNBLog("%s: registers are not currently valid.", GetRegisterSetName(regSet)); + } + return false; +} +bool MachThread::IsStepping() { return GetState() == eStateStepping; } + +bool MachThread::ThreadDidStop() { + // This thread has existed prior to resuming under debug nub control, + // and has just been stopped. Do any cleanup that needs to be done + // after running. + + // The thread state and breakpoint will still have the same values + // as they had prior to resuming the thread, so it makes it easy to check + // if we were trying to step a thread, or we tried to resume while being + // at a breakpoint. + + // When this method gets called, the process state is still in the + // state it was in while running so we can act accordingly. + m_arch_ap->ThreadDidStop(); + + // We may have suspended this thread so the primary thread could step + // without worrying about race conditions, so lets restore our suspend + // count. + RestoreSuspendCountAfterStop(); + + // Update the basic information for a thread + MachThread::GetBasicInfo(m_mach_port_number, &m_basic_info); + + if (m_basic_info.suspend_count > 0) + SetState(eStateSuspended); + else + SetState(eStateStopped); + return true; +} + +bool MachThread::NotifyException(MachException::Data &exc) { + // Allow the arch specific protocol to process (MachException::Data &)exc + // first before possible reassignment of m_stop_exception with exc. + // See also MachThread::GetStopException(). + bool handled = m_arch_ap->NotifyException(exc); + + if (m_stop_exception.IsValid()) { + // We may have more than one exception for a thread, but we need to + // only remember the one that we will say is the reason we stopped. + // We may have been single stepping and also gotten a signal exception, + // so just remember the most pertinent one. + if (m_stop_exception.IsBreakpoint()) + m_stop_exception = exc; + } else { + m_stop_exception = exc; + } + + return handled; +} + +nub_state_t MachThread::GetState() { + // If any other threads access this we will need a mutex for it + PTHREAD_MUTEX_LOCKER(locker, m_state_mutex); + return m_state; +} + +void MachThread::SetState(nub_state_t state) { + PTHREAD_MUTEX_LOCKER(locker, m_state_mutex); + m_state = state; + DNBLogThreadedIf(LOG_THREAD, + "MachThread::SetState ( %s ) for tid = 0x%8.8" PRIx64 "", + DNBStateAsString(state), m_unique_id); +} + +nub_size_t MachThread::GetNumRegistersInSet(nub_size_t regSet) const { + if (regSet < m_num_reg_sets) + return m_reg_sets[regSet].num_registers; + return 0; +} + +const char *MachThread::GetRegisterSetName(nub_size_t regSet) const { + if (regSet < m_num_reg_sets) + return m_reg_sets[regSet].name; + return NULL; +} + +const DNBRegisterInfo *MachThread::GetRegisterInfo(nub_size_t regSet, + nub_size_t regIndex) const { + if (regSet < m_num_reg_sets) + if (regIndex < m_reg_sets[regSet].num_registers) + return &m_reg_sets[regSet].registers[regIndex]; + return NULL; +} +void MachThread::DumpRegisterState(nub_size_t regSet) { + if (regSet == REGISTER_SET_ALL) { + for (regSet = 1; regSet < m_num_reg_sets; regSet++) + DumpRegisterState(regSet); + } else { + if (m_arch_ap->RegisterSetStateIsValid((int)regSet)) { + const size_t numRegisters = GetNumRegistersInSet(regSet); + uint32_t regIndex = 0; + DNBRegisterValueClass reg; + for (regIndex = 0; regIndex < numRegisters; ++regIndex) { + if (m_arch_ap->GetRegisterValue((uint32_t)regSet, regIndex, ®)) { + reg.Dump(NULL, NULL); } + } + } else { + DNBLog("%s: registers are not currently valid.", + GetRegisterSetName(regSet)); } + } } const DNBRegisterSetInfo * -MachThread::GetRegisterSetInfo(nub_size_t *num_reg_sets ) const -{ - *num_reg_sets = m_num_reg_sets; - return &m_reg_sets[0]; +MachThread::GetRegisterSetInfo(nub_size_t *num_reg_sets) const { + *num_reg_sets = m_num_reg_sets; + return &m_reg_sets[0]; } -bool -MachThread::GetRegisterValue ( uint32_t set, uint32_t reg, DNBRegisterValue *value ) -{ - return m_arch_ap->GetRegisterValue(set, reg, value); +bool MachThread::GetRegisterValue(uint32_t set, uint32_t reg, + DNBRegisterValue *value) { + return m_arch_ap->GetRegisterValue(set, reg, value); } -bool -MachThread::SetRegisterValue ( uint32_t set, uint32_t reg, const DNBRegisterValue *value ) -{ - return m_arch_ap->SetRegisterValue(set, reg, value); +bool MachThread::SetRegisterValue(uint32_t set, uint32_t reg, + const DNBRegisterValue *value) { + return m_arch_ap->SetRegisterValue(set, reg, value); } -nub_size_t -MachThread::GetRegisterContext (void *buf, nub_size_t buf_len) -{ - return m_arch_ap->GetRegisterContext(buf, buf_len); +nub_size_t MachThread::GetRegisterContext(void *buf, nub_size_t buf_len) { + return m_arch_ap->GetRegisterContext(buf, buf_len); } -nub_size_t -MachThread::SetRegisterContext (const void *buf, nub_size_t buf_len) -{ - return m_arch_ap->SetRegisterContext(buf, buf_len); +nub_size_t MachThread::SetRegisterContext(const void *buf, nub_size_t buf_len) { + return m_arch_ap->SetRegisterContext(buf, buf_len); } -uint32_t -MachThread::SaveRegisterState () -{ - return m_arch_ap->SaveRegisterState(); - +uint32_t MachThread::SaveRegisterState() { + return m_arch_ap->SaveRegisterState(); } -bool -MachThread::RestoreRegisterState (uint32_t save_id) -{ - return m_arch_ap->RestoreRegisterState(save_id); +bool MachThread::RestoreRegisterState(uint32_t save_id) { + return m_arch_ap->RestoreRegisterState(save_id); } -uint32_t -MachThread::EnableHardwareBreakpoint (const DNBBreakpoint *bp) -{ - if (bp != NULL && bp->IsBreakpoint()) - return m_arch_ap->EnableHardwareBreakpoint(bp->Address(), bp->ByteSize()); - return INVALID_NUB_HW_INDEX; +uint32_t MachThread::EnableHardwareBreakpoint(const DNBBreakpoint *bp) { + if (bp != NULL && bp->IsBreakpoint()) + return m_arch_ap->EnableHardwareBreakpoint(bp->Address(), bp->ByteSize()); + return INVALID_NUB_HW_INDEX; } -uint32_t -MachThread::EnableHardwareWatchpoint (const DNBBreakpoint *wp, bool also_set_on_task) -{ - if (wp != NULL && wp->IsWatchpoint()) - return m_arch_ap->EnableHardwareWatchpoint(wp->Address(), wp->ByteSize(), wp->WatchpointRead(), wp->WatchpointWrite(), also_set_on_task); - return INVALID_NUB_HW_INDEX; +uint32_t MachThread::EnableHardwareWatchpoint(const DNBBreakpoint *wp, + bool also_set_on_task) { + if (wp != NULL && wp->IsWatchpoint()) + return m_arch_ap->EnableHardwareWatchpoint( + wp->Address(), wp->ByteSize(), wp->WatchpointRead(), + wp->WatchpointWrite(), also_set_on_task); + return INVALID_NUB_HW_INDEX; } -bool -MachThread::RollbackTransForHWP() -{ - return m_arch_ap->RollbackTransForHWP(); +bool MachThread::RollbackTransForHWP() { + return m_arch_ap->RollbackTransForHWP(); } -bool -MachThread::FinishTransForHWP() -{ - return m_arch_ap->FinishTransForHWP(); -} +bool MachThread::FinishTransForHWP() { return m_arch_ap->FinishTransForHWP(); } -bool -MachThread::DisableHardwareBreakpoint (const DNBBreakpoint *bp) -{ - if (bp != NULL && bp->IsHardware()) - return m_arch_ap->DisableHardwareBreakpoint(bp->GetHardwareIndex()); - return false; +bool MachThread::DisableHardwareBreakpoint(const DNBBreakpoint *bp) { + if (bp != NULL && bp->IsHardware()) + return m_arch_ap->DisableHardwareBreakpoint(bp->GetHardwareIndex()); + return false; } -bool -MachThread::DisableHardwareWatchpoint (const DNBBreakpoint *wp, bool also_set_on_task) -{ - if (wp != NULL && wp->IsHardware()) - return m_arch_ap->DisableHardwareWatchpoint(wp->GetHardwareIndex(), also_set_on_task); - return false; +bool MachThread::DisableHardwareWatchpoint(const DNBBreakpoint *wp, + bool also_set_on_task) { + if (wp != NULL && wp->IsHardware()) + return m_arch_ap->DisableHardwareWatchpoint(wp->GetHardwareIndex(), + also_set_on_task); + return false; } -uint32_t -MachThread::NumSupportedHardwareWatchpoints () const -{ - return m_arch_ap->NumSupportedHardwareWatchpoints(); +uint32_t MachThread::NumSupportedHardwareWatchpoints() const { + return m_arch_ap->NumSupportedHardwareWatchpoints(); } -bool -MachThread::GetIdentifierInfo () -{ - // Don't try to get the thread info once and cache it for the life of the thread. It changes over time, for instance - // if the thread name changes, then the thread_handle also changes... So you have to refetch it every time. - mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; - kern_return_t kret = ::thread_info (m_mach_port_number, THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count); - return kret == KERN_SUCCESS; +bool MachThread::GetIdentifierInfo() { + // Don't try to get the thread info once and cache it for the life of the + // thread. It changes over time, for instance + // if the thread name changes, then the thread_handle also changes... So you + // have to refetch it every time. + mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; + kern_return_t kret = ::thread_info(m_mach_port_number, THREAD_IDENTIFIER_INFO, + (thread_info_t)&m_ident_info, &count); + return kret == KERN_SUCCESS; - return false; + return false; } +const char *MachThread::GetName() { + if (GetIdentifierInfo()) { + int len = ::proc_pidinfo(m_process->ProcessID(), PROC_PIDTHREADINFO, + m_ident_info.thread_handle, &m_proc_threadinfo, + sizeof(m_proc_threadinfo)); -const char * -MachThread::GetName () -{ - if (GetIdentifierInfo ()) - { - int len = ::proc_pidinfo (m_process->ProcessID(), PROC_PIDTHREADINFO, m_ident_info.thread_handle, &m_proc_threadinfo, sizeof (m_proc_threadinfo)); - - if (len && m_proc_threadinfo.pth_name[0]) - return m_proc_threadinfo.pth_name; - } - return NULL; + if (len && m_proc_threadinfo.pth_name[0]) + return m_proc_threadinfo.pth_name; + } + return NULL; } - -uint64_t -MachThread::GetGloballyUniqueThreadIDForMachPortID (thread_t mach_port_id) -{ +uint64_t +MachThread::GetGloballyUniqueThreadIDForMachPortID(thread_t mach_port_id) { + kern_return_t kr; + thread_identifier_info_data_t tident; + mach_msg_type_number_t tident_count = THREAD_IDENTIFIER_INFO_COUNT; + kr = thread_info(mach_port_id, THREAD_IDENTIFIER_INFO, (thread_info_t)&tident, + &tident_count); + if (kr != KERN_SUCCESS) { + return mach_port_id; + } + return tident.thread_id; +} + +nub_addr_t MachThread::GetPThreadT() { + nub_addr_t pthread_t_value = INVALID_NUB_ADDRESS; + if (MachPortNumberIsValid(m_mach_port_number)) { kern_return_t kr; thread_identifier_info_data_t tident; mach_msg_type_number_t tident_count = THREAD_IDENTIFIER_INFO_COUNT; - kr = thread_info (mach_port_id, THREAD_IDENTIFIER_INFO, - (thread_info_t) &tident, &tident_count); - if (kr != KERN_SUCCESS) - { - return mach_port_id; - } - return tident.thread_id; -} - -nub_addr_t -MachThread::GetPThreadT () -{ - nub_addr_t pthread_t_value = INVALID_NUB_ADDRESS; - if (MachPortNumberIsValid (m_mach_port_number)) - { - kern_return_t kr; - thread_identifier_info_data_t tident; - mach_msg_type_number_t tident_count = THREAD_IDENTIFIER_INFO_COUNT; - kr = thread_info (m_mach_port_number, THREAD_IDENTIFIER_INFO, - (thread_info_t) &tident, &tident_count); - if (kr == KERN_SUCCESS) - { - // Dereference thread_handle to get the pthread_t value for this thread. - if (m_is_64_bit) - { - uint64_t addr; - if (m_process->ReadMemory (tident.thread_handle, 8, &addr) == 8) - { - if (addr != 0) - { - pthread_t_value = addr; - } - } - } - else - { - uint32_t addr; - if (m_process->ReadMemory (tident.thread_handle, 4, &addr) == 4) - { - if (addr != 0) - { - pthread_t_value = addr; - } - } - } + kr = thread_info(m_mach_port_number, THREAD_IDENTIFIER_INFO, + (thread_info_t)&tident, &tident_count); + if (kr == KERN_SUCCESS) { + // Dereference thread_handle to get the pthread_t value for this thread. + if (m_is_64_bit) { + uint64_t addr; + if (m_process->ReadMemory(tident.thread_handle, 8, &addr) == 8) { + if (addr != 0) { + pthread_t_value = addr; + } + } + } else { + uint32_t addr; + if (m_process->ReadMemory(tident.thread_handle, 4, &addr) == 4) { + if (addr != 0) { + pthread_t_value = addr; + } } + } } - return pthread_t_value; + } + return pthread_t_value; } // Return this thread's TSD (Thread Specific Data) address. // This is computed based on this thread's pthread_t value. // // We compute the TSD from the pthread_t by one of two methods. -// -// If plo_pthread_tsd_base_offset is non-zero, this is a simple offset that we add to +// +// If plo_pthread_tsd_base_offset is non-zero, this is a simple offset that we +// add to // the pthread_t to get the TSD base address. // -// Else we read a pointer from memory at pthread_t + plo_pthread_tsd_base_address_offset and +// Else we read a pointer from memory at pthread_t + +// plo_pthread_tsd_base_address_offset and // that gives us the TSD address. // -// These plo_pthread_tsd_base values must be read out of libpthread by lldb & provided to debugserver. +// These plo_pthread_tsd_base values must be read out of libpthread by lldb & +// provided to debugserver. nub_addr_t -MachThread::GetTSDAddressForThread (uint64_t plo_pthread_tsd_base_address_offset, uint64_t plo_pthread_tsd_base_offset, uint64_t plo_pthread_tsd_entry_size) -{ - nub_addr_t tsd_addr = INVALID_NUB_ADDRESS; - nub_addr_t pthread_t_value = GetPThreadT(); - if (plo_pthread_tsd_base_offset != 0 && plo_pthread_tsd_base_offset != INVALID_NUB_ADDRESS) - { - tsd_addr = pthread_t_value + plo_pthread_tsd_base_offset; - } - else - { - if (plo_pthread_tsd_entry_size == 4) - { - uint32_t addr = 0; - if (m_process->ReadMemory (pthread_t_value + plo_pthread_tsd_base_address_offset, 4, &addr) == 4) - { - if (addr != 0) - { - tsd_addr = addr; - } - } +MachThread::GetTSDAddressForThread(uint64_t plo_pthread_tsd_base_address_offset, + uint64_t plo_pthread_tsd_base_offset, + uint64_t plo_pthread_tsd_entry_size) { + nub_addr_t tsd_addr = INVALID_NUB_ADDRESS; + nub_addr_t pthread_t_value = GetPThreadT(); + if (plo_pthread_tsd_base_offset != 0 && + plo_pthread_tsd_base_offset != INVALID_NUB_ADDRESS) { + tsd_addr = pthread_t_value + plo_pthread_tsd_base_offset; + } else { + if (plo_pthread_tsd_entry_size == 4) { + uint32_t addr = 0; + if (m_process->ReadMemory(pthread_t_value + + plo_pthread_tsd_base_address_offset, + 4, &addr) == 4) { + if (addr != 0) { + tsd_addr = addr; } - if (plo_pthread_tsd_entry_size == 4) - { - uint64_t addr = 0; - if (m_process->ReadMemory (pthread_t_value + plo_pthread_tsd_base_address_offset, 8, &addr) == 8) - { - if (addr != 0) - { - tsd_addr = addr; - } - } + } + } + if (plo_pthread_tsd_entry_size == 4) { + uint64_t addr = 0; + if (m_process->ReadMemory(pthread_t_value + + plo_pthread_tsd_base_address_offset, + 8, &addr) == 8) { + if (addr != 0) { + tsd_addr = addr; } + } } - return tsd_addr; + } + return tsd_addr; } - -nub_addr_t -MachThread::GetDispatchQueueT () -{ - nub_addr_t dispatch_queue_t_value = INVALID_NUB_ADDRESS; - if (MachPortNumberIsValid (m_mach_port_number)) - { - kern_return_t kr; - thread_identifier_info_data_t tident; - mach_msg_type_number_t tident_count = THREAD_IDENTIFIER_INFO_COUNT; - kr = thread_info (m_mach_port_number, THREAD_IDENTIFIER_INFO, - (thread_info_t) &tident, &tident_count); - if (kr == KERN_SUCCESS && tident.dispatch_qaddr != 0 && tident.dispatch_qaddr != INVALID_NUB_ADDRESS) - { - // Dereference dispatch_qaddr to get the dispatch_queue_t value for this thread's queue, if any. - if (m_is_64_bit) - { - uint64_t addr; - if (m_process->ReadMemory (tident.dispatch_qaddr, 8, &addr) == 8) - { - if (addr != 0) - dispatch_queue_t_value = addr; - } - } - else - { - uint32_t addr; - if (m_process->ReadMemory (tident.dispatch_qaddr, 4, &addr) == 4) - { - if (addr != 0) - dispatch_queue_t_value = addr; - } - } - } - } - return dispatch_queue_t_value; -} - - -ThreadInfo::QoS -MachThread::GetRequestedQoS (nub_addr_t tsd, uint64_t dti_qos_class_index) -{ - ThreadInfo::QoS qos_value; - if (MachPortNumberIsValid (m_mach_port_number) && m_pthread_qos_class_decode != nullptr) - { - uint64_t pthread_priority_value = 0; - if (m_is_64_bit) - { - uint64_t pri; - if (m_process->ReadMemory (tsd + (dti_qos_class_index * 8), 8, &pri) == 8) - { - pthread_priority_value = pri; - } +nub_addr_t MachThread::GetDispatchQueueT() { + nub_addr_t dispatch_queue_t_value = INVALID_NUB_ADDRESS; + if (MachPortNumberIsValid(m_mach_port_number)) { + kern_return_t kr; + thread_identifier_info_data_t tident; + mach_msg_type_number_t tident_count = THREAD_IDENTIFIER_INFO_COUNT; + kr = thread_info(m_mach_port_number, THREAD_IDENTIFIER_INFO, + (thread_info_t)&tident, &tident_count); + if (kr == KERN_SUCCESS && tident.dispatch_qaddr != 0 && + tident.dispatch_qaddr != INVALID_NUB_ADDRESS) { + // Dereference dispatch_qaddr to get the dispatch_queue_t value for this + // thread's queue, if any. + if (m_is_64_bit) { + uint64_t addr; + if (m_process->ReadMemory(tident.dispatch_qaddr, 8, &addr) == 8) { + if (addr != 0) + dispatch_queue_t_value = addr; } - else - { - uint32_t pri; - if (m_process->ReadMemory (tsd + (dti_qos_class_index * 4), 4, &pri) == 4) - { - pthread_priority_value = pri; - } + } else { + uint32_t addr; + if (m_process->ReadMemory(tident.dispatch_qaddr, 4, &addr) == 4) { + if (addr != 0) + dispatch_queue_t_value = addr; } + } + } + } + return dispatch_queue_t_value; +} + +ThreadInfo::QoS MachThread::GetRequestedQoS(nub_addr_t tsd, + uint64_t dti_qos_class_index) { + ThreadInfo::QoS qos_value; + if (MachPortNumberIsValid(m_mach_port_number) && + m_pthread_qos_class_decode != nullptr) { + uint64_t pthread_priority_value = 0; + if (m_is_64_bit) { + uint64_t pri; + if (m_process->ReadMemory(tsd + (dti_qos_class_index * 8), 8, &pri) == + 8) { + pthread_priority_value = pri; + } + } else { + uint32_t pri; + if (m_process->ReadMemory(tsd + (dti_qos_class_index * 4), 4, &pri) == + 4) { + pthread_priority_value = pri; + } + } - uint32_t requested_qos = m_pthread_qos_class_decode (pthread_priority_value, NULL, NULL); - - switch (requested_qos) - { - // These constants from <pthread/qos.h> - case 0x21: - qos_value.enum_value = requested_qos; - qos_value.constant_name = "QOS_CLASS_USER_INTERACTIVE"; - qos_value.printable_name = "User Interactive"; - break; - case 0x19: - qos_value.enum_value = requested_qos; - qos_value.constant_name = "QOS_CLASS_USER_INITIATED"; - qos_value.printable_name = "User Initiated"; - break; - case 0x15: - qos_value.enum_value = requested_qos; - qos_value.constant_name = "QOS_CLASS_DEFAULT"; - qos_value.printable_name = "Default"; - break; - case 0x11: - qos_value.enum_value = requested_qos; - qos_value.constant_name = "QOS_CLASS_UTILITY"; - qos_value.printable_name = "Utility"; - break; - case 0x09: - qos_value.enum_value = requested_qos; - qos_value.constant_name = "QOS_CLASS_BACKGROUND"; - qos_value.printable_name = "Background"; - break; - case 0x00: - qos_value.enum_value = requested_qos; - qos_value.constant_name = "QOS_CLASS_UNSPECIFIED"; - qos_value.printable_name = "Unspecified"; - break; - } + uint32_t requested_qos = + m_pthread_qos_class_decode(pthread_priority_value, NULL, NULL); + + switch (requested_qos) { + // These constants from <pthread/qos.h> + case 0x21: + qos_value.enum_value = requested_qos; + qos_value.constant_name = "QOS_CLASS_USER_INTERACTIVE"; + qos_value.printable_name = "User Interactive"; + break; + case 0x19: + qos_value.enum_value = requested_qos; + qos_value.constant_name = "QOS_CLASS_USER_INITIATED"; + qos_value.printable_name = "User Initiated"; + break; + case 0x15: + qos_value.enum_value = requested_qos; + qos_value.constant_name = "QOS_CLASS_DEFAULT"; + qos_value.printable_name = "Default"; + break; + case 0x11: + qos_value.enum_value = requested_qos; + qos_value.constant_name = "QOS_CLASS_UTILITY"; + qos_value.printable_name = "Utility"; + break; + case 0x09: + qos_value.enum_value = requested_qos; + qos_value.constant_name = "QOS_CLASS_BACKGROUND"; + qos_value.printable_name = "Background"; + break; + case 0x00: + qos_value.enum_value = requested_qos; + qos_value.constant_name = "QOS_CLASS_UNSPECIFIED"; + qos_value.printable_name = "Unspecified"; + break; } - return qos_value; + } + return qos_value; } diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.h b/lldb/tools/debugserver/source/MacOSX/MachThread.h index a2a31817258..a98d8aa2b05 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThread.h +++ b/lldb/tools/debugserver/source/MacOSX/MachThread.h @@ -22,11 +22,11 @@ #include <pthread.h> #include <sys/signal.h> -#include "PThreadCondition.h" -#include "PThreadMutex.h" -#include "MachException.h" #include "DNBArch.h" #include "DNBRegisterInfo.h" +#include "MachException.h" +#include "PThreadCondition.h" +#include "PThreadMutex.h" #include "ThreadInfo.h" @@ -34,124 +34,135 @@ class DNBBreakpoint; class MachProcess; class MachThreadList; -class MachThread -{ +class MachThread { public: - - MachThread (MachProcess *process, bool is_64_bit, uint64_t unique_thread_id = 0, thread_t mach_port_number = 0); - ~MachThread (); - - MachProcess * Process() { return m_process; } - const MachProcess * - Process() const { return m_process; } - nub_process_t ProcessID() const; - void Dump(uint32_t index); - uint64_t ThreadID() const { return m_unique_id; } - thread_t MachPortNumber() const { return m_mach_port_number; } - thread_t InferiorThreadID() const; - - uint32_t SequenceID() const { return m_seq_id; } - static bool ThreadIDIsValid(uint64_t thread); // The 64-bit system-wide unique thread identifier - static bool MachPortNumberIsValid(thread_t thread); // The mach port # for this thread in debugserver namespace - void Resume(bool others_stopped); - void Suspend(); - bool SetSuspendCountBeforeResume(bool others_stopped); - bool RestoreSuspendCountAfterStop(); - - bool GetRegisterState(int flavor, bool force); - bool SetRegisterState(int flavor); - uint64_t GetPC(uint64_t failValue = INVALID_NUB_ADDRESS); // Get program counter - bool SetPC(uint64_t value); // Set program counter - uint64_t GetSP(uint64_t failValue = INVALID_NUB_ADDRESS); // Get stack pointer - - DNBBreakpoint * CurrentBreakpoint(); - uint32_t EnableHardwareBreakpoint (const DNBBreakpoint *breakpoint); - uint32_t EnableHardwareWatchpoint (const DNBBreakpoint *watchpoint, bool also_set_on_task); - bool DisableHardwareBreakpoint (const DNBBreakpoint *breakpoint); - bool DisableHardwareWatchpoint (const DNBBreakpoint *watchpoint, bool also_set_on_task); - uint32_t NumSupportedHardwareWatchpoints () const; - bool RollbackTransForHWP(); - bool FinishTransForHWP(); - - nub_state_t GetState(); - void SetState(nub_state_t state); - - void ThreadWillResume (const DNBThreadResumeAction *thread_action, bool others_stopped = false); - bool ShouldStop(bool &step_more); - bool IsStepping(); - bool ThreadDidStop(); - bool NotifyException(MachException::Data& exc); - const MachException::Data& GetStopException() { return m_stop_exception; } - - nub_size_t GetNumRegistersInSet(nub_size_t regSet) const; - const char * GetRegisterSetName(nub_size_t regSet) const; - const DNBRegisterInfo * - GetRegisterInfo(nub_size_t regSet, nub_size_t regIndex) const; - void DumpRegisterState(nub_size_t regSet); - const DNBRegisterSetInfo * - GetRegisterSetInfo(nub_size_t *num_reg_sets ) const; - bool GetRegisterValue ( uint32_t reg_set_idx, uint32_t reg_idx, DNBRegisterValue *reg_value ); - bool SetRegisterValue ( uint32_t reg_set_idx, uint32_t reg_idx, const DNBRegisterValue *reg_value ); - nub_size_t GetRegisterContext (void *buf, nub_size_t buf_len); - nub_size_t SetRegisterContext (const void *buf, nub_size_t buf_len); - uint32_t SaveRegisterState (); - bool RestoreRegisterState (uint32_t save_id); - - void NotifyBreakpointChanged (const DNBBreakpoint *bp) - { - } - - bool IsUserReady(); - struct thread_basic_info * - GetBasicInfo (); - const char * GetBasicInfoAsString () const; - const char * GetName (); - - DNBArchProtocol* - GetArchProtocol() - { - return m_arch_ap.get(); - } - - ThreadInfo::QoS GetRequestedQoS (nub_addr_t tsd, uint64_t dti_qos_class_index); - nub_addr_t GetPThreadT(); - nub_addr_t GetDispatchQueueT(); - nub_addr_t GetTSDAddressForThread (uint64_t plo_pthread_tsd_base_address_offset, uint64_t plo_pthread_tsd_base_offset, uint64_t plo_pthread_tsd_entry_size); - - static uint64_t GetGloballyUniqueThreadIDForMachPortID (thread_t mach_port_id); + MachThread(MachProcess *process, bool is_64_bit, + uint64_t unique_thread_id = 0, thread_t mach_port_number = 0); + ~MachThread(); + + MachProcess *Process() { return m_process; } + const MachProcess *Process() const { return m_process; } + nub_process_t ProcessID() const; + void Dump(uint32_t index); + uint64_t ThreadID() const { return m_unique_id; } + thread_t MachPortNumber() const { return m_mach_port_number; } + thread_t InferiorThreadID() const; + + uint32_t SequenceID() const { return m_seq_id; } + static bool ThreadIDIsValid( + uint64_t thread); // The 64-bit system-wide unique thread identifier + static bool MachPortNumberIsValid(thread_t thread); // The mach port # for + // this thread in + // debugserver namespace + void Resume(bool others_stopped); + void Suspend(); + bool SetSuspendCountBeforeResume(bool others_stopped); + bool RestoreSuspendCountAfterStop(); + + bool GetRegisterState(int flavor, bool force); + bool SetRegisterState(int flavor); + uint64_t + GetPC(uint64_t failValue = INVALID_NUB_ADDRESS); // Get program counter + bool SetPC(uint64_t value); // Set program counter + uint64_t GetSP(uint64_t failValue = INVALID_NUB_ADDRESS); // Get stack pointer + + DNBBreakpoint *CurrentBreakpoint(); + uint32_t EnableHardwareBreakpoint(const DNBBreakpoint *breakpoint); + uint32_t EnableHardwareWatchpoint(const DNBBreakpoint *watchpoint, + bool also_set_on_task); + bool DisableHardwareBreakpoint(const DNBBreakpoint *breakpoint); + bool DisableHardwareWatchpoint(const DNBBreakpoint *watchpoint, + bool also_set_on_task); + uint32_t NumSupportedHardwareWatchpoints() const; + bool RollbackTransForHWP(); + bool FinishTransForHWP(); + + nub_state_t GetState(); + void SetState(nub_state_t state); + + void ThreadWillResume(const DNBThreadResumeAction *thread_action, + bool others_stopped = false); + bool ShouldStop(bool &step_more); + bool IsStepping(); + bool ThreadDidStop(); + bool NotifyException(MachException::Data &exc); + const MachException::Data &GetStopException() { return m_stop_exception; } + + nub_size_t GetNumRegistersInSet(nub_size_t regSet) const; + const char *GetRegisterSetName(nub_size_t regSet) const; + const DNBRegisterInfo *GetRegisterInfo(nub_size_t regSet, + nub_size_t regIndex) const; + void DumpRegisterState(nub_size_t regSet); + const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets) const; + bool GetRegisterValue(uint32_t reg_set_idx, uint32_t reg_idx, + DNBRegisterValue *reg_value); + bool SetRegisterValue(uint32_t reg_set_idx, uint32_t reg_idx, + const DNBRegisterValue *reg_value); + nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len); + nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len); + uint32_t SaveRegisterState(); + bool RestoreRegisterState(uint32_t save_id); + + void NotifyBreakpointChanged(const DNBBreakpoint *bp) {} + + bool IsUserReady(); + struct thread_basic_info *GetBasicInfo(); + const char *GetBasicInfoAsString() const; + const char *GetName(); + + DNBArchProtocol *GetArchProtocol() { return m_arch_ap.get(); } + + ThreadInfo::QoS GetRequestedQoS(nub_addr_t tsd, uint64_t dti_qos_class_index); + nub_addr_t GetPThreadT(); + nub_addr_t GetDispatchQueueT(); + nub_addr_t + GetTSDAddressForThread(uint64_t plo_pthread_tsd_base_address_offset, + uint64_t plo_pthread_tsd_base_offset, + uint64_t plo_pthread_tsd_entry_size); + + static uint64_t GetGloballyUniqueThreadIDForMachPortID(thread_t mach_port_id); protected: - static bool GetBasicInfo(thread_t threadID, struct thread_basic_info *basic_info); - - bool - GetIdentifierInfo (); - -// const char * -// GetDispatchQueueName(); -// - MachProcess * m_process; // The process that owns this thread - uint64_t m_unique_id; // The globally unique ID for this thread (nub_thread_t) - thread_t m_mach_port_number; // The mach port # for this thread in debugserver namesp. - uint32_t m_seq_id; // A Sequential ID that increments with each new thread - nub_state_t m_state; // The state of our process - PThreadMutex m_state_mutex; // Multithreaded protection for m_state - struct thread_basic_info m_basic_info; // Basic information for a thread used to see if a thread is valid - int32_t m_suspend_count; // The current suspend count > 0 means we have suspended m_suspendCount times, - // < 0 means we have resumed it m_suspendCount times. - MachException::Data m_stop_exception; // The best exception that describes why this thread is stopped - std::unique_ptr<DNBArchProtocol> m_arch_ap; // Arch specific information for register state and more - const DNBRegisterSetInfo * m_reg_sets; // Register set information for this thread - nub_size_t m_num_reg_sets; - thread_identifier_info_data_t m_ident_info; - struct proc_threadinfo m_proc_threadinfo; - std::string m_dispatch_queue_name; - bool m_is_64_bit; - - // qos_class_t _pthread_qos_class_decode(pthread_priority_t priority, int *, unsigned long *); - unsigned int (*m_pthread_qos_class_decode) (unsigned long priority, int*, unsigned long *); + static bool GetBasicInfo(thread_t threadID, + struct thread_basic_info *basic_info); + + bool GetIdentifierInfo(); + + // const char * + // GetDispatchQueueName(); + // + MachProcess *m_process; // The process that owns this thread + uint64_t m_unique_id; // The globally unique ID for this thread (nub_thread_t) + thread_t m_mach_port_number; // The mach port # for this thread in debugserver + // namesp. + uint32_t m_seq_id; // A Sequential ID that increments with each new thread + nub_state_t m_state; // The state of our process + PThreadMutex m_state_mutex; // Multithreaded protection for m_state + struct thread_basic_info m_basic_info; // Basic information for a thread used + // to see if a thread is valid + int32_t m_suspend_count; // The current suspend count > 0 means we have + // suspended m_suspendCount times, + // < 0 means we have resumed it m_suspendCount + // times. + MachException::Data m_stop_exception; // The best exception that describes why + // this thread is stopped + std::unique_ptr<DNBArchProtocol> + m_arch_ap; // Arch specific information for register state and more + const DNBRegisterSetInfo + *m_reg_sets; // Register set information for this thread + nub_size_t m_num_reg_sets; + thread_identifier_info_data_t m_ident_info; + struct proc_threadinfo m_proc_threadinfo; + std::string m_dispatch_queue_name; + bool m_is_64_bit; + + // qos_class_t _pthread_qos_class_decode(pthread_priority_t priority, int *, + // unsigned long *); + unsigned int (*m_pthread_qos_class_decode)(unsigned long priority, int *, + unsigned long *); private: - friend class MachThreadList; + friend class MachThreadList; }; typedef std::shared_ptr<MachThread> MachThreadSP; diff --git a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp index 8a7da6f4531..cf0e205b349 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp @@ -20,501 +20,434 @@ #include "DNBThreadResumeActions.h" #include "MachProcess.h" -MachThreadList::MachThreadList() : - m_threads(), - m_threads_mutex(PTHREAD_MUTEX_RECURSIVE), - m_is_64_bit(false) -{ -} +MachThreadList::MachThreadList() + : m_threads(), m_threads_mutex(PTHREAD_MUTEX_RECURSIVE), + m_is_64_bit(false) {} -MachThreadList::~MachThreadList() -{ -} +MachThreadList::~MachThreadList() {} -nub_state_t -MachThreadList::GetState(nub_thread_t tid) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetState(); - return eStateInvalid; +nub_state_t MachThreadList::GetState(nub_thread_t tid) { + MachThreadSP thread_sp(GetThreadByID(tid)); + if (thread_sp) + return thread_sp->GetState(); + return eStateInvalid; } -const char * -MachThreadList::GetName (nub_thread_t tid) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetName(); - return NULL; +const char *MachThreadList::GetName(nub_thread_t tid) { + MachThreadSP thread_sp(GetThreadByID(tid)); + if (thread_sp) + return thread_sp->GetName(); + return NULL; } -ThreadInfo::QoS -MachThreadList::GetRequestedQoS (nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetRequestedQoS(tsd, dti_qos_class_index); - return ThreadInfo::QoS(); +ThreadInfo::QoS MachThreadList::GetRequestedQoS(nub_thread_t tid, + nub_addr_t tsd, + uint64_t dti_qos_class_index) { + MachThreadSP thread_sp(GetThreadByID(tid)); + if (thread_sp) + return thread_sp->GetRequestedQoS(tsd, dti_qos_class_index); + return ThreadInfo::QoS(); } -nub_addr_t -MachThreadList::GetPThreadT (nub_thread_t tid) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetPThreadT(); - return INVALID_NUB_ADDRESS; +nub_addr_t MachThreadList::GetPThreadT(nub_thread_t tid) { + MachThreadSP thread_sp(GetThreadByID(tid)); + if (thread_sp) + return thread_sp->GetPThreadT(); + return INVALID_NUB_ADDRESS; } -nub_addr_t -MachThreadList::GetDispatchQueueT (nub_thread_t tid) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetDispatchQueueT(); - return INVALID_NUB_ADDRESS; +nub_addr_t MachThreadList::GetDispatchQueueT(nub_thread_t tid) { + MachThreadSP thread_sp(GetThreadByID(tid)); + if (thread_sp) + return thread_sp->GetDispatchQueueT(); + return INVALID_NUB_ADDRESS; } -nub_addr_t -MachThreadList::GetTSDAddressForThread (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) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetTSDAddressForThread(plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size); - return INVALID_NUB_ADDRESS; +nub_addr_t MachThreadList::GetTSDAddressForThread( + 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) { + MachThreadSP thread_sp(GetThreadByID(tid)); + if (thread_sp) + return thread_sp->GetTSDAddressForThread( + plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, + plo_pthread_tsd_entry_size); + return INVALID_NUB_ADDRESS; } -nub_thread_t -MachThreadList::SetCurrentThread(nub_thread_t tid) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - { - m_current_thread = thread_sp; - return tid; - } - return INVALID_NUB_THREAD; +nub_thread_t MachThreadList::SetCurrentThread(nub_thread_t tid) { + MachThreadSP thread_sp(GetThreadByID(tid)); + if (thread_sp) { + m_current_thread = thread_sp; + return tid; + } + return INVALID_NUB_THREAD; } - -bool -MachThreadList::GetThreadStoppedReason(nub_thread_t tid, struct DNBThreadStopInfo *stop_info) const -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetStopException().GetStopInfo(stop_info); - return false; +bool MachThreadList::GetThreadStoppedReason( + nub_thread_t tid, struct DNBThreadStopInfo *stop_info) const { + MachThreadSP thread_sp(GetThreadByID(tid)); + if (thread_sp) + return thread_sp->GetStopException().GetStopInfo(stop_info); + return false; } -bool -MachThreadList::GetIdentifierInfo (nub_thread_t tid, thread_identifier_info_data_t *ident_info) -{ - thread_t mach_port_number = GetMachPortNumberByThreadID (tid); +bool MachThreadList::GetIdentifierInfo( + nub_thread_t tid, thread_identifier_info_data_t *ident_info) { + thread_t mach_port_number = GetMachPortNumberByThreadID(tid); - mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; - return ::thread_info (mach_port_number, THREAD_IDENTIFIER_INFO, (thread_info_t)ident_info, &count) == KERN_SUCCESS; + mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; + return ::thread_info(mach_port_number, THREAD_IDENTIFIER_INFO, + (thread_info_t)ident_info, &count) == KERN_SUCCESS; } -void -MachThreadList::DumpThreadStoppedReason (nub_thread_t tid) const -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - thread_sp->GetStopException().DumpStopReason(); +void MachThreadList::DumpThreadStoppedReason(nub_thread_t tid) const { + MachThreadSP thread_sp(GetThreadByID(tid)); + if (thread_sp) + thread_sp->GetStopException().DumpStopReason(); } -const char * -MachThreadList::GetThreadInfo (nub_thread_t tid) const -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetBasicInfoAsString(); - return NULL; +const char *MachThreadList::GetThreadInfo(nub_thread_t tid) const { + MachThreadSP thread_sp(GetThreadByID(tid)); + if (thread_sp) + return thread_sp->GetBasicInfoAsString(); + return NULL; } -MachThreadSP -MachThreadList::GetThreadByID (nub_thread_t tid) const -{ - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - MachThreadSP thread_sp; - const size_t num_threads = m_threads.size(); - for (size_t idx = 0; idx < num_threads; ++idx) - { - if (m_threads[idx]->ThreadID() == tid) - { - thread_sp = m_threads[idx]; - break; - } +MachThreadSP MachThreadList::GetThreadByID(nub_thread_t tid) const { + PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); + MachThreadSP thread_sp; + const size_t num_threads = m_threads.size(); + for (size_t idx = 0; idx < num_threads; ++idx) { + if (m_threads[idx]->ThreadID() == tid) { + thread_sp = m_threads[idx]; + break; } - return thread_sp; + } + return thread_sp; } MachThreadSP -MachThreadList::GetThreadByMachPortNumber (thread_t mach_port_number) const -{ - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - MachThreadSP thread_sp; - const size_t num_threads = m_threads.size(); - for (size_t idx = 0; idx < num_threads; ++idx) - { - if (m_threads[idx]->MachPortNumber() == mach_port_number) - { - thread_sp = m_threads[idx]; - break; - } +MachThreadList::GetThreadByMachPortNumber(thread_t mach_port_number) const { + PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); + MachThreadSP thread_sp; + const size_t num_threads = m_threads.size(); + for (size_t idx = 0; idx < num_threads; ++idx) { + if (m_threads[idx]->MachPortNumber() == mach_port_number) { + thread_sp = m_threads[idx]; + break; } - return thread_sp; + } + return thread_sp; } nub_thread_t -MachThreadList::GetThreadIDByMachPortNumber (thread_t mach_port_number) const -{ - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - MachThreadSP thread_sp; - const size_t num_threads = m_threads.size(); - for (size_t idx = 0; idx < num_threads; ++idx) - { - if (m_threads[idx]->MachPortNumber() == mach_port_number) - { - return m_threads[idx]->ThreadID(); - } +MachThreadList::GetThreadIDByMachPortNumber(thread_t mach_port_number) const { + PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); + MachThreadSP thread_sp; + const size_t num_threads = m_threads.size(); + for (size_t idx = 0; idx < num_threads; ++idx) { + if (m_threads[idx]->MachPortNumber() == mach_port_number) { + return m_threads[idx]->ThreadID(); } - return INVALID_NUB_THREAD; -} - -thread_t -MachThreadList::GetMachPortNumberByThreadID (nub_thread_t globally_unique_id) const -{ - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - MachThreadSP thread_sp; - const size_t num_threads = m_threads.size(); - for (size_t idx = 0; idx < num_threads; ++idx) - { - if (m_threads[idx]->ThreadID() == globally_unique_id) - { - return m_threads[idx]->MachPortNumber(); - } + } + return INVALID_NUB_THREAD; +} + +thread_t MachThreadList::GetMachPortNumberByThreadID( + nub_thread_t globally_unique_id) const { + PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); + MachThreadSP thread_sp; + const size_t num_threads = m_threads.size(); + for (size_t idx = 0; idx < num_threads; ++idx) { + if (m_threads[idx]->ThreadID() == globally_unique_id) { + return m_threads[idx]->MachPortNumber(); } - return 0; + } + return 0; } -bool -MachThreadList::GetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *reg_value ) const -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetRegisterValue(set, reg, reg_value); +bool MachThreadList::GetRegisterValue(nub_thread_t tid, uint32_t set, + uint32_t reg, + DNBRegisterValue *reg_value) const { + MachThreadSP thread_sp(GetThreadByID(tid)); + if (thread_sp) + return thread_sp->GetRegisterValue(set, reg, reg_value); - return false; + return false; } -bool -MachThreadList::SetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *reg_value ) const -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->SetRegisterValue(set, reg, reg_value); +bool MachThreadList::SetRegisterValue(nub_thread_t tid, uint32_t set, + uint32_t reg, + const DNBRegisterValue *reg_value) const { + MachThreadSP thread_sp(GetThreadByID(tid)); + if (thread_sp) + return thread_sp->SetRegisterValue(set, reg, reg_value); - return false; + return false; } -nub_size_t -MachThreadList::GetRegisterContext (nub_thread_t tid, void *buf, size_t buf_len) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->GetRegisterContext (buf, buf_len); - return 0; +nub_size_t MachThreadList::GetRegisterContext(nub_thread_t tid, void *buf, + size_t buf_len) { + MachThreadSP thread_sp(GetThreadByID(tid)); + if (thread_sp) + return thread_sp->GetRegisterContext(buf, buf_len); + return 0; } -nub_size_t -MachThreadList::SetRegisterContext (nub_thread_t tid, const void *buf, size_t buf_len) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->SetRegisterContext (buf, buf_len); - return 0; +nub_size_t MachThreadList::SetRegisterContext(nub_thread_t tid, const void *buf, + size_t buf_len) { + MachThreadSP thread_sp(GetThreadByID(tid)); + if (thread_sp) + return thread_sp->SetRegisterContext(buf, buf_len); + return 0; } -uint32_t -MachThreadList::SaveRegisterState (nub_thread_t tid) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->SaveRegisterState (); - return 0; +uint32_t MachThreadList::SaveRegisterState(nub_thread_t tid) { + MachThreadSP thread_sp(GetThreadByID(tid)); + if (thread_sp) + return thread_sp->SaveRegisterState(); + return 0; } -bool -MachThreadList::RestoreRegisterState (nub_thread_t tid, uint32_t save_id) -{ - MachThreadSP thread_sp (GetThreadByID (tid)); - if (thread_sp) - return thread_sp->RestoreRegisterState (save_id); - return 0; +bool MachThreadList::RestoreRegisterState(nub_thread_t tid, uint32_t save_id) { + MachThreadSP thread_sp(GetThreadByID(tid)); + if (thread_sp) + return thread_sp->RestoreRegisterState(save_id); + return 0; } +nub_size_t MachThreadList::NumThreads() const { + PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); + return m_threads.size(); +} -nub_size_t -MachThreadList::NumThreads () const -{ - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - return m_threads.size(); +nub_thread_t MachThreadList::ThreadIDAtIndex(nub_size_t idx) const { + PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); + if (idx < m_threads.size()) + return m_threads[idx]->ThreadID(); + return INVALID_NUB_THREAD; } -nub_thread_t -MachThreadList::ThreadIDAtIndex (nub_size_t idx) const -{ - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - if (idx < m_threads.size()) - return m_threads[idx]->ThreadID(); - return INVALID_NUB_THREAD; +nub_thread_t MachThreadList::CurrentThreadID() { + MachThreadSP thread_sp; + CurrentThread(thread_sp); + if (thread_sp.get()) + return thread_sp->ThreadID(); + return INVALID_NUB_THREAD; } -nub_thread_t -MachThreadList::CurrentThreadID ( ) -{ - MachThreadSP thread_sp; - CurrentThread(thread_sp); - if (thread_sp.get()) - return thread_sp->ThreadID(); - return INVALID_NUB_THREAD; -} - -bool -MachThreadList::NotifyException(MachException::Data& exc) -{ - MachThreadSP thread_sp (GetThreadByMachPortNumber (exc.thread_port)); - if (thread_sp) - { - thread_sp->NotifyException(exc); - return true; - } - return false; +bool MachThreadList::NotifyException(MachException::Data &exc) { + MachThreadSP thread_sp(GetThreadByMachPortNumber(exc.thread_port)); + if (thread_sp) { + thread_sp->NotifyException(exc); + return true; + } + return false; } -void -MachThreadList::Clear() -{ - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - m_threads.clear(); +void MachThreadList::Clear() { + PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); + m_threads.clear(); } uint32_t -MachThreadList::UpdateThreadList(MachProcess *process, bool update, MachThreadList::collection *new_threads) -{ - // locker will keep a mutex locked until it goes out of scope - DNBLogThreadedIf (LOG_THREAD, "MachThreadList::UpdateThreadList (pid = %4.4x, update = %u) process stop count = %u", process->ProcessID(), update, process->StopCount()); - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - - if (process->StopCount() == 0) - { - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process->ProcessID() }; - struct kinfo_proc processInfo; - size_t bufsize = sizeof(processInfo); - if (sysctl(mib, (unsigned)(sizeof(mib)/sizeof(int)), &processInfo, &bufsize, NULL, 0) == 0 && bufsize > 0) - { - if (processInfo.kp_proc.p_flag & P_LP64) - m_is_64_bit = true; - } -#if defined (__i386__) || defined (__x86_64__) - if (m_is_64_bit) - DNBArchProtocol::SetArchitecture(CPU_TYPE_X86_64); - else - DNBArchProtocol::SetArchitecture(CPU_TYPE_I386); -#elif defined (__arm__) || defined (__arm64__) || defined (__aarch64__) - if (m_is_64_bit) - DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM64); - else - DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM); -#endif +MachThreadList::UpdateThreadList(MachProcess *process, bool update, + MachThreadList::collection *new_threads) { + // locker will keep a mutex locked until it goes out of scope + DNBLogThreadedIf(LOG_THREAD, "MachThreadList::UpdateThreadList (pid = %4.4x, " + "update = %u) process stop count = %u", + process->ProcessID(), update, process->StopCount()); + PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); + + if (process->StopCount() == 0) { + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, process->ProcessID()}; + struct kinfo_proc processInfo; + size_t bufsize = sizeof(processInfo); + if (sysctl(mib, (unsigned)(sizeof(mib) / sizeof(int)), &processInfo, + &bufsize, NULL, 0) == 0 && + bufsize > 0) { + if (processInfo.kp_proc.p_flag & P_LP64) + m_is_64_bit = true; } - - if (m_threads.empty() || update) - { - thread_array_t thread_list = NULL; - mach_msg_type_number_t thread_list_count = 0; - task_t task = process->Task().TaskPort(); - DNBError err(::task_threads (task, &thread_list, &thread_list_count), DNBError::MachKernel); - - if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) - err.LogThreaded("::task_threads ( task = 0x%4.4x, thread_list => %p, thread_list_count => %u )", task, thread_list, thread_list_count); - - if (err.Error() == KERN_SUCCESS && thread_list_count > 0) - { - MachThreadList::collection currThreads; - size_t idx; - // Iterator through the current thread list and see which threads - // we already have in our list (keep them), which ones we don't - // (add them), and which ones are not around anymore (remove them). - for (idx = 0; idx < thread_list_count; ++idx) - { - const thread_t mach_port_num = thread_list[idx]; - - uint64_t unique_thread_id = MachThread::GetGloballyUniqueThreadIDForMachPortID (mach_port_num); - MachThreadSP thread_sp (GetThreadByID (unique_thread_id)); - if (thread_sp) - { - // Keep the existing thread class - currThreads.push_back(thread_sp); - } - else - { - // We don't have this thread, lets add it. - thread_sp.reset(new MachThread(process, m_is_64_bit, unique_thread_id, mach_port_num)); - - // Add the new thread regardless of its is user ready state... - // Make sure the thread is ready to be displayed and shown to users - // before we add this thread to our list... - if (thread_sp->IsUserReady()) - { - if (new_threads) - new_threads->push_back(thread_sp); - - currThreads.push_back(thread_sp); - } - } - } - - m_threads.swap(currThreads); - m_current_thread.reset(); - - // Free the vm memory given to us by ::task_threads() - vm_size_t thread_list_size = (vm_size_t) (thread_list_count * sizeof (thread_t)); - ::vm_deallocate (::mach_task_self(), - (vm_address_t)thread_list, - thread_list_size); - } - } - return static_cast<uint32_t>(m_threads.size()); -} - - -void -MachThreadList::CurrentThread (MachThreadSP& thread_sp) -{ - // locker will keep a mutex locked until it goes out of scope - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - if (m_current_thread.get() == NULL) - { - // Figure out which thread is going to be our current thread. - // This is currently done by finding the first thread in the list - // that has a valid exception. - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) - { - if (m_threads[idx]->GetStopException().IsValid()) - { - m_current_thread = m_threads[idx]; - break; - } +#if defined(__i386__) || defined(__x86_64__) + if (m_is_64_bit) + DNBArchProtocol::SetArchitecture(CPU_TYPE_X86_64); + else + DNBArchProtocol::SetArchitecture(CPU_TYPE_I386); +#elif defined(__arm__) || defined(__arm64__) || defined(__aarch64__) + if (m_is_64_bit) + DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM64); + else + DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM); +#endif + } + + if (m_threads.empty() || update) { + thread_array_t thread_list = NULL; + mach_msg_type_number_t thread_list_count = 0; + task_t task = process->Task().TaskPort(); + DNBError err(::task_threads(task, &thread_list, &thread_list_count), + DNBError::MachKernel); + + if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail()) + err.LogThreaded("::task_threads ( task = 0x%4.4x, thread_list => %p, " + "thread_list_count => %u )", + task, thread_list, thread_list_count); + + if (err.Error() == KERN_SUCCESS && thread_list_count > 0) { + MachThreadList::collection currThreads; + size_t idx; + // Iterator through the current thread list and see which threads + // we already have in our list (keep them), which ones we don't + // (add them), and which ones are not around anymore (remove them). + for (idx = 0; idx < thread_list_count; ++idx) { + const thread_t mach_port_num = thread_list[idx]; + + uint64_t unique_thread_id = + MachThread::GetGloballyUniqueThreadIDForMachPortID(mach_port_num); + MachThreadSP thread_sp(GetThreadByID(unique_thread_id)); + if (thread_sp) { + // Keep the existing thread class + currThreads.push_back(thread_sp); + } else { + // We don't have this thread, lets add it. + thread_sp.reset(new MachThread(process, m_is_64_bit, unique_thread_id, + mach_port_num)); + + // Add the new thread regardless of its is user ready state... + // Make sure the thread is ready to be displayed and shown to users + // before we add this thread to our list... + if (thread_sp->IsUserReady()) { + if (new_threads) + new_threads->push_back(thread_sp); + + currThreads.push_back(thread_sp); + } } + } + + m_threads.swap(currThreads); + m_current_thread.reset(); + + // Free the vm memory given to us by ::task_threads() + vm_size_t thread_list_size = + (vm_size_t)(thread_list_count * sizeof(thread_t)); + ::vm_deallocate(::mach_task_self(), (vm_address_t)thread_list, + thread_list_size); } - thread_sp = m_current_thread; + } + return static_cast<uint32_t>(m_threads.size()); } -void -MachThreadList::Dump() const -{ - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); +void MachThreadList::CurrentThread(MachThreadSP &thread_sp) { + // locker will keep a mutex locked until it goes out of scope + PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); + if (m_current_thread.get() == NULL) { + // Figure out which thread is going to be our current thread. + // This is currently done by finding the first thread in the list + // that has a valid exception. const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) - { - m_threads[idx]->Dump(idx); + for (uint32_t idx = 0; idx < num_threads; ++idx) { + if (m_threads[idx]->GetStopException().IsValid()) { + m_current_thread = m_threads[idx]; + break; + } } -} - - -void -MachThreadList::ProcessWillResume(MachProcess *process, const DNBThreadResumeActions &thread_actions) -{ - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - - // Update our thread list, because sometimes libdispatch or the kernel - // will spawn threads while a task is suspended. - MachThreadList::collection new_threads; - - // First figure out if we were planning on running only one thread, and if so force that thread to resume. - bool run_one_thread; - nub_thread_t solo_thread = INVALID_NUB_THREAD; - if (thread_actions.GetSize() > 0 - && thread_actions.NumActionsWithState(eStateStepping) + thread_actions.NumActionsWithState (eStateRunning) == 1) - { - run_one_thread = true; - const DNBThreadResumeAction *action_ptr = thread_actions.GetFirst(); - size_t num_actions = thread_actions.GetSize(); - for (size_t i = 0; i < num_actions; i++, action_ptr++) - { - if (action_ptr->state == eStateStepping || action_ptr->state == eStateRunning) - { - solo_thread = action_ptr->tid; - break; - } - } + } + thread_sp = m_current_thread; +} + +void MachThreadList::Dump() const { + PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); + const size_t num_threads = m_threads.size(); + for (uint32_t idx = 0; idx < num_threads; ++idx) { + m_threads[idx]->Dump(idx); + } +} + +void MachThreadList::ProcessWillResume( + MachProcess *process, const DNBThreadResumeActions &thread_actions) { + PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); + + // Update our thread list, because sometimes libdispatch or the kernel + // will spawn threads while a task is suspended. + MachThreadList::collection new_threads; + + // First figure out if we were planning on running only one thread, and if so + // force that thread to resume. + bool run_one_thread; + nub_thread_t solo_thread = INVALID_NUB_THREAD; + if (thread_actions.GetSize() > 0 && + thread_actions.NumActionsWithState(eStateStepping) + + thread_actions.NumActionsWithState(eStateRunning) == + 1) { + run_one_thread = true; + const DNBThreadResumeAction *action_ptr = thread_actions.GetFirst(); + size_t num_actions = thread_actions.GetSize(); + for (size_t i = 0; i < num_actions; i++, action_ptr++) { + if (action_ptr->state == eStateStepping || + action_ptr->state == eStateRunning) { + solo_thread = action_ptr->tid; + break; + } + } + } else + run_one_thread = false; + + UpdateThreadList(process, true, &new_threads); + + DNBThreadResumeAction resume_new_threads = {-1U, eStateRunning, 0, + INVALID_NUB_ADDRESS}; + // If we are planning to run only one thread, any new threads should be + // suspended. + if (run_one_thread) + resume_new_threads.state = eStateSuspended; + + const size_t num_new_threads = new_threads.size(); + const size_t num_threads = m_threads.size(); + for (uint32_t idx = 0; idx < num_threads; ++idx) { + MachThread *thread = m_threads[idx].get(); + bool handled = false; + for (uint32_t new_idx = 0; new_idx < num_new_threads; ++new_idx) { + if (thread == new_threads[new_idx].get()) { + thread->ThreadWillResume(&resume_new_threads); + handled = true; + break; + } } - else - run_one_thread = false; - - UpdateThreadList(process, true, &new_threads); - - DNBThreadResumeAction resume_new_threads = { -1U, eStateRunning, 0, INVALID_NUB_ADDRESS }; - // If we are planning to run only one thread, any new threads should be suspended. - if (run_one_thread) - resume_new_threads.state = eStateSuspended; - - const size_t num_new_threads = new_threads.size(); - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) - { - MachThread *thread = m_threads[idx].get(); - bool handled = false; - for (uint32_t new_idx = 0; new_idx < num_new_threads; ++new_idx) - { - if (thread == new_threads[new_idx].get()) - { - thread->ThreadWillResume(&resume_new_threads); - handled = true; - break; - } - } - if (!handled) - { - const DNBThreadResumeAction *thread_action = thread_actions.GetActionForThread (thread->ThreadID(), true); - // There must always be a thread action for every thread. - assert (thread_action); - bool others_stopped = false; - if (solo_thread == thread->ThreadID()) - others_stopped = true; - thread->ThreadWillResume (thread_action, others_stopped); - } + if (!handled) { + const DNBThreadResumeAction *thread_action = + thread_actions.GetActionForThread(thread->ThreadID(), true); + // There must always be a thread action for every thread. + assert(thread_action); + bool others_stopped = false; + if (solo_thread == thread->ThreadID()) + others_stopped = true; + thread->ThreadWillResume(thread_action, others_stopped); } - - if (new_threads.size()) - { - for (uint32_t idx = 0; idx < num_new_threads; ++idx) - { - DNBLogThreadedIf (LOG_THREAD, "MachThreadList::ProcessWillResume (pid = %4.4x) stop-id=%u, resuming newly discovered thread: 0x%8.8" PRIx64 ", thread-is-user-ready=%i)", - process->ProcessID(), - process->StopCount(), - new_threads[idx]->ThreadID(), - new_threads[idx]->IsUserReady()); - } + } + + if (new_threads.size()) { + for (uint32_t idx = 0; idx < num_new_threads; ++idx) { + DNBLogThreadedIf( + LOG_THREAD, "MachThreadList::ProcessWillResume (pid = %4.4x) " + "stop-id=%u, resuming newly discovered thread: " + "0x%8.8" PRIx64 ", thread-is-user-ready=%i)", + process->ProcessID(), process->StopCount(), + new_threads[idx]->ThreadID(), new_threads[idx]->IsUserReady()); } + } } -uint32_t -MachThreadList::ProcessDidStop(MachProcess *process) -{ - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - // Update our thread list - const uint32_t num_threads = UpdateThreadList(process, true); - for (uint32_t idx = 0; idx < num_threads; ++idx) - { - m_threads[idx]->ThreadDidStop(); - } - return num_threads; +uint32_t MachThreadList::ProcessDidStop(MachProcess *process) { + PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); + // Update our thread list + const uint32_t num_threads = UpdateThreadList(process, true); + for (uint32_t idx = 0; idx < num_threads; ++idx) { + m_threads[idx]->ThreadDidStop(); + } + return num_threads; } //---------------------------------------------------------------------- @@ -528,141 +461,122 @@ MachThreadList::ProcessDidStop(MachProcess *process) // true if we should stop and notify our clients // false if we should resume our child process and skip notification //---------------------------------------------------------------------- -bool -MachThreadList::ShouldStop(bool &step_more) -{ - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - uint32_t should_stop = false; - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; !should_stop && idx < num_threads; ++idx) - { - should_stop = m_threads[idx]->ShouldStop(step_more); - } - return should_stop; +bool MachThreadList::ShouldStop(bool &step_more) { + PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); + uint32_t should_stop = false; + const size_t num_threads = m_threads.size(); + for (uint32_t idx = 0; !should_stop && idx < num_threads; ++idx) { + should_stop = m_threads[idx]->ShouldStop(step_more); + } + return should_stop; } - -void -MachThreadList::NotifyBreakpointChanged (const DNBBreakpoint *bp) -{ - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) - { - m_threads[idx]->NotifyBreakpointChanged(bp); - } +void MachThreadList::NotifyBreakpointChanged(const DNBBreakpoint *bp) { + PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); + const size_t num_threads = m_threads.size(); + for (uint32_t idx = 0; idx < num_threads; ++idx) { + m_threads[idx]->NotifyBreakpointChanged(bp); + } } - uint32_t -MachThreadList::EnableHardwareBreakpoint (const DNBBreakpoint* bp) const -{ - if (bp != NULL) - { - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) - m_threads[idx]->EnableHardwareBreakpoint(bp); - } - return INVALID_NUB_HW_INDEX; +MachThreadList::EnableHardwareBreakpoint(const DNBBreakpoint *bp) const { + if (bp != NULL) { + const size_t num_threads = m_threads.size(); + for (uint32_t idx = 0; idx < num_threads; ++idx) + m_threads[idx]->EnableHardwareBreakpoint(bp); + } + return INVALID_NUB_HW_INDEX; } -bool -MachThreadList::DisableHardwareBreakpoint (const DNBBreakpoint* bp) const -{ - if (bp != NULL) - { - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; idx < num_threads; ++idx) - m_threads[idx]->DisableHardwareBreakpoint(bp); - } - return false; +bool MachThreadList::DisableHardwareBreakpoint(const DNBBreakpoint *bp) const { + if (bp != NULL) { + const size_t num_threads = m_threads.size(); + for (uint32_t idx = 0; idx < num_threads; ++idx) + m_threads[idx]->DisableHardwareBreakpoint(bp); + } + return false; } -// DNBWatchpointSet() -> MachProcess::CreateWatchpoint() -> MachProcess::EnableWatchpoint() +// DNBWatchpointSet() -> MachProcess::CreateWatchpoint() -> +// MachProcess::EnableWatchpoint() // -> MachThreadList::EnableHardwareWatchpoint(). uint32_t -MachThreadList::EnableHardwareWatchpoint (const DNBBreakpoint* wp) const -{ - uint32_t hw_index = INVALID_NUB_HW_INDEX; - if (wp != NULL) - { - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - const size_t num_threads = m_threads.size(); - // On Mac OS X we have to prime the control registers for new threads. We do this - // using the control register data for the first thread, for lack of a better way of choosing. - bool also_set_on_task = true; - for (uint32_t idx = 0; idx < num_threads; ++idx) - { - if ((hw_index = m_threads[idx]->EnableHardwareWatchpoint(wp, also_set_on_task)) == INVALID_NUB_HW_INDEX) - { - // We know that idx failed for some reason. Let's rollback the transaction for [0, idx). - for (uint32_t i = 0; i < idx; ++i) - m_threads[i]->RollbackTransForHWP(); - return INVALID_NUB_HW_INDEX; - } - also_set_on_task = false; - } - // Notify each thread to commit the pending transaction. - for (uint32_t idx = 0; idx < num_threads; ++idx) - m_threads[idx]->FinishTransForHWP(); - - } - return hw_index; -} - -bool -MachThreadList::DisableHardwareWatchpoint (const DNBBreakpoint* wp) const -{ - if (wp != NULL) - { - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - const size_t num_threads = m_threads.size(); - - // On Mac OS X we have to prime the control registers for new threads. We do this - // using the control register data for the first thread, for lack of a better way of choosing. - bool also_set_on_task = true; - for (uint32_t idx = 0; idx < num_threads; ++idx) - { - if (!m_threads[idx]->DisableHardwareWatchpoint(wp, also_set_on_task)) - { - // We know that idx failed for some reason. Let's rollback the transaction for [0, idx). - for (uint32_t i = 0; i < idx; ++i) - m_threads[i]->RollbackTransForHWP(); - return false; - } - also_set_on_task = false; - } - // Notify each thread to commit the pending transaction. - for (uint32_t idx = 0; idx < num_threads; ++idx) - m_threads[idx]->FinishTransForHWP(); - - return true; +MachThreadList::EnableHardwareWatchpoint(const DNBBreakpoint *wp) const { + uint32_t hw_index = INVALID_NUB_HW_INDEX; + if (wp != NULL) { + PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); + const size_t num_threads = m_threads.size(); + // On Mac OS X we have to prime the control registers for new threads. We + // do this + // using the control register data for the first thread, for lack of a + // better way of choosing. + bool also_set_on_task = true; + for (uint32_t idx = 0; idx < num_threads; ++idx) { + if ((hw_index = m_threads[idx]->EnableHardwareWatchpoint( + wp, also_set_on_task)) == INVALID_NUB_HW_INDEX) { + // We know that idx failed for some reason. Let's rollback the + // transaction for [0, idx). + for (uint32_t i = 0; i < idx; ++i) + m_threads[i]->RollbackTransForHWP(); + return INVALID_NUB_HW_INDEX; + } + also_set_on_task = false; } - return false; + // Notify each thread to commit the pending transaction. + for (uint32_t idx = 0; idx < num_threads; ++idx) + m_threads[idx]->FinishTransForHWP(); + } + return hw_index; } -uint32_t -MachThreadList::NumSupportedHardwareWatchpoints () const -{ - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); +bool MachThreadList::DisableHardwareWatchpoint(const DNBBreakpoint *wp) const { + if (wp != NULL) { + PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); const size_t num_threads = m_threads.size(); - // Use an arbitrary thread to retrieve the number of supported hardware watchpoints. - if (num_threads) - return m_threads[0]->NumSupportedHardwareWatchpoints(); - return 0; -} -uint32_t -MachThreadList::GetThreadIndexForThreadStoppedWithSignal (const int signo) const -{ - PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); - uint32_t should_stop = false; - const size_t num_threads = m_threads.size(); - for (uint32_t idx = 0; !should_stop && idx < num_threads; ++idx) - { - if (m_threads[idx]->GetStopException().SoftSignal () == signo) - return idx; + // On Mac OS X we have to prime the control registers for new threads. We + // do this + // using the control register data for the first thread, for lack of a + // better way of choosing. + bool also_set_on_task = true; + for (uint32_t idx = 0; idx < num_threads; ++idx) { + if (!m_threads[idx]->DisableHardwareWatchpoint(wp, also_set_on_task)) { + // We know that idx failed for some reason. Let's rollback the + // transaction for [0, idx). + for (uint32_t i = 0; i < idx; ++i) + m_threads[i]->RollbackTransForHWP(); + return false; + } + also_set_on_task = false; } - return UINT32_MAX; + // Notify each thread to commit the pending transaction. + for (uint32_t idx = 0; idx < num_threads; ++idx) + m_threads[idx]->FinishTransForHWP(); + + return true; + } + return false; +} + +uint32_t MachThreadList::NumSupportedHardwareWatchpoints() const { + PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); + const size_t num_threads = m_threads.size(); + // Use an arbitrary thread to retrieve the number of supported hardware + // watchpoints. + if (num_threads) + return m_threads[0]->NumSupportedHardwareWatchpoints(); + return 0; +} + +uint32_t MachThreadList::GetThreadIndexForThreadStoppedWithSignal( + const int signo) const { + PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex); + uint32_t should_stop = false; + const size_t num_threads = m_threads.size(); + for (uint32_t idx = 0; !should_stop && idx < num_threads; ++idx) { + if (m_threads[idx]->GetStopException().SoftSignal() == signo) + return idx; + } + return UINT32_MAX; } - diff --git a/lldb/tools/debugserver/source/MacOSX/MachThreadList.h b/lldb/tools/debugserver/source/MacOSX/MachThreadList.h index 0ab550e83fc..bcef695edf8 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThreadList.h +++ b/lldb/tools/debugserver/source/MacOSX/MachThreadList.h @@ -19,69 +19,79 @@ class DNBThreadResumeActions; -class MachThreadList -{ +class MachThreadList { public: - MachThreadList (); - ~MachThreadList (); + MachThreadList(); + ~MachThreadList(); - void Clear (); - void Dump () const; - bool GetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *reg_value) const; - bool SetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *reg_value) const; - nub_size_t GetRegisterContext (nub_thread_t tid, void *buf, size_t buf_len); - nub_size_t SetRegisterContext (nub_thread_t tid, const void *buf, size_t buf_len); - uint32_t SaveRegisterState (nub_thread_t tid); - bool RestoreRegisterState (nub_thread_t tid, uint32_t save_id); - const char * GetThreadInfo (nub_thread_t tid) const; - void ProcessWillResume (MachProcess *process, const DNBThreadResumeActions &thread_actions); - uint32_t ProcessDidStop (MachProcess *process); - bool NotifyException (MachException::Data& exc); - bool ShouldStop (bool &step_more); - const char * GetName (nub_thread_t tid); - nub_state_t GetState (nub_thread_t tid); - nub_thread_t SetCurrentThread (nub_thread_t tid); + void Clear(); + void Dump() const; + bool GetRegisterValue(nub_thread_t tid, uint32_t set, uint32_t reg, + DNBRegisterValue *reg_value) const; + bool SetRegisterValue(nub_thread_t tid, uint32_t set, uint32_t reg, + const DNBRegisterValue *reg_value) const; + nub_size_t GetRegisterContext(nub_thread_t tid, void *buf, size_t buf_len); + nub_size_t SetRegisterContext(nub_thread_t tid, const void *buf, + size_t buf_len); + uint32_t SaveRegisterState(nub_thread_t tid); + bool RestoreRegisterState(nub_thread_t tid, uint32_t save_id); + const char *GetThreadInfo(nub_thread_t tid) const; + void ProcessWillResume(MachProcess *process, + const DNBThreadResumeActions &thread_actions); + uint32_t ProcessDidStop(MachProcess *process); + bool NotifyException(MachException::Data &exc); + bool ShouldStop(bool &step_more); + const char *GetName(nub_thread_t tid); + nub_state_t GetState(nub_thread_t tid); + nub_thread_t SetCurrentThread(nub_thread_t tid); - ThreadInfo::QoS GetRequestedQoS (nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index); - nub_addr_t GetPThreadT (nub_thread_t tid); - nub_addr_t GetDispatchQueueT (nub_thread_t tid); - nub_addr_t GetTSDAddressForThread (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); + ThreadInfo::QoS GetRequestedQoS(nub_thread_t tid, nub_addr_t tsd, + uint64_t dti_qos_class_index); + nub_addr_t GetPThreadT(nub_thread_t tid); + nub_addr_t GetDispatchQueueT(nub_thread_t tid); + nub_addr_t + GetTSDAddressForThread(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); - bool GetThreadStoppedReason (nub_thread_t tid, struct DNBThreadStopInfo *stop_info) const; - void DumpThreadStoppedReason (nub_thread_t tid) const; - bool GetIdentifierInfo (nub_thread_t tid, thread_identifier_info_data_t *ident_info); - nub_size_t NumThreads () const; - nub_thread_t ThreadIDAtIndex (nub_size_t idx) const; - nub_thread_t CurrentThreadID (); - void CurrentThread (MachThreadSP& threadSP); - void NotifyBreakpointChanged (const DNBBreakpoint *bp); - uint32_t EnableHardwareBreakpoint (const DNBBreakpoint *bp) const; - bool DisableHardwareBreakpoint (const DNBBreakpoint *bp) const; - uint32_t EnableHardwareWatchpoint (const DNBBreakpoint *wp) const; - bool DisableHardwareWatchpoint (const DNBBreakpoint *wp) const; - uint32_t NumSupportedHardwareWatchpoints () const; + bool GetThreadStoppedReason(nub_thread_t tid, + struct DNBThreadStopInfo *stop_info) const; + void DumpThreadStoppedReason(nub_thread_t tid) const; + bool GetIdentifierInfo(nub_thread_t tid, + thread_identifier_info_data_t *ident_info); + nub_size_t NumThreads() const; + nub_thread_t ThreadIDAtIndex(nub_size_t idx) const; + nub_thread_t CurrentThreadID(); + void CurrentThread(MachThreadSP &threadSP); + void NotifyBreakpointChanged(const DNBBreakpoint *bp); + uint32_t EnableHardwareBreakpoint(const DNBBreakpoint *bp) const; + bool DisableHardwareBreakpoint(const DNBBreakpoint *bp) const; + uint32_t EnableHardwareWatchpoint(const DNBBreakpoint *wp) const; + bool DisableHardwareWatchpoint(const DNBBreakpoint *wp) const; + uint32_t NumSupportedHardwareWatchpoints() const; - uint32_t GetThreadIndexForThreadStoppedWithSignal (const int signo) const; + uint32_t GetThreadIndexForThreadStoppedWithSignal(const int signo) const; - MachThreadSP GetThreadByID (nub_thread_t tid) const; + MachThreadSP GetThreadByID(nub_thread_t tid) const; - MachThreadSP GetThreadByMachPortNumber (thread_t mach_port_number) const; - nub_thread_t GetThreadIDByMachPortNumber (thread_t mach_port_number) const; - thread_t GetMachPortNumberByThreadID (nub_thread_t globally_unique_id) const; + MachThreadSP GetThreadByMachPortNumber(thread_t mach_port_number) const; + nub_thread_t GetThreadIDByMachPortNumber(thread_t mach_port_number) const; + thread_t GetMachPortNumberByThreadID(nub_thread_t globally_unique_id) const; protected: - typedef std::vector<MachThreadSP> collection; - typedef collection::iterator iterator; - typedef collection::const_iterator const_iterator; + typedef std::vector<MachThreadSP> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; - uint32_t UpdateThreadList (MachProcess *process, bool update, collection *num_threads = NULL); -// const_iterator FindThreadByID (thread_t tid) const; + uint32_t UpdateThreadList(MachProcess *process, bool update, + collection *num_threads = NULL); + // const_iterator FindThreadByID (thread_t tid) const; - collection m_threads; - mutable PThreadMutex m_threads_mutex; - MachThreadSP m_current_thread; - bool m_is_64_bit; + collection m_threads; + mutable PThreadMutex m_threads_mutex; + MachThreadSP m_current_thread; + bool m_is_64_bit; }; #endif // #ifndef __MachThreadList_h__ - diff --git a/lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp b/lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp index 3b86a83024d..76806ab1cc1 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp @@ -12,587 +12,559 @@ //===----------------------------------------------------------------------===// #include "MachVMMemory.h" -#include "MachVMRegion.h" #include "DNBLog.h" +#include "MachVMRegion.h" +#include <dlfcn.h> #include <mach/mach_vm.h> #include <mach/shared_region.h> #include <sys/sysctl.h> -#include <dlfcn.h> static const vm_size_t kInvalidPageSize = ~0; -MachVMMemory::MachVMMemory() : - m_page_size (kInvalidPageSize), - m_err (0) -{ +MachVMMemory::MachVMMemory() : m_page_size(kInvalidPageSize), m_err(0) {} + +MachVMMemory::~MachVMMemory() {} + +nub_size_t MachVMMemory::PageSize(task_t task) { + if (m_page_size == kInvalidPageSize) { +#if defined(TASK_VM_INFO) && TASK_VM_INFO >= 22 + if (task != TASK_NULL) { + kern_return_t kr; + mach_msg_type_number_t info_count = TASK_VM_INFO_COUNT; + task_vm_info_data_t vm_info; + kr = task_info(task, TASK_VM_INFO, (task_info_t)&vm_info, &info_count); + if (kr == KERN_SUCCESS) { + DNBLogThreadedIf( + LOG_TASK, + "MachVMMemory::PageSize task_info returned page size of 0x%x", + (int)vm_info.page_size); + m_page_size = vm_info.page_size; + return m_page_size; + } else { + DNBLogThreadedIf(LOG_TASK, "MachVMMemory::PageSize task_info call " + "failed to get page size, TASK_VM_INFO %d, " + "TASK_VM_INFO_COUNT %d, kern return %d", + TASK_VM_INFO, TASK_VM_INFO_COUNT, kr); + } + } +#endif + m_err = ::host_page_size(::mach_host_self(), &m_page_size); + if (m_err.Fail()) + m_page_size = 0; + } + return m_page_size; } -MachVMMemory::~MachVMMemory() -{ +nub_size_t MachVMMemory::MaxBytesLeftInPage(task_t task, nub_addr_t addr, + nub_size_t count) { + const nub_size_t page_size = PageSize(task); + if (page_size > 0) { + nub_size_t page_offset = (addr % page_size); + nub_size_t bytes_left_in_page = page_size - page_offset; + if (count > bytes_left_in_page) + count = bytes_left_in_page; + } + return count; } -nub_size_t -MachVMMemory::PageSize(task_t task) -{ - if (m_page_size == kInvalidPageSize) - { -#if defined (TASK_VM_INFO) && TASK_VM_INFO >= 22 - if (task != TASK_NULL) - { - kern_return_t kr; - mach_msg_type_number_t info_count = TASK_VM_INFO_COUNT; - task_vm_info_data_t vm_info; - kr = task_info (task, TASK_VM_INFO, (task_info_t) &vm_info, &info_count); - if (kr == KERN_SUCCESS) - { - DNBLogThreadedIf(LOG_TASK, "MachVMMemory::PageSize task_info returned page size of 0x%x", (int) vm_info.page_size); - m_page_size = vm_info.page_size; - return m_page_size; - } - else - { - DNBLogThreadedIf(LOG_TASK, "MachVMMemory::PageSize task_info call failed to get page size, TASK_VM_INFO %d, TASK_VM_INFO_COUNT %d, kern return %d", TASK_VM_INFO, TASK_VM_INFO_COUNT, kr); - } - } -#endif - m_err = ::host_page_size( ::mach_host_self(), &m_page_size); - if (m_err.Fail()) - m_page_size = 0; +nub_bool_t MachVMMemory::GetMemoryRegionInfo(task_t task, nub_addr_t address, + DNBRegionInfo *region_info) { + MachVMRegion vmRegion(task); + + if (vmRegion.GetRegionForAddress(address)) { + region_info->addr = vmRegion.StartAddress(); + region_info->size = vmRegion.GetByteSize(); + region_info->permissions = vmRegion.GetDNBPermissions(); + } else { + region_info->addr = address; + region_info->size = 0; + if (vmRegion.GetError().Success()) { + // vmRegion.GetRegionForAddress() return false, indicating that "address" + // wasn't in a valid region, but the "vmRegion" info was successfully + // read from the task which means the info describes the next valid + // region from which we can infer the size of this invalid region + mach_vm_address_t start_addr = vmRegion.StartAddress(); + if (address < start_addr) + region_info->size = start_addr - address; } - return m_page_size; + // If we can't get any info about the size from the next region it means + // we asked about an address that was past all mappings, so the size + // of this region will take up all remaining address space. + if (region_info->size == 0) + region_info->size = INVALID_NUB_ADDRESS - region_info->addr; + + // Not readable, writeable or executable + region_info->permissions = 0; + } + return true; } -nub_size_t -MachVMMemory::MaxBytesLeftInPage(task_t task, nub_addr_t addr, nub_size_t count) -{ - const nub_size_t page_size = PageSize(task); - if (page_size > 0) - { - nub_size_t page_offset = (addr % page_size); - nub_size_t bytes_left_in_page = page_size - page_offset; - if (count > bytes_left_in_page) - count = bytes_left_in_page; +// For integrated graphics chip, this makes the accounting info for 'wired' +// memory more like top. +uint64_t MachVMMemory::GetStolenPages(task_t task) { + static uint64_t stolenPages = 0; + static bool calculated = false; + if (calculated) + return stolenPages; + + static int mib_reserved[CTL_MAXNAME]; + static int mib_unusable[CTL_MAXNAME]; + static int mib_other[CTL_MAXNAME]; + static size_t mib_reserved_len = 0; + static size_t mib_unusable_len = 0; + static size_t mib_other_len = 0; + int r; + + /* This can be used for testing: */ + // tsamp->pages_stolen = (256 * 1024 * 1024ULL) / tsamp->pagesize; + + if (0 == mib_reserved_len) { + mib_reserved_len = CTL_MAXNAME; + + r = sysctlnametomib("machdep.memmap.Reserved", mib_reserved, + &mib_reserved_len); + + if (-1 == r) { + mib_reserved_len = 0; + return 0; } - return count; -} -nub_bool_t -MachVMMemory::GetMemoryRegionInfo(task_t task, nub_addr_t address, DNBRegionInfo *region_info) -{ - MachVMRegion vmRegion(task); + mib_unusable_len = CTL_MAXNAME; - if (vmRegion.GetRegionForAddress(address)) - { - region_info->addr = vmRegion.StartAddress(); - region_info->size = vmRegion.GetByteSize(); - region_info->permissions = vmRegion.GetDNBPermissions(); + r = sysctlnametomib("machdep.memmap.Unusable", mib_unusable, + &mib_unusable_len); + + if (-1 == r) { + mib_reserved_len = 0; + return 0; } - else - { - region_info->addr = address; - region_info->size = 0; - if (vmRegion.GetError().Success()) - { - // vmRegion.GetRegionForAddress() return false, indicating that "address" - // wasn't in a valid region, but the "vmRegion" info was successfully - // read from the task which means the info describes the next valid - // region from which we can infer the size of this invalid region - mach_vm_address_t start_addr = vmRegion.StartAddress(); - if (address < start_addr) - region_info->size = start_addr - address; - } - // If we can't get any info about the size from the next region it means - // we asked about an address that was past all mappings, so the size - // of this region will take up all remaining address space. - if (region_info->size == 0) - region_info->size = INVALID_NUB_ADDRESS - region_info->addr; - - // Not readable, writeable or executable - region_info->permissions = 0; + + mib_other_len = CTL_MAXNAME; + + r = sysctlnametomib("machdep.memmap.Other", mib_other, &mib_other_len); + + if (-1 == r) { + mib_reserved_len = 0; + return 0; } - return true; -} + } -// For integrated graphics chip, this makes the accounting info for 'wired' memory more like top. -uint64_t -MachVMMemory::GetStolenPages(task_t task) -{ - static uint64_t stolenPages = 0; - static bool calculated = false; - if (calculated) return stolenPages; - - static int mib_reserved[CTL_MAXNAME]; - static int mib_unusable[CTL_MAXNAME]; - static int mib_other[CTL_MAXNAME]; - static size_t mib_reserved_len = 0; - static size_t mib_unusable_len = 0; - static size_t mib_other_len = 0; - int r; - - /* This can be used for testing: */ - //tsamp->pages_stolen = (256 * 1024 * 1024ULL) / tsamp->pagesize; - - if(0 == mib_reserved_len) - { - mib_reserved_len = CTL_MAXNAME; - - r = sysctlnametomib("machdep.memmap.Reserved", mib_reserved, - &mib_reserved_len); - - if(-1 == r) - { - mib_reserved_len = 0; - return 0; - } - - mib_unusable_len = CTL_MAXNAME; - - r = sysctlnametomib("machdep.memmap.Unusable", mib_unusable, - &mib_unusable_len); - - if(-1 == r) - { - mib_reserved_len = 0; - return 0; - } - - - mib_other_len = CTL_MAXNAME; - - r = sysctlnametomib("machdep.memmap.Other", mib_other, - &mib_other_len); - - if(-1 == r) - { - mib_reserved_len = 0; - return 0; - } - } - - if(mib_reserved_len > 0 && mib_unusable_len > 0 && mib_other_len > 0) - { - uint64_t reserved = 0, unusable = 0, other = 0; - size_t reserved_len; - size_t unusable_len; - size_t other_len; - - reserved_len = sizeof(reserved); - unusable_len = sizeof(unusable); - other_len = sizeof(other); - - /* These are all declared as QUAD/uint64_t sysctls in the kernel. */ - - if (sysctl (mib_reserved, - static_cast<u_int>(mib_reserved_len), - &reserved, - &reserved_len, - NULL, - 0)) - { - return 0; - } - - if (sysctl (mib_unusable, - static_cast<u_int>(mib_unusable_len), - &unusable, - &unusable_len, - NULL, - 0)) - { - return 0; - } - - if (sysctl (mib_other, - static_cast<u_int>(mib_other_len), - &other, - &other_len, - NULL, - 0)) - { - return 0; - } - - if (reserved_len == sizeof(reserved) && - unusable_len == sizeof(unusable) && - other_len == sizeof(other)) - { - uint64_t stolen = reserved + unusable + other; - uint64_t mb128 = 128 * 1024 * 1024ULL; - - if(stolen >= mb128) - { - stolen = (stolen & ~((128 * 1024 * 1024ULL) - 1)); // rounding down - stolenPages = stolen / PageSize (task); - } - } - } - - calculated = true; - return stolenPages; + if (mib_reserved_len > 0 && mib_unusable_len > 0 && mib_other_len > 0) { + uint64_t reserved = 0, unusable = 0, other = 0; + size_t reserved_len; + size_t unusable_len; + size_t other_len; + + reserved_len = sizeof(reserved); + unusable_len = sizeof(unusable); + other_len = sizeof(other); + + /* These are all declared as QUAD/uint64_t sysctls in the kernel. */ + + if (sysctl(mib_reserved, static_cast<u_int>(mib_reserved_len), &reserved, + &reserved_len, NULL, 0)) { + return 0; + } + + if (sysctl(mib_unusable, static_cast<u_int>(mib_unusable_len), &unusable, + &unusable_len, NULL, 0)) { + return 0; + } + + if (sysctl(mib_other, static_cast<u_int>(mib_other_len), &other, &other_len, + NULL, 0)) { + return 0; + } + + if (reserved_len == sizeof(reserved) && unusable_len == sizeof(unusable) && + other_len == sizeof(other)) { + uint64_t stolen = reserved + unusable + other; + uint64_t mb128 = 128 * 1024 * 1024ULL; + + if (stolen >= mb128) { + stolen = (stolen & ~((128 * 1024 * 1024ULL) - 1)); // rounding down + stolenPages = stolen / PageSize(task); + } + } + } + + calculated = true; + return stolenPages; } -static uint64_t GetPhysicalMemory() -{ - // This doesn't change often at all. No need to poll each time. - static uint64_t physical_memory = 0; - static bool calculated = false; - if (calculated) return physical_memory; - - size_t len = sizeof(physical_memory); - sysctlbyname("hw.memsize", &physical_memory, &len, NULL, 0); - - calculated = true; +static uint64_t GetPhysicalMemory() { + // This doesn't change often at all. No need to poll each time. + static uint64_t physical_memory = 0; + static bool calculated = false; + if (calculated) return physical_memory; + + size_t len = sizeof(physical_memory); + sysctlbyname("hw.memsize", &physical_memory, &len, NULL, 0); + + calculated = true; + return physical_memory; } -// rsize and dirty_size is not adjusted for dyld shared cache and multiple __LINKEDIT segment, as in vmmap. In practice, dirty_size doesn't differ much but rsize may. There is performance penalty for the adjustment. Right now, only use the dirty_size. -void -MachVMMemory::GetRegionSizes(task_t task, mach_vm_size_t &rsize, mach_vm_size_t &dirty_size) -{ -#if defined (TASK_VM_INFO) && TASK_VM_INFO >= 22 - - task_vm_info_data_t vm_info; - mach_msg_type_number_t info_count; - kern_return_t kr; - - info_count = TASK_VM_INFO_COUNT; - kr = task_info(task, TASK_VM_INFO_PURGEABLE, (task_info_t)&vm_info, &info_count); - if (kr == KERN_SUCCESS) - dirty_size = vm_info.internal; +// rsize and dirty_size is not adjusted for dyld shared cache and multiple +// __LINKEDIT segment, as in vmmap. In practice, dirty_size doesn't differ much +// but rsize may. There is performance penalty for the adjustment. Right now, +// only use the dirty_size. +void MachVMMemory::GetRegionSizes(task_t task, mach_vm_size_t &rsize, + mach_vm_size_t &dirty_size) { +#if defined(TASK_VM_INFO) && TASK_VM_INFO >= 22 + + task_vm_info_data_t vm_info; + mach_msg_type_number_t info_count; + kern_return_t kr; + + info_count = TASK_VM_INFO_COUNT; + kr = task_info(task, TASK_VM_INFO_PURGEABLE, (task_info_t)&vm_info, + &info_count); + if (kr == KERN_SUCCESS) + dirty_size = vm_info.internal; #endif } // Test whether the virtual address is within the architecture's shared region. -static bool InSharedRegion(mach_vm_address_t addr, cpu_type_t type) -{ - mach_vm_address_t base = 0, size = 0; - - switch(type) { -#if defined (CPU_TYPE_ARM64) && defined (SHARED_REGION_BASE_ARM64) - case CPU_TYPE_ARM64: - base = SHARED_REGION_BASE_ARM64; - size = SHARED_REGION_SIZE_ARM64; - break; +static bool InSharedRegion(mach_vm_address_t addr, cpu_type_t type) { + mach_vm_address_t base = 0, size = 0; + + switch (type) { +#if defined(CPU_TYPE_ARM64) && defined(SHARED_REGION_BASE_ARM64) + case CPU_TYPE_ARM64: + base = SHARED_REGION_BASE_ARM64; + size = SHARED_REGION_SIZE_ARM64; + break; #endif - case CPU_TYPE_ARM: - base = SHARED_REGION_BASE_ARM; - size = SHARED_REGION_SIZE_ARM; - break; - - case CPU_TYPE_X86_64: - base = SHARED_REGION_BASE_X86_64; - size = SHARED_REGION_SIZE_X86_64; - break; - - case CPU_TYPE_I386: - base = SHARED_REGION_BASE_I386; - size = SHARED_REGION_SIZE_I386; - break; - - default: { - // Log error abut unknown CPU type - break; - } - } - - - return(addr >= base && addr < (base + size)); + case CPU_TYPE_ARM: + base = SHARED_REGION_BASE_ARM; + size = SHARED_REGION_SIZE_ARM; + break; + + case CPU_TYPE_X86_64: + base = SHARED_REGION_BASE_X86_64; + size = SHARED_REGION_SIZE_X86_64; + break; + + case CPU_TYPE_I386: + base = SHARED_REGION_BASE_I386; + size = SHARED_REGION_SIZE_I386; + break; + + default: { + // Log error abut unknown CPU type + break; + } + } + + return (addr >= base && addr < (base + size)); } -void -MachVMMemory::GetMemorySizes(task_t task, cpu_type_t cputype, nub_process_t pid, mach_vm_size_t &rprvt, mach_vm_size_t &vprvt) -{ - // Collecting some other info cheaply but not reporting for now. - mach_vm_size_t empty = 0; - mach_vm_size_t fw_private = 0; - - mach_vm_size_t aliased = 0; - bool global_shared_text_data_mapped = false; - vm_size_t pagesize = PageSize (task); - - for (mach_vm_address_t addr=0, size=0; ; addr += size) - { - vm_region_top_info_data_t info; - mach_msg_type_number_t count = VM_REGION_TOP_INFO_COUNT; - mach_port_t object_name; - - kern_return_t kr = mach_vm_region(task, &addr, &size, VM_REGION_TOP_INFO, (vm_region_info_t)&info, &count, &object_name); - if (kr != KERN_SUCCESS) break; - - if (InSharedRegion(addr, cputype)) - { - // Private Shared - fw_private += info.private_pages_resident * pagesize; - - // Check if this process has the globally shared text and data regions mapped in. If so, set global_shared_text_data_mapped to TRUE and avoid checking again. - if (global_shared_text_data_mapped == FALSE && info.share_mode == SM_EMPTY) { - vm_region_basic_info_data_64_t b_info; - mach_vm_address_t b_addr = addr; - mach_vm_size_t b_size = size; - count = VM_REGION_BASIC_INFO_COUNT_64; - - kr = mach_vm_region(task, &b_addr, &b_size, VM_REGION_BASIC_INFO, (vm_region_info_t)&b_info, &count, &object_name); - if (kr != KERN_SUCCESS) break; - - if (b_info.reserved) { - global_shared_text_data_mapped = TRUE; - } - } - - // Short circuit the loop if this isn't a shared private region, since that's the only region type we care about within the current address range. - if (info.share_mode != SM_PRIVATE) - { - continue; - } +void MachVMMemory::GetMemorySizes(task_t task, cpu_type_t cputype, + nub_process_t pid, mach_vm_size_t &rprvt, + mach_vm_size_t &vprvt) { + // Collecting some other info cheaply but not reporting for now. + mach_vm_size_t empty = 0; + mach_vm_size_t fw_private = 0; + + mach_vm_size_t aliased = 0; + bool global_shared_text_data_mapped = false; + vm_size_t pagesize = PageSize(task); + + for (mach_vm_address_t addr = 0, size = 0;; addr += size) { + vm_region_top_info_data_t info; + mach_msg_type_number_t count = VM_REGION_TOP_INFO_COUNT; + mach_port_t object_name; + + kern_return_t kr = + mach_vm_region(task, &addr, &size, VM_REGION_TOP_INFO, + (vm_region_info_t)&info, &count, &object_name); + if (kr != KERN_SUCCESS) + break; + + if (InSharedRegion(addr, cputype)) { + // Private Shared + fw_private += info.private_pages_resident * pagesize; + + // Check if this process has the globally shared text and data regions + // mapped in. If so, set global_shared_text_data_mapped to TRUE and avoid + // checking again. + if (global_shared_text_data_mapped == FALSE && + info.share_mode == SM_EMPTY) { + vm_region_basic_info_data_64_t b_info; + mach_vm_address_t b_addr = addr; + mach_vm_size_t b_size = size; + count = VM_REGION_BASIC_INFO_COUNT_64; + + kr = mach_vm_region(task, &b_addr, &b_size, VM_REGION_BASIC_INFO, + (vm_region_info_t)&b_info, &count, &object_name); + if (kr != KERN_SUCCESS) + break; + + if (b_info.reserved) { + global_shared_text_data_mapped = TRUE; } - - // Update counters according to the region type. - if (info.share_mode == SM_COW && info.ref_count == 1) - { - // Treat single reference SM_COW as SM_PRIVATE - info.share_mode = SM_PRIVATE; - } - - switch (info.share_mode) - { - case SM_LARGE_PAGE: - // Treat SM_LARGE_PAGE the same as SM_PRIVATE - // since they are not shareable and are wired. - case SM_PRIVATE: - rprvt += info.private_pages_resident * pagesize; - rprvt += info.shared_pages_resident * pagesize; - vprvt += size; - break; - - case SM_EMPTY: - empty += size; - break; - - case SM_COW: - case SM_SHARED: - { - if (pid == 0) - { - // Treat kernel_task specially - if (info.share_mode == SM_COW) - { - rprvt += info.private_pages_resident * pagesize; - vprvt += size; - } - break; - } - - if (info.share_mode == SM_COW) - { - rprvt += info.private_pages_resident * pagesize; - vprvt += info.private_pages_resident * pagesize; - } - break; - } - default: - // log that something is really bad. - break; + } + + // Short circuit the loop if this isn't a shared private region, since + // that's the only region type we care about within the current address + // range. + if (info.share_mode != SM_PRIVATE) { + continue; + } + } + + // Update counters according to the region type. + if (info.share_mode == SM_COW && info.ref_count == 1) { + // Treat single reference SM_COW as SM_PRIVATE + info.share_mode = SM_PRIVATE; + } + + switch (info.share_mode) { + case SM_LARGE_PAGE: + // Treat SM_LARGE_PAGE the same as SM_PRIVATE + // since they are not shareable and are wired. + case SM_PRIVATE: + rprvt += info.private_pages_resident * pagesize; + rprvt += info.shared_pages_resident * pagesize; + vprvt += size; + break; + + case SM_EMPTY: + empty += size; + break; + + case SM_COW: + case SM_SHARED: { + if (pid == 0) { + // Treat kernel_task specially + if (info.share_mode == SM_COW) { + rprvt += info.private_pages_resident * pagesize; + vprvt += size; } + break; + } + + if (info.share_mode == SM_COW) { + rprvt += info.private_pages_resident * pagesize; + vprvt += info.private_pages_resident * pagesize; + } + break; + } + default: + // log that something is really bad. + break; } - - rprvt += aliased; + } + + rprvt += aliased; } -static void -GetPurgeableAndAnonymous(task_t task, uint64_t &purgeable, uint64_t &anonymous) -{ -#if defined (TASK_VM_INFO) && TASK_VM_INFO >= 22 - - kern_return_t kr; - mach_msg_type_number_t info_count; - task_vm_info_data_t vm_info; - - info_count = TASK_VM_INFO_COUNT; - kr = task_info(task, TASK_VM_INFO_PURGEABLE, (task_info_t)&vm_info, &info_count); - if (kr == KERN_SUCCESS) - { - purgeable = vm_info.purgeable_volatile_resident; - anonymous = vm_info.internal + vm_info.compressed - vm_info.purgeable_volatile_pmap; - } +static void GetPurgeableAndAnonymous(task_t task, uint64_t &purgeable, + uint64_t &anonymous) { +#if defined(TASK_VM_INFO) && TASK_VM_INFO >= 22 + + kern_return_t kr; + mach_msg_type_number_t info_count; + task_vm_info_data_t vm_info; + + info_count = TASK_VM_INFO_COUNT; + kr = task_info(task, TASK_VM_INFO_PURGEABLE, (task_info_t)&vm_info, + &info_count); + if (kr == KERN_SUCCESS) { + purgeable = vm_info.purgeable_volatile_resident; + anonymous = + vm_info.internal + vm_info.compressed - vm_info.purgeable_volatile_pmap; + } #endif } -#if defined (HOST_VM_INFO64_COUNT) -nub_bool_t -MachVMMemory::GetMemoryProfile(DNBProfileDataScanType scanType, task_t task, struct task_basic_info ti, cpu_type_t cputype, nub_process_t pid, vm_statistics64_data_t &vminfo, uint64_t &physical_memory, mach_vm_size_t &rprvt, mach_vm_size_t &rsize, mach_vm_size_t &vprvt, mach_vm_size_t &vsize, mach_vm_size_t &dirty_size, mach_vm_size_t &purgeable, mach_vm_size_t &anonymous) +#if defined(HOST_VM_INFO64_COUNT) +nub_bool_t MachVMMemory::GetMemoryProfile( + DNBProfileDataScanType scanType, task_t task, struct task_basic_info ti, + cpu_type_t cputype, nub_process_t pid, vm_statistics64_data_t &vminfo, + uint64_t &physical_memory, mach_vm_size_t &rprvt, mach_vm_size_t &rsize, + mach_vm_size_t &vprvt, mach_vm_size_t &vsize, mach_vm_size_t &dirty_size, + mach_vm_size_t &purgeable, mach_vm_size_t &anonymous) #else -nub_bool_t -MachVMMemory::GetMemoryProfile(DNBProfileDataScanType scanType, task_t task, struct task_basic_info ti, cpu_type_t cputype, nub_process_t pid, vm_statistics_data_t &vminfo, uint64_t &physical_memory, mach_vm_size_t &rprvt, mach_vm_size_t &rsize, mach_vm_size_t &vprvt, mach_vm_size_t &vsize, mach_vm_size_t &dirty_size, mach_vm_size_t &purgeable, mach_vm_size_t &anonymous) +nub_bool_t MachVMMemory::GetMemoryProfile( + DNBProfileDataScanType scanType, task_t task, struct task_basic_info ti, + cpu_type_t cputype, nub_process_t pid, vm_statistics_data_t &vminfo, + uint64_t &physical_memory, mach_vm_size_t &rprvt, mach_vm_size_t &rsize, + mach_vm_size_t &vprvt, mach_vm_size_t &vsize, mach_vm_size_t &dirty_size, + mach_vm_size_t &purgeable, mach_vm_size_t &anonymous) #endif { - if (scanType & eProfileHostMemory) - physical_memory = GetPhysicalMemory(); - - if (scanType & eProfileMemory) - { - static mach_port_t localHost = mach_host_self(); -#if defined (HOST_VM_INFO64_COUNT) - mach_msg_type_number_t count = HOST_VM_INFO64_COUNT; - host_statistics64(localHost, HOST_VM_INFO64, (host_info64_t)&vminfo, &count); + if (scanType & eProfileHostMemory) + physical_memory = GetPhysicalMemory(); + + if (scanType & eProfileMemory) { + static mach_port_t localHost = mach_host_self(); +#if defined(HOST_VM_INFO64_COUNT) + mach_msg_type_number_t count = HOST_VM_INFO64_COUNT; + host_statistics64(localHost, HOST_VM_INFO64, (host_info64_t)&vminfo, + &count); #else - mach_msg_type_number_t count = HOST_VM_INFO_COUNT; - host_statistics(localHost, HOST_VM_INFO, (host_info_t)&vminfo, &count); - vminfo.wire_count += GetStolenPages(task); + mach_msg_type_number_t count = HOST_VM_INFO_COUNT; + host_statistics(localHost, HOST_VM_INFO, (host_info_t)&vminfo, &count); + vminfo.wire_count += GetStolenPages(task); #endif - - /* We are no longer reporting these. Let's not waste time. - GetMemorySizes(task, cputype, pid, rprvt, vprvt); - rsize = ti.resident_size; - vsize = ti.virtual_size; - - if (scanType & eProfileMemoryDirtyPage) - { - // This uses vmmap strategy. We don't use the returned rsize for now. We prefer to match top's version since that's what we do for the rest of the metrics. - GetRegionSizes(task, rsize, dirty_size); - } - */ - - if (scanType & eProfileMemoryAnonymous) - { - GetPurgeableAndAnonymous(task, purgeable, anonymous); - } - } - - return true; -} -nub_size_t -MachVMMemory::Read(task_t task, nub_addr_t address, void *data, nub_size_t data_count) -{ - if (data == NULL || data_count == 0) - return 0; + /* We are no longer reporting these. Let's not waste time. + GetMemorySizes(task, cputype, pid, rprvt, vprvt); + rsize = ti.resident_size; + vsize = ti.virtual_size; - nub_size_t total_bytes_read = 0; - nub_addr_t curr_addr = address; - uint8_t *curr_data = (uint8_t*)data; - while (total_bytes_read < data_count) + if (scanType & eProfileMemoryDirtyPage) { - mach_vm_size_t curr_size = MaxBytesLeftInPage(task, curr_addr, data_count - total_bytes_read); - mach_msg_type_number_t curr_bytes_read = 0; - vm_offset_t vm_memory = 0; - m_err = ::mach_vm_read (task, curr_addr, curr_size, &vm_memory, &curr_bytes_read); - - if (DNBLogCheckLogBit(LOG_MEMORY)) - m_err.LogThreaded("::mach_vm_read ( task = 0x%4.4x, addr = 0x%8.8llx, size = %llu, data => %8.8p, dataCnt => %i )", task, (uint64_t)curr_addr, (uint64_t)curr_size, vm_memory, curr_bytes_read); - - if (m_err.Success()) - { - if (curr_bytes_read != curr_size) - { - if (DNBLogCheckLogBit(LOG_MEMORY)) - m_err.LogThreaded("::mach_vm_read ( task = 0x%4.4x, addr = 0x%8.8llx, size = %llu, data => %8.8p, dataCnt=>%i ) only read %u of %llu bytes", task, (uint64_t)curr_addr, (uint64_t)curr_size, vm_memory, curr_bytes_read, curr_bytes_read, (uint64_t)curr_size); - } - ::memcpy (curr_data, (void *)vm_memory, curr_bytes_read); - ::vm_deallocate (mach_task_self (), vm_memory, curr_bytes_read); - total_bytes_read += curr_bytes_read; - curr_addr += curr_bytes_read; - curr_data += curr_bytes_read; - } - else - { - break; - } + // This uses vmmap strategy. We don't use the returned rsize for now. We + prefer to match top's version since that's what we do for the rest of the + metrics. + GetRegionSizes(task, rsize, dirty_size); } - return total_bytes_read; -} - + */ -nub_size_t -MachVMMemory::Write(task_t task, nub_addr_t address, const void *data, nub_size_t data_count) -{ - MachVMRegion vmRegion(task); + if (scanType & eProfileMemoryAnonymous) { + GetPurgeableAndAnonymous(task, purgeable, anonymous); + } + } - nub_size_t total_bytes_written = 0; - nub_addr_t curr_addr = address; - const uint8_t *curr_data = (const uint8_t*)data; + return true; +} +nub_size_t MachVMMemory::Read(task_t task, nub_addr_t address, void *data, + nub_size_t data_count) { + if (data == NULL || data_count == 0) + return 0; + + nub_size_t total_bytes_read = 0; + nub_addr_t curr_addr = address; + uint8_t *curr_data = (uint8_t *)data; + while (total_bytes_read < data_count) { + mach_vm_size_t curr_size = + MaxBytesLeftInPage(task, curr_addr, data_count - total_bytes_read); + mach_msg_type_number_t curr_bytes_read = 0; + vm_offset_t vm_memory = 0; + m_err = ::mach_vm_read(task, curr_addr, curr_size, &vm_memory, + &curr_bytes_read); + + if (DNBLogCheckLogBit(LOG_MEMORY)) + m_err.LogThreaded("::mach_vm_read ( task = 0x%4.4x, addr = 0x%8.8llx, " + "size = %llu, data => %8.8p, dataCnt => %i )", + task, (uint64_t)curr_addr, (uint64_t)curr_size, + vm_memory, curr_bytes_read); + + if (m_err.Success()) { + if (curr_bytes_read != curr_size) { + if (DNBLogCheckLogBit(LOG_MEMORY)) + m_err.LogThreaded( + "::mach_vm_read ( task = 0x%4.4x, addr = 0x%8.8llx, size = %llu, " + "data => %8.8p, dataCnt=>%i ) only read %u of %llu bytes", + task, (uint64_t)curr_addr, (uint64_t)curr_size, vm_memory, + curr_bytes_read, curr_bytes_read, (uint64_t)curr_size); + } + ::memcpy(curr_data, (void *)vm_memory, curr_bytes_read); + ::vm_deallocate(mach_task_self(), vm_memory, curr_bytes_read); + total_bytes_read += curr_bytes_read; + curr_addr += curr_bytes_read; + curr_data += curr_bytes_read; + } else { + break; + } + } + return total_bytes_read; +} - while (total_bytes_written < data_count) - { - if (vmRegion.GetRegionForAddress(curr_addr)) - { - mach_vm_size_t curr_data_count = data_count - total_bytes_written; - mach_vm_size_t region_bytes_left = vmRegion.BytesRemaining(curr_addr); - if (region_bytes_left == 0) - { - break; - } - if (curr_data_count > region_bytes_left) - curr_data_count = region_bytes_left; - - if (vmRegion.SetProtections(curr_addr, curr_data_count, VM_PROT_READ | VM_PROT_WRITE)) - { - nub_size_t bytes_written = WriteRegion(task, curr_addr, curr_data, curr_data_count); - if (bytes_written <= 0) - { - // Error should have already be posted by WriteRegion... - break; - } - else - { - total_bytes_written += bytes_written; - curr_addr += bytes_written; - curr_data += bytes_written; - } - } - else - { - DNBLogThreadedIf(LOG_MEMORY_PROTECTIONS, "Failed to set read/write protections on region for address: [0x%8.8llx-0x%8.8llx)", (uint64_t)curr_addr, (uint64_t)(curr_addr + curr_data_count)); - break; - } - } - else - { - DNBLogThreadedIf(LOG_MEMORY_PROTECTIONS, "Failed to get region for address: 0x%8.8llx", (uint64_t)address); - break; +nub_size_t MachVMMemory::Write(task_t task, nub_addr_t address, + const void *data, nub_size_t data_count) { + MachVMRegion vmRegion(task); + + nub_size_t total_bytes_written = 0; + nub_addr_t curr_addr = address; + const uint8_t *curr_data = (const uint8_t *)data; + + while (total_bytes_written < data_count) { + if (vmRegion.GetRegionForAddress(curr_addr)) { + mach_vm_size_t curr_data_count = data_count - total_bytes_written; + mach_vm_size_t region_bytes_left = vmRegion.BytesRemaining(curr_addr); + if (region_bytes_left == 0) { + break; + } + if (curr_data_count > region_bytes_left) + curr_data_count = region_bytes_left; + + if (vmRegion.SetProtections(curr_addr, curr_data_count, + VM_PROT_READ | VM_PROT_WRITE)) { + nub_size_t bytes_written = + WriteRegion(task, curr_addr, curr_data, curr_data_count); + if (bytes_written <= 0) { + // Error should have already be posted by WriteRegion... + break; + } else { + total_bytes_written += bytes_written; + curr_addr += bytes_written; + curr_data += bytes_written; } + } else { + DNBLogThreadedIf( + LOG_MEMORY_PROTECTIONS, "Failed to set read/write protections on " + "region for address: [0x%8.8llx-0x%8.8llx)", + (uint64_t)curr_addr, (uint64_t)(curr_addr + curr_data_count)); + break; + } + } else { + DNBLogThreadedIf(LOG_MEMORY_PROTECTIONS, + "Failed to get region for address: 0x%8.8llx", + (uint64_t)address); + break; } + } - return total_bytes_written; + return total_bytes_written; } - -nub_size_t -MachVMMemory::WriteRegion(task_t task, const nub_addr_t address, const void *data, const nub_size_t data_count) -{ - if (data == NULL || data_count == 0) - return 0; - - nub_size_t total_bytes_written = 0; - nub_addr_t curr_addr = address; - const uint8_t *curr_data = (const uint8_t*)data; - while (total_bytes_written < data_count) - { - mach_msg_type_number_t curr_data_count = static_cast<mach_msg_type_number_t>(MaxBytesLeftInPage(task, curr_addr, data_count - total_bytes_written)); - m_err = ::mach_vm_write (task, curr_addr, (pointer_t) curr_data, curr_data_count); - if (DNBLogCheckLogBit(LOG_MEMORY) || m_err.Fail()) - m_err.LogThreaded("::mach_vm_write ( task = 0x%4.4x, addr = 0x%8.8llx, data = %8.8p, dataCnt = %u )", task, (uint64_t)curr_addr, curr_data, curr_data_count); - -#if !defined (__i386__) && !defined (__x86_64__) - vm_machine_attribute_val_t mattr_value = MATTR_VAL_CACHE_FLUSH; - - m_err = ::vm_machine_attribute (task, curr_addr, curr_data_count, MATTR_CACHE, &mattr_value); - if (DNBLogCheckLogBit(LOG_MEMORY) || m_err.Fail()) - m_err.LogThreaded("::vm_machine_attribute ( task = 0x%4.4x, addr = 0x%8.8llx, size = %u, attr = MATTR_CACHE, mattr_value => MATTR_VAL_CACHE_FLUSH )", task, (uint64_t)curr_addr, curr_data_count); +nub_size_t MachVMMemory::WriteRegion(task_t task, const nub_addr_t address, + const void *data, + const nub_size_t data_count) { + if (data == NULL || data_count == 0) + return 0; + + nub_size_t total_bytes_written = 0; + nub_addr_t curr_addr = address; + const uint8_t *curr_data = (const uint8_t *)data; + while (total_bytes_written < data_count) { + mach_msg_type_number_t curr_data_count = + static_cast<mach_msg_type_number_t>(MaxBytesLeftInPage( + task, curr_addr, data_count - total_bytes_written)); + m_err = + ::mach_vm_write(task, curr_addr, (pointer_t)curr_data, curr_data_count); + if (DNBLogCheckLogBit(LOG_MEMORY) || m_err.Fail()) + m_err.LogThreaded("::mach_vm_write ( task = 0x%4.4x, addr = 0x%8.8llx, " + "data = %8.8p, dataCnt = %u )", + task, (uint64_t)curr_addr, curr_data, curr_data_count); + +#if !defined(__i386__) && !defined(__x86_64__) + vm_machine_attribute_val_t mattr_value = MATTR_VAL_CACHE_FLUSH; + + m_err = ::vm_machine_attribute(task, curr_addr, curr_data_count, + MATTR_CACHE, &mattr_value); + if (DNBLogCheckLogBit(LOG_MEMORY) || m_err.Fail()) + m_err.LogThreaded("::vm_machine_attribute ( task = 0x%4.4x, addr = " + "0x%8.8llx, size = %u, attr = MATTR_CACHE, mattr_value " + "=> MATTR_VAL_CACHE_FLUSH )", + task, (uint64_t)curr_addr, curr_data_count); #endif - if (m_err.Success()) - { - total_bytes_written += curr_data_count; - curr_addr += curr_data_count; - curr_data += curr_data_count; - } - else - { - break; - } + if (m_err.Success()) { + total_bytes_written += curr_data_count; + curr_addr += curr_data_count; + curr_data += curr_data_count; + } else { + break; } - return total_bytes_written; + } + return total_bytes_written; } diff --git a/lldb/tools/debugserver/source/MacOSX/MachVMMemory.h b/lldb/tools/debugserver/source/MacOSX/MachVMMemory.h index abaa20368a2..c4d3f533137 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachVMMemory.h +++ b/lldb/tools/debugserver/source/MacOSX/MachVMMemory.h @@ -18,34 +18,51 @@ #include "DNBError.h" #include <mach/mach.h> -class MachVMMemory -{ +class MachVMMemory { public: - MachVMMemory(); - ~MachVMMemory(); - nub_size_t Read(task_t task, nub_addr_t address, void *data, nub_size_t data_count); - nub_size_t Write(task_t task, nub_addr_t address, const void *data, nub_size_t data_count); - nub_size_t PageSize(task_t task); - nub_bool_t GetMemoryRegionInfo(task_t task, nub_addr_t address, DNBRegionInfo *region_info); -#if defined (HOST_VM_INFO64_COUNT) - nub_bool_t GetMemoryProfile(DNBProfileDataScanType scanType, task_t task, struct task_basic_info ti, cpu_type_t cputype, nub_process_t pid, vm_statistics64_data_t &vminfo, uint64_t &physical_memory, mach_vm_size_t &rprvt, mach_vm_size_t &rsize, mach_vm_size_t &vprvt, mach_vm_size_t &vsize, mach_vm_size_t &dirty_size, mach_vm_size_t &purgeable, mach_vm_size_t &anonymous); + MachVMMemory(); + ~MachVMMemory(); + nub_size_t Read(task_t task, nub_addr_t address, void *data, + nub_size_t data_count); + nub_size_t Write(task_t task, nub_addr_t address, const void *data, + nub_size_t data_count); + nub_size_t PageSize(task_t task); + nub_bool_t GetMemoryRegionInfo(task_t task, nub_addr_t address, + DNBRegionInfo *region_info); +#if defined(HOST_VM_INFO64_COUNT) + nub_bool_t GetMemoryProfile(DNBProfileDataScanType scanType, task_t task, + struct task_basic_info ti, cpu_type_t cputype, + nub_process_t pid, vm_statistics64_data_t &vminfo, + uint64_t &physical_memory, mach_vm_size_t &rprvt, + mach_vm_size_t &rsize, mach_vm_size_t &vprvt, + mach_vm_size_t &vsize, mach_vm_size_t &dirty_size, + mach_vm_size_t &purgeable, + mach_vm_size_t &anonymous); #else - nub_bool_t GetMemoryProfile(DNBProfileDataScanType scanType, task_t task, struct task_basic_info ti, cpu_type_t cputype, nub_process_t pid, vm_statistics_data_t &vminfo, uint64_t &physical_memory, mach_vm_size_t &rprvt, mach_vm_size_t &rsize, mach_vm_size_t &vprvt, mach_vm_size_t &vsize, mach_vm_size_t &dirty_size, mach_vm_size_t &purgeable, mach_vm_size_t &anonymous); + nub_bool_t GetMemoryProfile(DNBProfileDataScanType scanType, task_t task, + struct task_basic_info ti, cpu_type_t cputype, + nub_process_t pid, vm_statistics_data_t &vminfo, + uint64_t &physical_memory, mach_vm_size_t &rprvt, + mach_vm_size_t &rsize, mach_vm_size_t &vprvt, + mach_vm_size_t &vsize, mach_vm_size_t &dirty_size, + mach_vm_size_t &purgeable, + mach_vm_size_t &anonymous); #endif protected: - nub_size_t MaxBytesLeftInPage(task_t task, nub_addr_t addr, nub_size_t count); + nub_size_t MaxBytesLeftInPage(task_t task, nub_addr_t addr, nub_size_t count); - uint64_t GetStolenPages(task_t task); - void GetRegionSizes(task_t task, mach_vm_size_t &rsize, mach_vm_size_t &dirty_size); - void GetMemorySizes(task_t task, cpu_type_t cputype, nub_process_t pid, mach_vm_size_t &rprvt, mach_vm_size_t &vprvt); + uint64_t GetStolenPages(task_t task); + void GetRegionSizes(task_t task, mach_vm_size_t &rsize, + mach_vm_size_t &dirty_size); + void GetMemorySizes(task_t task, cpu_type_t cputype, nub_process_t pid, + mach_vm_size_t &rprvt, mach_vm_size_t &vprvt); + nub_size_t WriteRegion(task_t task, const nub_addr_t address, + const void *data, const nub_size_t data_count); - nub_size_t WriteRegion(task_t task, const nub_addr_t address, const void *data, const nub_size_t data_count); - - vm_size_t m_page_size; - DNBError m_err; + vm_size_t m_page_size; + DNBError m_err; }; - #endif // #ifndef __MachVMMemory_h__ diff --git a/lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp b/lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp index 38757595cfe..c011c133ac3 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachVMRegion.cpp @@ -12,191 +12,177 @@ //===----------------------------------------------------------------------===// #include "MachVMRegion.h" -#include <mach/mach_vm.h> #include "DNBLog.h" #include <assert.h> +#include <mach/mach_vm.h> -MachVMRegion::MachVMRegion(task_t task) : - m_task(task), - m_addr(INVALID_NUB_ADDRESS), - m_err(), - m_start(INVALID_NUB_ADDRESS), - m_size(0), - m_depth(-1), - m_curr_protection(0), - m_protection_addr(INVALID_NUB_ADDRESS), - m_protection_size(0) -{ - memset(&m_data, 0, sizeof(m_data)); +MachVMRegion::MachVMRegion(task_t task) + : m_task(task), m_addr(INVALID_NUB_ADDRESS), m_err(), + m_start(INVALID_NUB_ADDRESS), m_size(0), m_depth(-1), + m_curr_protection(0), m_protection_addr(INVALID_NUB_ADDRESS), + m_protection_size(0) { + memset(&m_data, 0, sizeof(m_data)); } -MachVMRegion::~MachVMRegion() -{ - // Restore any original protections and clear our vars - Clear(); +MachVMRegion::~MachVMRegion() { + // Restore any original protections and clear our vars + Clear(); } -void -MachVMRegion::Clear() -{ - RestoreProtections(); - m_addr = INVALID_NUB_ADDRESS; - m_err.Clear(); - m_start = INVALID_NUB_ADDRESS; - m_size = 0; - m_depth = -1; - memset(&m_data, 0, sizeof(m_data)); - m_curr_protection = 0; - m_protection_addr = INVALID_NUB_ADDRESS; - m_protection_size = 0; +void MachVMRegion::Clear() { + RestoreProtections(); + m_addr = INVALID_NUB_ADDRESS; + m_err.Clear(); + m_start = INVALID_NUB_ADDRESS; + m_size = 0; + m_depth = -1; + memset(&m_data, 0, sizeof(m_data)); + m_curr_protection = 0; + m_protection_addr = INVALID_NUB_ADDRESS; + m_protection_size = 0; } -bool -MachVMRegion::SetProtections(mach_vm_address_t addr, mach_vm_size_t size, vm_prot_t prot) -{ - if (ContainsAddress(addr)) - { - mach_vm_size_t prot_size = size; - mach_vm_address_t end_addr = EndAddress(); - if (prot_size > (end_addr - addr)) - prot_size = end_addr - addr; - - if (prot_size > 0) - { - if (prot == (m_curr_protection & VM_PROT_ALL)) - { - DNBLogThreadedIf(LOG_MEMORY_PROTECTIONS | LOG_VERBOSE, "MachVMRegion::%s: protections (%u) already sufficient for task 0x%4.4x at address 0x%8.8llx) ", __FUNCTION__, prot, m_task, (uint64_t)addr); - // Protections are already set as requested... - return true; - } - else - { - m_err = ::mach_vm_protect (m_task, addr, prot_size, 0, prot); - if (DNBLogCheckLogBit(LOG_MEMORY_PROTECTIONS)) - m_err.LogThreaded("::mach_vm_protect ( task = 0x%4.4x, addr = 0x%8.8llx, size = %llu, set_max = %i, prot = %u )", m_task, (uint64_t)addr, (uint64_t)prot_size, 0, prot); - if (m_err.Fail()) - { - // Try again with the ability to create a copy on write region - m_err = ::mach_vm_protect (m_task, addr, prot_size, 0, prot | VM_PROT_COPY); - if (DNBLogCheckLogBit(LOG_MEMORY_PROTECTIONS) || m_err.Fail()) - m_err.LogThreaded("::mach_vm_protect ( task = 0x%4.4x, addr = 0x%8.8llx, size = %llu, set_max = %i, prot = %u )", m_task, (uint64_t)addr, (uint64_t)prot_size, 0, prot | VM_PROT_COPY); - } - if (m_err.Success()) - { - m_curr_protection = prot; - m_protection_addr = addr; - m_protection_size = prot_size; - return true; - } - } +bool MachVMRegion::SetProtections(mach_vm_address_t addr, mach_vm_size_t size, + vm_prot_t prot) { + if (ContainsAddress(addr)) { + mach_vm_size_t prot_size = size; + mach_vm_address_t end_addr = EndAddress(); + if (prot_size > (end_addr - addr)) + prot_size = end_addr - addr; + + if (prot_size > 0) { + if (prot == (m_curr_protection & VM_PROT_ALL)) { + DNBLogThreadedIf(LOG_MEMORY_PROTECTIONS | LOG_VERBOSE, + "MachVMRegion::%s: protections (%u) already " + "sufficient for task 0x%4.4x at address 0x%8.8llx) ", + __FUNCTION__, prot, m_task, (uint64_t)addr); + // Protections are already set as requested... + return true; + } else { + m_err = ::mach_vm_protect(m_task, addr, prot_size, 0, prot); + if (DNBLogCheckLogBit(LOG_MEMORY_PROTECTIONS)) + m_err.LogThreaded("::mach_vm_protect ( task = 0x%4.4x, addr = " + "0x%8.8llx, size = %llu, set_max = %i, prot = %u )", + m_task, (uint64_t)addr, (uint64_t)prot_size, 0, + prot); + if (m_err.Fail()) { + // Try again with the ability to create a copy on write region + m_err = ::mach_vm_protect(m_task, addr, prot_size, 0, + prot | VM_PROT_COPY); + if (DNBLogCheckLogBit(LOG_MEMORY_PROTECTIONS) || m_err.Fail()) + m_err.LogThreaded("::mach_vm_protect ( task = 0x%4.4x, addr = " + "0x%8.8llx, size = %llu, set_max = %i, prot = %u " + ")", + m_task, (uint64_t)addr, (uint64_t)prot_size, 0, + prot | VM_PROT_COPY); } - else - { - DNBLogThreadedIf(LOG_MEMORY_PROTECTIONS | LOG_VERBOSE, "%s: Zero size for task 0x%4.4x at address 0x%8.8llx) ", __FUNCTION__, m_task, (uint64_t)addr); + if (m_err.Success()) { + m_curr_protection = prot; + m_protection_addr = addr; + m_protection_size = prot_size; + return true; } + } + } else { + DNBLogThreadedIf(LOG_MEMORY_PROTECTIONS | LOG_VERBOSE, + "%s: Zero size for task 0x%4.4x at address 0x%8.8llx) ", + __FUNCTION__, m_task, (uint64_t)addr); } - return false; + } + return false; } -bool -MachVMRegion::RestoreProtections() -{ - if (m_curr_protection != m_data.protection && m_protection_size > 0) - { - m_err = ::mach_vm_protect (m_task, m_protection_addr, m_protection_size, 0, m_data.protection); - if (DNBLogCheckLogBit(LOG_MEMORY_PROTECTIONS) || m_err.Fail()) - m_err.LogThreaded("::mach_vm_protect ( task = 0x%4.4x, addr = 0x%8.8llx, size = %llu, set_max = %i, prot = %u )", m_task, (uint64_t)m_protection_addr, (uint64_t)m_protection_size, 0, m_data.protection); - if (m_err.Success()) - { - m_protection_size = 0; - m_protection_addr = INVALID_NUB_ADDRESS; - m_curr_protection = m_data.protection; - return true; - } - } - else - { - m_err.Clear(); - return true; +bool MachVMRegion::RestoreProtections() { + if (m_curr_protection != m_data.protection && m_protection_size > 0) { + m_err = ::mach_vm_protect(m_task, m_protection_addr, m_protection_size, 0, + m_data.protection); + if (DNBLogCheckLogBit(LOG_MEMORY_PROTECTIONS) || m_err.Fail()) + m_err.LogThreaded("::mach_vm_protect ( task = 0x%4.4x, addr = 0x%8.8llx, " + "size = %llu, set_max = %i, prot = %u )", + m_task, (uint64_t)m_protection_addr, + (uint64_t)m_protection_size, 0, m_data.protection); + if (m_err.Success()) { + m_protection_size = 0; + m_protection_addr = INVALID_NUB_ADDRESS; + m_curr_protection = m_data.protection; + return true; } + } else { + m_err.Clear(); + return true; + } - return false; + return false; } -bool -MachVMRegion::GetRegionForAddress(nub_addr_t addr) -{ - // Restore any original protections and clear our vars - Clear(); - m_err.Clear(); - m_addr = addr; - m_start = addr; - m_depth = 1024; - mach_msg_type_number_t info_size = kRegionInfoSize; - assert(sizeof(info_size) == 4); - m_err = ::mach_vm_region_recurse (m_task, &m_start, &m_size, &m_depth, (vm_region_recurse_info_t)&m_data, &info_size); - - const bool failed = m_err.Fail(); - const bool log_protections = DNBLogCheckLogBit(LOG_MEMORY_PROTECTIONS); - - if (log_protections || failed) - m_err.LogThreaded("::mach_vm_region_recurse ( task = 0x%4.4x, address => 0x%8.8llx, size => %llu, nesting_depth => %d, info => %p, infoCnt => %d) addr = 0x%8.8llx ", m_task, (uint64_t)m_start, (uint64_t)m_size, m_depth, &m_data, info_size, (uint64_t)addr); - - if (failed) - return false; - if (log_protections) - { - DNBLogThreaded("info = { prot = %u, " - "max_prot = %u, " - "inheritance = 0x%8.8x, " - "offset = 0x%8.8llx, " - "user_tag = 0x%8.8x, " - "ref_count = %u, " - "shadow_depth = %u, " - "ext_pager = %u, " - "share_mode = %u, " - "is_submap = %d, " - "behavior = %d, " - "object_id = 0x%8.8x, " - "user_wired_count = 0x%4.4x }", - m_data.protection, - m_data.max_protection, - m_data.inheritance, - (uint64_t)m_data.offset, - m_data.user_tag, - m_data.ref_count, - m_data.shadow_depth, - m_data.external_pager, - m_data.share_mode, - m_data.is_submap, - m_data.behavior, - m_data.object_id, - m_data.user_wired_count); - } - m_curr_protection = m_data.protection; - - // We make a request for an address and got no error back, but this - // doesn't mean that "addr" is in the range. The data in this object will - // be valid though, so you could see where the next region begins. So we - // return false, yet leave "m_err" with a successfull return code. - if ((addr < m_start) || (addr >= (m_start + m_size))) - return false; +bool MachVMRegion::GetRegionForAddress(nub_addr_t addr) { + // Restore any original protections and clear our vars + Clear(); + m_err.Clear(); + m_addr = addr; + m_start = addr; + m_depth = 1024; + mach_msg_type_number_t info_size = kRegionInfoSize; + assert(sizeof(info_size) == 4); + m_err = + ::mach_vm_region_recurse(m_task, &m_start, &m_size, &m_depth, + (vm_region_recurse_info_t)&m_data, &info_size); - return true; + const bool failed = m_err.Fail(); + const bool log_protections = DNBLogCheckLogBit(LOG_MEMORY_PROTECTIONS); + + if (log_protections || failed) + m_err.LogThreaded("::mach_vm_region_recurse ( task = 0x%4.4x, address => " + "0x%8.8llx, size => %llu, nesting_depth => %d, info => " + "%p, infoCnt => %d) addr = 0x%8.8llx ", + m_task, (uint64_t)m_start, (uint64_t)m_size, m_depth, + &m_data, info_size, (uint64_t)addr); + + if (failed) + return false; + if (log_protections) { + DNBLogThreaded("info = { prot = %u, " + "max_prot = %u, " + "inheritance = 0x%8.8x, " + "offset = 0x%8.8llx, " + "user_tag = 0x%8.8x, " + "ref_count = %u, " + "shadow_depth = %u, " + "ext_pager = %u, " + "share_mode = %u, " + "is_submap = %d, " + "behavior = %d, " + "object_id = 0x%8.8x, " + "user_wired_count = 0x%4.4x }", + m_data.protection, m_data.max_protection, m_data.inheritance, + (uint64_t)m_data.offset, m_data.user_tag, m_data.ref_count, + m_data.shadow_depth, m_data.external_pager, + m_data.share_mode, m_data.is_submap, m_data.behavior, + m_data.object_id, m_data.user_wired_count); + } + m_curr_protection = m_data.protection; + + // We make a request for an address and got no error back, but this + // doesn't mean that "addr" is in the range. The data in this object will + // be valid though, so you could see where the next region begins. So we + // return false, yet leave "m_err" with a successfull return code. + if ((addr < m_start) || (addr >= (m_start + m_size))) + return false; + + return true; } -uint32_t -MachVMRegion::GetDNBPermissions () const -{ - if (m_addr == INVALID_NUB_ADDRESS || m_start == INVALID_NUB_ADDRESS || m_size == 0) - return 0; - uint32_t dnb_permissions = 0; - - if ((m_data.protection & VM_PROT_READ) == VM_PROT_READ) - dnb_permissions |= eMemoryPermissionsReadable; - if ((m_data.protection & VM_PROT_WRITE) == VM_PROT_WRITE) - dnb_permissions |= eMemoryPermissionsWritable; - if ((m_data.protection & VM_PROT_EXECUTE) == VM_PROT_EXECUTE) - dnb_permissions |= eMemoryPermissionsExecutable; - return dnb_permissions; +uint32_t MachVMRegion::GetDNBPermissions() const { + if (m_addr == INVALID_NUB_ADDRESS || m_start == INVALID_NUB_ADDRESS || + m_size == 0) + return 0; + uint32_t dnb_permissions = 0; + + if ((m_data.protection & VM_PROT_READ) == VM_PROT_READ) + dnb_permissions |= eMemoryPermissionsReadable; + if ((m_data.protection & VM_PROT_WRITE) == VM_PROT_WRITE) + dnb_permissions |= eMemoryPermissionsWritable; + if ((m_data.protection & VM_PROT_EXECUTE) == VM_PROT_EXECUTE) + dnb_permissions |= eMemoryPermissionsExecutable; + return dnb_permissions; } diff --git a/lldb/tools/debugserver/source/MacOSX/MachVMRegion.h b/lldb/tools/debugserver/source/MacOSX/MachVMRegion.h index bcac60b8318..758112d236d 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachVMRegion.h +++ b/lldb/tools/debugserver/source/MacOSX/MachVMRegion.h @@ -18,60 +18,56 @@ #include "DNBError.h" #include <mach/mach.h> -class MachVMRegion -{ +class MachVMRegion { public: - MachVMRegion(task_t task); - ~MachVMRegion(); + MachVMRegion(task_t task); + ~MachVMRegion(); - void Clear(); - mach_vm_address_t StartAddress() const { return m_start; } - mach_vm_address_t EndAddress() const { return m_start + m_size; } - mach_vm_size_t GetByteSize () const { return m_size; } - mach_vm_address_t BytesRemaining(mach_vm_address_t addr) const - { - if (ContainsAddress(addr)) - return m_size - (addr - m_start); - else - return 0; - } - bool ContainsAddress(mach_vm_address_t addr) const - { - return addr >= StartAddress() && addr < EndAddress(); - } + void Clear(); + mach_vm_address_t StartAddress() const { return m_start; } + mach_vm_address_t EndAddress() const { return m_start + m_size; } + mach_vm_size_t GetByteSize() const { return m_size; } + mach_vm_address_t BytesRemaining(mach_vm_address_t addr) const { + if (ContainsAddress(addr)) + return m_size - (addr - m_start); + else + return 0; + } + bool ContainsAddress(mach_vm_address_t addr) const { + return addr >= StartAddress() && addr < EndAddress(); + } - bool SetProtections(mach_vm_address_t addr, mach_vm_size_t size, vm_prot_t prot); - bool RestoreProtections(); - bool GetRegionForAddress(nub_addr_t addr); + bool SetProtections(mach_vm_address_t addr, mach_vm_size_t size, + vm_prot_t prot); + bool RestoreProtections(); + bool GetRegionForAddress(nub_addr_t addr); - uint32_t - GetDNBPermissions () const; + uint32_t GetDNBPermissions() const; + + const DNBError &GetError() { return m_err; } - const DNBError & - GetError () - { - return m_err; - } protected: -#if defined (VM_REGION_SUBMAP_SHORT_INFO_COUNT_64) - typedef vm_region_submap_short_info_data_64_t RegionInfo; - enum { kRegionInfoSize = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 }; +#if defined(VM_REGION_SUBMAP_SHORT_INFO_COUNT_64) + typedef vm_region_submap_short_info_data_64_t RegionInfo; + enum { kRegionInfoSize = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 }; #else - typedef vm_region_submap_info_data_64_t RegionInfo; - enum { kRegionInfoSize = VM_REGION_SUBMAP_INFO_COUNT_64 }; + typedef vm_region_submap_info_data_64_t RegionInfo; + enum { kRegionInfoSize = VM_REGION_SUBMAP_INFO_COUNT_64 }; #endif - task_t m_task; - mach_vm_address_t m_addr; - DNBError m_err; - mach_vm_address_t m_start; - mach_vm_size_t m_size; - natural_t m_depth; - RegionInfo m_data; - vm_prot_t m_curr_protection; // The current, possibly modified protections. Original value is saved in m_data.protections. - mach_vm_address_t m_protection_addr; // The start address at which protections were changed - mach_vm_size_t m_protection_size; // The size of memory that had its protections changed - + task_t m_task; + mach_vm_address_t m_addr; + DNBError m_err; + mach_vm_address_t m_start; + mach_vm_size_t m_size; + natural_t m_depth; + RegionInfo m_data; + vm_prot_t m_curr_protection; // The current, possibly modified protections. + // Original value is saved in m_data.protections. + mach_vm_address_t + m_protection_addr; // The start address at which protections were changed + mach_vm_size_t + m_protection_size; // The size of memory that had its protections changed }; -#endif // #ifndef __MachVMRegion_h__ +#endif // #ifndef __MachVMRegion_h__ diff --git a/lldb/tools/debugserver/source/MacOSX/OsLogger.cpp b/lldb/tools/debugserver/source/MacOSX/OsLogger.cpp index 1f424e7da17..efecea30212 100644 --- a/lldb/tools/debugserver/source/MacOSX/OsLogger.cpp +++ b/lldb/tools/debugserver/source/MacOSX/OsLogger.cpp @@ -18,54 +18,49 @@ #define LLDB_OS_LOG_MAX_BUFFER_LENGTH 256 -namespace -{ - //---------------------------------------------------------------------- - // Darwin os_log logging callback that can be registered with - // DNBLogSetLogCallback - //---------------------------------------------------------------------- - void - DarwinLogCallback(void *baton, uint32_t flags, const char *format, - va_list args) - { - if (format == nullptr) - return; +namespace { +//---------------------------------------------------------------------- +// Darwin os_log logging callback that can be registered with +// DNBLogSetLogCallback +//---------------------------------------------------------------------- +void DarwinLogCallback(void *baton, uint32_t flags, const char *format, + va_list args) { + if (format == nullptr) + return; - static os_log_t g_logger; - if (!g_logger) - { - g_logger = os_log_create("com.apple.dt.lldb", "debugserver"); - if (!g_logger) - return; - } + static os_log_t g_logger; + if (!g_logger) { + g_logger = os_log_create("com.apple.dt.lldb", "debugserver"); + if (!g_logger) + return; + } - os_log_type_t log_type; - if (flags & DNBLOG_FLAG_FATAL) log_type = OS_LOG_TYPE_FAULT; - else if (flags & DNBLOG_FLAG_ERROR) log_type = OS_LOG_TYPE_ERROR; - else if (flags & DNBLOG_FLAG_WARNING) log_type = OS_LOG_TYPE_DEFAULT; - else if (flags & DNBLOG_FLAG_VERBOSE) log_type = OS_LOG_TYPE_DEBUG; - else log_type = OS_LOG_TYPE_DEFAULT; + os_log_type_t log_type; + if (flags & DNBLOG_FLAG_FATAL) + log_type = OS_LOG_TYPE_FAULT; + else if (flags & DNBLOG_FLAG_ERROR) + log_type = OS_LOG_TYPE_ERROR; + else if (flags & DNBLOG_FLAG_WARNING) + log_type = OS_LOG_TYPE_DEFAULT; + else if (flags & DNBLOG_FLAG_VERBOSE) + log_type = OS_LOG_TYPE_DEBUG; + else + log_type = OS_LOG_TYPE_DEFAULT; - // This code is unfortunate. os_log* only takes static strings, but - // our current log API isn't set up to make use of that style. - char buffer[LLDB_OS_LOG_MAX_BUFFER_LENGTH]; - vsnprintf(buffer, sizeof(buffer), format, args); - os_log_with_type(g_logger, log_type, "%{public}s", buffer); - } + // This code is unfortunate. os_log* only takes static strings, but + // our current log API isn't set up to make use of that style. + char buffer[LLDB_OS_LOG_MAX_BUFFER_LENGTH]; + vsnprintf(buffer, sizeof(buffer), format, args); + os_log_with_type(g_logger, log_type, "%{public}s", buffer); +} } -DNBCallbackLog -OsLogger::GetLogFunction() -{ - return _os_log_impl ? DarwinLogCallback : nullptr; +DNBCallbackLog OsLogger::GetLogFunction() { + return _os_log_impl ? DarwinLogCallback : nullptr; } #else -DNBCallbackLog -OsLogger::GetLogFunction() -{ - return nullptr; -} +DNBCallbackLog OsLogger::GetLogFunction() { return nullptr; } #endif diff --git a/lldb/tools/debugserver/source/MacOSX/OsLogger.h b/lldb/tools/debugserver/source/MacOSX/OsLogger.h index 6733b925335..9afdcb974d9 100644 --- a/lldb/tools/debugserver/source/MacOSX/OsLogger.h +++ b/lldb/tools/debugserver/source/MacOSX/OsLogger.h @@ -12,13 +12,9 @@ #include "DNBDefs.h" -class OsLogger -{ +class OsLogger { public: - - static DNBCallbackLog - GetLogFunction(); - + static DNBCallbackLog GetLogFunction(); }; #endif /* OsLogger_h */ diff --git a/lldb/tools/debugserver/source/MacOSX/ThreadInfo.h b/lldb/tools/debugserver/source/MacOSX/ThreadInfo.h index 1fd9d5790cf..e9773caf9ea 100644 --- a/lldb/tools/debugserver/source/MacOSX/ThreadInfo.h +++ b/lldb/tools/debugserver/source/MacOSX/ThreadInfo.h @@ -1,4 +1,5 @@ -//===-- ThreadInfo.h -----------------------------------------------*- C++ -*-===// +//===-- ThreadInfo.h -----------------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -14,13 +15,12 @@ namespace ThreadInfo { class QoS { public: - QoS () : constant_name(), printable_name(), enum_value(UINT32_MAX) { } - bool IsValid () { return enum_value != UINT32_MAX; } - std::string constant_name; - std::string printable_name; - uint32_t enum_value; + QoS() : constant_name(), printable_name(), enum_value(UINT32_MAX) {} + bool IsValid() { return enum_value != UINT32_MAX; } + std::string constant_name; + std::string printable_name; + uint32_t enum_value; }; - }; #endif // __ThreadInfo_h__ diff --git a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp index 2eac47b045c..175aab1ae3f 100644 --- a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp +++ b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp @@ -11,93 +11,93 @@ // //===----------------------------------------------------------------------===// -#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) +#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) #include "MacOSX/arm/DNBArchImpl.h" -#include "MacOSX/MachProcess.h" -#include "MacOSX/MachThread.h" +#include "ARM_DWARF_Registers.h" +#include "ARM_ehframe_Registers.h" +#include "DNB.h" #include "DNBBreakpoint.h" #include "DNBLog.h" #include "DNBRegisterInfo.h" -#include "DNB.h" -#include "ARM_ehframe_Registers.h" -#include "ARM_DWARF_Registers.h" +#include "MacOSX/MachProcess.h" +#include "MacOSX/MachThread.h" #include <inttypes.h> #include <sys/sysctl.h> // BCR address match type -#define BCR_M_IMVA_MATCH ((uint32_t)(0u << 21)) -#define BCR_M_CONTEXT_ID_MATCH ((uint32_t)(1u << 21)) -#define BCR_M_IMVA_MISMATCH ((uint32_t)(2u << 21)) -#define BCR_M_RESERVED ((uint32_t)(3u << 21)) +#define BCR_M_IMVA_MATCH ((uint32_t)(0u << 21)) +#define BCR_M_CONTEXT_ID_MATCH ((uint32_t)(1u << 21)) +#define BCR_M_IMVA_MISMATCH ((uint32_t)(2u << 21)) +#define BCR_M_RESERVED ((uint32_t)(3u << 21)) // Link a BVR/BCR or WVR/WCR pair to another -#define E_ENABLE_LINKING ((uint32_t)(1u << 20)) +#define E_ENABLE_LINKING ((uint32_t)(1u << 20)) // Byte Address Select -#define BAS_IMVA_PLUS_0 ((uint32_t)(1u << 5)) -#define BAS_IMVA_PLUS_1 ((uint32_t)(1u << 6)) -#define BAS_IMVA_PLUS_2 ((uint32_t)(1u << 7)) -#define BAS_IMVA_PLUS_3 ((uint32_t)(1u << 8)) -#define BAS_IMVA_0_1 ((uint32_t)(3u << 5)) -#define BAS_IMVA_2_3 ((uint32_t)(3u << 7)) -#define BAS_IMVA_ALL ((uint32_t)(0xfu << 5)) +#define BAS_IMVA_PLUS_0 ((uint32_t)(1u << 5)) +#define BAS_IMVA_PLUS_1 ((uint32_t)(1u << 6)) +#define BAS_IMVA_PLUS_2 ((uint32_t)(1u << 7)) +#define BAS_IMVA_PLUS_3 ((uint32_t)(1u << 8)) +#define BAS_IMVA_0_1 ((uint32_t)(3u << 5)) +#define BAS_IMVA_2_3 ((uint32_t)(3u << 7)) +#define BAS_IMVA_ALL ((uint32_t)(0xfu << 5)) // Break only in privileged or user mode -#define S_RSVD ((uint32_t)(0u << 1)) -#define S_PRIV ((uint32_t)(1u << 1)) -#define S_USER ((uint32_t)(2u << 1)) -#define S_PRIV_USER ((S_PRIV) | (S_USER)) +#define S_RSVD ((uint32_t)(0u << 1)) +#define S_PRIV ((uint32_t)(1u << 1)) +#define S_USER ((uint32_t)(2u << 1)) +#define S_PRIV_USER ((S_PRIV) | (S_USER)) -#define BCR_ENABLE ((uint32_t)(1u)) -#define WCR_ENABLE ((uint32_t)(1u)) +#define BCR_ENABLE ((uint32_t)(1u)) +#define WCR_ENABLE ((uint32_t)(1u)) // Watchpoint load/store -#define WCR_LOAD ((uint32_t)(1u << 3)) -#define WCR_STORE ((uint32_t)(1u << 4)) +#define WCR_LOAD ((uint32_t)(1u << 3)) +#define WCR_STORE ((uint32_t)(1u << 4)) // Definitions for the Debug Status and Control Register fields: // [5:2] => Method of debug entry //#define WATCHPOINT_OCCURRED ((uint32_t)(2u)) // I'm seeing this, instead. -#define WATCHPOINT_OCCURRED ((uint32_t)(10u)) +#define WATCHPOINT_OCCURRED ((uint32_t)(10u)) // 0xE120BE70 -static const uint8_t g_arm_breakpoint_opcode[] = { 0x70, 0xBE, 0x20, 0xE1 }; -static const uint8_t g_thumb_breakpoint_opcode[] = { 0x70, 0xBE }; +static const uint8_t g_arm_breakpoint_opcode[] = {0x70, 0xBE, 0x20, 0xE1}; +static const uint8_t g_thumb_breakpoint_opcode[] = {0x70, 0xBE}; // A watchpoint may need to be implemented using two watchpoint registers. // e.g. watching an 8-byte region when the device can only watch 4-bytes. // // This stores the lo->hi mappings. It's safe to initialize to all 0's // since hi > lo and therefore LoHi[i] cannot be 0. -static uint32_t LoHi[16] = { 0 }; +static uint32_t LoHi[16] = {0}; // ARM constants used during decoding -#define REG_RD 0 -#define LDM_REGLIST 1 -#define PC_REG 15 -#define PC_REGLIST_BIT 0x8000 +#define REG_RD 0 +#define LDM_REGLIST 1 +#define PC_REG 15 +#define PC_REGLIST_BIT 0x8000 // ARM conditions -#define COND_EQ 0x0 -#define COND_NE 0x1 -#define COND_CS 0x2 -#define COND_HS 0x2 -#define COND_CC 0x3 -#define COND_LO 0x3 -#define COND_MI 0x4 -#define COND_PL 0x5 -#define COND_VS 0x6 -#define COND_VC 0x7 -#define COND_HI 0x8 -#define COND_LS 0x9 -#define COND_GE 0xA -#define COND_LT 0xB -#define COND_GT 0xC -#define COND_LE 0xD -#define COND_AL 0xE +#define COND_EQ 0x0 +#define COND_NE 0x1 +#define COND_CS 0x2 +#define COND_HS 0x2 +#define COND_CC 0x3 +#define COND_LO 0x3 +#define COND_MI 0x4 +#define COND_PL 0x5 +#define COND_VS 0x6 +#define COND_VC 0x7 +#define COND_HI 0x8 +#define COND_LS 0x9 +#define COND_GE 0xA +#define COND_LT 0xB +#define COND_GT 0xC +#define COND_LE 0xD +#define COND_AL 0xE #define COND_UNCOND 0xF #define MASK_CPSR_T (1u << 5) @@ -108,962 +108,971 @@ static uint32_t LoHi[16] = { 0 }; // Returns true if the first 16 bit opcode of a thumb instruction indicates // the instruction will be a 32 bit thumb opcode -static bool -IsThumb32Opcode (uint16_t opcode) -{ - if (((opcode & 0xE000) == 0xE000) && (opcode & 0x1800)) - return true; - return false; +static bool IsThumb32Opcode(uint16_t opcode) { + if (((opcode & 0xE000) == 0xE000) && (opcode & 0x1800)) + return true; + return false; } -void -DNBArchMachARM::Initialize() -{ - DNBArchPluginInfo arch_plugin_info = - { - CPU_TYPE_ARM, - DNBArchMachARM::Create, - DNBArchMachARM::GetRegisterSetInfo, - DNBArchMachARM::SoftwareBreakpointOpcode - }; - - // Register this arch plug-in with the main protocol class - DNBArchProtocol::RegisterArchPlugin (arch_plugin_info); -} +void DNBArchMachARM::Initialize() { + DNBArchPluginInfo arch_plugin_info = { + CPU_TYPE_ARM, DNBArchMachARM::Create, DNBArchMachARM::GetRegisterSetInfo, + DNBArchMachARM::SoftwareBreakpointOpcode}; - -DNBArchProtocol * -DNBArchMachARM::Create (MachThread *thread) -{ - DNBArchMachARM *obj = new DNBArchMachARM (thread); - return obj; + // Register this arch plug-in with the main protocol class + DNBArchProtocol::RegisterArchPlugin(arch_plugin_info); } -const uint8_t * -DNBArchMachARM::SoftwareBreakpointOpcode (nub_size_t byte_size) -{ - switch (byte_size) - { - case 2: return g_thumb_breakpoint_opcode; - case 4: return g_arm_breakpoint_opcode; - } - return NULL; +DNBArchProtocol *DNBArchMachARM::Create(MachThread *thread) { + DNBArchMachARM *obj = new DNBArchMachARM(thread); + return obj; } -uint32_t -DNBArchMachARM::GetCPUType() -{ - return CPU_TYPE_ARM; +const uint8_t *DNBArchMachARM::SoftwareBreakpointOpcode(nub_size_t byte_size) { + switch (byte_size) { + case 2: + return g_thumb_breakpoint_opcode; + case 4: + return g_arm_breakpoint_opcode; + } + return NULL; } -uint64_t -DNBArchMachARM::GetPC(uint64_t failValue) -{ - // Get program counter - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.context.gpr.__pc; - return failValue; -} +uint32_t DNBArchMachARM::GetCPUType() { return CPU_TYPE_ARM; } -kern_return_t -DNBArchMachARM::SetPC(uint64_t value) -{ - // Get program counter - kern_return_t err = GetGPRState(false); - if (err == KERN_SUCCESS) - { - m_state.context.gpr.__pc = (uint32_t) value; - err = SetGPRState(); - } - return err == KERN_SUCCESS; +uint64_t DNBArchMachARM::GetPC(uint64_t failValue) { + // Get program counter + if (GetGPRState(false) == KERN_SUCCESS) + return m_state.context.gpr.__pc; + return failValue; } -uint64_t -DNBArchMachARM::GetSP(uint64_t failValue) -{ - // Get stack pointer - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.context.gpr.__sp; - return failValue; +kern_return_t DNBArchMachARM::SetPC(uint64_t value) { + // Get program counter + kern_return_t err = GetGPRState(false); + if (err == KERN_SUCCESS) { + m_state.context.gpr.__pc = (uint32_t)value; + err = SetGPRState(); + } + return err == KERN_SUCCESS; } -kern_return_t -DNBArchMachARM::GetGPRState(bool force) -{ - int set = e_regSetGPR; - // Check if we have valid cached registers - if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) - return KERN_SUCCESS; - - // Read the registers from our thread - mach_msg_type_number_t count = ARM_THREAD_STATE_COUNT; - kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_THREAD_STATE, (thread_state_t)&m_state.context.gpr, &count); - uint32_t *r = &m_state.context.gpr.__r[0]; - DNBLogThreadedIf(LOG_THREAD, "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count = %u) regs r0=%8.8x r1=%8.8x r2=%8.8x r3=%8.8x r4=%8.8x r5=%8.8x r6=%8.8x r7=%8.8x r8=%8.8x r9=%8.8x r10=%8.8x r11=%8.8x s12=%8.8x sp=%8.8x lr=%8.8x pc=%8.8x cpsr=%8.8x", - m_thread->MachPortNumber(), - ARM_THREAD_STATE, - ARM_THREAD_STATE_COUNT, - kret, - count, - r[0], - r[1], - r[2], - r[3], - r[4], - r[5], - r[6], - r[7], - r[8], - r[9], - r[10], - r[11], - r[12], - r[13], - r[14], - r[15], - r[16]); - m_state.SetError(set, Read, kret); - return kret; +uint64_t DNBArchMachARM::GetSP(uint64_t failValue) { + // Get stack pointer + if (GetGPRState(false) == KERN_SUCCESS) + return m_state.context.gpr.__sp; + return failValue; } -kern_return_t -DNBArchMachARM::GetVFPState(bool force) -{ - int set = e_regSetVFP; - // Check if we have valid cached registers - if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) - return KERN_SUCCESS; - - kern_return_t kret; - -#if defined (__arm64__) || defined (__aarch64__) - // Read the registers from our thread - mach_msg_type_number_t count = ARM_NEON_STATE_COUNT; - kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_NEON_STATE, (thread_state_t)&m_state.context.vfp, &count); - if (DNBLogEnabledForAny (LOG_THREAD)) - { - DNBLogThreaded("thread_get_state(0x%4.4x, %u, &vfp, %u) => 0x%8.8x (count = %u) regs" - "\n q0 = 0x%16.16llx%16.16llx" - "\n q1 = 0x%16.16llx%16.16llx" - "\n q2 = 0x%16.16llx%16.16llx" - "\n q3 = 0x%16.16llx%16.16llx" - "\n q4 = 0x%16.16llx%16.16llx" - "\n q5 = 0x%16.16llx%16.16llx" - "\n q6 = 0x%16.16llx%16.16llx" - "\n q7 = 0x%16.16llx%16.16llx" - "\n q8 = 0x%16.16llx%16.16llx" - "\n q9 = 0x%16.16llx%16.16llx" - "\n q10 = 0x%16.16llx%16.16llx" - "\n q11 = 0x%16.16llx%16.16llx" - "\n q12 = 0x%16.16llx%16.16llx" - "\n q13 = 0x%16.16llx%16.16llx" - "\n q14 = 0x%16.16llx%16.16llx" - "\n q15 = 0x%16.16llx%16.16llx" - "\n fpsr = 0x%8.8x" - "\n fpcr = 0x%8.8x\n\n", - m_thread->MachPortNumber(), - ARM_NEON_STATE, - ARM_NEON_STATE_COUNT, - kret, - count, - ((uint64_t *)&m_state.context.vfp.__v[0])[0] , ((uint64_t *)&m_state.context.vfp.__v[0])[1], - ((uint64_t *)&m_state.context.vfp.__v[1])[0] , ((uint64_t *)&m_state.context.vfp.__v[1])[1], - ((uint64_t *)&m_state.context.vfp.__v[2])[0] , ((uint64_t *)&m_state.context.vfp.__v[2])[1], - ((uint64_t *)&m_state.context.vfp.__v[3])[0] , ((uint64_t *)&m_state.context.vfp.__v[3])[1], - ((uint64_t *)&m_state.context.vfp.__v[4])[0] , ((uint64_t *)&m_state.context.vfp.__v[4])[1], - ((uint64_t *)&m_state.context.vfp.__v[5])[0] , ((uint64_t *)&m_state.context.vfp.__v[5])[1], - ((uint64_t *)&m_state.context.vfp.__v[6])[0] , ((uint64_t *)&m_state.context.vfp.__v[6])[1], - ((uint64_t *)&m_state.context.vfp.__v[7])[0] , ((uint64_t *)&m_state.context.vfp.__v[7])[1], - ((uint64_t *)&m_state.context.vfp.__v[8])[0] , ((uint64_t *)&m_state.context.vfp.__v[8])[1], - ((uint64_t *)&m_state.context.vfp.__v[9])[0] , ((uint64_t *)&m_state.context.vfp.__v[9])[1], - ((uint64_t *)&m_state.context.vfp.__v[10])[0], ((uint64_t *)&m_state.context.vfp.__v[10])[1], - ((uint64_t *)&m_state.context.vfp.__v[11])[0], ((uint64_t *)&m_state.context.vfp.__v[11])[1], - ((uint64_t *)&m_state.context.vfp.__v[12])[0], ((uint64_t *)&m_state.context.vfp.__v[12])[1], - ((uint64_t *)&m_state.context.vfp.__v[13])[0], ((uint64_t *)&m_state.context.vfp.__v[13])[1], - ((uint64_t *)&m_state.context.vfp.__v[14])[0], ((uint64_t *)&m_state.context.vfp.__v[14])[1], - ((uint64_t *)&m_state.context.vfp.__v[15])[0], ((uint64_t *)&m_state.context.vfp.__v[15])[1], - m_state.context.vfp.__fpsr, - m_state.context.vfp.__fpcr); +kern_return_t DNBArchMachARM::GetGPRState(bool force) { + int set = e_regSetGPR; + // Check if we have valid cached registers + if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) + return KERN_SUCCESS; + + // Read the registers from our thread + mach_msg_type_number_t count = ARM_THREAD_STATE_COUNT; + kern_return_t kret = + ::thread_get_state(m_thread->MachPortNumber(), ARM_THREAD_STATE, + (thread_state_t)&m_state.context.gpr, &count); + uint32_t *r = &m_state.context.gpr.__r[0]; + DNBLogThreadedIf( + LOG_THREAD, "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count = " + "%u) regs r0=%8.8x r1=%8.8x r2=%8.8x r3=%8.8x r4=%8.8x " + "r5=%8.8x r6=%8.8x r7=%8.8x r8=%8.8x r9=%8.8x r10=%8.8x " + "r11=%8.8x s12=%8.8x sp=%8.8x lr=%8.8x pc=%8.8x cpsr=%8.8x", + m_thread->MachPortNumber(), ARM_THREAD_STATE, ARM_THREAD_STATE_COUNT, + kret, count, r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], + r[10], r[11], r[12], r[13], r[14], r[15], r[16]); + m_state.SetError(set, Read, kret); + return kret; +} - } +kern_return_t DNBArchMachARM::GetVFPState(bool force) { + int set = e_regSetVFP; + // Check if we have valid cached registers + if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) + return KERN_SUCCESS; + + kern_return_t kret; + +#if defined(__arm64__) || defined(__aarch64__) + // Read the registers from our thread + mach_msg_type_number_t count = ARM_NEON_STATE_COUNT; + kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_NEON_STATE, + (thread_state_t)&m_state.context.vfp, &count); + if (DNBLogEnabledForAny(LOG_THREAD)) { + DNBLogThreaded( + "thread_get_state(0x%4.4x, %u, &vfp, %u) => 0x%8.8x (count = %u) regs" + "\n q0 = 0x%16.16llx%16.16llx" + "\n q1 = 0x%16.16llx%16.16llx" + "\n q2 = 0x%16.16llx%16.16llx" + "\n q3 = 0x%16.16llx%16.16llx" + "\n q4 = 0x%16.16llx%16.16llx" + "\n q5 = 0x%16.16llx%16.16llx" + "\n q6 = 0x%16.16llx%16.16llx" + "\n q7 = 0x%16.16llx%16.16llx" + "\n q8 = 0x%16.16llx%16.16llx" + "\n q9 = 0x%16.16llx%16.16llx" + "\n q10 = 0x%16.16llx%16.16llx" + "\n q11 = 0x%16.16llx%16.16llx" + "\n q12 = 0x%16.16llx%16.16llx" + "\n q13 = 0x%16.16llx%16.16llx" + "\n q14 = 0x%16.16llx%16.16llx" + "\n q15 = 0x%16.16llx%16.16llx" + "\n fpsr = 0x%8.8x" + "\n fpcr = 0x%8.8x\n\n", + m_thread->MachPortNumber(), ARM_NEON_STATE, ARM_NEON_STATE_COUNT, kret, + count, ((uint64_t *)&m_state.context.vfp.__v[0])[0], + ((uint64_t *)&m_state.context.vfp.__v[0])[1], + ((uint64_t *)&m_state.context.vfp.__v[1])[0], + ((uint64_t *)&m_state.context.vfp.__v[1])[1], + ((uint64_t *)&m_state.context.vfp.__v[2])[0], + ((uint64_t *)&m_state.context.vfp.__v[2])[1], + ((uint64_t *)&m_state.context.vfp.__v[3])[0], + ((uint64_t *)&m_state.context.vfp.__v[3])[1], + ((uint64_t *)&m_state.context.vfp.__v[4])[0], + ((uint64_t *)&m_state.context.vfp.__v[4])[1], + ((uint64_t *)&m_state.context.vfp.__v[5])[0], + ((uint64_t *)&m_state.context.vfp.__v[5])[1], + ((uint64_t *)&m_state.context.vfp.__v[6])[0], + ((uint64_t *)&m_state.context.vfp.__v[6])[1], + ((uint64_t *)&m_state.context.vfp.__v[7])[0], + ((uint64_t *)&m_state.context.vfp.__v[7])[1], + ((uint64_t *)&m_state.context.vfp.__v[8])[0], + ((uint64_t *)&m_state.context.vfp.__v[8])[1], + ((uint64_t *)&m_state.context.vfp.__v[9])[0], + ((uint64_t *)&m_state.context.vfp.__v[9])[1], + ((uint64_t *)&m_state.context.vfp.__v[10])[0], + ((uint64_t *)&m_state.context.vfp.__v[10])[1], + ((uint64_t *)&m_state.context.vfp.__v[11])[0], + ((uint64_t *)&m_state.context.vfp.__v[11])[1], + ((uint64_t *)&m_state.context.vfp.__v[12])[0], + ((uint64_t *)&m_state.context.vfp.__v[12])[1], + ((uint64_t *)&m_state.context.vfp.__v[13])[0], + ((uint64_t *)&m_state.context.vfp.__v[13])[1], + ((uint64_t *)&m_state.context.vfp.__v[14])[0], + ((uint64_t *)&m_state.context.vfp.__v[14])[1], + ((uint64_t *)&m_state.context.vfp.__v[15])[0], + ((uint64_t *)&m_state.context.vfp.__v[15])[1], + m_state.context.vfp.__fpsr, m_state.context.vfp.__fpcr); + } #else - // Read the registers from our thread - mach_msg_type_number_t count = ARM_VFP_STATE_COUNT; - kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_VFP_STATE, (thread_state_t)&m_state.context.vfp, &count); - - if (DNBLogEnabledForAny (LOG_THREAD)) - { - uint32_t *r = &m_state.context.vfp.__r[0]; - DNBLogThreaded ("thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count => %u)", - m_thread->MachPortNumber(), - ARM_THREAD_STATE, - ARM_THREAD_STATE_COUNT, - kret, - count); - DNBLogThreaded(" s0=%8.8x s1=%8.8x s2=%8.8x s3=%8.8x s4=%8.8x s5=%8.8x s6=%8.8x s7=%8.8x",r[ 0],r[ 1],r[ 2],r[ 3],r[ 4],r[ 5],r[ 6],r[ 7]); - DNBLogThreaded(" s8=%8.8x s9=%8.8x s10=%8.8x s11=%8.8x s12=%8.8x s13=%8.8x s14=%8.8x s15=%8.8x",r[ 8],r[ 9],r[10],r[11],r[12],r[13],r[14],r[15]); - DNBLogThreaded(" s16=%8.8x s17=%8.8x s18=%8.8x s19=%8.8x s20=%8.8x s21=%8.8x s22=%8.8x s23=%8.8x",r[16],r[17],r[18],r[19],r[20],r[21],r[22],r[23]); - DNBLogThreaded(" s24=%8.8x s25=%8.8x s26=%8.8x s27=%8.8x s28=%8.8x s29=%8.8x s30=%8.8x s31=%8.8x",r[24],r[25],r[26],r[27],r[28],r[29],r[30],r[31]); - DNBLogThreaded(" s32=%8.8x s33=%8.8x s34=%8.8x s35=%8.8x s36=%8.8x s37=%8.8x s38=%8.8x s39=%8.8x",r[32],r[33],r[34],r[35],r[36],r[37],r[38],r[39]); - DNBLogThreaded(" s40=%8.8x s41=%8.8x s42=%8.8x s43=%8.8x s44=%8.8x s45=%8.8x s46=%8.8x s47=%8.8x",r[40],r[41],r[42],r[43],r[44],r[45],r[46],r[47]); - DNBLogThreaded(" s48=%8.8x s49=%8.8x s50=%8.8x s51=%8.8x s52=%8.8x s53=%8.8x s54=%8.8x s55=%8.8x",r[48],r[49],r[50],r[51],r[52],r[53],r[54],r[55]); - DNBLogThreaded(" s56=%8.8x s57=%8.8x s58=%8.8x s59=%8.8x s60=%8.8x s61=%8.8x s62=%8.8x s63=%8.8x fpscr=%8.8x",r[56],r[57],r[58],r[59],r[60],r[61],r[62],r[63],r[64]); - } + // Read the registers from our thread + mach_msg_type_number_t count = ARM_VFP_STATE_COUNT; + kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_VFP_STATE, + (thread_state_t)&m_state.context.vfp, &count); + + if (DNBLogEnabledForAny(LOG_THREAD)) { + uint32_t *r = &m_state.context.vfp.__r[0]; + DNBLogThreaded( + "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count => %u)", + m_thread->MachPortNumber(), ARM_THREAD_STATE, ARM_THREAD_STATE_COUNT, + kret, count); + DNBLogThreaded(" s0=%8.8x s1=%8.8x s2=%8.8x s3=%8.8x s4=%8.8x " + "s5=%8.8x s6=%8.8x s7=%8.8x", + r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]); + DNBLogThreaded(" s8=%8.8x s9=%8.8x s10=%8.8x s11=%8.8x s12=%8.8x " + "s13=%8.8x s14=%8.8x s15=%8.8x", + r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15]); + DNBLogThreaded(" s16=%8.8x s17=%8.8x s18=%8.8x s19=%8.8x s20=%8.8x " + "s21=%8.8x s22=%8.8x s23=%8.8x", + r[16], r[17], r[18], r[19], r[20], r[21], r[22], r[23]); + DNBLogThreaded(" s24=%8.8x s25=%8.8x s26=%8.8x s27=%8.8x s28=%8.8x " + "s29=%8.8x s30=%8.8x s31=%8.8x", + r[24], r[25], r[26], r[27], r[28], r[29], r[30], r[31]); + DNBLogThreaded(" s32=%8.8x s33=%8.8x s34=%8.8x s35=%8.8x s36=%8.8x " + "s37=%8.8x s38=%8.8x s39=%8.8x", + r[32], r[33], r[34], r[35], r[36], r[37], r[38], r[39]); + DNBLogThreaded(" s40=%8.8x s41=%8.8x s42=%8.8x s43=%8.8x s44=%8.8x " + "s45=%8.8x s46=%8.8x s47=%8.8x", + r[40], r[41], r[42], r[43], r[44], r[45], r[46], r[47]); + DNBLogThreaded(" s48=%8.8x s49=%8.8x s50=%8.8x s51=%8.8x s52=%8.8x " + "s53=%8.8x s54=%8.8x s55=%8.8x", + r[48], r[49], r[50], r[51], r[52], r[53], r[54], r[55]); + DNBLogThreaded(" s56=%8.8x s57=%8.8x s58=%8.8x s59=%8.8x s60=%8.8x " + "s61=%8.8x s62=%8.8x s63=%8.8x fpscr=%8.8x", + r[56], r[57], r[58], r[59], r[60], r[61], r[62], r[63], + r[64]); + } #endif - m_state.SetError(set, Read, kret); - return kret; + m_state.SetError(set, Read, kret); + return kret; } -kern_return_t -DNBArchMachARM::GetEXCState(bool force) -{ - int set = e_regSetEXC; - // Check if we have valid cached registers - if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) - return KERN_SUCCESS; - - // Read the registers from our thread - mach_msg_type_number_t count = ARM_EXCEPTION_STATE_COUNT; - kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, &count); - m_state.SetError(set, Read, kret); - return kret; +kern_return_t DNBArchMachARM::GetEXCState(bool force) { + int set = e_regSetEXC; + // Check if we have valid cached registers + if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) + return KERN_SUCCESS; + + // Read the registers from our thread + mach_msg_type_number_t count = ARM_EXCEPTION_STATE_COUNT; + kern_return_t kret = + ::thread_get_state(m_thread->MachPortNumber(), ARM_EXCEPTION_STATE, + (thread_state_t)&m_state.context.exc, &count); + m_state.SetError(set, Read, kret); + return kret; } -static void -DumpDBGState(const DNBArchMachARM::DBG& dbg) -{ - uint32_t i = 0; - for (i=0; i<16; i++) - { - DNBLogThreadedIf(LOG_STEP, "BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }", - i, i, dbg.__bvr[i], dbg.__bcr[i], - i, i, dbg.__wvr[i], dbg.__wcr[i]); - } +static void DumpDBGState(const DNBArchMachARM::DBG &dbg) { + uint32_t i = 0; + for (i = 0; i < 16; i++) { + DNBLogThreadedIf(LOG_STEP, "BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } " + "WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }", + i, i, dbg.__bvr[i], dbg.__bcr[i], i, i, dbg.__wvr[i], + dbg.__wcr[i]); + } } -kern_return_t -DNBArchMachARM::GetDBGState(bool force) -{ - int set = e_regSetDBG; +kern_return_t DNBArchMachARM::GetDBGState(bool force) { + int set = e_regSetDBG; - // Check if we have valid cached registers - if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) - return KERN_SUCCESS; + // Check if we have valid cached registers + if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) + return KERN_SUCCESS; - // Read the registers from our thread -#if defined (ARM_DEBUG_STATE32) && (defined (__arm64__) || defined (__aarch64__)) - mach_msg_type_number_t count = ARM_DEBUG_STATE32_COUNT; - kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE32, (thread_state_t)&m_state.dbg, &count); +// Read the registers from our thread +#if defined(ARM_DEBUG_STATE32) && (defined(__arm64__) || defined(__aarch64__)) + mach_msg_type_number_t count = ARM_DEBUG_STATE32_COUNT; + kern_return_t kret = + ::thread_get_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE32, + (thread_state_t)&m_state.dbg, &count); #else - mach_msg_type_number_t count = ARM_DEBUG_STATE_COUNT; - kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE, (thread_state_t)&m_state.dbg, &count); + mach_msg_type_number_t count = ARM_DEBUG_STATE_COUNT; + kern_return_t kret = + ::thread_get_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE, + (thread_state_t)&m_state.dbg, &count); #endif - m_state.SetError(set, Read, kret); + m_state.SetError(set, Read, kret); - return kret; + return kret; } -kern_return_t -DNBArchMachARM::SetGPRState() -{ - int set = e_regSetGPR; - kern_return_t kret = ::thread_set_state(m_thread->MachPortNumber(), ARM_THREAD_STATE, (thread_state_t)&m_state.context.gpr, ARM_THREAD_STATE_COUNT); - m_state.SetError(set, Write, kret); // Set the current write error for this register set - m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently - return kret; // Return the error code +kern_return_t DNBArchMachARM::SetGPRState() { + int set = e_regSetGPR; + kern_return_t kret = ::thread_set_state( + m_thread->MachPortNumber(), ARM_THREAD_STATE, + (thread_state_t)&m_state.context.gpr, ARM_THREAD_STATE_COUNT); + m_state.SetError(set, Write, + kret); // Set the current write error for this register set + m_state.InvalidateRegisterSetState(set); // Invalidate the current register + // state in case registers are read + // back differently + return kret; // Return the error code } -kern_return_t -DNBArchMachARM::SetVFPState() -{ - int set = e_regSetVFP; - kern_return_t kret; - mach_msg_type_number_t count; +kern_return_t DNBArchMachARM::SetVFPState() { + int set = e_regSetVFP; + kern_return_t kret; + mach_msg_type_number_t count; -#if defined (__arm64__) || defined (__aarch64__) - count = ARM_NEON_STATE_COUNT; - kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_NEON_STATE, (thread_state_t)&m_state.context.vfp, count); +#if defined(__arm64__) || defined(__aarch64__) + count = ARM_NEON_STATE_COUNT; + kret = ::thread_set_state(m_thread->MachPortNumber(), ARM_NEON_STATE, + (thread_state_t)&m_state.context.vfp, count); #else - count = ARM_VFP_STATE_COUNT; - kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_VFP_STATE, (thread_state_t)&m_state.context.vfp, count); + count = ARM_VFP_STATE_COUNT; + kret = ::thread_set_state(m_thread->MachPortNumber(), ARM_VFP_STATE, + (thread_state_t)&m_state.context.vfp, count); #endif -#if defined (__arm64__) || defined (__aarch64__) - if (DNBLogEnabledForAny (LOG_THREAD)) - { - DNBLogThreaded("thread_set_state(0x%4.4x, %u, &vfp, %u) => 0x%8.8x (count = %u) regs" - "\n q0 = 0x%16.16llx%16.16llx" - "\n q1 = 0x%16.16llx%16.16llx" - "\n q2 = 0x%16.16llx%16.16llx" - "\n q3 = 0x%16.16llx%16.16llx" - "\n q4 = 0x%16.16llx%16.16llx" - "\n q5 = 0x%16.16llx%16.16llx" - "\n q6 = 0x%16.16llx%16.16llx" - "\n q7 = 0x%16.16llx%16.16llx" - "\n q8 = 0x%16.16llx%16.16llx" - "\n q9 = 0x%16.16llx%16.16llx" - "\n q10 = 0x%16.16llx%16.16llx" - "\n q11 = 0x%16.16llx%16.16llx" - "\n q12 = 0x%16.16llx%16.16llx" - "\n q13 = 0x%16.16llx%16.16llx" - "\n q14 = 0x%16.16llx%16.16llx" - "\n q15 = 0x%16.16llx%16.16llx" - "\n fpsr = 0x%8.8x" - "\n fpcr = 0x%8.8x\n\n", - m_thread->MachPortNumber(), - ARM_NEON_STATE, - ARM_NEON_STATE_COUNT, - kret, - count, - ((uint64_t *)&m_state.context.vfp.__v[0])[0] , ((uint64_t *)&m_state.context.vfp.__v[0])[1], - ((uint64_t *)&m_state.context.vfp.__v[1])[0] , ((uint64_t *)&m_state.context.vfp.__v[1])[1], - ((uint64_t *)&m_state.context.vfp.__v[2])[0] , ((uint64_t *)&m_state.context.vfp.__v[2])[1], - ((uint64_t *)&m_state.context.vfp.__v[3])[0] , ((uint64_t *)&m_state.context.vfp.__v[3])[1], - ((uint64_t *)&m_state.context.vfp.__v[4])[0] , ((uint64_t *)&m_state.context.vfp.__v[4])[1], - ((uint64_t *)&m_state.context.vfp.__v[5])[0] , ((uint64_t *)&m_state.context.vfp.__v[5])[1], - ((uint64_t *)&m_state.context.vfp.__v[6])[0] , ((uint64_t *)&m_state.context.vfp.__v[6])[1], - ((uint64_t *)&m_state.context.vfp.__v[7])[0] , ((uint64_t *)&m_state.context.vfp.__v[7])[1], - ((uint64_t *)&m_state.context.vfp.__v[8])[0] , ((uint64_t *)&m_state.context.vfp.__v[8])[1], - ((uint64_t *)&m_state.context.vfp.__v[9])[0] , ((uint64_t *)&m_state.context.vfp.__v[9])[1], - ((uint64_t *)&m_state.context.vfp.__v[10])[0], ((uint64_t *)&m_state.context.vfp.__v[10])[1], - ((uint64_t *)&m_state.context.vfp.__v[11])[0], ((uint64_t *)&m_state.context.vfp.__v[11])[1], - ((uint64_t *)&m_state.context.vfp.__v[12])[0], ((uint64_t *)&m_state.context.vfp.__v[12])[1], - ((uint64_t *)&m_state.context.vfp.__v[13])[0], ((uint64_t *)&m_state.context.vfp.__v[13])[1], - ((uint64_t *)&m_state.context.vfp.__v[14])[0], ((uint64_t *)&m_state.context.vfp.__v[14])[1], - ((uint64_t *)&m_state.context.vfp.__v[15])[0], ((uint64_t *)&m_state.context.vfp.__v[15])[1], - m_state.context.vfp.__fpsr, - m_state.context.vfp.__fpcr); - } +#if defined(__arm64__) || defined(__aarch64__) + if (DNBLogEnabledForAny(LOG_THREAD)) { + DNBLogThreaded( + "thread_set_state(0x%4.4x, %u, &vfp, %u) => 0x%8.8x (count = %u) regs" + "\n q0 = 0x%16.16llx%16.16llx" + "\n q1 = 0x%16.16llx%16.16llx" + "\n q2 = 0x%16.16llx%16.16llx" + "\n q3 = 0x%16.16llx%16.16llx" + "\n q4 = 0x%16.16llx%16.16llx" + "\n q5 = 0x%16.16llx%16.16llx" + "\n q6 = 0x%16.16llx%16.16llx" + "\n q7 = 0x%16.16llx%16.16llx" + "\n q8 = 0x%16.16llx%16.16llx" + "\n q9 = 0x%16.16llx%16.16llx" + "\n q10 = 0x%16.16llx%16.16llx" + "\n q11 = 0x%16.16llx%16.16llx" + "\n q12 = 0x%16.16llx%16.16llx" + "\n q13 = 0x%16.16llx%16.16llx" + "\n q14 = 0x%16.16llx%16.16llx" + "\n q15 = 0x%16.16llx%16.16llx" + "\n fpsr = 0x%8.8x" + "\n fpcr = 0x%8.8x\n\n", + m_thread->MachPortNumber(), ARM_NEON_STATE, ARM_NEON_STATE_COUNT, kret, + count, ((uint64_t *)&m_state.context.vfp.__v[0])[0], + ((uint64_t *)&m_state.context.vfp.__v[0])[1], + ((uint64_t *)&m_state.context.vfp.__v[1])[0], + ((uint64_t *)&m_state.context.vfp.__v[1])[1], + ((uint64_t *)&m_state.context.vfp.__v[2])[0], + ((uint64_t *)&m_state.context.vfp.__v[2])[1], + ((uint64_t *)&m_state.context.vfp.__v[3])[0], + ((uint64_t *)&m_state.context.vfp.__v[3])[1], + ((uint64_t *)&m_state.context.vfp.__v[4])[0], + ((uint64_t *)&m_state.context.vfp.__v[4])[1], + ((uint64_t *)&m_state.context.vfp.__v[5])[0], + ((uint64_t *)&m_state.context.vfp.__v[5])[1], + ((uint64_t *)&m_state.context.vfp.__v[6])[0], + ((uint64_t *)&m_state.context.vfp.__v[6])[1], + ((uint64_t *)&m_state.context.vfp.__v[7])[0], + ((uint64_t *)&m_state.context.vfp.__v[7])[1], + ((uint64_t *)&m_state.context.vfp.__v[8])[0], + ((uint64_t *)&m_state.context.vfp.__v[8])[1], + ((uint64_t *)&m_state.context.vfp.__v[9])[0], + ((uint64_t *)&m_state.context.vfp.__v[9])[1], + ((uint64_t *)&m_state.context.vfp.__v[10])[0], + ((uint64_t *)&m_state.context.vfp.__v[10])[1], + ((uint64_t *)&m_state.context.vfp.__v[11])[0], + ((uint64_t *)&m_state.context.vfp.__v[11])[1], + ((uint64_t *)&m_state.context.vfp.__v[12])[0], + ((uint64_t *)&m_state.context.vfp.__v[12])[1], + ((uint64_t *)&m_state.context.vfp.__v[13])[0], + ((uint64_t *)&m_state.context.vfp.__v[13])[1], + ((uint64_t *)&m_state.context.vfp.__v[14])[0], + ((uint64_t *)&m_state.context.vfp.__v[14])[1], + ((uint64_t *)&m_state.context.vfp.__v[15])[0], + ((uint64_t *)&m_state.context.vfp.__v[15])[1], + m_state.context.vfp.__fpsr, m_state.context.vfp.__fpcr); + } #else - if (DNBLogEnabledForAny (LOG_THREAD)) - { - uint32_t *r = &m_state.context.vfp.__r[0]; - DNBLogThreaded ("thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count => %u)", - m_thread->MachPortNumber(), - ARM_THREAD_STATE, - ARM_THREAD_STATE_COUNT, - kret, - count); - DNBLogThreaded(" s0=%8.8x s1=%8.8x s2=%8.8x s3=%8.8x s4=%8.8x s5=%8.8x s6=%8.8x s7=%8.8x",r[ 0],r[ 1],r[ 2],r[ 3],r[ 4],r[ 5],r[ 6],r[ 7]); - DNBLogThreaded(" s8=%8.8x s9=%8.8x s10=%8.8x s11=%8.8x s12=%8.8x s13=%8.8x s14=%8.8x s15=%8.8x",r[ 8],r[ 9],r[10],r[11],r[12],r[13],r[14],r[15]); - DNBLogThreaded(" s16=%8.8x s17=%8.8x s18=%8.8x s19=%8.8x s20=%8.8x s21=%8.8x s22=%8.8x s23=%8.8x",r[16],r[17],r[18],r[19],r[20],r[21],r[22],r[23]); - DNBLogThreaded(" s24=%8.8x s25=%8.8x s26=%8.8x s27=%8.8x s28=%8.8x s29=%8.8x s30=%8.8x s31=%8.8x",r[24],r[25],r[26],r[27],r[28],r[29],r[30],r[31]); - DNBLogThreaded(" s32=%8.8x s33=%8.8x s34=%8.8x s35=%8.8x s36=%8.8x s37=%8.8x s38=%8.8x s39=%8.8x",r[32],r[33],r[34],r[35],r[36],r[37],r[38],r[39]); - DNBLogThreaded(" s40=%8.8x s41=%8.8x s42=%8.8x s43=%8.8x s44=%8.8x s45=%8.8x s46=%8.8x s47=%8.8x",r[40],r[41],r[42],r[43],r[44],r[45],r[46],r[47]); - DNBLogThreaded(" s48=%8.8x s49=%8.8x s50=%8.8x s51=%8.8x s52=%8.8x s53=%8.8x s54=%8.8x s55=%8.8x",r[48],r[49],r[50],r[51],r[52],r[53],r[54],r[55]); - DNBLogThreaded(" s56=%8.8x s57=%8.8x s58=%8.8x s59=%8.8x s60=%8.8x s61=%8.8x s62=%8.8x s63=%8.8x fpscr=%8.8x",r[56],r[57],r[58],r[59],r[60],r[61],r[62],r[63],r[64]); - } + if (DNBLogEnabledForAny(LOG_THREAD)) { + uint32_t *r = &m_state.context.vfp.__r[0]; + DNBLogThreaded( + "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count => %u)", + m_thread->MachPortNumber(), ARM_THREAD_STATE, ARM_THREAD_STATE_COUNT, + kret, count); + DNBLogThreaded(" s0=%8.8x s1=%8.8x s2=%8.8x s3=%8.8x s4=%8.8x " + "s5=%8.8x s6=%8.8x s7=%8.8x", + r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]); + DNBLogThreaded(" s8=%8.8x s9=%8.8x s10=%8.8x s11=%8.8x s12=%8.8x " + "s13=%8.8x s14=%8.8x s15=%8.8x", + r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15]); + DNBLogThreaded(" s16=%8.8x s17=%8.8x s18=%8.8x s19=%8.8x s20=%8.8x " + "s21=%8.8x s22=%8.8x s23=%8.8x", + r[16], r[17], r[18], r[19], r[20], r[21], r[22], r[23]); + DNBLogThreaded(" s24=%8.8x s25=%8.8x s26=%8.8x s27=%8.8x s28=%8.8x " + "s29=%8.8x s30=%8.8x s31=%8.8x", + r[24], r[25], r[26], r[27], r[28], r[29], r[30], r[31]); + DNBLogThreaded(" s32=%8.8x s33=%8.8x s34=%8.8x s35=%8.8x s36=%8.8x " + "s37=%8.8x s38=%8.8x s39=%8.8x", + r[32], r[33], r[34], r[35], r[36], r[37], r[38], r[39]); + DNBLogThreaded(" s40=%8.8x s41=%8.8x s42=%8.8x s43=%8.8x s44=%8.8x " + "s45=%8.8x s46=%8.8x s47=%8.8x", + r[40], r[41], r[42], r[43], r[44], r[45], r[46], r[47]); + DNBLogThreaded(" s48=%8.8x s49=%8.8x s50=%8.8x s51=%8.8x s52=%8.8x " + "s53=%8.8x s54=%8.8x s55=%8.8x", + r[48], r[49], r[50], r[51], r[52], r[53], r[54], r[55]); + DNBLogThreaded(" s56=%8.8x s57=%8.8x s58=%8.8x s59=%8.8x s60=%8.8x " + "s61=%8.8x s62=%8.8x s63=%8.8x fpscr=%8.8x", + r[56], r[57], r[58], r[59], r[60], r[61], r[62], r[63], + r[64]); + } #endif - m_state.SetError(set, Write, kret); // Set the current write error for this register set - m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently - return kret; // Return the error code + m_state.SetError(set, Write, + kret); // Set the current write error for this register set + m_state.InvalidateRegisterSetState(set); // Invalidate the current register + // state in case registers are read + // back differently + return kret; // Return the error code } -kern_return_t -DNBArchMachARM::SetEXCState() -{ - int set = e_regSetEXC; - kern_return_t kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, ARM_EXCEPTION_STATE_COUNT); - m_state.SetError(set, Write, kret); // Set the current write error for this register set - m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently - return kret; // Return the error code +kern_return_t DNBArchMachARM::SetEXCState() { + int set = e_regSetEXC; + kern_return_t kret = ::thread_set_state( + m_thread->MachPortNumber(), ARM_EXCEPTION_STATE, + (thread_state_t)&m_state.context.exc, ARM_EXCEPTION_STATE_COUNT); + m_state.SetError(set, Write, + kret); // Set the current write error for this register set + m_state.InvalidateRegisterSetState(set); // Invalidate the current register + // state in case registers are read + // back differently + return kret; // Return the error code } -kern_return_t -DNBArchMachARM::SetDBGState(bool also_set_on_task) -{ - int set = e_regSetDBG; -#if defined (ARM_DEBUG_STATE32) && (defined (__arm64__) || defined (__aarch64__)) - kern_return_t kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_DEBUG_STATE32, (thread_state_t)&m_state.dbg, ARM_DEBUG_STATE32_COUNT); - if (also_set_on_task) - { - kern_return_t task_kret = ::task_set_state (m_thread->Process()->Task().TaskPort(), ARM_DEBUG_STATE32, (thread_state_t)&m_state.dbg, ARM_DEBUG_STATE32_COUNT); - if (task_kret != KERN_SUCCESS) - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::SetDBGState failed to set debug control register state: 0x%8.8x.", kret); - } +kern_return_t DNBArchMachARM::SetDBGState(bool also_set_on_task) { + int set = e_regSetDBG; +#if defined(ARM_DEBUG_STATE32) && (defined(__arm64__) || defined(__aarch64__)) + kern_return_t kret = + ::thread_set_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE32, + (thread_state_t)&m_state.dbg, ARM_DEBUG_STATE32_COUNT); + if (also_set_on_task) { + kern_return_t task_kret = ::task_set_state( + m_thread->Process()->Task().TaskPort(), ARM_DEBUG_STATE32, + (thread_state_t)&m_state.dbg, ARM_DEBUG_STATE32_COUNT); + if (task_kret != KERN_SUCCESS) + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::SetDBGState failed to " + "set debug control register state: " + "0x%8.8x.", + kret); + } #else - kern_return_t kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_DEBUG_STATE, (thread_state_t)&m_state.dbg, ARM_DEBUG_STATE_COUNT); - if (also_set_on_task) - { - kern_return_t task_kret = ::task_set_state (m_thread->Process()->Task().TaskPort(), ARM_DEBUG_STATE, (thread_state_t)&m_state.dbg, ARM_DEBUG_STATE_COUNT); - if (task_kret != KERN_SUCCESS) - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::SetDBGState failed to set debug control register state: 0x%8.8x.", kret); - } + kern_return_t kret = + ::thread_set_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE, + (thread_state_t)&m_state.dbg, ARM_DEBUG_STATE_COUNT); + if (also_set_on_task) { + kern_return_t task_kret = ::task_set_state( + m_thread->Process()->Task().TaskPort(), ARM_DEBUG_STATE, + (thread_state_t)&m_state.dbg, ARM_DEBUG_STATE_COUNT); + if (task_kret != KERN_SUCCESS) + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::SetDBGState failed to " + "set debug control register state: " + "0x%8.8x.", + kret); + } #endif - m_state.SetError(set, Write, kret); // Set the current write error for this register set - m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently - return kret; // Return the error code + m_state.SetError(set, Write, + kret); // Set the current write error for this register set + m_state.InvalidateRegisterSetState(set); // Invalidate the current register + // state in case registers are read + // back differently + return kret; // Return the error code } -void -DNBArchMachARM::ThreadWillResume() -{ - // Do we need to step this thread? If so, let the mach thread tell us so. - if (m_thread->IsStepping()) - { - // This is the primary thread, let the arch do anything it needs - if (NumSupportedHardwareBreakpoints() > 0) - { - if (EnableHardwareSingleStep(true) != KERN_SUCCESS) - { - DNBLogThreaded("DNBArchMachARM::ThreadWillResume() failed to enable hardware single step"); - } - } +void DNBArchMachARM::ThreadWillResume() { + // Do we need to step this thread? If so, let the mach thread tell us so. + if (m_thread->IsStepping()) { + // This is the primary thread, let the arch do anything it needs + if (NumSupportedHardwareBreakpoints() > 0) { + if (EnableHardwareSingleStep(true) != KERN_SUCCESS) { + DNBLogThreaded("DNBArchMachARM::ThreadWillResume() failed to enable " + "hardware single step"); + } } - - // Disable the triggered watchpoint temporarily before we resume. - // Plus, we try to enable hardware single step to execute past the instruction which triggered our watchpoint. - if (m_watchpoint_did_occur) - { - if (m_watchpoint_hw_index >= 0) - { - kern_return_t kret = GetDBGState(false); - if (kret == KERN_SUCCESS && !IsWatchpointEnabled(m_state.dbg, m_watchpoint_hw_index)) { - // The watchpoint might have been disabled by the user. We don't need to do anything at all - // to enable hardware single stepping. - m_watchpoint_did_occur = false; - m_watchpoint_hw_index = -1; - return; - } - - DisableHardwareWatchpoint(m_watchpoint_hw_index, false); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() DisableHardwareWatchpoint(%d) called", - m_watchpoint_hw_index); - - // Enable hardware single step to move past the watchpoint-triggering instruction. - m_watchpoint_resume_single_step_enabled = (EnableHardwareSingleStep(true) == KERN_SUCCESS); - - // If we are not able to enable single step to move past the watchpoint-triggering instruction, - // at least we should reset the two watchpoint member variables so that the next time around - // this callback function is invoked, the enclosing logical branch is skipped. - if (!m_watchpoint_resume_single_step_enabled) { - // Reset the two watchpoint member variables. - m_watchpoint_did_occur = false; - m_watchpoint_hw_index = -1; - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() failed to enable single step"); - } - else - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() succeeded to enable single step"); - } + } + + // Disable the triggered watchpoint temporarily before we resume. + // Plus, we try to enable hardware single step to execute past the instruction + // which triggered our watchpoint. + if (m_watchpoint_did_occur) { + if (m_watchpoint_hw_index >= 0) { + kern_return_t kret = GetDBGState(false); + if (kret == KERN_SUCCESS && + !IsWatchpointEnabled(m_state.dbg, m_watchpoint_hw_index)) { + // The watchpoint might have been disabled by the user. We don't need + // to do anything at all + // to enable hardware single stepping. + m_watchpoint_did_occur = false; + m_watchpoint_hw_index = -1; + return; + } + + DisableHardwareWatchpoint(m_watchpoint_hw_index, false); + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() " + "DisableHardwareWatchpoint(%d) called", + m_watchpoint_hw_index); + + // Enable hardware single step to move past the watchpoint-triggering + // instruction. + m_watchpoint_resume_single_step_enabled = + (EnableHardwareSingleStep(true) == KERN_SUCCESS); + + // If we are not able to enable single step to move past the + // watchpoint-triggering instruction, + // at least we should reset the two watchpoint member variables so that + // the next time around + // this callback function is invoked, the enclosing logical branch is + // skipped. + if (!m_watchpoint_resume_single_step_enabled) { + // Reset the two watchpoint member variables. + m_watchpoint_did_occur = false; + m_watchpoint_hw_index = -1; + DNBLogThreadedIf( + LOG_WATCHPOINTS, + "DNBArchMachARM::ThreadWillResume() failed to enable single step"); + } else + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() " + "succeeded to enable single step"); } + } } -bool -DNBArchMachARM::ThreadDidStop() -{ - bool success = true; - - m_state.InvalidateRegisterSetState (e_regSetALL); - - if (m_watchpoint_resume_single_step_enabled) - { - // Great! We now disable the hardware single step as well as re-enable the hardware watchpoint. - // See also ThreadWillResume(). - if (EnableHardwareSingleStep(false) == KERN_SUCCESS) - { - if (m_watchpoint_did_occur && m_watchpoint_hw_index >= 0) - { - ReenableHardwareWatchpoint(m_watchpoint_hw_index); - m_watchpoint_resume_single_step_enabled = false; - m_watchpoint_did_occur = false; - m_watchpoint_hw_index = -1; - } - else - { - DNBLogError("internal error detected: m_watchpoint_resume_step_enabled is true but (m_watchpoint_did_occur && m_watchpoint_hw_index >= 0) does not hold!"); - } - } - else - { - DNBLogError("internal error detected: m_watchpoint_resume_step_enabled is true but unable to disable single step!"); - } +bool DNBArchMachARM::ThreadDidStop() { + bool success = true; + + m_state.InvalidateRegisterSetState(e_regSetALL); + + if (m_watchpoint_resume_single_step_enabled) { + // Great! We now disable the hardware single step as well as re-enable the + // hardware watchpoint. + // See also ThreadWillResume(). + if (EnableHardwareSingleStep(false) == KERN_SUCCESS) { + if (m_watchpoint_did_occur && m_watchpoint_hw_index >= 0) { + ReenableHardwareWatchpoint(m_watchpoint_hw_index); + m_watchpoint_resume_single_step_enabled = false; + m_watchpoint_did_occur = false; + m_watchpoint_hw_index = -1; + } else { + DNBLogError("internal error detected: m_watchpoint_resume_step_enabled " + "is true but (m_watchpoint_did_occur && " + "m_watchpoint_hw_index >= 0) does not hold!"); + } + } else { + DNBLogError("internal error detected: m_watchpoint_resume_step_enabled " + "is true but unable to disable single step!"); } - - // Are we stepping a single instruction? - if (GetGPRState(true) == KERN_SUCCESS) - { - // We are single stepping, was this the primary thread? - if (m_thread->IsStepping()) - { - success = EnableHardwareSingleStep(false) == KERN_SUCCESS; - } - else - { - // The MachThread will automatically restore the suspend count - // in ThreadDidStop(), so we don't need to do anything here if - // we weren't the primary thread the last time - } + } + + // Are we stepping a single instruction? + if (GetGPRState(true) == KERN_SUCCESS) { + // We are single stepping, was this the primary thread? + if (m_thread->IsStepping()) { + success = EnableHardwareSingleStep(false) == KERN_SUCCESS; + } else { + // The MachThread will automatically restore the suspend count + // in ThreadDidStop(), so we don't need to do anything here if + // we weren't the primary thread the last time } - return success; + } + return success; } -bool -DNBArchMachARM::NotifyException(MachException::Data& exc) -{ - switch (exc.exc_type) - { - default: - break; - case EXC_BREAKPOINT: - if (exc.exc_data.size() == 2 && exc.exc_data[0] == EXC_ARM_DA_DEBUG) - { - // The data break address is passed as exc_data[1]. - nub_addr_t addr = exc.exc_data[1]; - // Find the hardware index with the side effect of possibly massaging the - // addr to return the starting address as seen from the debugger side. - uint32_t hw_index = GetHardwareWatchpointHit(addr); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::NotifyException watchpoint %d was hit on address 0x%llx", hw_index, (uint64_t) addr); - const int num_watchpoints = NumSupportedHardwareWatchpoints (); - for (int i = 0; i < num_watchpoints; i++) - { - if (LoHi[i] != 0 - && LoHi[i] == hw_index - && LoHi[i] != i - && GetWatchpointAddressByIndex (i) != INVALID_NUB_ADDRESS) - { - addr = GetWatchpointAddressByIndex (i); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::NotifyException It is a linked watchpoint; rewritten to index %d addr 0x%llx", LoHi[i], (uint64_t) addr); - } - } - if (hw_index != INVALID_NUB_HW_INDEX) - { - m_watchpoint_did_occur = true; - m_watchpoint_hw_index = hw_index; - exc.exc_data[1] = addr; - // Piggyback the hw_index in the exc.data. - exc.exc_data.push_back(hw_index); - } - - return true; - } - break; +bool DNBArchMachARM::NotifyException(MachException::Data &exc) { + switch (exc.exc_type) { + default: + break; + case EXC_BREAKPOINT: + if (exc.exc_data.size() == 2 && exc.exc_data[0] == EXC_ARM_DA_DEBUG) { + // The data break address is passed as exc_data[1]. + nub_addr_t addr = exc.exc_data[1]; + // Find the hardware index with the side effect of possibly massaging the + // addr to return the starting address as seen from the debugger side. + uint32_t hw_index = GetHardwareWatchpointHit(addr); + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::NotifyException " + "watchpoint %d was hit on address " + "0x%llx", + hw_index, (uint64_t)addr); + const int num_watchpoints = NumSupportedHardwareWatchpoints(); + for (int i = 0; i < num_watchpoints; i++) { + if (LoHi[i] != 0 && LoHi[i] == hw_index && LoHi[i] != i && + GetWatchpointAddressByIndex(i) != INVALID_NUB_ADDRESS) { + addr = GetWatchpointAddressByIndex(i); + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::NotifyException " + "It is a linked watchpoint; " + "rewritten to index %d addr 0x%llx", + LoHi[i], (uint64_t)addr); + } + } + if (hw_index != INVALID_NUB_HW_INDEX) { + m_watchpoint_did_occur = true; + m_watchpoint_hw_index = hw_index; + exc.exc_data[1] = addr; + // Piggyback the hw_index in the exc.data. + exc.exc_data.push_back(hw_index); + } + + return true; } - return false; + break; + } + return false; } -bool -DNBArchMachARM::StepNotComplete () -{ - if (m_hw_single_chained_step_addr != INVALID_NUB_ADDRESS) - { - kern_return_t kret = KERN_INVALID_ARGUMENT; - kret = GetGPRState(false); - if (kret == KERN_SUCCESS) - { - if (m_state.context.gpr.__pc == m_hw_single_chained_step_addr) - { - DNBLogThreadedIf(LOG_STEP, "Need to step some more at 0x%8.8llx", (uint64_t) m_hw_single_chained_step_addr); - return true; - } - } +bool DNBArchMachARM::StepNotComplete() { + if (m_hw_single_chained_step_addr != INVALID_NUB_ADDRESS) { + kern_return_t kret = KERN_INVALID_ARGUMENT; + kret = GetGPRState(false); + if (kret == KERN_SUCCESS) { + if (m_state.context.gpr.__pc == m_hw_single_chained_step_addr) { + DNBLogThreadedIf(LOG_STEP, "Need to step some more at 0x%8.8llx", + (uint64_t)m_hw_single_chained_step_addr); + return true; + } } + } - m_hw_single_chained_step_addr = INVALID_NUB_ADDRESS; - return false; + m_hw_single_chained_step_addr = INVALID_NUB_ADDRESS; + return false; } // Set the single step bit in the processor status register. -kern_return_t -DNBArchMachARM::EnableHardwareSingleStep (bool enable) -{ - DNBError err; - DNBLogThreadedIf(LOG_STEP, "%s( enable = %d )", __FUNCTION__, enable); - - err = GetGPRState(false); - - if (err.Fail()) - { - err.LogThreaded("%s: failed to read the GPR registers", __FUNCTION__); - return err.Error(); - } +kern_return_t DNBArchMachARM::EnableHardwareSingleStep(bool enable) { + DNBError err; + DNBLogThreadedIf(LOG_STEP, "%s( enable = %d )", __FUNCTION__, enable); - err = GetDBGState(false); + err = GetGPRState(false); - if (err.Fail()) - { - err.LogThreaded("%s: failed to read the DBG registers", __FUNCTION__); - return err.Error(); - } + if (err.Fail()) { + err.LogThreaded("%s: failed to read the GPR registers", __FUNCTION__); + return err.Error(); + } + + err = GetDBGState(false); + + if (err.Fail()) { + err.LogThreaded("%s: failed to read the DBG registers", __FUNCTION__); + return err.Error(); + } // The use of __arm64__ here is not ideal. If debugserver is running on -// an armv8 device, regardless of whether it was built for arch arm or arch arm64, +// an armv8 device, regardless of whether it was built for arch arm or arch +// arm64, // it needs to use the MDSCR_EL1 SS bit to single instruction step. -#if defined (__arm64__) || defined (__aarch64__) - if (enable) - { - DNBLogThreadedIf(LOG_STEP, "%s: Setting MDSCR_EL1 Single Step bit at pc 0x%llx", __FUNCTION__, (uint64_t) m_state.context.gpr.__pc); - m_state.dbg.__mdscr_el1 |= 1; // Set bit 0 (single step, SS) in the MDSCR_EL1. - } - else - { - DNBLogThreadedIf(LOG_STEP, "%s: Clearing MDSCR_EL1 Single Step bit at pc 0x%llx", __FUNCTION__, (uint64_t) m_state.context.gpr.__pc); - m_state.dbg.__mdscr_el1 &= ~(1ULL); // Clear bit 0 (single step, SS) in the MDSCR_EL1. - } +#if defined(__arm64__) || defined(__aarch64__) + if (enable) { + DNBLogThreadedIf(LOG_STEP, + "%s: Setting MDSCR_EL1 Single Step bit at pc 0x%llx", + __FUNCTION__, (uint64_t)m_state.context.gpr.__pc); + m_state.dbg.__mdscr_el1 |= + 1; // Set bit 0 (single step, SS) in the MDSCR_EL1. + } else { + DNBLogThreadedIf(LOG_STEP, + "%s: Clearing MDSCR_EL1 Single Step bit at pc 0x%llx", + __FUNCTION__, (uint64_t)m_state.context.gpr.__pc); + m_state.dbg.__mdscr_el1 &= + ~(1ULL); // Clear bit 0 (single step, SS) in the MDSCR_EL1. + } #else - const uint32_t i = 0; - if (enable) - { - m_hw_single_chained_step_addr = INVALID_NUB_ADDRESS; - - // Save our previous state - m_dbg_save = m_state.dbg; - // Set a breakpoint that will stop when the PC doesn't match the current one! - m_state.dbg.__bvr[i] = m_state.context.gpr.__pc & 0xFFFFFFFCu; // Set the current PC as the breakpoint address - m_state.dbg.__bcr[i] = BCR_M_IMVA_MISMATCH | // Stop on address mismatch - S_USER | // Stop only in user mode - BCR_ENABLE; // Enable this breakpoint - if (m_state.context.gpr.__cpsr & 0x20) - { - // Thumb breakpoint - if (m_state.context.gpr.__pc & 2) - m_state.dbg.__bcr[i] |= BAS_IMVA_2_3; - else - m_state.dbg.__bcr[i] |= BAS_IMVA_0_1; - - uint16_t opcode; - if (sizeof(opcode) == m_thread->Process()->Task().ReadMemory(m_state.context.gpr.__pc, sizeof(opcode), &opcode)) - { - if (IsThumb32Opcode(opcode)) - { - // 32 bit thumb opcode... - if (m_state.context.gpr.__pc & 2) - { - // We can't take care of a 32 bit thumb instruction single step - // with just IVA mismatching. We will need to chain an extra - // hardware single step in order to complete this single step... - m_hw_single_chained_step_addr = m_state.context.gpr.__pc + 2; - } - else - { - // Extend the number of bits to ignore for the mismatch - m_state.dbg.__bcr[i] |= BAS_IMVA_ALL; - } - } - } - } - else - { - // ARM breakpoint - m_state.dbg.__bcr[i] |= BAS_IMVA_ALL; // Stop when any address bits change - } - - DNBLogThreadedIf(LOG_STEP, "%s: BVR%u=0x%8.8x BCR%u=0x%8.8x", __FUNCTION__, i, m_state.dbg.__bvr[i], i, m_state.dbg.__bcr[i]); + const uint32_t i = 0; + if (enable) { + m_hw_single_chained_step_addr = INVALID_NUB_ADDRESS; - for (uint32_t j=i+1; j<16; ++j) - { - // Disable all others - m_state.dbg.__bvr[j] = 0; - m_state.dbg.__bcr[j] = 0; + // Save our previous state + m_dbg_save = m_state.dbg; + // Set a breakpoint that will stop when the PC doesn't match the current + // one! + m_state.dbg.__bvr[i] = + m_state.context.gpr.__pc & + 0xFFFFFFFCu; // Set the current PC as the breakpoint address + m_state.dbg.__bcr[i] = BCR_M_IMVA_MISMATCH | // Stop on address mismatch + S_USER | // Stop only in user mode + BCR_ENABLE; // Enable this breakpoint + if (m_state.context.gpr.__cpsr & 0x20) { + // Thumb breakpoint + if (m_state.context.gpr.__pc & 2) + m_state.dbg.__bcr[i] |= BAS_IMVA_2_3; + else + m_state.dbg.__bcr[i] |= BAS_IMVA_0_1; + + uint16_t opcode; + if (sizeof(opcode) == + m_thread->Process()->Task().ReadMemory(m_state.context.gpr.__pc, + sizeof(opcode), &opcode)) { + if (IsThumb32Opcode(opcode)) { + // 32 bit thumb opcode... + if (m_state.context.gpr.__pc & 2) { + // We can't take care of a 32 bit thumb instruction single step + // with just IVA mismatching. We will need to chain an extra + // hardware single step in order to complete this single step... + m_hw_single_chained_step_addr = m_state.context.gpr.__pc + 2; + } else { + // Extend the number of bits to ignore for the mismatch + m_state.dbg.__bcr[i] |= BAS_IMVA_ALL; + } } + } + } else { + // ARM breakpoint + m_state.dbg.__bcr[i] |= BAS_IMVA_ALL; // Stop when any address bits change } - else - { - // Just restore the state we had before we did single stepping - m_state.dbg = m_dbg_save; + + DNBLogThreadedIf(LOG_STEP, "%s: BVR%u=0x%8.8x BCR%u=0x%8.8x", __FUNCTION__, + i, m_state.dbg.__bvr[i], i, m_state.dbg.__bcr[i]); + + for (uint32_t j = i + 1; j < 16; ++j) { + // Disable all others + m_state.dbg.__bvr[j] = 0; + m_state.dbg.__bcr[j] = 0; } + } else { + // Just restore the state we had before we did single stepping + m_state.dbg = m_dbg_save; + } #endif - return SetDBGState(false); + return SetDBGState(false); } // return 1 if bit "BIT" is set in "value" -static inline uint32_t bit(uint32_t value, uint32_t bit) -{ - return (value >> bit) & 1u; +static inline uint32_t bit(uint32_t value, uint32_t bit) { + return (value >> bit) & 1u; } // return the bitfield "value[msbit:lsbit]". -static inline uint32_t bits(uint32_t value, uint32_t msbit, uint32_t lsbit) -{ - assert(msbit >= lsbit); - uint32_t shift_left = sizeof(value) * 8 - 1 - msbit; - value <<= shift_left; // shift anything above the msbit off of the unsigned edge - value >>= (shift_left + lsbit); // shift it back again down to the lsbit (including undoing any shift from above) - return value; // return our result +static inline uint32_t bits(uint32_t value, uint32_t msbit, uint32_t lsbit) { + assert(msbit >= lsbit); + uint32_t shift_left = sizeof(value) * 8 - 1 - msbit; + value <<= + shift_left; // shift anything above the msbit off of the unsigned edge + value >>= (shift_left + lsbit); // shift it back again down to the lsbit + // (including undoing any shift from above) + return value; // return our result } -bool -DNBArchMachARM::ConditionPassed(uint8_t condition, uint32_t cpsr) -{ - uint32_t cpsr_n = bit(cpsr, 31); // Negative condition code flag - uint32_t cpsr_z = bit(cpsr, 30); // Zero condition code flag - uint32_t cpsr_c = bit(cpsr, 29); // Carry condition code flag - uint32_t cpsr_v = bit(cpsr, 28); // Overflow condition code flag - - switch (condition) { - case COND_EQ: // (0x0) - if (cpsr_z == 1) return true; - break; - case COND_NE: // (0x1) - if (cpsr_z == 0) return true; - break; - case COND_CS: // (0x2) - if (cpsr_c == 1) return true; - break; - case COND_CC: // (0x3) - if (cpsr_c == 0) return true; - break; - case COND_MI: // (0x4) - if (cpsr_n == 1) return true; - break; - case COND_PL: // (0x5) - if (cpsr_n == 0) return true; - break; - case COND_VS: // (0x6) - if (cpsr_v == 1) return true; - break; - case COND_VC: // (0x7) - if (cpsr_v == 0) return true; - break; - case COND_HI: // (0x8) - if ((cpsr_c == 1) && (cpsr_z == 0)) return true; - break; - case COND_LS: // (0x9) - if ((cpsr_c == 0) || (cpsr_z == 1)) return true; - break; - case COND_GE: // (0xA) - if (cpsr_n == cpsr_v) return true; - break; - case COND_LT: // (0xB) - if (cpsr_n != cpsr_v) return true; - break; - case COND_GT: // (0xC) - if ((cpsr_z == 0) && (cpsr_n == cpsr_v)) return true; - break; - case COND_LE: // (0xD) - if ((cpsr_z == 1) || (cpsr_n != cpsr_v)) return true; - break; - default: - return true; - break; - } - - return false; +bool DNBArchMachARM::ConditionPassed(uint8_t condition, uint32_t cpsr) { + uint32_t cpsr_n = bit(cpsr, 31); // Negative condition code flag + uint32_t cpsr_z = bit(cpsr, 30); // Zero condition code flag + uint32_t cpsr_c = bit(cpsr, 29); // Carry condition code flag + uint32_t cpsr_v = bit(cpsr, 28); // Overflow condition code flag + + switch (condition) { + case COND_EQ: // (0x0) + if (cpsr_z == 1) + return true; + break; + case COND_NE: // (0x1) + if (cpsr_z == 0) + return true; + break; + case COND_CS: // (0x2) + if (cpsr_c == 1) + return true; + break; + case COND_CC: // (0x3) + if (cpsr_c == 0) + return true; + break; + case COND_MI: // (0x4) + if (cpsr_n == 1) + return true; + break; + case COND_PL: // (0x5) + if (cpsr_n == 0) + return true; + break; + case COND_VS: // (0x6) + if (cpsr_v == 1) + return true; + break; + case COND_VC: // (0x7) + if (cpsr_v == 0) + return true; + break; + case COND_HI: // (0x8) + if ((cpsr_c == 1) && (cpsr_z == 0)) + return true; + break; + case COND_LS: // (0x9) + if ((cpsr_c == 0) || (cpsr_z == 1)) + return true; + break; + case COND_GE: // (0xA) + if (cpsr_n == cpsr_v) + return true; + break; + case COND_LT: // (0xB) + if (cpsr_n != cpsr_v) + return true; + break; + case COND_GT: // (0xC) + if ((cpsr_z == 0) && (cpsr_n == cpsr_v)) + return true; + break; + case COND_LE: // (0xD) + if ((cpsr_z == 1) || (cpsr_n != cpsr_v)) + return true; + break; + default: + return true; + break; + } + + return false; } -uint32_t -DNBArchMachARM::NumSupportedHardwareBreakpoints() -{ - // Set the init value to something that will let us know that we need to - // autodetect how many breakpoints are supported dynamically... - static uint32_t g_num_supported_hw_breakpoints = UINT_MAX; - if (g_num_supported_hw_breakpoints == UINT_MAX) - { - // Set this to zero in case we can't tell if there are any HW breakpoints - g_num_supported_hw_breakpoints = 0; - - size_t len; - uint32_t n = 0; - len = sizeof (n); - if (::sysctlbyname("hw.optional.breakpoint", &n, &len, NULL, 0) == 0) - { - g_num_supported_hw_breakpoints = n; - DNBLogThreadedIf(LOG_THREAD, "hw.optional.breakpoint=%u", n); +uint32_t DNBArchMachARM::NumSupportedHardwareBreakpoints() { + // Set the init value to something that will let us know that we need to + // autodetect how many breakpoints are supported dynamically... + static uint32_t g_num_supported_hw_breakpoints = UINT_MAX; + if (g_num_supported_hw_breakpoints == UINT_MAX) { + // Set this to zero in case we can't tell if there are any HW breakpoints + g_num_supported_hw_breakpoints = 0; + + size_t len; + uint32_t n = 0; + len = sizeof(n); + if (::sysctlbyname("hw.optional.breakpoint", &n, &len, NULL, 0) == 0) { + g_num_supported_hw_breakpoints = n; + DNBLogThreadedIf(LOG_THREAD, "hw.optional.breakpoint=%u", n); + } else { +#if !defined(__arm64__) && !defined(__aarch64__) + // Read the DBGDIDR to get the number of available hardware breakpoints + // However, in some of our current armv7 processors, hardware + // breakpoints/watchpoints were not properly connected. So detect those + // cases using a field in a sysctl. For now we are using "hw.cpusubtype" + // field to distinguish CPU architectures. This is a hack until we can + // get <rdar://problem/6372672> fixed, at which point we will switch to + // using a different sysctl string that will tell us how many BRPs + // are available to us directly without having to read DBGDIDR. + uint32_t register_DBGDIDR; + + asm("mrc p14, 0, %0, c0, c0, 0" : "=r"(register_DBGDIDR)); + uint32_t numBRPs = bits(register_DBGDIDR, 27, 24); + // Zero is reserved for the BRP count, so don't increment it if it is zero + if (numBRPs > 0) + numBRPs++; + DNBLogThreadedIf(LOG_THREAD, "DBGDIDR=0x%8.8x (number BRP pairs = %u)", + register_DBGDIDR, numBRPs); + + if (numBRPs > 0) { + uint32_t cpusubtype; + len = sizeof(cpusubtype); + // TODO: remove this hack and change to using hw.optional.xx when + // implmented + if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0) { + DNBLogThreadedIf(LOG_THREAD, "hw.cpusubtype=%d", cpusubtype); + if (cpusubtype == CPU_SUBTYPE_ARM_V7) + DNBLogThreadedIf(LOG_THREAD, "Hardware breakpoints disabled for " + "armv7 (rdar://problem/6372672)"); + else + g_num_supported_hw_breakpoints = numBRPs; } - else - { -#if !defined (__arm64__) && !defined (__aarch64__) - // Read the DBGDIDR to get the number of available hardware breakpoints - // However, in some of our current armv7 processors, hardware - // breakpoints/watchpoints were not properly connected. So detect those - // cases using a field in a sysctl. For now we are using "hw.cpusubtype" - // field to distinguish CPU architectures. This is a hack until we can - // get <rdar://problem/6372672> fixed, at which point we will switch to - // using a different sysctl string that will tell us how many BRPs - // are available to us directly without having to read DBGDIDR. - uint32_t register_DBGDIDR; - - asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR)); - uint32_t numBRPs = bits(register_DBGDIDR, 27, 24); - // Zero is reserved for the BRP count, so don't increment it if it is zero - if (numBRPs > 0) - numBRPs++; - DNBLogThreadedIf(LOG_THREAD, "DBGDIDR=0x%8.8x (number BRP pairs = %u)", register_DBGDIDR, numBRPs); - - if (numBRPs > 0) - { - uint32_t cpusubtype; - len = sizeof(cpusubtype); - // TODO: remove this hack and change to using hw.optional.xx when implmented - if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0) - { - DNBLogThreadedIf(LOG_THREAD, "hw.cpusubtype=%d", cpusubtype); - if (cpusubtype == CPU_SUBTYPE_ARM_V7) - DNBLogThreadedIf(LOG_THREAD, "Hardware breakpoints disabled for armv7 (rdar://problem/6372672)"); - else - g_num_supported_hw_breakpoints = numBRPs; - } - } + } #endif - } } - return g_num_supported_hw_breakpoints; + } + return g_num_supported_hw_breakpoints; } - -uint32_t -DNBArchMachARM::NumSupportedHardwareWatchpoints() -{ - // Set the init value to something that will let us know that we need to - // autodetect how many watchpoints are supported dynamically... - static uint32_t g_num_supported_hw_watchpoints = UINT_MAX; - if (g_num_supported_hw_watchpoints == UINT_MAX) - { - // Set this to zero in case we can't tell if there are any HW breakpoints - g_num_supported_hw_watchpoints = 0; - - +uint32_t DNBArchMachARM::NumSupportedHardwareWatchpoints() { + // Set the init value to something that will let us know that we need to + // autodetect how many watchpoints are supported dynamically... + static uint32_t g_num_supported_hw_watchpoints = UINT_MAX; + if (g_num_supported_hw_watchpoints == UINT_MAX) { + // Set this to zero in case we can't tell if there are any HW breakpoints + g_num_supported_hw_watchpoints = 0; + + size_t len; + uint32_t n = 0; + len = sizeof(n); + if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0) { + g_num_supported_hw_watchpoints = n; + DNBLogThreadedIf(LOG_THREAD, "hw.optional.watchpoint=%u", n); + } else { +#if !defined(__arm64__) && !defined(__aarch64__) + // Read the DBGDIDR to get the number of available hardware breakpoints + // However, in some of our current armv7 processors, hardware + // breakpoints/watchpoints were not properly connected. So detect those + // cases using a field in a sysctl. For now we are using "hw.cpusubtype" + // field to distinguish CPU architectures. This is a hack until we can + // get <rdar://problem/6372672> fixed, at which point we will switch to + // using a different sysctl string that will tell us how many WRPs + // are available to us directly without having to read DBGDIDR. + + uint32_t register_DBGDIDR; + asm("mrc p14, 0, %0, c0, c0, 0" : "=r"(register_DBGDIDR)); + uint32_t numWRPs = bits(register_DBGDIDR, 31, 28) + 1; + DNBLogThreadedIf(LOG_THREAD, "DBGDIDR=0x%8.8x (number WRP pairs = %u)", + register_DBGDIDR, numWRPs); + + if (numWRPs > 0) { + uint32_t cpusubtype; size_t len; - uint32_t n = 0; - len = sizeof (n); - if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0) - { - g_num_supported_hw_watchpoints = n; - DNBLogThreadedIf(LOG_THREAD, "hw.optional.watchpoint=%u", n); + len = sizeof(cpusubtype); + // TODO: remove this hack and change to using hw.optional.xx when + // implmented + if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0) { + DNBLogThreadedIf(LOG_THREAD, "hw.cpusubtype=0x%d", cpusubtype); + + if (cpusubtype == CPU_SUBTYPE_ARM_V7) + DNBLogThreadedIf(LOG_THREAD, "Hardware watchpoints disabled for " + "armv7 (rdar://problem/6372672)"); + else + g_num_supported_hw_watchpoints = numWRPs; } - else - { -#if !defined (__arm64__) && !defined (__aarch64__) - // Read the DBGDIDR to get the number of available hardware breakpoints - // However, in some of our current armv7 processors, hardware - // breakpoints/watchpoints were not properly connected. So detect those - // cases using a field in a sysctl. For now we are using "hw.cpusubtype" - // field to distinguish CPU architectures. This is a hack until we can - // get <rdar://problem/6372672> fixed, at which point we will switch to - // using a different sysctl string that will tell us how many WRPs - // are available to us directly without having to read DBGDIDR. - - uint32_t register_DBGDIDR; - asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR)); - uint32_t numWRPs = bits(register_DBGDIDR, 31, 28) + 1; - DNBLogThreadedIf(LOG_THREAD, "DBGDIDR=0x%8.8x (number WRP pairs = %u)", register_DBGDIDR, numWRPs); - - if (numWRPs > 0) - { - uint32_t cpusubtype; - size_t len; - len = sizeof(cpusubtype); - // TODO: remove this hack and change to using hw.optional.xx when implmented - if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0) - { - DNBLogThreadedIf(LOG_THREAD, "hw.cpusubtype=0x%d", cpusubtype); - - if (cpusubtype == CPU_SUBTYPE_ARM_V7) - DNBLogThreadedIf(LOG_THREAD, "Hardware watchpoints disabled for armv7 (rdar://problem/6372672)"); - else - g_num_supported_hw_watchpoints = numWRPs; - } - } + } #endif - } } - return g_num_supported_hw_watchpoints; + } + return g_num_supported_hw_watchpoints; } +uint32_t DNBArchMachARM::EnableHardwareBreakpoint(nub_addr_t addr, + nub_size_t size) { + // Make sure our address isn't bogus + if (addr & 1) + return INVALID_NUB_HW_INDEX; -uint32_t -DNBArchMachARM::EnableHardwareBreakpoint (nub_addr_t addr, nub_size_t size) -{ - // Make sure our address isn't bogus - if (addr & 1) - return INVALID_NUB_HW_INDEX; - - kern_return_t kret = GetDBGState(false); + kern_return_t kret = GetDBGState(false); - if (kret == KERN_SUCCESS) - { - const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints(); - uint32_t i; - for (i=0; i<num_hw_breakpoints; ++i) - { - if ((m_state.dbg.__bcr[i] & BCR_ENABLE) == 0) - break; // We found an available hw breakpoint slot (in i) - } + if (kret == KERN_SUCCESS) { + const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints(); + uint32_t i; + for (i = 0; i < num_hw_breakpoints; ++i) { + if ((m_state.dbg.__bcr[i] & BCR_ENABLE) == 0) + break; // We found an available hw breakpoint slot (in i) + } - // See if we found an available hw breakpoint slot above - if (i < num_hw_breakpoints) - { - // Make sure bits 1:0 are clear in our address - m_state.dbg.__bvr[i] = addr & ~((nub_addr_t)3); - - if (size == 2 || addr & 2) - { - uint32_t byte_addr_select = (addr & 2) ? BAS_IMVA_2_3 : BAS_IMVA_0_1; - - // We have a thumb breakpoint - // We have an ARM breakpoint - m_state.dbg.__bcr[i] = BCR_M_IMVA_MATCH | // Stop on address mismatch - byte_addr_select | // Set the correct byte address select so we only trigger on the correct opcode - S_USER | // Which modes should this breakpoint stop in? - BCR_ENABLE; // Enable this hardware breakpoint - DNBLogThreadedIf (LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint( addr = 0x%8.8llx, size = %llu ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (Thumb)", - (uint64_t)addr, - (uint64_t)size, - i, - i, - m_state.dbg.__bvr[i], - m_state.dbg.__bcr[i]); - } - else if (size == 4) - { - // We have an ARM breakpoint - m_state.dbg.__bcr[i] = BCR_M_IMVA_MATCH | // Stop on address mismatch - BAS_IMVA_ALL | // Stop on any of the four bytes following the IMVA - S_USER | // Which modes should this breakpoint stop in? - BCR_ENABLE; // Enable this hardware breakpoint - DNBLogThreadedIf (LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint( addr = 0x%8.8llx, size = %llu ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (ARM)", - (uint64_t)addr, - (uint64_t)size, - i, - i, - m_state.dbg.__bvr[i], - m_state.dbg.__bcr[i]); - } - - kret = SetDBGState(false); - DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint() SetDBGState() => 0x%8.8x.", kret); - - if (kret == KERN_SUCCESS) - return i; - } - else - { - DNBLogThreadedIf (LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint(addr = 0x%8.8llx, size = %llu) => all hardware breakpoint resources are being used.", (uint64_t)addr, (uint64_t)size); - } + // See if we found an available hw breakpoint slot above + if (i < num_hw_breakpoints) { + // Make sure bits 1:0 are clear in our address + m_state.dbg.__bvr[i] = addr & ~((nub_addr_t)3); + + if (size == 2 || addr & 2) { + uint32_t byte_addr_select = (addr & 2) ? BAS_IMVA_2_3 : BAS_IMVA_0_1; + + // We have a thumb breakpoint + // We have an ARM breakpoint + m_state.dbg.__bcr[i] = + BCR_M_IMVA_MATCH | // Stop on address mismatch + byte_addr_select | // Set the correct byte address select so we only + // trigger on the correct opcode + S_USER | // Which modes should this breakpoint stop in? + BCR_ENABLE; // Enable this hardware breakpoint + DNBLogThreadedIf(LOG_BREAKPOINTS, + "DNBArchMachARM::EnableHardwareBreakpoint( addr = " + "0x%8.8llx, size = %llu ) - BVR%u/BCR%u = 0x%8.8x / " + "0x%8.8x (Thumb)", + (uint64_t)addr, (uint64_t)size, i, i, + m_state.dbg.__bvr[i], m_state.dbg.__bcr[i]); + } else if (size == 4) { + // We have an ARM breakpoint + m_state.dbg.__bcr[i] = + BCR_M_IMVA_MATCH | // Stop on address mismatch + BAS_IMVA_ALL | // Stop on any of the four bytes following the IMVA + S_USER | // Which modes should this breakpoint stop in? + BCR_ENABLE; // Enable this hardware breakpoint + DNBLogThreadedIf(LOG_BREAKPOINTS, + "DNBArchMachARM::EnableHardwareBreakpoint( addr = " + "0x%8.8llx, size = %llu ) - BVR%u/BCR%u = 0x%8.8x / " + "0x%8.8x (ARM)", + (uint64_t)addr, (uint64_t)size, i, i, + m_state.dbg.__bvr[i], m_state.dbg.__bcr[i]); + } + + kret = SetDBGState(false); + DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::" + "EnableHardwareBreakpoint() " + "SetDBGState() => 0x%8.8x.", + kret); + + if (kret == KERN_SUCCESS) + return i; + } else { + DNBLogThreadedIf(LOG_BREAKPOINTS, + "DNBArchMachARM::EnableHardwareBreakpoint(addr = " + "0x%8.8llx, size = %llu) => all hardware breakpoint " + "resources are being used.", + (uint64_t)addr, (uint64_t)size); } + } - return INVALID_NUB_HW_INDEX; + return INVALID_NUB_HW_INDEX; } -bool -DNBArchMachARM::DisableHardwareBreakpoint (uint32_t hw_index) -{ - kern_return_t kret = GetDBGState(false); - - const uint32_t num_hw_points = NumSupportedHardwareBreakpoints(); - if (kret == KERN_SUCCESS) - { - if (hw_index < num_hw_points) - { - m_state.dbg.__bcr[hw_index] = 0; - DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::SetHardwareBreakpoint( %u ) - BVR%u = 0x%8.8x BCR%u = 0x%8.8x", - hw_index, - hw_index, - m_state.dbg.__bvr[hw_index], - hw_index, - m_state.dbg.__bcr[hw_index]); - - kret = SetDBGState(false); - - if (kret == KERN_SUCCESS) - return true; - } +bool DNBArchMachARM::DisableHardwareBreakpoint(uint32_t hw_index) { + kern_return_t kret = GetDBGState(false); + + const uint32_t num_hw_points = NumSupportedHardwareBreakpoints(); + if (kret == KERN_SUCCESS) { + if (hw_index < num_hw_points) { + m_state.dbg.__bcr[hw_index] = 0; + DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::SetHardwareBreakpoint(" + " %u ) - BVR%u = 0x%8.8x BCR%u = " + "0x%8.8x", + hw_index, hw_index, m_state.dbg.__bvr[hw_index], + hw_index, m_state.dbg.__bcr[hw_index]); + + kret = SetDBGState(false); + + if (kret == KERN_SUCCESS) + return true; } - return false; + } + return false; } // ARM v7 watchpoints may be either word-size or double-word-size. @@ -1071,1092 +1080,1115 @@ DNBArchMachARM::DisableHardwareBreakpoint (uint32_t hw_index) // armv8 device, armv7 processes can watch dwords. But on a genuine armv7 // device I tried, only word watchpoints are supported. -#if defined (__arm64__) || defined (__aarch64__) +#if defined(__arm64__) || defined(__aarch64__) #define WATCHPOINTS_ARE_DWORD 1 #else #undef WATCHPOINTS_ARE_DWORD #endif -uint32_t -DNBArchMachARM::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task) -{ - - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint(addr = 0x%8.8llx, size = %zu, read = %u, write = %u)", (uint64_t)addr, size, read, write); - - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - - // Can't watch zero bytes - if (size == 0) - return INVALID_NUB_HW_INDEX; +uint32_t DNBArchMachARM::EnableHardwareWatchpoint(nub_addr_t addr, + nub_size_t size, bool read, + bool write, + bool also_set_on_task) { - // We must watch for either read or write - if (read == false && write == false) - return INVALID_NUB_HW_INDEX; + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint(" + "addr = 0x%8.8llx, size = %zu, read = %u, " + "write = %u)", + (uint64_t)addr, size, read, write); - // Otherwise, can't watch more than 8 bytes per WVR/WCR pair - if (size > 8) - return INVALID_NUB_HW_INDEX; + const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - // Treat arm watchpoints as having an 8-byte alignment requirement. You can put a watchpoint on a 4-byte - // offset address but you can only watch 4 bytes with that watchpoint. + // Can't watch zero bytes + if (size == 0) + return INVALID_NUB_HW_INDEX; - // arm watchpoints on an 8-byte (double word) aligned addr can watch any bytes in that - // 8-byte long region of memory. They can watch the 1st byte, the 2nd byte, 3rd byte, etc, or any - // combination therein by setting the bits in the BAS [12:5] (Byte Address Select) field of - // the DBGWCRn_EL1 reg for the watchpoint. + // We must watch for either read or write + if (read == false && write == false) + return INVALID_NUB_HW_INDEX; - // If the MASK [28:24] bits in the DBGWCRn_EL1 allow a single watchpoint to monitor a larger region - // of memory (16 bytes, 32 bytes, or 2GB) but the Byte Address Select bitfield then selects a larger - // range of bytes, instead of individual bytes. See the ARMv8 Debug Architecture manual for details. - // This implementation does not currently use the MASK bits; the largest single region watched by a single - // watchpoint right now is 8-bytes. + // Otherwise, can't watch more than 8 bytes per WVR/WCR pair + if (size > 8) + return INVALID_NUB_HW_INDEX; -#if defined (WATCHPOINTS_ARE_DWORD) - nub_addr_t aligned_wp_address = addr & ~0x7; - uint32_t addr_dword_offset = addr & 0x7; - const int max_watchpoint_size = 8; +// Treat arm watchpoints as having an 8-byte alignment requirement. You can put +// a watchpoint on a 4-byte +// offset address but you can only watch 4 bytes with that watchpoint. + +// arm watchpoints on an 8-byte (double word) aligned addr can watch any bytes +// in that +// 8-byte long region of memory. They can watch the 1st byte, the 2nd byte, 3rd +// byte, etc, or any +// combination therein by setting the bits in the BAS [12:5] (Byte Address +// Select) field of +// the DBGWCRn_EL1 reg for the watchpoint. + +// If the MASK [28:24] bits in the DBGWCRn_EL1 allow a single watchpoint to +// monitor a larger region +// of memory (16 bytes, 32 bytes, or 2GB) but the Byte Address Select bitfield +// then selects a larger +// range of bytes, instead of individual bytes. See the ARMv8 Debug +// Architecture manual for details. +// This implementation does not currently use the MASK bits; the largest single +// region watched by a single +// watchpoint right now is 8-bytes. + +#if defined(WATCHPOINTS_ARE_DWORD) + nub_addr_t aligned_wp_address = addr & ~0x7; + uint32_t addr_dword_offset = addr & 0x7; + const int max_watchpoint_size = 8; #else - nub_addr_t aligned_wp_address = addr & ~0x3; - uint32_t addr_dword_offset = addr & 0x3; - const int max_watchpoint_size = 4; + nub_addr_t aligned_wp_address = addr & ~0x3; + uint32_t addr_dword_offset = addr & 0x3; + const int max_watchpoint_size = 4; #endif - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint aligned_wp_address is 0x%llx and addr_dword_offset is 0x%x", (uint64_t)aligned_wp_address, addr_dword_offset); - - // Do we need to split up this logical watchpoint into two hardware watchpoint - // registers? - // e.g. a watchpoint of length 4 on address 6. We need do this with - // one watchpoint on address 0 with bytes 6 & 7 being monitored - // one watchpoint on address 8 with bytes 0, 1, 2, 3 being monitored - - if (addr_dword_offset + size > max_watchpoint_size) - { - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint(addr = 0x%8.8llx, size = %zu) needs two hardware watchpoints slots to monitor", (uint64_t)addr, size); - int low_watchpoint_size = max_watchpoint_size - addr_dword_offset; - int high_watchpoint_size = addr_dword_offset + size - max_watchpoint_size; - - uint32_t lo = EnableHardwareWatchpoint(addr, low_watchpoint_size, read, write, also_set_on_task); - if (lo == INVALID_NUB_HW_INDEX) - return INVALID_NUB_HW_INDEX; - uint32_t hi = EnableHardwareWatchpoint (aligned_wp_address + max_watchpoint_size, high_watchpoint_size, read, write, also_set_on_task); - if (hi == INVALID_NUB_HW_INDEX) - { - DisableHardwareWatchpoint (lo, also_set_on_task); - return INVALID_NUB_HW_INDEX; - } - // Tag this lo->hi mapping in our database. - LoHi[lo] = hi; - return lo; + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint " + "aligned_wp_address is 0x%llx and " + "addr_dword_offset is 0x%x", + (uint64_t)aligned_wp_address, addr_dword_offset); + + // Do we need to split up this logical watchpoint into two hardware watchpoint + // registers? + // e.g. a watchpoint of length 4 on address 6. We need do this with + // one watchpoint on address 0 with bytes 6 & 7 being monitored + // one watchpoint on address 8 with bytes 0, 1, 2, 3 being monitored + + if (addr_dword_offset + size > max_watchpoint_size) { + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::" + "EnableHardwareWatchpoint(addr = " + "0x%8.8llx, size = %zu) needs two " + "hardware watchpoints slots to monitor", + (uint64_t)addr, size); + int low_watchpoint_size = max_watchpoint_size - addr_dword_offset; + int high_watchpoint_size = addr_dword_offset + size - max_watchpoint_size; + + uint32_t lo = EnableHardwareWatchpoint(addr, low_watchpoint_size, read, + write, also_set_on_task); + if (lo == INVALID_NUB_HW_INDEX) + return INVALID_NUB_HW_INDEX; + uint32_t hi = EnableHardwareWatchpoint( + aligned_wp_address + max_watchpoint_size, high_watchpoint_size, read, + write, also_set_on_task); + if (hi == INVALID_NUB_HW_INDEX) { + DisableHardwareWatchpoint(lo, also_set_on_task); + return INVALID_NUB_HW_INDEX; } + // Tag this lo->hi mapping in our database. + LoHi[lo] = hi; + return lo; + } + + // At this point + // 1 aligned_wp_address is the requested address rounded down to 8-byte + // alignment + // 2 addr_dword_offset is the offset into that double word (8-byte) region + // that we are watching + // 3 size is the number of bytes within that 8-byte region that we are + // watching + + // Set the Byte Address Selects bits DBGWCRn_EL1 bits [12:5] based on the + // above. + // The bit shift and negation operation will give us 0b11 for 2, 0b1111 for 4, + // etc, up to 0b11111111 for 8. + // then we shift those bits left by the offset into this dword that we are + // interested in. + // e.g. if we are watching bytes 4,5,6,7 in a dword we want a BAS of + // 0b11110000. + uint32_t byte_address_select = ((1 << size) - 1) << addr_dword_offset; + + // Read the debug state + kern_return_t kret = GetDBGState(true); + + if (kret == KERN_SUCCESS) { + // Check to make sure we have the needed hardware support + uint32_t i = 0; - // At this point - // 1 aligned_wp_address is the requested address rounded down to 8-byte alignment - // 2 addr_dword_offset is the offset into that double word (8-byte) region that we are watching - // 3 size is the number of bytes within that 8-byte region that we are watching - - // Set the Byte Address Selects bits DBGWCRn_EL1 bits [12:5] based on the above. - // The bit shift and negation operation will give us 0b11 for 2, 0b1111 for 4, etc, up to 0b11111111 for 8. - // then we shift those bits left by the offset into this dword that we are interested in. - // e.g. if we are watching bytes 4,5,6,7 in a dword we want a BAS of 0b11110000. - uint32_t byte_address_select = ((1 << size) - 1) << addr_dword_offset; - - // Read the debug state - kern_return_t kret = GetDBGState(true); - - if (kret == KERN_SUCCESS) - { - // Check to make sure we have the needed hardware support - uint32_t i = 0; - - for (i=0; i<num_hw_watchpoints; ++i) - { - if ((m_state.dbg.__wcr[i] & WCR_ENABLE) == 0) - break; // We found an available hw watchpoint slot (in i) - } - - // See if we found an available hw watchpoint slot above - if (i < num_hw_watchpoints) - { - //DumpDBGState(m_state.dbg); - - // Clear any previous LoHi joined-watchpoint that may have been in use - LoHi[i] = 0; - - // shift our Byte Address Select bits up to the correct bit range for the DBGWCRn_EL1 - byte_address_select = byte_address_select << 5; - - // Make sure bits 1:0 are clear in our address - m_state.dbg.__wvr[i] = aligned_wp_address; // DVA (Data Virtual Address) - m_state.dbg.__wcr[i] = byte_address_select | // Which bytes that follow the DVA that we will watch - S_USER | // Stop only in user mode - (read ? WCR_LOAD : 0) | // Stop on read access? - (write ? WCR_STORE : 0) | // Stop on write access? - WCR_ENABLE; // Enable this watchpoint; - - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() adding watchpoint on address 0x%llx with control register value 0x%x", (uint64_t) m_state.dbg.__wvr[i], (uint32_t) m_state.dbg.__wcr[i]); - - // The kernel will set the MDE_ENABLE bit in the MDSCR_EL1 for us automatically, don't need to do it here. - - kret = SetDBGState(also_set_on_task); - //DumpDBGState(m_state.dbg); - - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() SetDBGState() => 0x%8.8x.", kret); + for (i = 0; i < num_hw_watchpoints; ++i) { + if ((m_state.dbg.__wcr[i] & WCR_ENABLE) == 0) + break; // We found an available hw watchpoint slot (in i) + } - if (kret == KERN_SUCCESS) - return i; - } - else - { - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints); - } + // See if we found an available hw watchpoint slot above + if (i < num_hw_watchpoints) { + // DumpDBGState(m_state.dbg); + + // Clear any previous LoHi joined-watchpoint that may have been in use + LoHi[i] = 0; + + // shift our Byte Address Select bits up to the correct bit range for the + // DBGWCRn_EL1 + byte_address_select = byte_address_select << 5; + + // Make sure bits 1:0 are clear in our address + m_state.dbg.__wvr[i] = aligned_wp_address; // DVA (Data Virtual Address) + m_state.dbg.__wcr[i] = byte_address_select | // Which bytes that follow + // the DVA that we will watch + S_USER | // Stop only in user mode + (read ? WCR_LOAD : 0) | // Stop on read access? + (write ? WCR_STORE : 0) | // Stop on write access? + WCR_ENABLE; // Enable this watchpoint; + + DNBLogThreadedIf( + LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() adding " + "watchpoint on address 0x%llx with control register " + "value 0x%x", + (uint64_t)m_state.dbg.__wvr[i], (uint32_t)m_state.dbg.__wcr[i]); + + // The kernel will set the MDE_ENABLE bit in the MDSCR_EL1 for us + // automatically, don't need to do it here. + + kret = SetDBGState(also_set_on_task); + // DumpDBGState(m_state.dbg); + + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::" + "EnableHardwareWatchpoint() " + "SetDBGState() => 0x%8.8x.", + kret); + + if (kret == KERN_SUCCESS) + return i; + } else { + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::" + "EnableHardwareWatchpoint(): All " + "hardware resources (%u) are in use.", + num_hw_watchpoints); } - return INVALID_NUB_HW_INDEX; + } + return INVALID_NUB_HW_INDEX; } -bool -DNBArchMachARM::ReenableHardwareWatchpoint (uint32_t hw_index) -{ - // If this logical watchpoint # is actually implemented using - // two hardware watchpoint registers, re-enable both of them. +bool DNBArchMachARM::ReenableHardwareWatchpoint(uint32_t hw_index) { + // If this logical watchpoint # is actually implemented using + // two hardware watchpoint registers, re-enable both of them. - if (hw_index < NumSupportedHardwareWatchpoints() && LoHi[hw_index]) - { - return ReenableHardwareWatchpoint_helper (hw_index) && ReenableHardwareWatchpoint_helper (LoHi[hw_index]); - } - else - { - return ReenableHardwareWatchpoint_helper (hw_index); - } + if (hw_index < NumSupportedHardwareWatchpoints() && LoHi[hw_index]) { + return ReenableHardwareWatchpoint_helper(hw_index) && + ReenableHardwareWatchpoint_helper(LoHi[hw_index]); + } else { + return ReenableHardwareWatchpoint_helper(hw_index); + } } -bool -DNBArchMachARM::ReenableHardwareWatchpoint_helper (uint32_t hw_index) -{ - kern_return_t kret = GetDBGState(false); - if (kret != KERN_SUCCESS) - return false; - const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); - if (hw_index >= num_hw_points) - return false; +bool DNBArchMachARM::ReenableHardwareWatchpoint_helper(uint32_t hw_index) { + kern_return_t kret = GetDBGState(false); + if (kret != KERN_SUCCESS) + return false; + const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); + if (hw_index >= num_hw_points) + return false; - m_state.dbg.__wvr[hw_index] = m_disabled_watchpoints[hw_index].addr; - m_state.dbg.__wcr[hw_index] = m_disabled_watchpoints[hw_index].control; + m_state.dbg.__wvr[hw_index] = m_disabled_watchpoints[hw_index].addr; + m_state.dbg.__wcr[hw_index] = m_disabled_watchpoints[hw_index].control; - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint( %u ) - WVR%u = 0x%8.8llx WCR%u = 0x%8.8llx", - hw_index, - hw_index, - (uint64_t) m_state.dbg.__wvr[hw_index], - hw_index, - (uint64_t) m_state.dbg.__wcr[hw_index]); + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint( " + "%u ) - WVR%u = 0x%8.8llx WCR%u = " + "0x%8.8llx", + hw_index, hw_index, (uint64_t)m_state.dbg.__wvr[hw_index], + hw_index, (uint64_t)m_state.dbg.__wcr[hw_index]); - // The kernel will set the MDE_ENABLE bit in the MDSCR_EL1 for us automatically, don't need to do it here. + // The kernel will set the MDE_ENABLE bit in the MDSCR_EL1 for us + // automatically, don't need to do it here. - kret = SetDBGState(false); + kret = SetDBGState(false); - return (kret == KERN_SUCCESS); + return (kret == KERN_SUCCESS); } -bool -DNBArchMachARM::DisableHardwareWatchpoint (uint32_t hw_index, bool also_set_on_task) -{ - if (hw_index < NumSupportedHardwareWatchpoints() && LoHi[hw_index]) - { - return DisableHardwareWatchpoint_helper (hw_index, also_set_on_task) && DisableHardwareWatchpoint_helper (LoHi[hw_index], also_set_on_task); - } - else - { - return DisableHardwareWatchpoint_helper (hw_index, also_set_on_task); - } +bool DNBArchMachARM::DisableHardwareWatchpoint(uint32_t hw_index, + bool also_set_on_task) { + if (hw_index < NumSupportedHardwareWatchpoints() && LoHi[hw_index]) { + return DisableHardwareWatchpoint_helper(hw_index, also_set_on_task) && + DisableHardwareWatchpoint_helper(LoHi[hw_index], also_set_on_task); + } else { + return DisableHardwareWatchpoint_helper(hw_index, also_set_on_task); + } } -bool -DNBArchMachARM::DisableHardwareWatchpoint_helper (uint32_t hw_index, bool also_set_on_task) -{ - kern_return_t kret = GetDBGState(false); - if (kret != KERN_SUCCESS) - return false; +bool DNBArchMachARM::DisableHardwareWatchpoint_helper(uint32_t hw_index, + bool also_set_on_task) { + kern_return_t kret = GetDBGState(false); + if (kret != KERN_SUCCESS) + return false; - const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); - if (hw_index >= num_hw_points) - return false; + const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); + if (hw_index >= num_hw_points) + return false; - m_disabled_watchpoints[hw_index].addr = m_state.dbg.__wvr[hw_index]; - m_disabled_watchpoints[hw_index].control = m_state.dbg.__wcr[hw_index]; + m_disabled_watchpoints[hw_index].addr = m_state.dbg.__wvr[hw_index]; + m_disabled_watchpoints[hw_index].control = m_state.dbg.__wcr[hw_index]; - m_state.dbg.__wvr[hw_index] = 0; - m_state.dbg.__wcr[hw_index] = 0; - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::DisableHardwareWatchpoint( %u ) - WVR%u = 0x%8.8llx WCR%u = 0x%8.8llx", - hw_index, - hw_index, - (uint64_t) m_state.dbg.__wvr[hw_index], - hw_index, - (uint64_t) m_state.dbg.__wcr[hw_index]); + m_state.dbg.__wvr[hw_index] = 0; + m_state.dbg.__wcr[hw_index] = 0; + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::DisableHardwareWatchpoint(" + " %u ) - WVR%u = 0x%8.8llx WCR%u = " + "0x%8.8llx", + hw_index, hw_index, (uint64_t)m_state.dbg.__wvr[hw_index], + hw_index, (uint64_t)m_state.dbg.__wcr[hw_index]); - kret = SetDBGState(also_set_on_task); + kret = SetDBGState(also_set_on_task); - return (kret == KERN_SUCCESS); + return (kret == KERN_SUCCESS); } // Returns -1 if the trailing bit patterns are not one of: // { 0b???1, 0b??10, 0b?100, 0b1000 }. -static inline -int32_t -LowestBitSet(uint32_t val) -{ - for (unsigned i = 0; i < 4; ++i) { - if (bit(val, i)) - return i; - } - return -1; +static inline int32_t LowestBitSet(uint32_t val) { + for (unsigned i = 0; i < 4; ++i) { + if (bit(val, i)) + return i; + } + return -1; } -// Iterate through the debug registers; return the index of the first watchpoint whose address matches. -// As a side effect, the starting address as understood by the debugger is returned which could be +// Iterate through the debug registers; return the index of the first watchpoint +// whose address matches. +// As a side effect, the starting address as understood by the debugger is +// returned which could be // different from 'addr' passed as an in/out argument. -uint32_t -DNBArchMachARM::GetHardwareWatchpointHit(nub_addr_t &addr) -{ - // Read the debug state - kern_return_t kret = GetDBGState(true); - //DumpDBGState(m_state.dbg); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::GetHardwareWatchpointHit() addr = 0x%llx", (uint64_t)addr); - - // This is the watchpoint value to match against, i.e., word address. -#if defined (WATCHPOINTS_ARE_DWORD) - nub_addr_t wp_val = addr & ~((nub_addr_t)7); +uint32_t DNBArchMachARM::GetHardwareWatchpointHit(nub_addr_t &addr) { + // Read the debug state + kern_return_t kret = GetDBGState(true); + // DumpDBGState(m_state.dbg); + DNBLogThreadedIf( + LOG_WATCHPOINTS, + "DNBArchMachARM::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", + kret); + DNBLogThreadedIf(LOG_WATCHPOINTS, + "DNBArchMachARM::GetHardwareWatchpointHit() addr = 0x%llx", + (uint64_t)addr); + +// This is the watchpoint value to match against, i.e., word address. +#if defined(WATCHPOINTS_ARE_DWORD) + nub_addr_t wp_val = addr & ~((nub_addr_t)7); #else - nub_addr_t wp_val = addr & ~((nub_addr_t)3); + nub_addr_t wp_val = addr & ~((nub_addr_t)3); #endif - if (kret == KERN_SUCCESS) - { - DBG &debug_state = m_state.dbg; - uint32_t i, num = NumSupportedHardwareWatchpoints(); - for (i = 0; i < num; ++i) - { - nub_addr_t wp_addr = GetWatchAddress(debug_state, i); - DNBLogThreadedIf(LOG_WATCHPOINTS, - "DNBArchMachARM::GetHardwareWatchpointHit() slot: %u (addr = 0x%llx).", - i, (uint64_t)wp_addr); - if (wp_val == wp_addr) { -#if defined (WATCHPOINTS_ARE_DWORD) - uint32_t byte_mask = bits(debug_state.__wcr[i], 12, 5); + if (kret == KERN_SUCCESS) { + DBG &debug_state = m_state.dbg; + uint32_t i, num = NumSupportedHardwareWatchpoints(); + for (i = 0; i < num; ++i) { + nub_addr_t wp_addr = GetWatchAddress(debug_state, i); + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::" + "GetHardwareWatchpointHit() slot: %u " + "(addr = 0x%llx).", + i, (uint64_t)wp_addr); + if (wp_val == wp_addr) { +#if defined(WATCHPOINTS_ARE_DWORD) + uint32_t byte_mask = bits(debug_state.__wcr[i], 12, 5); #else - uint32_t byte_mask = bits(debug_state.__wcr[i], 8, 5); + uint32_t byte_mask = bits(debug_state.__wcr[i], 8, 5); #endif - // Sanity check the byte_mask, first. - if (LowestBitSet(byte_mask) < 0) - continue; + // Sanity check the byte_mask, first. + if (LowestBitSet(byte_mask) < 0) + continue; - // Compute the starting address (from the point of view of the debugger). - addr = wp_addr + LowestBitSet(byte_mask); - return i; - } - } + // Compute the starting address (from the point of view of the + // debugger). + addr = wp_addr + LowestBitSet(byte_mask); + return i; + } } - return INVALID_NUB_HW_INDEX; + } + return INVALID_NUB_HW_INDEX; } -nub_addr_t -DNBArchMachARM::GetWatchpointAddressByIndex (uint32_t hw_index) -{ - kern_return_t kret = GetDBGState(true); - if (kret != KERN_SUCCESS) - return INVALID_NUB_ADDRESS; - const uint32_t num = NumSupportedHardwareWatchpoints(); - if (hw_index >= num) - return INVALID_NUB_ADDRESS; - if (IsWatchpointEnabled (m_state.dbg, hw_index)) - return GetWatchAddress (m_state.dbg, hw_index); +nub_addr_t DNBArchMachARM::GetWatchpointAddressByIndex(uint32_t hw_index) { + kern_return_t kret = GetDBGState(true); + if (kret != KERN_SUCCESS) return INVALID_NUB_ADDRESS; + const uint32_t num = NumSupportedHardwareWatchpoints(); + if (hw_index >= num) + return INVALID_NUB_ADDRESS; + if (IsWatchpointEnabled(m_state.dbg, hw_index)) + return GetWatchAddress(m_state.dbg, hw_index); + return INVALID_NUB_ADDRESS; } -bool -DNBArchMachARM::IsWatchpointEnabled(const DBG &debug_state, uint32_t hw_index) -{ - // Watchpoint Control Registers, bitfield definitions - // ... - // Bits Value Description - // [0] 0 Watchpoint disabled - // 1 Watchpoint enabled. - return (debug_state.__wcr[hw_index] & 1u); +bool DNBArchMachARM::IsWatchpointEnabled(const DBG &debug_state, + uint32_t hw_index) { + // Watchpoint Control Registers, bitfield definitions + // ... + // Bits Value Description + // [0] 0 Watchpoint disabled + // 1 Watchpoint enabled. + return (debug_state.__wcr[hw_index] & 1u); } -nub_addr_t -DNBArchMachARM::GetWatchAddress(const DBG &debug_state, uint32_t hw_index) -{ - // Watchpoint Value Registers, bitfield definitions - // Bits Description - // [31:2] Watchpoint value (word address, i.e., 4-byte aligned) - // [1:0] RAZ/SBZP - return bits(debug_state.__wvr[hw_index], 31, 0); +nub_addr_t DNBArchMachARM::GetWatchAddress(const DBG &debug_state, + uint32_t hw_index) { + // Watchpoint Value Registers, bitfield definitions + // Bits Description + // [31:2] Watchpoint value (word address, i.e., 4-byte aligned) + // [1:0] RAZ/SBZP + return bits(debug_state.__wvr[hw_index], 31, 0); } //---------------------------------------------------------------------- // Register information definitions for 32 bit ARMV7. //---------------------------------------------------------------------- -enum gpr_regnums -{ - gpr_r0 = 0, - gpr_r1, - gpr_r2, - gpr_r3, - gpr_r4, - gpr_r5, - gpr_r6, - gpr_r7, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_sp, - gpr_lr, - gpr_pc, - gpr_cpsr +enum gpr_regnums { + gpr_r0 = 0, + gpr_r1, + gpr_r2, + gpr_r3, + gpr_r4, + gpr_r5, + gpr_r6, + gpr_r7, + gpr_r8, + gpr_r9, + gpr_r10, + gpr_r11, + gpr_r12, + gpr_sp, + gpr_lr, + gpr_pc, + gpr_cpsr }; -enum -{ - vfp_s0 = 0, - vfp_s1, - vfp_s2, - vfp_s3, - vfp_s4, - vfp_s5, - vfp_s6, - vfp_s7, - vfp_s8, - vfp_s9, - vfp_s10, - vfp_s11, - vfp_s12, - vfp_s13, - vfp_s14, - vfp_s15, - vfp_s16, - vfp_s17, - vfp_s18, - vfp_s19, - vfp_s20, - vfp_s21, - vfp_s22, - vfp_s23, - vfp_s24, - vfp_s25, - vfp_s26, - vfp_s27, - vfp_s28, - vfp_s29, - vfp_s30, - vfp_s31, - vfp_d0, - vfp_d1, - vfp_d2, - vfp_d3, - vfp_d4, - vfp_d5, - vfp_d6, - vfp_d7, - vfp_d8, - vfp_d9, - vfp_d10, - vfp_d11, - vfp_d12, - vfp_d13, - vfp_d14, - vfp_d15, - vfp_d16, - vfp_d17, - vfp_d18, - vfp_d19, - vfp_d20, - vfp_d21, - vfp_d22, - vfp_d23, - vfp_d24, - vfp_d25, - vfp_d26, - vfp_d27, - vfp_d28, - vfp_d29, - vfp_d30, - vfp_d31, - vfp_q0, - vfp_q1, - vfp_q2, - vfp_q3, - vfp_q4, - vfp_q5, - vfp_q6, - vfp_q7, - vfp_q8, - vfp_q9, - vfp_q10, - vfp_q11, - vfp_q12, - vfp_q13, - vfp_q14, - vfp_q15, -#if defined (__arm64__) || defined (__aarch64__) - vfp_fpsr, - vfp_fpcr, +enum { + vfp_s0 = 0, + vfp_s1, + vfp_s2, + vfp_s3, + vfp_s4, + vfp_s5, + vfp_s6, + vfp_s7, + vfp_s8, + vfp_s9, + vfp_s10, + vfp_s11, + vfp_s12, + vfp_s13, + vfp_s14, + vfp_s15, + vfp_s16, + vfp_s17, + vfp_s18, + vfp_s19, + vfp_s20, + vfp_s21, + vfp_s22, + vfp_s23, + vfp_s24, + vfp_s25, + vfp_s26, + vfp_s27, + vfp_s28, + vfp_s29, + vfp_s30, + vfp_s31, + vfp_d0, + vfp_d1, + vfp_d2, + vfp_d3, + vfp_d4, + vfp_d5, + vfp_d6, + vfp_d7, + vfp_d8, + vfp_d9, + vfp_d10, + vfp_d11, + vfp_d12, + vfp_d13, + vfp_d14, + vfp_d15, + vfp_d16, + vfp_d17, + vfp_d18, + vfp_d19, + vfp_d20, + vfp_d21, + vfp_d22, + vfp_d23, + vfp_d24, + vfp_d25, + vfp_d26, + vfp_d27, + vfp_d28, + vfp_d29, + vfp_d30, + vfp_d31, + vfp_q0, + vfp_q1, + vfp_q2, + vfp_q3, + vfp_q4, + vfp_q5, + vfp_q6, + vfp_q7, + vfp_q8, + vfp_q9, + vfp_q10, + vfp_q11, + vfp_q12, + vfp_q13, + vfp_q14, + vfp_q15, +#if defined(__arm64__) || defined(__aarch64__) + vfp_fpsr, + vfp_fpcr, #else - vfp_fpscr + vfp_fpscr #endif }; -enum -{ - exc_exception, - exc_fsr, - exc_far, +enum { + exc_exception, + exc_fsr, + exc_far, }; -#define GPR_OFFSET_IDX(idx) (offsetof (DNBArchMachARM::GPR, __r[idx])) -#define GPR_OFFSET_NAME(reg) (offsetof (DNBArchMachARM::GPR, __##reg)) +#define GPR_OFFSET_IDX(idx) (offsetof(DNBArchMachARM::GPR, __r[idx])) +#define GPR_OFFSET_NAME(reg) (offsetof(DNBArchMachARM::GPR, __##reg)) -#define EXC_OFFSET(reg) (offsetof (DNBArchMachARM::EXC, __##reg) + offsetof (DNBArchMachARM::Context, exc)) +#define EXC_OFFSET(reg) \ + (offsetof(DNBArchMachARM::EXC, __##reg) + \ + offsetof(DNBArchMachARM::Context, exc)) // These macros will auto define the register name, alt name, register size, // register offset, encoding, format and native register. This ensures that // the register state structures are defined correctly and have the correct // sizes and offsets. -#define DEFINE_GPR_IDX(idx, reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 4, GPR_OFFSET_IDX(idx), ehframe_##reg, dwarf_##reg, gen, INVALID_NUB_REGNUM, NULL, NULL} -#define DEFINE_GPR_NAME(reg, alt, gen, inval) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 4, GPR_OFFSET_NAME(reg), ehframe_##reg, dwarf_##reg, gen, INVALID_NUB_REGNUM, NULL, inval} +#define DEFINE_GPR_IDX(idx, reg, alt, gen) \ + { \ + e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 4, GPR_OFFSET_IDX(idx), \ + ehframe_##reg, dwarf_##reg, gen, INVALID_NUB_REGNUM, NULL, NULL \ + } +#define DEFINE_GPR_NAME(reg, alt, gen, inval) \ + { \ + e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 4, GPR_OFFSET_NAME(reg), \ + ehframe_##reg, dwarf_##reg, gen, INVALID_NUB_REGNUM, NULL, inval \ + } // In case we are debugging to a debug target that the ability to // change into the protected modes with folded registers (ABT, IRQ, // FIQ, SYS, USR, etc..), we should invalidate r8-r14 if the CPSR // gets modified. -const char * g_invalidate_cpsr[] = { "r8", "r9", "r10", "r11", "r12", "sp", "lr", NULL }; +const char *g_invalidate_cpsr[] = {"r8", "r9", "r10", "r11", + "r12", "sp", "lr", NULL}; // General purpose registers -const DNBRegisterInfo -DNBArchMachARM::g_gpr_registers[] = -{ - DEFINE_GPR_IDX ( 0, r0,"arg1", GENERIC_REGNUM_ARG1 ), - DEFINE_GPR_IDX ( 1, r1,"arg2", GENERIC_REGNUM_ARG2 ), - DEFINE_GPR_IDX ( 2, r2,"arg3", GENERIC_REGNUM_ARG3 ), - DEFINE_GPR_IDX ( 3, r3,"arg4", GENERIC_REGNUM_ARG4 ), - DEFINE_GPR_IDX ( 4, r4, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX ( 5, r5, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX ( 6, r6, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX ( 7, r7, "fp", GENERIC_REGNUM_FP ), - DEFINE_GPR_IDX ( 8, r8, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX ( 9, r9, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (10, r10, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (11, r11, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (12, r12, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_NAME (sp, "r13", GENERIC_REGNUM_SP, NULL), - DEFINE_GPR_NAME (lr, "r14", GENERIC_REGNUM_RA, NULL), - DEFINE_GPR_NAME (pc, "r15", GENERIC_REGNUM_PC, NULL), - DEFINE_GPR_NAME (cpsr, "flags", GENERIC_REGNUM_FLAGS, g_invalidate_cpsr) -}; - -const char *g_contained_q0 [] { "q0", NULL }; -const char *g_contained_q1 [] { "q1", NULL }; -const char *g_contained_q2 [] { "q2", NULL }; -const char *g_contained_q3 [] { "q3", NULL }; -const char *g_contained_q4 [] { "q4", NULL }; -const char *g_contained_q5 [] { "q5", NULL }; -const char *g_contained_q6 [] { "q6", NULL }; -const char *g_contained_q7 [] { "q7", NULL }; -const char *g_contained_q8 [] { "q8", NULL }; -const char *g_contained_q9 [] { "q9", NULL }; -const char *g_contained_q10[] { "q10", NULL }; -const char *g_contained_q11[] { "q11", NULL }; -const char *g_contained_q12[] { "q12", NULL }; -const char *g_contained_q13[] { "q13", NULL }; -const char *g_contained_q14[] { "q14", NULL }; -const char *g_contained_q15[] { "q15", NULL }; - -const char *g_invalidate_q0[] { "q0", "d0" , "d1" , "s0" , "s1" , "s2" , "s3" , NULL }; -const char *g_invalidate_q1[] { "q1", "d2" , "d3" , "s4" , "s5" , "s6" , "s7" , NULL }; -const char *g_invalidate_q2[] { "q2", "d4" , "d5" , "s8" , "s9" , "s10", "s11", NULL }; -const char *g_invalidate_q3[] { "q3", "d6" , "d7" , "s12", "s13", "s14", "s15", NULL }; -const char *g_invalidate_q4[] { "q4", "d8" , "d9" , "s16", "s17", "s18", "s19", NULL }; -const char *g_invalidate_q5[] { "q5", "d10", "d11", "s20", "s21", "s22", "s23", NULL }; -const char *g_invalidate_q6[] { "q6", "d12", "d13", "s24", "s25", "s26", "s27", NULL }; -const char *g_invalidate_q7[] { "q7", "d14", "d15", "s28", "s29", "s30", "s31", NULL }; -const char *g_invalidate_q8[] { "q8", "d16", "d17", NULL }; -const char *g_invalidate_q9[] { "q9", "d18", "d19", NULL }; -const char *g_invalidate_q10[] { "q10", "d20", "d21", NULL }; -const char *g_invalidate_q11[] { "q11", "d22", "d23", NULL }; -const char *g_invalidate_q12[] { "q12", "d24", "d25", NULL }; -const char *g_invalidate_q13[] { "q13", "d26", "d27", NULL }; -const char *g_invalidate_q14[] { "q14", "d28", "d29", NULL }; -const char *g_invalidate_q15[] { "q15", "d30", "d31", NULL }; - -#define VFP_S_OFFSET_IDX(idx) (((idx) % 4) * 4) // offset into q reg: 0, 4, 8, 12 -#define VFP_D_OFFSET_IDX(idx) (((idx) % 2) * 8) // offset into q reg: 0, 8 -#define VFP_Q_OFFSET_IDX(idx) (VFP_S_OFFSET_IDX ((idx) * 4)) - -#define VFP_OFFSET_NAME(reg) (offsetof (DNBArchMachARM::FPU, __##reg) + offsetof (DNBArchMachARM::Context, vfp)) +const DNBRegisterInfo DNBArchMachARM::g_gpr_registers[] = { + DEFINE_GPR_IDX(0, r0, "arg1", GENERIC_REGNUM_ARG1), + DEFINE_GPR_IDX(1, r1, "arg2", GENERIC_REGNUM_ARG2), + DEFINE_GPR_IDX(2, r2, "arg3", GENERIC_REGNUM_ARG3), + DEFINE_GPR_IDX(3, r3, "arg4", GENERIC_REGNUM_ARG4), + DEFINE_GPR_IDX(4, r4, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(5, r5, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(6, r6, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(7, r7, "fp", GENERIC_REGNUM_FP), + DEFINE_GPR_IDX(8, r8, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(9, r9, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(10, r10, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(11, r11, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(12, r12, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_NAME(sp, "r13", GENERIC_REGNUM_SP, NULL), + DEFINE_GPR_NAME(lr, "r14", GENERIC_REGNUM_RA, NULL), + DEFINE_GPR_NAME(pc, "r15", GENERIC_REGNUM_PC, NULL), + DEFINE_GPR_NAME(cpsr, "flags", GENERIC_REGNUM_FLAGS, g_invalidate_cpsr)}; + +const char *g_contained_q0[]{"q0", NULL}; +const char *g_contained_q1[]{"q1", NULL}; +const char *g_contained_q2[]{"q2", NULL}; +const char *g_contained_q3[]{"q3", NULL}; +const char *g_contained_q4[]{"q4", NULL}; +const char *g_contained_q5[]{"q5", NULL}; +const char *g_contained_q6[]{"q6", NULL}; +const char *g_contained_q7[]{"q7", NULL}; +const char *g_contained_q8[]{"q8", NULL}; +const char *g_contained_q9[]{"q9", NULL}; +const char *g_contained_q10[]{"q10", NULL}; +const char *g_contained_q11[]{"q11", NULL}; +const char *g_contained_q12[]{"q12", NULL}; +const char *g_contained_q13[]{"q13", NULL}; +const char *g_contained_q14[]{"q14", NULL}; +const char *g_contained_q15[]{"q15", NULL}; + +const char *g_invalidate_q0[]{"q0", "d0", "d1", "s0", "s1", "s2", "s3", NULL}; +const char *g_invalidate_q1[]{"q1", "d2", "d3", "s4", "s5", "s6", "s7", NULL}; +const char *g_invalidate_q2[]{"q2", "d4", "d5", "s8", "s9", "s10", "s11", NULL}; +const char *g_invalidate_q3[]{"q3", "d6", "d7", "s12", + "s13", "s14", "s15", NULL}; +const char *g_invalidate_q4[]{"q4", "d8", "d9", "s16", + "s17", "s18", "s19", NULL}; +const char *g_invalidate_q5[]{"q5", "d10", "d11", "s20", + "s21", "s22", "s23", NULL}; +const char *g_invalidate_q6[]{"q6", "d12", "d13", "s24", + "s25", "s26", "s27", NULL}; +const char *g_invalidate_q7[]{"q7", "d14", "d15", "s28", + "s29", "s30", "s31", NULL}; +const char *g_invalidate_q8[]{"q8", "d16", "d17", NULL}; +const char *g_invalidate_q9[]{"q9", "d18", "d19", NULL}; +const char *g_invalidate_q10[]{"q10", "d20", "d21", NULL}; +const char *g_invalidate_q11[]{"q11", "d22", "d23", NULL}; +const char *g_invalidate_q12[]{"q12", "d24", "d25", NULL}; +const char *g_invalidate_q13[]{"q13", "d26", "d27", NULL}; +const char *g_invalidate_q14[]{"q14", "d28", "d29", NULL}; +const char *g_invalidate_q15[]{"q15", "d30", "d31", NULL}; + +#define VFP_S_OFFSET_IDX(idx) \ + (((idx) % 4) * 4) // offset into q reg: 0, 4, 8, 12 +#define VFP_D_OFFSET_IDX(idx) (((idx) % 2) * 8) // offset into q reg: 0, 8 +#define VFP_Q_OFFSET_IDX(idx) (VFP_S_OFFSET_IDX((idx)*4)) + +#define VFP_OFFSET_NAME(reg) \ + (offsetof(DNBArchMachARM::FPU, __##reg) + \ + offsetof(DNBArchMachARM::Context, vfp)) #define FLOAT_FORMAT Float -#define DEFINE_VFP_S_IDX(idx) e_regSetVFP, vfp_s##idx, "s" #idx, NULL, IEEE754, FLOAT_FORMAT, 4, VFP_S_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_s##idx, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM -#define DEFINE_VFP_D_IDX(idx) e_regSetVFP, vfp_d##idx, "d" #idx, NULL, IEEE754, FLOAT_FORMAT, 8, VFP_D_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_d##idx, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM -#define DEFINE_VFP_Q_IDX(idx) e_regSetVFP, vfp_q##idx, "q" #idx, NULL, Vector, VectorOfUInt8, 16, VFP_Q_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_q##idx, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM +#define DEFINE_VFP_S_IDX(idx) \ + e_regSetVFP, vfp_s##idx, "s" #idx, NULL, IEEE754, FLOAT_FORMAT, 4, \ + VFP_S_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_s##idx, \ + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM +#define DEFINE_VFP_D_IDX(idx) \ + e_regSetVFP, vfp_d##idx, "d" #idx, NULL, IEEE754, FLOAT_FORMAT, 8, \ + VFP_D_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_d##idx, \ + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM +#define DEFINE_VFP_Q_IDX(idx) \ + e_regSetVFP, vfp_q##idx, "q" #idx, NULL, Vector, VectorOfUInt8, 16, \ + VFP_Q_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_q##idx, \ + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM // Floating point registers -const DNBRegisterInfo -DNBArchMachARM::g_vfp_registers[] = -{ - { DEFINE_VFP_S_IDX ( 0), g_contained_q0, g_invalidate_q0 }, - { DEFINE_VFP_S_IDX ( 1), g_contained_q0, g_invalidate_q0 }, - { DEFINE_VFP_S_IDX ( 2), g_contained_q0, g_invalidate_q0 }, - { DEFINE_VFP_S_IDX ( 3), g_contained_q0, g_invalidate_q0 }, - { DEFINE_VFP_S_IDX ( 4), g_contained_q1, g_invalidate_q1 }, - { DEFINE_VFP_S_IDX ( 5), g_contained_q1, g_invalidate_q1 }, - { DEFINE_VFP_S_IDX ( 6), g_contained_q1, g_invalidate_q1 }, - { DEFINE_VFP_S_IDX ( 7), g_contained_q1, g_invalidate_q1 }, - { DEFINE_VFP_S_IDX ( 8), g_contained_q2, g_invalidate_q2 }, - { DEFINE_VFP_S_IDX ( 9), g_contained_q2, g_invalidate_q2 }, - { DEFINE_VFP_S_IDX (10), g_contained_q2, g_invalidate_q2 }, - { DEFINE_VFP_S_IDX (11), g_contained_q2, g_invalidate_q2 }, - { DEFINE_VFP_S_IDX (12), g_contained_q3, g_invalidate_q3 }, - { DEFINE_VFP_S_IDX (13), g_contained_q3, g_invalidate_q3 }, - { DEFINE_VFP_S_IDX (14), g_contained_q3, g_invalidate_q3 }, - { DEFINE_VFP_S_IDX (15), g_contained_q3, g_invalidate_q3 }, - { DEFINE_VFP_S_IDX (16), g_contained_q4, g_invalidate_q4 }, - { DEFINE_VFP_S_IDX (17), g_contained_q4, g_invalidate_q4 }, - { DEFINE_VFP_S_IDX (18), g_contained_q4, g_invalidate_q4 }, - { DEFINE_VFP_S_IDX (19), g_contained_q4, g_invalidate_q4 }, - { DEFINE_VFP_S_IDX (20), g_contained_q5, g_invalidate_q5 }, - { DEFINE_VFP_S_IDX (21), g_contained_q5, g_invalidate_q5 }, - { DEFINE_VFP_S_IDX (22), g_contained_q5, g_invalidate_q5 }, - { DEFINE_VFP_S_IDX (23), g_contained_q5, g_invalidate_q5 }, - { DEFINE_VFP_S_IDX (24), g_contained_q6, g_invalidate_q6 }, - { DEFINE_VFP_S_IDX (25), g_contained_q6, g_invalidate_q6 }, - { DEFINE_VFP_S_IDX (26), g_contained_q6, g_invalidate_q6 }, - { DEFINE_VFP_S_IDX (27), g_contained_q6, g_invalidate_q6 }, - { DEFINE_VFP_S_IDX (28), g_contained_q7, g_invalidate_q7 }, - { DEFINE_VFP_S_IDX (29), g_contained_q7, g_invalidate_q7 }, - { DEFINE_VFP_S_IDX (30), g_contained_q7, g_invalidate_q7 }, - { DEFINE_VFP_S_IDX (31), g_contained_q7, g_invalidate_q7 }, - - { DEFINE_VFP_D_IDX (0), g_contained_q0, g_invalidate_q0 }, - { DEFINE_VFP_D_IDX (1), g_contained_q0, g_invalidate_q0 }, - { DEFINE_VFP_D_IDX (2), g_contained_q1, g_invalidate_q1 }, - { DEFINE_VFP_D_IDX (3), g_contained_q1, g_invalidate_q1 }, - { DEFINE_VFP_D_IDX (4), g_contained_q2, g_invalidate_q2 }, - { DEFINE_VFP_D_IDX (5), g_contained_q2, g_invalidate_q2 }, - { DEFINE_VFP_D_IDX (6), g_contained_q3, g_invalidate_q3 }, - { DEFINE_VFP_D_IDX (7), g_contained_q3, g_invalidate_q3 }, - { DEFINE_VFP_D_IDX (8), g_contained_q4, g_invalidate_q4 }, - { DEFINE_VFP_D_IDX (9), g_contained_q4, g_invalidate_q4 }, - { DEFINE_VFP_D_IDX (10), g_contained_q5, g_invalidate_q5 }, - { DEFINE_VFP_D_IDX (11), g_contained_q5, g_invalidate_q5 }, - { DEFINE_VFP_D_IDX (12), g_contained_q6, g_invalidate_q6 }, - { DEFINE_VFP_D_IDX (13), g_contained_q6, g_invalidate_q6 }, - { DEFINE_VFP_D_IDX (14), g_contained_q7, g_invalidate_q7 }, - { DEFINE_VFP_D_IDX (15), g_contained_q7, g_invalidate_q7 }, - { DEFINE_VFP_D_IDX (16), g_contained_q8, g_invalidate_q8 }, - { DEFINE_VFP_D_IDX (17), g_contained_q8, g_invalidate_q8 }, - { DEFINE_VFP_D_IDX (18), g_contained_q9, g_invalidate_q9 }, - { DEFINE_VFP_D_IDX (19), g_contained_q9, g_invalidate_q9 }, - { DEFINE_VFP_D_IDX (20), g_contained_q10, g_invalidate_q10 }, - { DEFINE_VFP_D_IDX (21), g_contained_q10, g_invalidate_q10 }, - { DEFINE_VFP_D_IDX (22), g_contained_q11, g_invalidate_q11 }, - { DEFINE_VFP_D_IDX (23), g_contained_q11, g_invalidate_q11 }, - { DEFINE_VFP_D_IDX (24), g_contained_q12, g_invalidate_q12 }, - { DEFINE_VFP_D_IDX (25), g_contained_q12, g_invalidate_q12 }, - { DEFINE_VFP_D_IDX (26), g_contained_q13, g_invalidate_q13 }, - { DEFINE_VFP_D_IDX (27), g_contained_q13, g_invalidate_q13 }, - { DEFINE_VFP_D_IDX (28), g_contained_q14, g_invalidate_q14 }, - { DEFINE_VFP_D_IDX (29), g_contained_q14, g_invalidate_q14 }, - { DEFINE_VFP_D_IDX (30), g_contained_q15, g_invalidate_q15 }, - { DEFINE_VFP_D_IDX (31), g_contained_q15, g_invalidate_q15 }, - - { DEFINE_VFP_Q_IDX (0), NULL, g_invalidate_q0 }, - { DEFINE_VFP_Q_IDX (1), NULL, g_invalidate_q1 }, - { DEFINE_VFP_Q_IDX (2), NULL, g_invalidate_q2 }, - { DEFINE_VFP_Q_IDX (3), NULL, g_invalidate_q3 }, - { DEFINE_VFP_Q_IDX (4), NULL, g_invalidate_q4 }, - { DEFINE_VFP_Q_IDX (5), NULL, g_invalidate_q5 }, - { DEFINE_VFP_Q_IDX (6), NULL, g_invalidate_q6 }, - { DEFINE_VFP_Q_IDX (7), NULL, g_invalidate_q7 }, - { DEFINE_VFP_Q_IDX (8), NULL, g_invalidate_q8 }, - { DEFINE_VFP_Q_IDX (9), NULL, g_invalidate_q9 }, - { DEFINE_VFP_Q_IDX (10), NULL, g_invalidate_q10 }, - { DEFINE_VFP_Q_IDX (11), NULL, g_invalidate_q11 }, - { DEFINE_VFP_Q_IDX (12), NULL, g_invalidate_q12 }, - { DEFINE_VFP_Q_IDX (13), NULL, g_invalidate_q13 }, - { DEFINE_VFP_Q_IDX (14), NULL, g_invalidate_q14 }, - { DEFINE_VFP_Q_IDX (15), NULL, g_invalidate_q15 }, - -#if defined (__arm64__) || defined (__aarch64__) - { e_regSetVFP, vfp_fpsr, "fpsr", NULL, Uint, Hex, 4, VFP_OFFSET_NAME(fpsr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, - { e_regSetVFP, vfp_fpcr, "fpcr", NULL, Uint, Hex, 4, VFP_OFFSET_NAME(fpcr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL } +const DNBRegisterInfo DNBArchMachARM::g_vfp_registers[] = { + {DEFINE_VFP_S_IDX(0), g_contained_q0, g_invalidate_q0}, + {DEFINE_VFP_S_IDX(1), g_contained_q0, g_invalidate_q0}, + {DEFINE_VFP_S_IDX(2), g_contained_q0, g_invalidate_q0}, + {DEFINE_VFP_S_IDX(3), g_contained_q0, g_invalidate_q0}, + {DEFINE_VFP_S_IDX(4), g_contained_q1, g_invalidate_q1}, + {DEFINE_VFP_S_IDX(5), g_contained_q1, g_invalidate_q1}, + {DEFINE_VFP_S_IDX(6), g_contained_q1, g_invalidate_q1}, + {DEFINE_VFP_S_IDX(7), g_contained_q1, g_invalidate_q1}, + {DEFINE_VFP_S_IDX(8), g_contained_q2, g_invalidate_q2}, + {DEFINE_VFP_S_IDX(9), g_contained_q2, g_invalidate_q2}, + {DEFINE_VFP_S_IDX(10), g_contained_q2, g_invalidate_q2}, + {DEFINE_VFP_S_IDX(11), g_contained_q2, g_invalidate_q2}, + {DEFINE_VFP_S_IDX(12), g_contained_q3, g_invalidate_q3}, + {DEFINE_VFP_S_IDX(13), g_contained_q3, g_invalidate_q3}, + {DEFINE_VFP_S_IDX(14), g_contained_q3, g_invalidate_q3}, + {DEFINE_VFP_S_IDX(15), g_contained_q3, g_invalidate_q3}, + {DEFINE_VFP_S_IDX(16), g_contained_q4, g_invalidate_q4}, + {DEFINE_VFP_S_IDX(17), g_contained_q4, g_invalidate_q4}, + {DEFINE_VFP_S_IDX(18), g_contained_q4, g_invalidate_q4}, + {DEFINE_VFP_S_IDX(19), g_contained_q4, g_invalidate_q4}, + {DEFINE_VFP_S_IDX(20), g_contained_q5, g_invalidate_q5}, + {DEFINE_VFP_S_IDX(21), g_contained_q5, g_invalidate_q5}, + {DEFINE_VFP_S_IDX(22), g_contained_q5, g_invalidate_q5}, + {DEFINE_VFP_S_IDX(23), g_contained_q5, g_invalidate_q5}, + {DEFINE_VFP_S_IDX(24), g_contained_q6, g_invalidate_q6}, + {DEFINE_VFP_S_IDX(25), g_contained_q6, g_invalidate_q6}, + {DEFINE_VFP_S_IDX(26), g_contained_q6, g_invalidate_q6}, + {DEFINE_VFP_S_IDX(27), g_contained_q6, g_invalidate_q6}, + {DEFINE_VFP_S_IDX(28), g_contained_q7, g_invalidate_q7}, + {DEFINE_VFP_S_IDX(29), g_contained_q7, g_invalidate_q7}, + {DEFINE_VFP_S_IDX(30), g_contained_q7, g_invalidate_q7}, + {DEFINE_VFP_S_IDX(31), g_contained_q7, g_invalidate_q7}, + + {DEFINE_VFP_D_IDX(0), g_contained_q0, g_invalidate_q0}, + {DEFINE_VFP_D_IDX(1), g_contained_q0, g_invalidate_q0}, + {DEFINE_VFP_D_IDX(2), g_contained_q1, g_invalidate_q1}, + {DEFINE_VFP_D_IDX(3), g_contained_q1, g_invalidate_q1}, + {DEFINE_VFP_D_IDX(4), g_contained_q2, g_invalidate_q2}, + {DEFINE_VFP_D_IDX(5), g_contained_q2, g_invalidate_q2}, + {DEFINE_VFP_D_IDX(6), g_contained_q3, g_invalidate_q3}, + {DEFINE_VFP_D_IDX(7), g_contained_q3, g_invalidate_q3}, + {DEFINE_VFP_D_IDX(8), g_contained_q4, g_invalidate_q4}, + {DEFINE_VFP_D_IDX(9), g_contained_q4, g_invalidate_q4}, + {DEFINE_VFP_D_IDX(10), g_contained_q5, g_invalidate_q5}, + {DEFINE_VFP_D_IDX(11), g_contained_q5, g_invalidate_q5}, + {DEFINE_VFP_D_IDX(12), g_contained_q6, g_invalidate_q6}, + {DEFINE_VFP_D_IDX(13), g_contained_q6, g_invalidate_q6}, + {DEFINE_VFP_D_IDX(14), g_contained_q7, g_invalidate_q7}, + {DEFINE_VFP_D_IDX(15), g_contained_q7, g_invalidate_q7}, + {DEFINE_VFP_D_IDX(16), g_contained_q8, g_invalidate_q8}, + {DEFINE_VFP_D_IDX(17), g_contained_q8, g_invalidate_q8}, + {DEFINE_VFP_D_IDX(18), g_contained_q9, g_invalidate_q9}, + {DEFINE_VFP_D_IDX(19), g_contained_q9, g_invalidate_q9}, + {DEFINE_VFP_D_IDX(20), g_contained_q10, g_invalidate_q10}, + {DEFINE_VFP_D_IDX(21), g_contained_q10, g_invalidate_q10}, + {DEFINE_VFP_D_IDX(22), g_contained_q11, g_invalidate_q11}, + {DEFINE_VFP_D_IDX(23), g_contained_q11, g_invalidate_q11}, + {DEFINE_VFP_D_IDX(24), g_contained_q12, g_invalidate_q12}, + {DEFINE_VFP_D_IDX(25), g_contained_q12, g_invalidate_q12}, + {DEFINE_VFP_D_IDX(26), g_contained_q13, g_invalidate_q13}, + {DEFINE_VFP_D_IDX(27), g_contained_q13, g_invalidate_q13}, + {DEFINE_VFP_D_IDX(28), g_contained_q14, g_invalidate_q14}, + {DEFINE_VFP_D_IDX(29), g_contained_q14, g_invalidate_q14}, + {DEFINE_VFP_D_IDX(30), g_contained_q15, g_invalidate_q15}, + {DEFINE_VFP_D_IDX(31), g_contained_q15, g_invalidate_q15}, + + {DEFINE_VFP_Q_IDX(0), NULL, g_invalidate_q0}, + {DEFINE_VFP_Q_IDX(1), NULL, g_invalidate_q1}, + {DEFINE_VFP_Q_IDX(2), NULL, g_invalidate_q2}, + {DEFINE_VFP_Q_IDX(3), NULL, g_invalidate_q3}, + {DEFINE_VFP_Q_IDX(4), NULL, g_invalidate_q4}, + {DEFINE_VFP_Q_IDX(5), NULL, g_invalidate_q5}, + {DEFINE_VFP_Q_IDX(6), NULL, g_invalidate_q6}, + {DEFINE_VFP_Q_IDX(7), NULL, g_invalidate_q7}, + {DEFINE_VFP_Q_IDX(8), NULL, g_invalidate_q8}, + {DEFINE_VFP_Q_IDX(9), NULL, g_invalidate_q9}, + {DEFINE_VFP_Q_IDX(10), NULL, g_invalidate_q10}, + {DEFINE_VFP_Q_IDX(11), NULL, g_invalidate_q11}, + {DEFINE_VFP_Q_IDX(12), NULL, g_invalidate_q12}, + {DEFINE_VFP_Q_IDX(13), NULL, g_invalidate_q13}, + {DEFINE_VFP_Q_IDX(14), NULL, g_invalidate_q14}, + {DEFINE_VFP_Q_IDX(15), NULL, g_invalidate_q15}, + +#if defined(__arm64__) || defined(__aarch64__) + {e_regSetVFP, vfp_fpsr, "fpsr", NULL, Uint, Hex, 4, VFP_OFFSET_NAME(fpsr), + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetVFP, vfp_fpcr, "fpcr", NULL, Uint, Hex, 4, VFP_OFFSET_NAME(fpcr), + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, NULL, NULL} #else - { e_regSetVFP, vfp_fpscr, "fpscr", NULL, Uint, Hex, 4, VFP_OFFSET_NAME(fpscr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL } + {e_regSetVFP, vfp_fpscr, "fpscr", NULL, Uint, Hex, 4, + VFP_OFFSET_NAME(fpscr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL} #endif }; // Exception registers -const DNBRegisterInfo -DNBArchMachARM::g_exc_registers[] = -{ - { e_regSetVFP, exc_exception , "exception" , NULL, Uint, Hex, 4, EXC_OFFSET(exception) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM }, - { e_regSetVFP, exc_fsr , "fsr" , NULL, Uint, Hex, 4, EXC_OFFSET(fsr) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM }, - { e_regSetVFP, exc_far , "far" , NULL, Uint, Hex, 4, EXC_OFFSET(far) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM } -}; +const DNBRegisterInfo DNBArchMachARM::g_exc_registers[] = { + {e_regSetVFP, exc_exception, "exception", NULL, Uint, Hex, 4, + EXC_OFFSET(exception), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM}, + {e_regSetVFP, exc_fsr, "fsr", NULL, Uint, Hex, 4, EXC_OFFSET(fsr), + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM}, + {e_regSetVFP, exc_far, "far", NULL, Uint, Hex, 4, EXC_OFFSET(far), + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM}}; // Number of registers in each register set -const size_t DNBArchMachARM::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo); -const size_t DNBArchMachARM::k_num_vfp_registers = sizeof(g_vfp_registers)/sizeof(DNBRegisterInfo); -const size_t DNBArchMachARM::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo); -const size_t DNBArchMachARM::k_num_all_registers = k_num_gpr_registers + k_num_vfp_registers + k_num_exc_registers; +const size_t DNBArchMachARM::k_num_gpr_registers = + sizeof(g_gpr_registers) / sizeof(DNBRegisterInfo); +const size_t DNBArchMachARM::k_num_vfp_registers = + sizeof(g_vfp_registers) / sizeof(DNBRegisterInfo); +const size_t DNBArchMachARM::k_num_exc_registers = + sizeof(g_exc_registers) / sizeof(DNBRegisterInfo); +const size_t DNBArchMachARM::k_num_all_registers = + k_num_gpr_registers + k_num_vfp_registers + k_num_exc_registers; //---------------------------------------------------------------------- // Register set definitions. The first definitions at register set index // of zero is for all registers, followed by other registers sets. The // register information for the all register set need not be filled in. //---------------------------------------------------------------------- -const DNBRegisterSetInfo -DNBArchMachARM::g_reg_sets[] = -{ - { "ARM Registers", NULL, k_num_all_registers }, - { "General Purpose Registers", g_gpr_registers, k_num_gpr_registers }, - { "Floating Point Registers", g_vfp_registers, k_num_vfp_registers }, - { "Exception State Registers", g_exc_registers, k_num_exc_registers } -}; +const DNBRegisterSetInfo DNBArchMachARM::g_reg_sets[] = { + {"ARM Registers", NULL, k_num_all_registers}, + {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers}, + {"Floating Point Registers", g_vfp_registers, k_num_vfp_registers}, + {"Exception State Registers", g_exc_registers, k_num_exc_registers}}; // Total number of register sets for this architecture -const size_t DNBArchMachARM::k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo); - +const size_t DNBArchMachARM::k_num_register_sets = + sizeof(g_reg_sets) / sizeof(DNBRegisterSetInfo); const DNBRegisterSetInfo * -DNBArchMachARM::GetRegisterSetInfo(nub_size_t *num_reg_sets) -{ - *num_reg_sets = k_num_register_sets; - return g_reg_sets; +DNBArchMachARM::GetRegisterSetInfo(nub_size_t *num_reg_sets) { + *num_reg_sets = k_num_register_sets; + return g_reg_sets; } -bool -DNBArchMachARM::GetRegisterValue(uint32_t set, uint32_t reg, DNBRegisterValue *value) -{ - if (set == REGISTER_SET_GENERIC) - { - switch (reg) - { - case GENERIC_REGNUM_PC: // Program Counter - set = e_regSetGPR; - reg = gpr_pc; - break; - - case GENERIC_REGNUM_SP: // Stack Pointer - set = e_regSetGPR; - reg = gpr_sp; - break; - - case GENERIC_REGNUM_FP: // Frame Pointer - set = e_regSetGPR; - reg = gpr_r7; // is this the right reg? - break; - - case GENERIC_REGNUM_RA: // Return Address - set = e_regSetGPR; - reg = gpr_lr; - break; - - case GENERIC_REGNUM_FLAGS: // Processor flags register - set = e_regSetGPR; - reg = gpr_cpsr; - break; - - default: - return false; - } +bool DNBArchMachARM::GetRegisterValue(uint32_t set, uint32_t reg, + DNBRegisterValue *value) { + if (set == REGISTER_SET_GENERIC) { + switch (reg) { + case GENERIC_REGNUM_PC: // Program Counter + set = e_regSetGPR; + reg = gpr_pc; + break; + + case GENERIC_REGNUM_SP: // Stack Pointer + set = e_regSetGPR; + reg = gpr_sp; + break; + + case GENERIC_REGNUM_FP: // Frame Pointer + set = e_regSetGPR; + reg = gpr_r7; // is this the right reg? + break; + + case GENERIC_REGNUM_RA: // Return Address + set = e_regSetGPR; + reg = gpr_lr; + break; + + case GENERIC_REGNUM_FLAGS: // Processor flags register + set = e_regSetGPR; + reg = gpr_cpsr; + break; + + default: + return false; } + } + + if (GetRegisterState(set, false) != KERN_SUCCESS) + return false; - if (GetRegisterState(set, false) != KERN_SUCCESS) - return false; - - const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); - if (regInfo) - { - value->info = *regInfo; - switch (set) - { - case e_regSetGPR: - if (reg < k_num_gpr_registers) - { - value->value.uint32 = m_state.context.gpr.__r[reg]; - return true; - } - break; - - case e_regSetVFP: - // "reg" is an index into the floating point register set at this point. - // We need to translate it up so entry 0 in the fp reg set is the same as vfp_s0 - // in the enumerated values for case statement below. - if (reg >= vfp_s0 && reg <= vfp_s31) - { -#if defined (__arm64__) || defined (__aarch64__) - uint32_t *s_reg = ((uint32_t *) &m_state.context.vfp.__v[0]) + (reg - vfp_s0); - memcpy (&value->value.v_uint8, s_reg, 4); + const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); + if (regInfo) { + value->info = *regInfo; + switch (set) { + case e_regSetGPR: + if (reg < k_num_gpr_registers) { + value->value.uint32 = m_state.context.gpr.__r[reg]; + return true; + } + break; + + case e_regSetVFP: + // "reg" is an index into the floating point register set at this point. + // We need to translate it up so entry 0 in the fp reg set is the same as + // vfp_s0 + // in the enumerated values for case statement below. + if (reg >= vfp_s0 && reg <= vfp_s31) { +#if defined(__arm64__) || defined(__aarch64__) + uint32_t *s_reg = + ((uint32_t *)&m_state.context.vfp.__v[0]) + (reg - vfp_s0); + memcpy(&value->value.v_uint8, s_reg, 4); #else - value->value.uint32 = m_state.context.vfp.__r[reg]; + value->value.uint32 = m_state.context.vfp.__r[reg]; #endif - return true; - } - else if (reg >= vfp_d0 && reg <= vfp_d31) - { -#if defined (__arm64__) || defined (__aarch64__) - uint64_t *d_reg = ((uint64_t *) &m_state.context.vfp.__v[0]) + (reg - vfp_d0); - memcpy (&value->value.v_uint8, d_reg, 8); + return true; + } else if (reg >= vfp_d0 && reg <= vfp_d31) { +#if defined(__arm64__) || defined(__aarch64__) + uint64_t *d_reg = + ((uint64_t *)&m_state.context.vfp.__v[0]) + (reg - vfp_d0); + memcpy(&value->value.v_uint8, d_reg, 8); #else - uint32_t d_reg_idx = reg - vfp_d0; - uint32_t s_reg_idx = d_reg_idx * 2; - value->value.v_sint32[0] = m_state.context.vfp.__r[s_reg_idx + 0]; - value->value.v_sint32[1] = m_state.context.vfp.__r[s_reg_idx + 1]; + uint32_t d_reg_idx = reg - vfp_d0; + uint32_t s_reg_idx = d_reg_idx * 2; + value->value.v_sint32[0] = m_state.context.vfp.__r[s_reg_idx + 0]; + value->value.v_sint32[1] = m_state.context.vfp.__r[s_reg_idx + 1]; #endif - return true; - } - else if (reg >= vfp_q0 && reg <= vfp_q15) - { -#if defined (__arm64__) || defined (__aarch64__) - memcpy (&value->value.v_uint8, (uint8_t *) &m_state.context.vfp.__v[reg - vfp_q0], 16); + return true; + } else if (reg >= vfp_q0 && reg <= vfp_q15) { +#if defined(__arm64__) || defined(__aarch64__) + memcpy(&value->value.v_uint8, + (uint8_t *)&m_state.context.vfp.__v[reg - vfp_q0], 16); #else - uint32_t s_reg_idx = (reg - vfp_q0) * 4; - memcpy (&value->value.v_uint8, (uint8_t *) &m_state.context.vfp.__r[s_reg_idx], 16); + uint32_t s_reg_idx = (reg - vfp_q0) * 4; + memcpy(&value->value.v_uint8, + (uint8_t *)&m_state.context.vfp.__r[s_reg_idx], 16); #endif - return true; - } -#if defined (__arm64__) || defined (__aarch64__) - else if (reg == vfp_fpsr) - { - value->value.uint32 = m_state.context.vfp.__fpsr; - return true; - } - else if (reg == vfp_fpcr) - { - value->value.uint32 = m_state.context.vfp.__fpcr; - return true; - } + return true; + } +#if defined(__arm64__) || defined(__aarch64__) + else if (reg == vfp_fpsr) { + value->value.uint32 = m_state.context.vfp.__fpsr; + return true; + } else if (reg == vfp_fpcr) { + value->value.uint32 = m_state.context.vfp.__fpcr; + return true; + } #else - else if (reg == vfp_fpscr) - { - value->value.uint32 = m_state.context.vfp.__fpscr; - return true; - } + else if (reg == vfp_fpscr) { + value->value.uint32 = m_state.context.vfp.__fpscr; + return true; + } #endif - break; - - case e_regSetEXC: - if (reg < k_num_exc_registers) - { - value->value.uint32 = (&m_state.context.exc.__exception)[reg]; - return true; - } - break; - } + break; + + case e_regSetEXC: + if (reg < k_num_exc_registers) { + value->value.uint32 = (&m_state.context.exc.__exception)[reg]; + return true; + } + break; } - return false; + } + return false; } -bool -DNBArchMachARM::SetRegisterValue(uint32_t set, uint32_t reg, const DNBRegisterValue *value) -{ - if (set == REGISTER_SET_GENERIC) - { - switch (reg) - { - case GENERIC_REGNUM_PC: // Program Counter - set = e_regSetGPR; - reg = gpr_pc; - break; - - case GENERIC_REGNUM_SP: // Stack Pointer - set = e_regSetGPR; - reg = gpr_sp; - break; - - case GENERIC_REGNUM_FP: // Frame Pointer - set = e_regSetGPR; - reg = gpr_r7; - break; - - case GENERIC_REGNUM_RA: // Return Address - set = e_regSetGPR; - reg = gpr_lr; - break; - - case GENERIC_REGNUM_FLAGS: // Processor flags register - set = e_regSetGPR; - reg = gpr_cpsr; - break; - - default: - return false; - } +bool DNBArchMachARM::SetRegisterValue(uint32_t set, uint32_t reg, + const DNBRegisterValue *value) { + if (set == REGISTER_SET_GENERIC) { + switch (reg) { + case GENERIC_REGNUM_PC: // Program Counter + set = e_regSetGPR; + reg = gpr_pc; + break; + + case GENERIC_REGNUM_SP: // Stack Pointer + set = e_regSetGPR; + reg = gpr_sp; + break; + + case GENERIC_REGNUM_FP: // Frame Pointer + set = e_regSetGPR; + reg = gpr_r7; + break; + + case GENERIC_REGNUM_RA: // Return Address + set = e_regSetGPR; + reg = gpr_lr; + break; + + case GENERIC_REGNUM_FLAGS: // Processor flags register + set = e_regSetGPR; + reg = gpr_cpsr; + break; + + default: + return false; } + } - if (GetRegisterState(set, false) != KERN_SUCCESS) - return false; - - bool success = false; - const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); - if (regInfo) - { - switch (set) - { - case e_regSetGPR: - if (reg < k_num_gpr_registers) - { - m_state.context.gpr.__r[reg] = value->value.uint32; - success = true; - } - break; - - case e_regSetVFP: - // "reg" is an index into the floating point register set at this point. - // We need to translate it up so entry 0 in the fp reg set is the same as vfp_s0 - // in the enumerated values for case statement below. - if (reg >= vfp_s0 && reg <= vfp_s31) - { -#if defined (__arm64__) || defined (__aarch64__) - uint32_t *s_reg = ((uint32_t *) &m_state.context.vfp.__v[0]) + (reg - vfp_s0); - memcpy (s_reg, &value->value.v_uint8, 4); + if (GetRegisterState(set, false) != KERN_SUCCESS) + return false; + + bool success = false; + const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); + if (regInfo) { + switch (set) { + case e_regSetGPR: + if (reg < k_num_gpr_registers) { + m_state.context.gpr.__r[reg] = value->value.uint32; + success = true; + } + break; + + case e_regSetVFP: + // "reg" is an index into the floating point register set at this point. + // We need to translate it up so entry 0 in the fp reg set is the same as + // vfp_s0 + // in the enumerated values for case statement below. + if (reg >= vfp_s0 && reg <= vfp_s31) { +#if defined(__arm64__) || defined(__aarch64__) + uint32_t *s_reg = + ((uint32_t *)&m_state.context.vfp.__v[0]) + (reg - vfp_s0); + memcpy(s_reg, &value->value.v_uint8, 4); #else - m_state.context.vfp.__r[reg] = value->value.uint32; + m_state.context.vfp.__r[reg] = value->value.uint32; #endif - success = true; - } - else if (reg >= vfp_d0 && reg <= vfp_d31) - { -#if defined (__arm64__) || defined (__aarch64__) - uint64_t *d_reg = ((uint64_t *) &m_state.context.vfp.__v[0]) + (reg - vfp_d0); - memcpy (d_reg, &value->value.v_uint8, 8); + success = true; + } else if (reg >= vfp_d0 && reg <= vfp_d31) { +#if defined(__arm64__) || defined(__aarch64__) + uint64_t *d_reg = + ((uint64_t *)&m_state.context.vfp.__v[0]) + (reg - vfp_d0); + memcpy(d_reg, &value->value.v_uint8, 8); #else - uint32_t d_reg_idx = reg - vfp_d0; - uint32_t s_reg_idx = d_reg_idx * 2; - m_state.context.vfp.__r[s_reg_idx + 0] = value->value.v_sint32[0]; - m_state.context.vfp.__r[s_reg_idx + 1] = value->value.v_sint32[1]; + uint32_t d_reg_idx = reg - vfp_d0; + uint32_t s_reg_idx = d_reg_idx * 2; + m_state.context.vfp.__r[s_reg_idx + 0] = value->value.v_sint32[0]; + m_state.context.vfp.__r[s_reg_idx + 1] = value->value.v_sint32[1]; #endif - success = true; - } - else if (reg >= vfp_q0 && reg <= vfp_q15) - { -#if defined (__arm64__) || defined (__aarch64__) - memcpy ((uint8_t *) &m_state.context.vfp.__v[reg - vfp_q0], &value->value.v_uint8, 16); + success = true; + } else if (reg >= vfp_q0 && reg <= vfp_q15) { +#if defined(__arm64__) || defined(__aarch64__) + memcpy((uint8_t *)&m_state.context.vfp.__v[reg - vfp_q0], + &value->value.v_uint8, 16); #else - uint32_t s_reg_idx = (reg - vfp_q0) * 4; - memcpy ((uint8_t *) &m_state.context.vfp.__r[s_reg_idx], &value->value.v_uint8, 16); + uint32_t s_reg_idx = (reg - vfp_q0) * 4; + memcpy((uint8_t *)&m_state.context.vfp.__r[s_reg_idx], + &value->value.v_uint8, 16); #endif - success = true; - } -#if defined (__arm64__) || defined (__aarch64__) - else if (reg == vfp_fpsr) - { - m_state.context.vfp.__fpsr = value->value.uint32; - success = true; - } - else if (reg == vfp_fpcr) - { - m_state.context.vfp.__fpcr = value->value.uint32; - success = true; - } + success = true; + } +#if defined(__arm64__) || defined(__aarch64__) + else if (reg == vfp_fpsr) { + m_state.context.vfp.__fpsr = value->value.uint32; + success = true; + } else if (reg == vfp_fpcr) { + m_state.context.vfp.__fpcr = value->value.uint32; + success = true; + } #else - else if (reg == vfp_fpscr) - { - m_state.context.vfp.__fpscr = value->value.uint32; - success = true; - } + else if (reg == vfp_fpscr) { + m_state.context.vfp.__fpscr = value->value.uint32; + success = true; + } #endif - break; - - case e_regSetEXC: - if (reg < k_num_exc_registers) - { - (&m_state.context.exc.__exception)[reg] = value->value.uint32; - success = true; - } - break; - } - + break; + + case e_regSetEXC: + if (reg < k_num_exc_registers) { + (&m_state.context.exc.__exception)[reg] = value->value.uint32; + success = true; + } + break; } - if (success) - return SetRegisterState(set) == KERN_SUCCESS; - return false; + } + if (success) + return SetRegisterState(set) == KERN_SUCCESS; + return false; } -kern_return_t -DNBArchMachARM::GetRegisterState(int set, bool force) -{ - switch (set) - { - case e_regSetALL: return GetGPRState(force) | - GetVFPState(force) | - GetEXCState(force) | - GetDBGState(force); - case e_regSetGPR: return GetGPRState(force); - case e_regSetVFP: return GetVFPState(force); - case e_regSetEXC: return GetEXCState(force); - case e_regSetDBG: return GetDBGState(force); - default: break; - } - return KERN_INVALID_ARGUMENT; +kern_return_t DNBArchMachARM::GetRegisterState(int set, bool force) { + switch (set) { + case e_regSetALL: + return GetGPRState(force) | GetVFPState(force) | GetEXCState(force) | + GetDBGState(force); + case e_regSetGPR: + return GetGPRState(force); + case e_regSetVFP: + return GetVFPState(force); + case e_regSetEXC: + return GetEXCState(force); + case e_regSetDBG: + return GetDBGState(force); + default: + break; + } + return KERN_INVALID_ARGUMENT; } -kern_return_t -DNBArchMachARM::SetRegisterState(int set) -{ - // Make sure we have a valid context to set. - kern_return_t err = GetRegisterState(set, false); - if (err != KERN_SUCCESS) - return err; - - switch (set) - { - case e_regSetALL: return SetGPRState() | - SetVFPState() | - SetEXCState() | - SetDBGState(false); - case e_regSetGPR: return SetGPRState(); - case e_regSetVFP: return SetVFPState(); - case e_regSetEXC: return SetEXCState(); - case e_regSetDBG: return SetDBGState(false); - default: break; - } - return KERN_INVALID_ARGUMENT; +kern_return_t DNBArchMachARM::SetRegisterState(int set) { + // Make sure we have a valid context to set. + kern_return_t err = GetRegisterState(set, false); + if (err != KERN_SUCCESS) + return err; + + switch (set) { + case e_regSetALL: + return SetGPRState() | SetVFPState() | SetEXCState() | SetDBGState(false); + case e_regSetGPR: + return SetGPRState(); + case e_regSetVFP: + return SetVFPState(); + case e_regSetEXC: + return SetEXCState(); + case e_regSetDBG: + return SetDBGState(false); + default: + break; + } + return KERN_INVALID_ARGUMENT; } -bool -DNBArchMachARM::RegisterSetStateIsValid (int set) const -{ - return m_state.RegsAreValid(set); +bool DNBArchMachARM::RegisterSetStateIsValid(int set) const { + return m_state.RegsAreValid(set); } - -nub_size_t -DNBArchMachARM::GetRegisterContext (void *buf, nub_size_t buf_len) -{ - nub_size_t size = sizeof (m_state.context.gpr) + - sizeof (m_state.context.vfp) + - sizeof (m_state.context.exc); - - if (buf && buf_len) - { - if (size > buf_len) - size = buf_len; - - bool force = false; - if (GetGPRState(force) | GetVFPState(force) | GetEXCState(force)) - return 0; - - // Copy each struct individually to avoid any padding that might be between the structs in m_state.context - uint8_t *p = (uint8_t *)buf; - ::memcpy (p, &m_state.context.gpr, sizeof(m_state.context.gpr)); - p += sizeof(m_state.context.gpr); - ::memcpy (p, &m_state.context.vfp, sizeof(m_state.context.vfp)); - p += sizeof(m_state.context.vfp); - ::memcpy (p, &m_state.context.exc, sizeof(m_state.context.exc)); - p += sizeof(m_state.context.exc); - - size_t bytes_written = p - (uint8_t *)buf; - UNUSED_IF_ASSERT_DISABLED(bytes_written); - assert (bytes_written == size); - - } - DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::GetRegisterContext (buf = %p, len = %llu) => %llu", buf, (uint64_t)buf_len, (uint64_t)size); - // Return the size of the register context even if NULL was passed in - return size; +nub_size_t DNBArchMachARM::GetRegisterContext(void *buf, nub_size_t buf_len) { + nub_size_t size = sizeof(m_state.context.gpr) + sizeof(m_state.context.vfp) + + sizeof(m_state.context.exc); + + if (buf && buf_len) { + if (size > buf_len) + size = buf_len; + + bool force = false; + if (GetGPRState(force) | GetVFPState(force) | GetEXCState(force)) + return 0; + + // Copy each struct individually to avoid any padding that might be between + // the structs in m_state.context + uint8_t *p = (uint8_t *)buf; + ::memcpy(p, &m_state.context.gpr, sizeof(m_state.context.gpr)); + p += sizeof(m_state.context.gpr); + ::memcpy(p, &m_state.context.vfp, sizeof(m_state.context.vfp)); + p += sizeof(m_state.context.vfp); + ::memcpy(p, &m_state.context.exc, sizeof(m_state.context.exc)); + p += sizeof(m_state.context.exc); + + size_t bytes_written = p - (uint8_t *)buf; + UNUSED_IF_ASSERT_DISABLED(bytes_written); + assert(bytes_written == size); + } + DNBLogThreadedIf( + LOG_THREAD, + "DNBArchMachARM::GetRegisterContext (buf = %p, len = %llu) => %llu", buf, + (uint64_t)buf_len, (uint64_t)size); + // Return the size of the register context even if NULL was passed in + return size; } -nub_size_t -DNBArchMachARM::SetRegisterContext (const void *buf, nub_size_t buf_len) -{ - nub_size_t size = sizeof (m_state.context.gpr) + - sizeof (m_state.context.vfp) + - sizeof (m_state.context.exc); - - if (buf == NULL || buf_len == 0) - size = 0; - - if (size) - { - if (size > buf_len) - size = buf_len; - - // Copy each struct individually to avoid any padding that might be between the structs in m_state.context - uint8_t *p = (uint8_t *)buf; - ::memcpy (&m_state.context.gpr, p, sizeof(m_state.context.gpr)); - p += sizeof(m_state.context.gpr); - ::memcpy (&m_state.context.vfp, p, sizeof(m_state.context.vfp)); - p += sizeof(m_state.context.vfp); - ::memcpy (&m_state.context.exc, p, sizeof(m_state.context.exc)); - p += sizeof(m_state.context.exc); - - size_t bytes_written = p - (uint8_t *)buf; - UNUSED_IF_ASSERT_DISABLED(bytes_written); - assert (bytes_written == size); - - if (SetGPRState() | SetVFPState() | SetEXCState()) - return 0; - } - DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::SetRegisterContext (buf = %p, len = %llu) => %llu", buf, (uint64_t)buf_len, (uint64_t)size); - return size; +nub_size_t DNBArchMachARM::SetRegisterContext(const void *buf, + nub_size_t buf_len) { + nub_size_t size = sizeof(m_state.context.gpr) + sizeof(m_state.context.vfp) + + sizeof(m_state.context.exc); + + if (buf == NULL || buf_len == 0) + size = 0; + + if (size) { + if (size > buf_len) + size = buf_len; + + // Copy each struct individually to avoid any padding that might be between + // the structs in m_state.context + uint8_t *p = (uint8_t *)buf; + ::memcpy(&m_state.context.gpr, p, sizeof(m_state.context.gpr)); + p += sizeof(m_state.context.gpr); + ::memcpy(&m_state.context.vfp, p, sizeof(m_state.context.vfp)); + p += sizeof(m_state.context.vfp); + ::memcpy(&m_state.context.exc, p, sizeof(m_state.context.exc)); + p += sizeof(m_state.context.exc); + + size_t bytes_written = p - (uint8_t *)buf; + UNUSED_IF_ASSERT_DISABLED(bytes_written); + assert(bytes_written == size); + + if (SetGPRState() | SetVFPState() | SetEXCState()) + return 0; + } + DNBLogThreadedIf( + LOG_THREAD, + "DNBArchMachARM::SetRegisterContext (buf = %p, len = %llu) => %llu", buf, + (uint64_t)buf_len, (uint64_t)size); + return size; } - -uint32_t -DNBArchMachARM::SaveRegisterState () -{ - kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); - DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); - - // Always re-read the registers because above we call thread_abort_safely(); - bool force = true; - - if ((kret = GetGPRState(force)) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::SaveRegisterState () error: GPR regs failed to read: %u ", kret); - } - else if ((kret = GetVFPState(force)) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::SaveRegisterState () error: %s regs failed to read: %u", "VFP", kret); - } - else - { - const uint32_t save_id = GetNextRegisterStateSaveID (); - m_saved_register_states[save_id] = m_state.context; - return save_id; - } - return UINT32_MAX; +uint32_t DNBArchMachARM::SaveRegisterState() { + kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); + DNBLogThreadedIf( + LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u " + "(SetGPRState() for stop_count = %u)", + m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); + + // Always re-read the registers because above we call thread_abort_safely(); + bool force = true; + + if ((kret = GetGPRState(force)) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchMachARM::SaveRegisterState () error: " + "GPR regs failed to read: %u ", + kret); + } else if ((kret = GetVFPState(force)) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchMachARM::SaveRegisterState () error: " + "%s regs failed to read: %u", + "VFP", kret); + } else { + const uint32_t save_id = GetNextRegisterStateSaveID(); + m_saved_register_states[save_id] = m_state.context; + return save_id; + } + return UINT32_MAX; } -bool -DNBArchMachARM::RestoreRegisterState (uint32_t save_id) -{ - SaveRegisterStates::iterator pos = m_saved_register_states.find(save_id); - if (pos != m_saved_register_states.end()) - { - m_state.context.gpr = pos->second.gpr; - m_state.context.vfp = pos->second.vfp; - kern_return_t kret; - bool success = true; - if ((kret = SetGPRState()) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::RestoreRegisterState (save_id = %u) error: GPR regs failed to write: %u", save_id, kret); - success = false; - } - else if ((kret = SetVFPState()) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::RestoreRegisterState (save_id = %u) error: %s regs failed to write: %u", save_id, "VFP", kret); - success = false; - } - m_saved_register_states.erase(pos); - return success; +bool DNBArchMachARM::RestoreRegisterState(uint32_t save_id) { + SaveRegisterStates::iterator pos = m_saved_register_states.find(save_id); + if (pos != m_saved_register_states.end()) { + m_state.context.gpr = pos->second.gpr; + m_state.context.vfp = pos->second.vfp; + kern_return_t kret; + bool success = true; + if ((kret = SetGPRState()) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchMachARM::RestoreRegisterState " + "(save_id = %u) error: GPR regs failed to " + "write: %u", + save_id, kret); + success = false; + } else if ((kret = SetVFPState()) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchMachARM::RestoreRegisterState " + "(save_id = %u) error: %s regs failed to " + "write: %u", + save_id, "VFP", kret); + success = false; } - return false; + m_saved_register_states.erase(pos); + return success; + } + return false; } - -#endif // #if defined (__arm__) - +#endif // #if defined (__arm__) diff --git a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h index ae897485523..e8622c4ec7e 100644 --- a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h +++ b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h @@ -14,7 +14,7 @@ #ifndef __DebugNubArchMachARM_h__ #define __DebugNubArchMachARM_h__ -#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) +#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) #include "DNBArch.h" @@ -22,261 +22,254 @@ class MachThread; -class DNBArchMachARM : public DNBArchProtocol -{ +class DNBArchMachARM : public DNBArchProtocol { public: - enum { kMaxNumThumbITBreakpoints = 4 }; + enum { kMaxNumThumbITBreakpoints = 4 }; - DNBArchMachARM(MachThread *thread) : - m_thread(thread), - m_state(), - m_disabled_watchpoints(), + DNBArchMachARM(MachThread *thread) + : m_thread(thread), m_state(), m_disabled_watchpoints(), m_hw_single_chained_step_addr(INVALID_NUB_ADDRESS), - m_last_decode_pc(INVALID_NUB_ADDRESS), - m_watchpoint_hw_index(-1), + m_last_decode_pc(INVALID_NUB_ADDRESS), m_watchpoint_hw_index(-1), m_watchpoint_did_occur(false), m_watchpoint_resume_single_step_enabled(false), - m_saved_register_states() - { - m_disabled_watchpoints.resize (16); - memset(&m_dbg_save, 0, sizeof(m_dbg_save)); -#if defined (USE_ARM_DISASSEMBLER_FRAMEWORK) - ThumbStaticsInit(&m_last_decode_thumb); + m_saved_register_states() { + m_disabled_watchpoints.resize(16); + memset(&m_dbg_save, 0, sizeof(m_dbg_save)); +#if defined(USE_ARM_DISASSEMBLER_FRAMEWORK) + ThumbStaticsInit(&m_last_decode_thumb); #endif - } - - virtual ~DNBArchMachARM() - { - } - - static void Initialize(); - static const DNBRegisterSetInfo * - GetRegisterSetInfo(nub_size_t *num_reg_sets); - - virtual bool GetRegisterValue(uint32_t set, uint32_t reg, DNBRegisterValue *value); - virtual bool SetRegisterValue(uint32_t set, uint32_t reg, const DNBRegisterValue *value); - virtual nub_size_t GetRegisterContext (void *buf, nub_size_t buf_len); - virtual nub_size_t SetRegisterContext (const void *buf, nub_size_t buf_len); - virtual uint32_t SaveRegisterState (); - virtual bool RestoreRegisterState (uint32_t save_id); - - virtual kern_return_t GetRegisterState (int set, bool force); - virtual kern_return_t SetRegisterState (int set); - virtual bool RegisterSetStateIsValid (int set) const; - - virtual uint64_t GetPC(uint64_t failValue); // Get program counter - virtual kern_return_t SetPC(uint64_t value); - virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer - virtual void ThreadWillResume(); - virtual bool ThreadDidStop(); - virtual bool NotifyException(MachException::Data& exc); - - static DNBArchProtocol *Create (MachThread *thread); - static const uint8_t * SoftwareBreakpointOpcode (nub_size_t byte_size); - static uint32_t GetCPUType(); - - virtual uint32_t NumSupportedHardwareBreakpoints(); - virtual uint32_t NumSupportedHardwareWatchpoints(); - virtual uint32_t EnableHardwareBreakpoint (nub_addr_t addr, nub_size_t size); - virtual bool DisableHardwareBreakpoint (uint32_t hw_break_index); - - virtual uint32_t EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task); - virtual bool DisableHardwareWatchpoint (uint32_t hw_break_index, bool also_set_on_task); - virtual bool DisableHardwareWatchpoint_helper (uint32_t hw_break_index, bool also_set_on_task); - virtual bool ReenableHardwareWatchpoint (uint32_t hw_break_index); - virtual bool ReenableHardwareWatchpoint_helper (uint32_t hw_break_index); - - virtual bool StepNotComplete (); - virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); - -#if defined (ARM_DEBUG_STATE32) && (defined (__arm64__) || defined (__aarch64__)) - typedef arm_debug_state32_t DBG; + } + + virtual ~DNBArchMachARM() {} + + static void Initialize(); + static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets); + + virtual bool GetRegisterValue(uint32_t set, uint32_t reg, + DNBRegisterValue *value); + virtual bool SetRegisterValue(uint32_t set, uint32_t reg, + const DNBRegisterValue *value); + virtual nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len); + virtual nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len); + virtual uint32_t SaveRegisterState(); + virtual bool RestoreRegisterState(uint32_t save_id); + + virtual kern_return_t GetRegisterState(int set, bool force); + virtual kern_return_t SetRegisterState(int set); + virtual bool RegisterSetStateIsValid(int set) const; + + virtual uint64_t GetPC(uint64_t failValue); // Get program counter + virtual kern_return_t SetPC(uint64_t value); + virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer + virtual void ThreadWillResume(); + virtual bool ThreadDidStop(); + virtual bool NotifyException(MachException::Data &exc); + + static DNBArchProtocol *Create(MachThread *thread); + static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size); + static uint32_t GetCPUType(); + + virtual uint32_t NumSupportedHardwareBreakpoints(); + virtual uint32_t NumSupportedHardwareWatchpoints(); + virtual uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size); + virtual bool DisableHardwareBreakpoint(uint32_t hw_break_index); + + virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, + bool read, bool write, + bool also_set_on_task); + virtual bool DisableHardwareWatchpoint(uint32_t hw_break_index, + bool also_set_on_task); + virtual bool DisableHardwareWatchpoint_helper(uint32_t hw_break_index, + bool also_set_on_task); + virtual bool ReenableHardwareWatchpoint(uint32_t hw_break_index); + virtual bool ReenableHardwareWatchpoint_helper(uint32_t hw_break_index); + + virtual bool StepNotComplete(); + virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); + +#if defined(ARM_DEBUG_STATE32) && (defined(__arm64__) || defined(__aarch64__)) + typedef arm_debug_state32_t DBG; #else - typedef arm_debug_state_t DBG; + typedef arm_debug_state_t DBG; #endif protected: - - - kern_return_t EnableHardwareSingleStep (bool enable); - kern_return_t SetSingleStepSoftwareBreakpoints (); - - bool ConditionPassed(uint8_t condition, uint32_t cpsr); -#if defined (USE_ARM_DISASSEMBLER_FRAMEWORK) - bool ComputeNextPC(nub_addr_t currentPC, arm_decoded_instruction_t decodedInstruction, bool currentPCIsThumb, nub_addr_t *targetPC); - arm_error_t DecodeInstructionUsingDisassembler(nub_addr_t curr_pc, uint32_t curr_cpsr, arm_decoded_instruction_t *decodedInstruction, thumb_static_data_t *thumbStaticData, nub_addr_t *next_pc); - void DecodeITBlockInstructions(nub_addr_t curr_pc); + kern_return_t EnableHardwareSingleStep(bool enable); + kern_return_t SetSingleStepSoftwareBreakpoints(); + + bool ConditionPassed(uint8_t condition, uint32_t cpsr); +#if defined(USE_ARM_DISASSEMBLER_FRAMEWORK) + bool ComputeNextPC(nub_addr_t currentPC, + arm_decoded_instruction_t decodedInstruction, + bool currentPCIsThumb, nub_addr_t *targetPC); + arm_error_t DecodeInstructionUsingDisassembler( + nub_addr_t curr_pc, uint32_t curr_cpsr, + arm_decoded_instruction_t *decodedInstruction, + thumb_static_data_t *thumbStaticData, nub_addr_t *next_pc); + void DecodeITBlockInstructions(nub_addr_t curr_pc); #endif - void EvaluateNextInstructionForSoftwareBreakpointSetup(nub_addr_t currentPC, uint32_t cpsr, bool currentPCIsThumb, nub_addr_t *nextPC, bool *nextPCIsThumb); - - - typedef enum RegisterSetTag - { - e_regSetALL = REGISTER_SET_ALL, - e_regSetGPR, // ARM_THREAD_STATE - e_regSetVFP, // ARM_VFP_STATE (ARM_NEON_STATE if defined __arm64__) - e_regSetEXC, // ARM_EXCEPTION_STATE - e_regSetDBG, // ARM_DEBUG_STATE (ARM_DEBUG_STATE32 if defined __arm64__) - kNumRegisterSets - } RegisterSet; - - enum - { - Read = 0, - Write = 1, - kNumErrors = 2 - }; - - typedef arm_thread_state_t GPR; -#if defined (__arm64__) || defined (__aarch64__) - typedef arm_neon_state_t FPU; + void EvaluateNextInstructionForSoftwareBreakpointSetup(nub_addr_t currentPC, + uint32_t cpsr, + bool currentPCIsThumb, + nub_addr_t *nextPC, + bool *nextPCIsThumb); + + typedef enum RegisterSetTag { + e_regSetALL = REGISTER_SET_ALL, + e_regSetGPR, // ARM_THREAD_STATE + e_regSetVFP, // ARM_VFP_STATE (ARM_NEON_STATE if defined __arm64__) + e_regSetEXC, // ARM_EXCEPTION_STATE + e_regSetDBG, // ARM_DEBUG_STATE (ARM_DEBUG_STATE32 if defined __arm64__) + kNumRegisterSets + } RegisterSet; + + enum { Read = 0, Write = 1, kNumErrors = 2 }; + + typedef arm_thread_state_t GPR; +#if defined(__arm64__) || defined(__aarch64__) + typedef arm_neon_state_t FPU; #else - typedef arm_vfp_state_t FPU; + typedef arm_vfp_state_t FPU; #endif - typedef arm_exception_state_t EXC; - - static const DNBRegisterInfo g_gpr_registers[]; - static const DNBRegisterInfo g_vfp_registers[]; - static const DNBRegisterInfo g_exc_registers[]; - static const DNBRegisterSetInfo g_reg_sets[]; - - static const size_t k_num_gpr_registers; - static const size_t k_num_vfp_registers; - static const size_t k_num_exc_registers; - static const size_t k_num_all_registers; - static const size_t k_num_register_sets; - - struct Context - { - GPR gpr; - FPU vfp; - EXC exc; - }; - - struct State - { - Context context; - DBG dbg; - kern_return_t gpr_errs[2]; // Read/Write errors - kern_return_t vfp_errs[2]; // Read/Write errors - kern_return_t exc_errs[2]; // Read/Write errors - kern_return_t dbg_errs[2]; // Read/Write errors - State() - { - uint32_t i; - for (i=0; i<kNumErrors; i++) - { - gpr_errs[i] = -1; - vfp_errs[i] = -1; - exc_errs[i] = -1; - dbg_errs[i] = -1; - } - } - void InvalidateRegisterSetState(int set) - { - SetError (set, Read, -1); - } - kern_return_t GetError (int set, uint32_t err_idx) const - { - if (err_idx < kNumErrors) - { - switch (set) - { - // When getting all errors, just OR all values together to see if - // we got any kind of error. - case e_regSetALL: return gpr_errs[err_idx] | - vfp_errs[err_idx] | - exc_errs[err_idx] | - dbg_errs[err_idx] ; - case e_regSetGPR: return gpr_errs[err_idx]; - case e_regSetVFP: return vfp_errs[err_idx]; - case e_regSetEXC: return exc_errs[err_idx]; - case e_regSetDBG: return dbg_errs[err_idx]; - default: break; - } - } - return -1; - } - bool SetError (int set, uint32_t err_idx, kern_return_t err) - { - if (err_idx < kNumErrors) - { - switch (set) - { - case e_regSetALL: - gpr_errs[err_idx] = err; - vfp_errs[err_idx] = err; - dbg_errs[err_idx] = err; - exc_errs[err_idx] = err; - return true; - - case e_regSetGPR: - gpr_errs[err_idx] = err; - return true; - - case e_regSetVFP: - vfp_errs[err_idx] = err; - return true; - - case e_regSetEXC: - exc_errs[err_idx] = err; - return true; - - case e_regSetDBG: - dbg_errs[err_idx] = err; - return true; - default: break; - } - } - return false; + typedef arm_exception_state_t EXC; + + static const DNBRegisterInfo g_gpr_registers[]; + static const DNBRegisterInfo g_vfp_registers[]; + static const DNBRegisterInfo g_exc_registers[]; + static const DNBRegisterSetInfo g_reg_sets[]; + + static const size_t k_num_gpr_registers; + static const size_t k_num_vfp_registers; + static const size_t k_num_exc_registers; + static const size_t k_num_all_registers; + static const size_t k_num_register_sets; + + struct Context { + GPR gpr; + FPU vfp; + EXC exc; + }; + + struct State { + Context context; + DBG dbg; + kern_return_t gpr_errs[2]; // Read/Write errors + kern_return_t vfp_errs[2]; // Read/Write errors + kern_return_t exc_errs[2]; // Read/Write errors + kern_return_t dbg_errs[2]; // Read/Write errors + State() { + uint32_t i; + for (i = 0; i < kNumErrors; i++) { + gpr_errs[i] = -1; + vfp_errs[i] = -1; + exc_errs[i] = -1; + dbg_errs[i] = -1; + } + } + void InvalidateRegisterSetState(int set) { SetError(set, Read, -1); } + kern_return_t GetError(int set, uint32_t err_idx) const { + if (err_idx < kNumErrors) { + switch (set) { + // When getting all errors, just OR all values together to see if + // we got any kind of error. + case e_regSetALL: + return gpr_errs[err_idx] | vfp_errs[err_idx] | exc_errs[err_idx] | + dbg_errs[err_idx]; + case e_regSetGPR: + return gpr_errs[err_idx]; + case e_regSetVFP: + return vfp_errs[err_idx]; + case e_regSetEXC: + return exc_errs[err_idx]; + case e_regSetDBG: + return dbg_errs[err_idx]; + default: + break; } - bool RegsAreValid (int set) const - { - return GetError(set, Read) == KERN_SUCCESS; + } + return -1; + } + bool SetError(int set, uint32_t err_idx, kern_return_t err) { + if (err_idx < kNumErrors) { + switch (set) { + case e_regSetALL: + gpr_errs[err_idx] = err; + vfp_errs[err_idx] = err; + dbg_errs[err_idx] = err; + exc_errs[err_idx] = err; + return true; + + case e_regSetGPR: + gpr_errs[err_idx] = err; + return true; + + case e_regSetVFP: + vfp_errs[err_idx] = err; + return true; + + case e_regSetEXC: + exc_errs[err_idx] = err; + return true; + + case e_regSetDBG: + dbg_errs[err_idx] = err; + return true; + default: + break; } - }; - - kern_return_t GetGPRState (bool force); - kern_return_t GetVFPState (bool force); - kern_return_t GetEXCState (bool force); - kern_return_t GetDBGState (bool force); - - kern_return_t SetGPRState (); - kern_return_t SetVFPState (); - kern_return_t SetEXCState (); - kern_return_t SetDBGState (bool also_set_on_task); - - bool IsWatchpointEnabled(const DBG &debug_state, uint32_t hw_index); - nub_addr_t GetWatchpointAddressByIndex (uint32_t hw_index); - nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); - - class disabled_watchpoint { - public: - disabled_watchpoint () { addr = 0; control = 0; } - nub_addr_t addr; - uint32_t control; - }; + } + return false; + } + bool RegsAreValid(int set) const { + return GetError(set, Read) == KERN_SUCCESS; + } + }; + + kern_return_t GetGPRState(bool force); + kern_return_t GetVFPState(bool force); + kern_return_t GetEXCState(bool force); + kern_return_t GetDBGState(bool force); + + kern_return_t SetGPRState(); + kern_return_t SetVFPState(); + kern_return_t SetEXCState(); + kern_return_t SetDBGState(bool also_set_on_task); + + bool IsWatchpointEnabled(const DBG &debug_state, uint32_t hw_index); + nub_addr_t GetWatchpointAddressByIndex(uint32_t hw_index); + nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); + + class disabled_watchpoint { + public: + disabled_watchpoint() { + addr = 0; + control = 0; + } + nub_addr_t addr; + uint32_t control; + }; protected: - MachThread * m_thread; - State m_state; - DBG m_dbg_save; + MachThread *m_thread; + State m_state; + DBG m_dbg_save; - // armv8 doesn't keep the disabled watchpoint values in the debug register context like armv7; - // we need to save them aside when we disable them temporarily. - std::vector<disabled_watchpoint> m_disabled_watchpoints; + // armv8 doesn't keep the disabled watchpoint values in the debug register + // context like armv7; + // we need to save them aside when we disable them temporarily. + std::vector<disabled_watchpoint> m_disabled_watchpoints; - nub_addr_t m_hw_single_chained_step_addr; - nub_addr_t m_last_decode_pc; + nub_addr_t m_hw_single_chained_step_addr; + nub_addr_t m_last_decode_pc; - // The following member variables should be updated atomically. - int32_t m_watchpoint_hw_index; - bool m_watchpoint_did_occur; - bool m_watchpoint_resume_single_step_enabled; + // The following member variables should be updated atomically. + int32_t m_watchpoint_hw_index; + bool m_watchpoint_did_occur; + bool m_watchpoint_resume_single_step_enabled; - typedef std::map<uint32_t, Context> SaveRegisterStates; - SaveRegisterStates m_saved_register_states; + typedef std::map<uint32_t, Context> SaveRegisterStates; + SaveRegisterStates m_saved_register_states; }; -#endif // #if defined (__arm__) -#endif // #ifndef __DebugNubArchMachARM_h__ +#endif // #if defined (__arm__) +#endif // #ifndef __DebugNubArchMachARM_h__ diff --git a/lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp b/lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp index e79d3d52e8f..7d04170623d 100644 --- a/lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp +++ b/lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp @@ -11,1349 +11,1359 @@ // //===----------------------------------------------------------------------===// -#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) +#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) #include "MacOSX/arm64/DNBArchImplARM64.h" -#if defined (ARM_THREAD_STATE64_COUNT) +#if defined(ARM_THREAD_STATE64_COUNT) -#include "MacOSX/MachProcess.h" -#include "MacOSX/MachThread.h" +#include "DNB.h" #include "DNBBreakpoint.h" #include "DNBLog.h" #include "DNBRegisterInfo.h" -#include "DNB.h" +#include "MacOSX/MachProcess.h" +#include "MacOSX/MachThread.h" #include <inttypes.h> #include <sys/sysctl.h> // Break only in privileged or user mode // (PAC bits in the DBGWVRn_EL1 watchpoint control register) -#define S_USER ((uint32_t)(2u << 1)) +#define S_USER ((uint32_t)(2u << 1)) -#define BCR_ENABLE ((uint32_t)(1u)) -#define WCR_ENABLE ((uint32_t)(1u)) +#define BCR_ENABLE ((uint32_t)(1u)) +#define WCR_ENABLE ((uint32_t)(1u)) // Watchpoint load/store // (LSC bits in the DBGWVRn_EL1 watchpoint control register) -#define WCR_LOAD ((uint32_t)(1u << 3)) -#define WCR_STORE ((uint32_t)(1u << 4)) +#define WCR_LOAD ((uint32_t)(1u << 3)) +#define WCR_STORE ((uint32_t)(1u << 4)) // Enable breakpoint, watchpoint, and vector catch debug exceptions. -// (MDE bit in the MDSCR_EL1 register. Equivalent to the MDBGen bit in DBGDSCRext in Aarch32) +// (MDE bit in the MDSCR_EL1 register. Equivalent to the MDBGen bit in +// DBGDSCRext in Aarch32) #define MDE_ENABLE ((uint32_t)(1u << 15)) // Single instruction step // (SS bit in the MDSCR_EL1 register) #define SS_ENABLE ((uint32_t)(1u)) -static const uint8_t g_arm64_breakpoint_opcode[] = { 0x00, 0x00, 0x20, 0xD4 }; // "brk #0", 0xd4200000 in BE byte order -static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 }; // this armv7 insn also works in arm64 +static const uint8_t g_arm64_breakpoint_opcode[] = { + 0x00, 0x00, 0x20, 0xD4}; // "brk #0", 0xd4200000 in BE byte order +static const uint8_t g_arm_breakpoint_opcode[] = { + 0xFE, 0xDE, 0xFF, 0xE7}; // this armv7 insn also works in arm64 // If we need to set one logical watchpoint by using // two hardware watchpoint registers, the watchpoint // will be split into a "high" and "low" watchpoint. // Record both of them in the LoHi array. -// It's safe to initialize to all 0's since +// It's safe to initialize to all 0's since // hi > lo and therefore LoHi[i] cannot be 0. -static uint32_t LoHi[16] = { 0 }; - - -void -DNBArchMachARM64::Initialize() -{ - DNBArchPluginInfo arch_plugin_info = - { - CPU_TYPE_ARM64, - DNBArchMachARM64::Create, - DNBArchMachARM64::GetRegisterSetInfo, - DNBArchMachARM64::SoftwareBreakpointOpcode - }; - - // Register this arch plug-in with the main protocol class - DNBArchProtocol::RegisterArchPlugin (arch_plugin_info); -} +static uint32_t LoHi[16] = {0}; +void DNBArchMachARM64::Initialize() { + DNBArchPluginInfo arch_plugin_info = { + CPU_TYPE_ARM64, DNBArchMachARM64::Create, + DNBArchMachARM64::GetRegisterSetInfo, + DNBArchMachARM64::SoftwareBreakpointOpcode}; -DNBArchProtocol * -DNBArchMachARM64::Create (MachThread *thread) -{ - DNBArchMachARM64 *obj = new DNBArchMachARM64 (thread); + // Register this arch plug-in with the main protocol class + DNBArchProtocol::RegisterArchPlugin(arch_plugin_info); +} + +DNBArchProtocol *DNBArchMachARM64::Create(MachThread *thread) { + DNBArchMachARM64 *obj = new DNBArchMachARM64(thread); - return obj; + return obj; } const uint8_t * -DNBArchMachARM64::SoftwareBreakpointOpcode (nub_size_t byte_size) -{ - return g_arm_breakpoint_opcode; +DNBArchMachARM64::SoftwareBreakpointOpcode(nub_size_t byte_size) { + return g_arm_breakpoint_opcode; } -uint32_t -DNBArchMachARM64::GetCPUType() -{ - return CPU_TYPE_ARM64; -} +uint32_t DNBArchMachARM64::GetCPUType() { return CPU_TYPE_ARM64; } -uint64_t -DNBArchMachARM64::GetPC(uint64_t failValue) -{ - // Get program counter - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.context.gpr.__pc; - return failValue; +uint64_t DNBArchMachARM64::GetPC(uint64_t failValue) { + // Get program counter + if (GetGPRState(false) == KERN_SUCCESS) + return m_state.context.gpr.__pc; + return failValue; } -kern_return_t -DNBArchMachARM64::SetPC(uint64_t value) -{ - // Get program counter - kern_return_t err = GetGPRState(false); - if (err == KERN_SUCCESS) - { - m_state.context.gpr.__pc = value; - err = SetGPRState(); - } - return err == KERN_SUCCESS; +kern_return_t DNBArchMachARM64::SetPC(uint64_t value) { + // Get program counter + kern_return_t err = GetGPRState(false); + if (err == KERN_SUCCESS) { + m_state.context.gpr.__pc = value; + err = SetGPRState(); + } + return err == KERN_SUCCESS; } -uint64_t -DNBArchMachARM64::GetSP(uint64_t failValue) -{ - // Get stack pointer - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.context.gpr.__sp; - return failValue; +uint64_t DNBArchMachARM64::GetSP(uint64_t failValue) { + // Get stack pointer + if (GetGPRState(false) == KERN_SUCCESS) + return m_state.context.gpr.__sp; + return failValue; } -kern_return_t -DNBArchMachARM64::GetGPRState(bool force) -{ - int set = e_regSetGPR; - // Check if we have valid cached registers - if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) - return KERN_SUCCESS; - - // Read the registers from our thread - mach_msg_type_number_t count = e_regSetGPRCount; - kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_THREAD_STATE64, (thread_state_t)&m_state.context.gpr, &count); - if (DNBLogEnabledForAny (LOG_THREAD)) - { - uint64_t *x = &m_state.context.gpr.__x[0]; - DNBLogThreaded("thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count = %u) regs" - "\n x0=%16.16llx" - "\n x1=%16.16llx" - "\n x2=%16.16llx" - "\n x3=%16.16llx" - "\n x4=%16.16llx" - "\n x5=%16.16llx" - "\n x6=%16.16llx" - "\n x7=%16.16llx" - "\n x8=%16.16llx" - "\n x9=%16.16llx" - "\n x10=%16.16llx" - "\n x11=%16.16llx" - "\n x12=%16.16llx" - "\n x13=%16.16llx" - "\n x14=%16.16llx" - "\n x15=%16.16llx" - "\n x16=%16.16llx" - "\n x17=%16.16llx" - "\n x18=%16.16llx" - "\n x19=%16.16llx" - "\n x20=%16.16llx" - "\n x21=%16.16llx" - "\n x22=%16.16llx" - "\n x23=%16.16llx" - "\n x24=%16.16llx" - "\n x25=%16.16llx" - "\n x26=%16.16llx" - "\n x27=%16.16llx" - "\n x28=%16.16llx" - "\n fp=%16.16llx" - "\n lr=%16.16llx" - "\n sp=%16.16llx" - "\n pc=%16.16llx" - "\n cpsr=%8.8x", - m_thread->MachPortNumber(), - e_regSetGPR, - e_regSetGPRCount, - kret, - count, - x[0], - x[1], - x[2], - x[3], - x[4], - x[5], - x[6], - x[7], - x[8], - x[9], - x[0], - x[11], - x[12], - x[13], - x[14], - x[15], - x[16], - x[17], - x[18], - x[19], - x[20], - x[21], - x[22], - x[23], - x[24], - x[25], - x[26], - x[27], - x[28], - m_state.context.gpr.__fp, - m_state.context.gpr.__lr, - m_state.context.gpr.__sp, - m_state.context.gpr.__pc, - m_state.context.gpr.__cpsr); - } - m_state.SetError(set, Read, kret); - return kret; +kern_return_t DNBArchMachARM64::GetGPRState(bool force) { + int set = e_regSetGPR; + // Check if we have valid cached registers + if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) + return KERN_SUCCESS; + + // Read the registers from our thread + mach_msg_type_number_t count = e_regSetGPRCount; + kern_return_t kret = + ::thread_get_state(m_thread->MachPortNumber(), ARM_THREAD_STATE64, + (thread_state_t)&m_state.context.gpr, &count); + if (DNBLogEnabledForAny(LOG_THREAD)) { + uint64_t *x = &m_state.context.gpr.__x[0]; + DNBLogThreaded( + "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count = %u) regs" + "\n x0=%16.16llx" + "\n x1=%16.16llx" + "\n x2=%16.16llx" + "\n x3=%16.16llx" + "\n x4=%16.16llx" + "\n x5=%16.16llx" + "\n x6=%16.16llx" + "\n x7=%16.16llx" + "\n x8=%16.16llx" + "\n x9=%16.16llx" + "\n x10=%16.16llx" + "\n x11=%16.16llx" + "\n x12=%16.16llx" + "\n x13=%16.16llx" + "\n x14=%16.16llx" + "\n x15=%16.16llx" + "\n x16=%16.16llx" + "\n x17=%16.16llx" + "\n x18=%16.16llx" + "\n x19=%16.16llx" + "\n x20=%16.16llx" + "\n x21=%16.16llx" + "\n x22=%16.16llx" + "\n x23=%16.16llx" + "\n x24=%16.16llx" + "\n x25=%16.16llx" + "\n x26=%16.16llx" + "\n x27=%16.16llx" + "\n x28=%16.16llx" + "\n fp=%16.16llx" + "\n lr=%16.16llx" + "\n sp=%16.16llx" + "\n pc=%16.16llx" + "\n cpsr=%8.8x", + m_thread->MachPortNumber(), e_regSetGPR, e_regSetGPRCount, kret, count, + x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[0], x[11], + x[12], x[13], x[14], x[15], x[16], x[17], x[18], x[19], x[20], x[21], + x[22], x[23], x[24], x[25], x[26], x[27], x[28], + m_state.context.gpr.__fp, m_state.context.gpr.__lr, + m_state.context.gpr.__sp, m_state.context.gpr.__pc, + m_state.context.gpr.__cpsr); + } + m_state.SetError(set, Read, kret); + return kret; } -kern_return_t -DNBArchMachARM64::GetVFPState(bool force) -{ - int set = e_regSetVFP; - // Check if we have valid cached registers - if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) - return KERN_SUCCESS; - - // Read the registers from our thread - mach_msg_type_number_t count = e_regSetVFPCount; - kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_NEON_STATE64, (thread_state_t)&m_state.context.vfp, &count); - if (DNBLogEnabledForAny (LOG_THREAD)) - { -#if defined (__arm64__) || defined (__aarch64__) - DNBLogThreaded("thread_get_state(0x%4.4x, %u, &vfp, %u) => 0x%8.8x (count = %u) regs" - "\n q0 = 0x%16.16llx%16.16llx" - "\n q1 = 0x%16.16llx%16.16llx" - "\n q2 = 0x%16.16llx%16.16llx" - "\n q3 = 0x%16.16llx%16.16llx" - "\n q4 = 0x%16.16llx%16.16llx" - "\n q5 = 0x%16.16llx%16.16llx" - "\n q6 = 0x%16.16llx%16.16llx" - "\n q7 = 0x%16.16llx%16.16llx" - "\n q8 = 0x%16.16llx%16.16llx" - "\n q9 = 0x%16.16llx%16.16llx" - "\n q10 = 0x%16.16llx%16.16llx" - "\n q11 = 0x%16.16llx%16.16llx" - "\n q12 = 0x%16.16llx%16.16llx" - "\n q13 = 0x%16.16llx%16.16llx" - "\n q14 = 0x%16.16llx%16.16llx" - "\n q15 = 0x%16.16llx%16.16llx" - "\n q16 = 0x%16.16llx%16.16llx" - "\n q17 = 0x%16.16llx%16.16llx" - "\n q18 = 0x%16.16llx%16.16llx" - "\n q19 = 0x%16.16llx%16.16llx" - "\n q20 = 0x%16.16llx%16.16llx" - "\n q21 = 0x%16.16llx%16.16llx" - "\n q22 = 0x%16.16llx%16.16llx" - "\n q23 = 0x%16.16llx%16.16llx" - "\n q24 = 0x%16.16llx%16.16llx" - "\n q25 = 0x%16.16llx%16.16llx" - "\n q26 = 0x%16.16llx%16.16llx" - "\n q27 = 0x%16.16llx%16.16llx" - "\n q28 = 0x%16.16llx%16.16llx" - "\n q29 = 0x%16.16llx%16.16llx" - "\n q30 = 0x%16.16llx%16.16llx" - "\n q31 = 0x%16.16llx%16.16llx" - "\n fpsr = 0x%8.8x" - "\n fpcr = 0x%8.8x\n\n", - m_thread->MachPortNumber(), - e_regSetVFP, - e_regSetVFPCount, - kret, - count, - ((uint64_t *)&m_state.context.vfp.__v[0])[0] , ((uint64_t *)&m_state.context.vfp.__v[0])[1], - ((uint64_t *)&m_state.context.vfp.__v[1])[0] , ((uint64_t *)&m_state.context.vfp.__v[1])[1], - ((uint64_t *)&m_state.context.vfp.__v[2])[0] , ((uint64_t *)&m_state.context.vfp.__v[2])[1], - ((uint64_t *)&m_state.context.vfp.__v[3])[0] , ((uint64_t *)&m_state.context.vfp.__v[3])[1], - ((uint64_t *)&m_state.context.vfp.__v[4])[0] , ((uint64_t *)&m_state.context.vfp.__v[4])[1], - ((uint64_t *)&m_state.context.vfp.__v[5])[0] , ((uint64_t *)&m_state.context.vfp.__v[5])[1], - ((uint64_t *)&m_state.context.vfp.__v[6])[0] , ((uint64_t *)&m_state.context.vfp.__v[6])[1], - ((uint64_t *)&m_state.context.vfp.__v[7])[0] , ((uint64_t *)&m_state.context.vfp.__v[7])[1], - ((uint64_t *)&m_state.context.vfp.__v[8])[0] , ((uint64_t *)&m_state.context.vfp.__v[8])[1], - ((uint64_t *)&m_state.context.vfp.__v[9])[0] , ((uint64_t *)&m_state.context.vfp.__v[9])[1], - ((uint64_t *)&m_state.context.vfp.__v[10])[0], ((uint64_t *)&m_state.context.vfp.__v[10])[1], - ((uint64_t *)&m_state.context.vfp.__v[11])[0], ((uint64_t *)&m_state.context.vfp.__v[11])[1], - ((uint64_t *)&m_state.context.vfp.__v[12])[0], ((uint64_t *)&m_state.context.vfp.__v[12])[1], - ((uint64_t *)&m_state.context.vfp.__v[13])[0], ((uint64_t *)&m_state.context.vfp.__v[13])[1], - ((uint64_t *)&m_state.context.vfp.__v[14])[0], ((uint64_t *)&m_state.context.vfp.__v[14])[1], - ((uint64_t *)&m_state.context.vfp.__v[15])[0], ((uint64_t *)&m_state.context.vfp.__v[15])[1], - ((uint64_t *)&m_state.context.vfp.__v[16])[0], ((uint64_t *)&m_state.context.vfp.__v[16])[1], - ((uint64_t *)&m_state.context.vfp.__v[17])[0], ((uint64_t *)&m_state.context.vfp.__v[17])[1], - ((uint64_t *)&m_state.context.vfp.__v[18])[0], ((uint64_t *)&m_state.context.vfp.__v[18])[1], - ((uint64_t *)&m_state.context.vfp.__v[19])[0], ((uint64_t *)&m_state.context.vfp.__v[19])[1], - ((uint64_t *)&m_state.context.vfp.__v[20])[0], ((uint64_t *)&m_state.context.vfp.__v[20])[1], - ((uint64_t *)&m_state.context.vfp.__v[21])[0], ((uint64_t *)&m_state.context.vfp.__v[21])[1], - ((uint64_t *)&m_state.context.vfp.__v[22])[0], ((uint64_t *)&m_state.context.vfp.__v[22])[1], - ((uint64_t *)&m_state.context.vfp.__v[23])[0], ((uint64_t *)&m_state.context.vfp.__v[23])[1], - ((uint64_t *)&m_state.context.vfp.__v[24])[0], ((uint64_t *)&m_state.context.vfp.__v[24])[1], - ((uint64_t *)&m_state.context.vfp.__v[25])[0], ((uint64_t *)&m_state.context.vfp.__v[25])[1], - ((uint64_t *)&m_state.context.vfp.__v[26])[0], ((uint64_t *)&m_state.context.vfp.__v[26])[1], - ((uint64_t *)&m_state.context.vfp.__v[27])[0], ((uint64_t *)&m_state.context.vfp.__v[27])[1], - ((uint64_t *)&m_state.context.vfp.__v[28])[0], ((uint64_t *)&m_state.context.vfp.__v[28])[1], - ((uint64_t *)&m_state.context.vfp.__v[29])[0], ((uint64_t *)&m_state.context.vfp.__v[29])[1], - ((uint64_t *)&m_state.context.vfp.__v[30])[0], ((uint64_t *)&m_state.context.vfp.__v[30])[1], - ((uint64_t *)&m_state.context.vfp.__v[31])[0], ((uint64_t *)&m_state.context.vfp.__v[31])[1], - m_state.context.vfp.__fpsr, - m_state.context.vfp.__fpcr); +kern_return_t DNBArchMachARM64::GetVFPState(bool force) { + int set = e_regSetVFP; + // Check if we have valid cached registers + if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) + return KERN_SUCCESS; + + // Read the registers from our thread + mach_msg_type_number_t count = e_regSetVFPCount; + kern_return_t kret = + ::thread_get_state(m_thread->MachPortNumber(), ARM_NEON_STATE64, + (thread_state_t)&m_state.context.vfp, &count); + if (DNBLogEnabledForAny(LOG_THREAD)) { +#if defined(__arm64__) || defined(__aarch64__) + DNBLogThreaded( + "thread_get_state(0x%4.4x, %u, &vfp, %u) => 0x%8.8x (count = %u) regs" + "\n q0 = 0x%16.16llx%16.16llx" + "\n q1 = 0x%16.16llx%16.16llx" + "\n q2 = 0x%16.16llx%16.16llx" + "\n q3 = 0x%16.16llx%16.16llx" + "\n q4 = 0x%16.16llx%16.16llx" + "\n q5 = 0x%16.16llx%16.16llx" + "\n q6 = 0x%16.16llx%16.16llx" + "\n q7 = 0x%16.16llx%16.16llx" + "\n q8 = 0x%16.16llx%16.16llx" + "\n q9 = 0x%16.16llx%16.16llx" + "\n q10 = 0x%16.16llx%16.16llx" + "\n q11 = 0x%16.16llx%16.16llx" + "\n q12 = 0x%16.16llx%16.16llx" + "\n q13 = 0x%16.16llx%16.16llx" + "\n q14 = 0x%16.16llx%16.16llx" + "\n q15 = 0x%16.16llx%16.16llx" + "\n q16 = 0x%16.16llx%16.16llx" + "\n q17 = 0x%16.16llx%16.16llx" + "\n q18 = 0x%16.16llx%16.16llx" + "\n q19 = 0x%16.16llx%16.16llx" + "\n q20 = 0x%16.16llx%16.16llx" + "\n q21 = 0x%16.16llx%16.16llx" + "\n q22 = 0x%16.16llx%16.16llx" + "\n q23 = 0x%16.16llx%16.16llx" + "\n q24 = 0x%16.16llx%16.16llx" + "\n q25 = 0x%16.16llx%16.16llx" + "\n q26 = 0x%16.16llx%16.16llx" + "\n q27 = 0x%16.16llx%16.16llx" + "\n q28 = 0x%16.16llx%16.16llx" + "\n q29 = 0x%16.16llx%16.16llx" + "\n q30 = 0x%16.16llx%16.16llx" + "\n q31 = 0x%16.16llx%16.16llx" + "\n fpsr = 0x%8.8x" + "\n fpcr = 0x%8.8x\n\n", + m_thread->MachPortNumber(), e_regSetVFP, e_regSetVFPCount, kret, count, + ((uint64_t *)&m_state.context.vfp.__v[0])[0], + ((uint64_t *)&m_state.context.vfp.__v[0])[1], + ((uint64_t *)&m_state.context.vfp.__v[1])[0], + ((uint64_t *)&m_state.context.vfp.__v[1])[1], + ((uint64_t *)&m_state.context.vfp.__v[2])[0], + ((uint64_t *)&m_state.context.vfp.__v[2])[1], + ((uint64_t *)&m_state.context.vfp.__v[3])[0], + ((uint64_t *)&m_state.context.vfp.__v[3])[1], + ((uint64_t *)&m_state.context.vfp.__v[4])[0], + ((uint64_t *)&m_state.context.vfp.__v[4])[1], + ((uint64_t *)&m_state.context.vfp.__v[5])[0], + ((uint64_t *)&m_state.context.vfp.__v[5])[1], + ((uint64_t *)&m_state.context.vfp.__v[6])[0], + ((uint64_t *)&m_state.context.vfp.__v[6])[1], + ((uint64_t *)&m_state.context.vfp.__v[7])[0], + ((uint64_t *)&m_state.context.vfp.__v[7])[1], + ((uint64_t *)&m_state.context.vfp.__v[8])[0], + ((uint64_t *)&m_state.context.vfp.__v[8])[1], + ((uint64_t *)&m_state.context.vfp.__v[9])[0], + ((uint64_t *)&m_state.context.vfp.__v[9])[1], + ((uint64_t *)&m_state.context.vfp.__v[10])[0], + ((uint64_t *)&m_state.context.vfp.__v[10])[1], + ((uint64_t *)&m_state.context.vfp.__v[11])[0], + ((uint64_t *)&m_state.context.vfp.__v[11])[1], + ((uint64_t *)&m_state.context.vfp.__v[12])[0], + ((uint64_t *)&m_state.context.vfp.__v[12])[1], + ((uint64_t *)&m_state.context.vfp.__v[13])[0], + ((uint64_t *)&m_state.context.vfp.__v[13])[1], + ((uint64_t *)&m_state.context.vfp.__v[14])[0], + ((uint64_t *)&m_state.context.vfp.__v[14])[1], + ((uint64_t *)&m_state.context.vfp.__v[15])[0], + ((uint64_t *)&m_state.context.vfp.__v[15])[1], + ((uint64_t *)&m_state.context.vfp.__v[16])[0], + ((uint64_t *)&m_state.context.vfp.__v[16])[1], + ((uint64_t *)&m_state.context.vfp.__v[17])[0], + ((uint64_t *)&m_state.context.vfp.__v[17])[1], + ((uint64_t *)&m_state.context.vfp.__v[18])[0], + ((uint64_t *)&m_state.context.vfp.__v[18])[1], + ((uint64_t *)&m_state.context.vfp.__v[19])[0], + ((uint64_t *)&m_state.context.vfp.__v[19])[1], + ((uint64_t *)&m_state.context.vfp.__v[20])[0], + ((uint64_t *)&m_state.context.vfp.__v[20])[1], + ((uint64_t *)&m_state.context.vfp.__v[21])[0], + ((uint64_t *)&m_state.context.vfp.__v[21])[1], + ((uint64_t *)&m_state.context.vfp.__v[22])[0], + ((uint64_t *)&m_state.context.vfp.__v[22])[1], + ((uint64_t *)&m_state.context.vfp.__v[23])[0], + ((uint64_t *)&m_state.context.vfp.__v[23])[1], + ((uint64_t *)&m_state.context.vfp.__v[24])[0], + ((uint64_t *)&m_state.context.vfp.__v[24])[1], + ((uint64_t *)&m_state.context.vfp.__v[25])[0], + ((uint64_t *)&m_state.context.vfp.__v[25])[1], + ((uint64_t *)&m_state.context.vfp.__v[26])[0], + ((uint64_t *)&m_state.context.vfp.__v[26])[1], + ((uint64_t *)&m_state.context.vfp.__v[27])[0], + ((uint64_t *)&m_state.context.vfp.__v[27])[1], + ((uint64_t *)&m_state.context.vfp.__v[28])[0], + ((uint64_t *)&m_state.context.vfp.__v[28])[1], + ((uint64_t *)&m_state.context.vfp.__v[29])[0], + ((uint64_t *)&m_state.context.vfp.__v[29])[1], + ((uint64_t *)&m_state.context.vfp.__v[30])[0], + ((uint64_t *)&m_state.context.vfp.__v[30])[1], + ((uint64_t *)&m_state.context.vfp.__v[31])[0], + ((uint64_t *)&m_state.context.vfp.__v[31])[1], + m_state.context.vfp.__fpsr, m_state.context.vfp.__fpcr); #endif - } - m_state.SetError(set, Read, kret); - return kret; + } + m_state.SetError(set, Read, kret); + return kret; } -kern_return_t -DNBArchMachARM64::GetEXCState(bool force) -{ - int set = e_regSetEXC; - // Check if we have valid cached registers - if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) - return KERN_SUCCESS; - - // Read the registers from our thread - mach_msg_type_number_t count = e_regSetEXCCount; - kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_EXCEPTION_STATE64, (thread_state_t)&m_state.context.exc, &count); - m_state.SetError(set, Read, kret); - return kret; +kern_return_t DNBArchMachARM64::GetEXCState(bool force) { + int set = e_regSetEXC; + // Check if we have valid cached registers + if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) + return KERN_SUCCESS; + + // Read the registers from our thread + mach_msg_type_number_t count = e_regSetEXCCount; + kern_return_t kret = + ::thread_get_state(m_thread->MachPortNumber(), ARM_EXCEPTION_STATE64, + (thread_state_t)&m_state.context.exc, &count); + m_state.SetError(set, Read, kret); + return kret; } -static void -DumpDBGState(const arm_debug_state_t& dbg) -{ - uint32_t i = 0; - for (i=0; i<16; i++) - DNBLogThreadedIf(LOG_STEP, "BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }", - i, i, dbg.__bvr[i], dbg.__bcr[i], - i, i, dbg.__wvr[i], dbg.__wcr[i]); +static void DumpDBGState(const arm_debug_state_t &dbg) { + uint32_t i = 0; + for (i = 0; i < 16; i++) + DNBLogThreadedIf(LOG_STEP, "BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } " + "WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }", + i, i, dbg.__bvr[i], dbg.__bcr[i], i, i, dbg.__wvr[i], + dbg.__wcr[i]); } -kern_return_t -DNBArchMachARM64::GetDBGState(bool force) -{ - int set = e_regSetDBG; +kern_return_t DNBArchMachARM64::GetDBGState(bool force) { + int set = e_regSetDBG; - // Check if we have valid cached registers - if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) - return KERN_SUCCESS; + // Check if we have valid cached registers + if (!force && m_state.GetError(set, Read) == KERN_SUCCESS) + return KERN_SUCCESS; - // Read the registers from our thread - mach_msg_type_number_t count = e_regSetDBGCount; - kern_return_t kret = ::thread_get_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE64, (thread_state_t)&m_state.dbg, &count); - m_state.SetError(set, Read, kret); + // Read the registers from our thread + mach_msg_type_number_t count = e_regSetDBGCount; + kern_return_t kret = + ::thread_get_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE64, + (thread_state_t)&m_state.dbg, &count); + m_state.SetError(set, Read, kret); - return kret; + return kret; } -kern_return_t -DNBArchMachARM64::SetGPRState() -{ - int set = e_regSetGPR; - kern_return_t kret = ::thread_set_state(m_thread->MachPortNumber(), ARM_THREAD_STATE64, (thread_state_t)&m_state.context.gpr, e_regSetGPRCount); - m_state.SetError(set, Write, kret); // Set the current write error for this register set - m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently - return kret; // Return the error code +kern_return_t DNBArchMachARM64::SetGPRState() { + int set = e_regSetGPR; + kern_return_t kret = ::thread_set_state( + m_thread->MachPortNumber(), ARM_THREAD_STATE64, + (thread_state_t)&m_state.context.gpr, e_regSetGPRCount); + m_state.SetError(set, Write, + kret); // Set the current write error for this register set + m_state.InvalidateRegisterSetState(set); // Invalidate the current register + // state in case registers are read + // back differently + return kret; // Return the error code } -kern_return_t -DNBArchMachARM64::SetVFPState() -{ - int set = e_regSetVFP; - kern_return_t kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_NEON_STATE64, (thread_state_t)&m_state.context.vfp, e_regSetVFPCount); - m_state.SetError(set, Write, kret); // Set the current write error for this register set - m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently - return kret; // Return the error code +kern_return_t DNBArchMachARM64::SetVFPState() { + int set = e_regSetVFP; + kern_return_t kret = ::thread_set_state( + m_thread->MachPortNumber(), ARM_NEON_STATE64, + (thread_state_t)&m_state.context.vfp, e_regSetVFPCount); + m_state.SetError(set, Write, + kret); // Set the current write error for this register set + m_state.InvalidateRegisterSetState(set); // Invalidate the current register + // state in case registers are read + // back differently + return kret; // Return the error code } -kern_return_t -DNBArchMachARM64::SetEXCState() -{ - int set = e_regSetEXC; - kern_return_t kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_EXCEPTION_STATE64, (thread_state_t)&m_state.context.exc, e_regSetEXCCount); - m_state.SetError(set, Write, kret); // Set the current write error for this register set - m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently - return kret; // Return the error code +kern_return_t DNBArchMachARM64::SetEXCState() { + int set = e_regSetEXC; + kern_return_t kret = ::thread_set_state( + m_thread->MachPortNumber(), ARM_EXCEPTION_STATE64, + (thread_state_t)&m_state.context.exc, e_regSetEXCCount); + m_state.SetError(set, Write, + kret); // Set the current write error for this register set + m_state.InvalidateRegisterSetState(set); // Invalidate the current register + // state in case registers are read + // back differently + return kret; // Return the error code } -kern_return_t -DNBArchMachARM64::SetDBGState(bool also_set_on_task) -{ - int set = e_regSetDBG; - kern_return_t kret = ::thread_set_state (m_thread->MachPortNumber(), ARM_DEBUG_STATE64, (thread_state_t)&m_state.dbg, e_regSetDBGCount); - if (also_set_on_task) - { - kern_return_t task_kret = task_set_state (m_thread->Process()->Task().TaskPort(), ARM_DEBUG_STATE64, (thread_state_t)&m_state.dbg, e_regSetDBGCount); - if (task_kret != KERN_SUCCESS) - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::SetDBGState failed to set debug control register state: 0x%8.8x.", task_kret); - } - m_state.SetError(set, Write, kret); // Set the current write error for this register set - m_state.InvalidateRegisterSetState(set); // Invalidate the current register state in case registers are read back differently - - return kret; // Return the error code +kern_return_t DNBArchMachARM64::SetDBGState(bool also_set_on_task) { + int set = e_regSetDBG; + kern_return_t kret = + ::thread_set_state(m_thread->MachPortNumber(), ARM_DEBUG_STATE64, + (thread_state_t)&m_state.dbg, e_regSetDBGCount); + if (also_set_on_task) { + kern_return_t task_kret = task_set_state( + m_thread->Process()->Task().TaskPort(), ARM_DEBUG_STATE64, + (thread_state_t)&m_state.dbg, e_regSetDBGCount); + if (task_kret != KERN_SUCCESS) + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::SetDBGState failed " + "to set debug control register state: " + "0x%8.8x.", + task_kret); + } + m_state.SetError(set, Write, + kret); // Set the current write error for this register set + m_state.InvalidateRegisterSetState(set); // Invalidate the current register + // state in case registers are read + // back differently + + return kret; // Return the error code } -void -DNBArchMachARM64::ThreadWillResume() -{ - // Do we need to step this thread? If so, let the mach thread tell us so. - if (m_thread->IsStepping()) - { - EnableHardwareSingleStep(true); +void DNBArchMachARM64::ThreadWillResume() { + // Do we need to step this thread? If so, let the mach thread tell us so. + if (m_thread->IsStepping()) { + EnableHardwareSingleStep(true); + } + + // Disable the triggered watchpoint temporarily before we resume. + // Plus, we try to enable hardware single step to execute past the instruction + // which triggered our watchpoint. + if (m_watchpoint_did_occur) { + if (m_watchpoint_hw_index >= 0) { + kern_return_t kret = GetDBGState(false); + if (kret == KERN_SUCCESS && + !IsWatchpointEnabled(m_state.dbg, m_watchpoint_hw_index)) { + // The watchpoint might have been disabled by the user. We don't need + // to do anything at all + // to enable hardware single stepping. + m_watchpoint_did_occur = false; + m_watchpoint_hw_index = -1; + return; + } + + DisableHardwareWatchpoint(m_watchpoint_hw_index, false); + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() " + "DisableHardwareWatchpoint(%d) called", + m_watchpoint_hw_index); + + // Enable hardware single step to move past the watchpoint-triggering + // instruction. + m_watchpoint_resume_single_step_enabled = + (EnableHardwareSingleStep(true) == KERN_SUCCESS); + + // If we are not able to enable single step to move past the + // watchpoint-triggering instruction, + // at least we should reset the two watchpoint member variables so that + // the next time around + // this callback function is invoked, the enclosing logical branch is + // skipped. + if (!m_watchpoint_resume_single_step_enabled) { + // Reset the two watchpoint member variables. + m_watchpoint_did_occur = false; + m_watchpoint_hw_index = -1; + DNBLogThreadedIf( + LOG_WATCHPOINTS, + "DNBArchMachARM::ThreadWillResume() failed to enable single step"); + } else + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() " + "succeeded to enable single step"); } + } +} - // Disable the triggered watchpoint temporarily before we resume. - // Plus, we try to enable hardware single step to execute past the instruction which triggered our watchpoint. - if (m_watchpoint_did_occur) - { - if (m_watchpoint_hw_index >= 0) - { - kern_return_t kret = GetDBGState(false); - if (kret == KERN_SUCCESS && !IsWatchpointEnabled(m_state.dbg, m_watchpoint_hw_index)) { - // The watchpoint might have been disabled by the user. We don't need to do anything at all - // to enable hardware single stepping. - m_watchpoint_did_occur = false; - m_watchpoint_hw_index = -1; - return; - } - - DisableHardwareWatchpoint(m_watchpoint_hw_index, false); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() DisableHardwareWatchpoint(%d) called", - m_watchpoint_hw_index); - - // Enable hardware single step to move past the watchpoint-triggering instruction. - m_watchpoint_resume_single_step_enabled = (EnableHardwareSingleStep(true) == KERN_SUCCESS); - - // If we are not able to enable single step to move past the watchpoint-triggering instruction, - // at least we should reset the two watchpoint member variables so that the next time around - // this callback function is invoked, the enclosing logical branch is skipped. - if (!m_watchpoint_resume_single_step_enabled) { - // Reset the two watchpoint member variables. - m_watchpoint_did_occur = false; - m_watchpoint_hw_index = -1; - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() failed to enable single step"); - } - else - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ThreadWillResume() succeeded to enable single step"); +bool DNBArchMachARM64::NotifyException(MachException::Data &exc) { + + switch (exc.exc_type) { + default: + break; + case EXC_BREAKPOINT: + if (exc.exc_data.size() == 2 && exc.exc_data[0] == EXC_ARM_DA_DEBUG) { + // The data break address is passed as exc_data[1]. + nub_addr_t addr = exc.exc_data[1]; + // Find the hardware index with the side effect of possibly massaging the + // addr to return the starting address as seen from the debugger side. + uint32_t hw_index = GetHardwareWatchpointHit(addr); + + // One logical watchpoint was split into two watchpoint locations because + // it was too big. If the watchpoint exception is indicating the 2nd half + // of the two-parter, find the address of the 1st half and report that -- + // that's what lldb is going to expect to see. + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::NotifyException " + "watchpoint %d was hit on address " + "0x%llx", + hw_index, (uint64_t)addr); + const int num_watchpoints = NumSupportedHardwareWatchpoints(); + for (int i = 0; i < num_watchpoints; i++) { + if (LoHi[i] != 0 && LoHi[i] == hw_index && LoHi[i] != i && + GetWatchpointAddressByIndex(i) != INVALID_NUB_ADDRESS) { + addr = GetWatchpointAddressByIndex(i); + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::NotifyException " + "It is a linked watchpoint; " + "rewritten to index %d addr 0x%llx", + LoHi[i], (uint64_t)addr); } - } -} + } + + if (hw_index != INVALID_NUB_HW_INDEX) { + m_watchpoint_did_occur = true; + m_watchpoint_hw_index = hw_index; + exc.exc_data[1] = addr; + // Piggyback the hw_index in the exc.data. + exc.exc_data.push_back(hw_index); + } -bool -DNBArchMachARM64::NotifyException(MachException::Data& exc) -{ - - switch (exc.exc_type) - { - default: - break; - case EXC_BREAKPOINT: - if (exc.exc_data.size() == 2 && exc.exc_data[0] == EXC_ARM_DA_DEBUG) - { - // The data break address is passed as exc_data[1]. - nub_addr_t addr = exc.exc_data[1]; - // Find the hardware index with the side effect of possibly massaging the - // addr to return the starting address as seen from the debugger side. - uint32_t hw_index = GetHardwareWatchpointHit(addr); - - // One logical watchpoint was split into two watchpoint locations because - // it was too big. If the watchpoint exception is indicating the 2nd half - // of the two-parter, find the address of the 1st half and report that -- - // that's what lldb is going to expect to see. - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::NotifyException watchpoint %d was hit on address 0x%llx", hw_index, (uint64_t) addr); - const int num_watchpoints = NumSupportedHardwareWatchpoints (); - for (int i = 0; i < num_watchpoints; i++) - { - if (LoHi[i] != 0 - && LoHi[i] == hw_index - && LoHi[i] != i - && GetWatchpointAddressByIndex (i) != INVALID_NUB_ADDRESS) - { - addr = GetWatchpointAddressByIndex (i); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::NotifyException It is a linked watchpoint; rewritten to index %d addr 0x%llx", LoHi[i], (uint64_t) addr); - } - } - - if (hw_index != INVALID_NUB_HW_INDEX) - { - m_watchpoint_did_occur = true; - m_watchpoint_hw_index = hw_index; - exc.exc_data[1] = addr; - // Piggyback the hw_index in the exc.data. - exc.exc_data.push_back(hw_index); - } - - return true; - } - break; + return true; } - return false; + break; + } + return false; } -bool -DNBArchMachARM64::ThreadDidStop() -{ - bool success = true; - - m_state.InvalidateAllRegisterStates(); - - if (m_watchpoint_resume_single_step_enabled) - { - // Great! We now disable the hardware single step as well as re-enable the hardware watchpoint. - // See also ThreadWillResume(). - if (EnableHardwareSingleStep(false) == KERN_SUCCESS) - { - if (m_watchpoint_did_occur && m_watchpoint_hw_index >= 0) - { - ReenableHardwareWatchpoint(m_watchpoint_hw_index); - m_watchpoint_resume_single_step_enabled = false; - m_watchpoint_did_occur = false; - m_watchpoint_hw_index = -1; - } - else - { - DNBLogError("internal error detected: m_watchpoint_resume_step_enabled is true but (m_watchpoint_did_occur && m_watchpoint_hw_index >= 0) does not hold!"); - } - } - else - { - DNBLogError("internal error detected: m_watchpoint_resume_step_enabled is true but unable to disable single step!"); - } +bool DNBArchMachARM64::ThreadDidStop() { + bool success = true; + + m_state.InvalidateAllRegisterStates(); + + if (m_watchpoint_resume_single_step_enabled) { + // Great! We now disable the hardware single step as well as re-enable the + // hardware watchpoint. + // See also ThreadWillResume(). + if (EnableHardwareSingleStep(false) == KERN_SUCCESS) { + if (m_watchpoint_did_occur && m_watchpoint_hw_index >= 0) { + ReenableHardwareWatchpoint(m_watchpoint_hw_index); + m_watchpoint_resume_single_step_enabled = false; + m_watchpoint_did_occur = false; + m_watchpoint_hw_index = -1; + } else { + DNBLogError("internal error detected: m_watchpoint_resume_step_enabled " + "is true but (m_watchpoint_did_occur && " + "m_watchpoint_hw_index >= 0) does not hold!"); + } + } else { + DNBLogError("internal error detected: m_watchpoint_resume_step_enabled " + "is true but unable to disable single step!"); } - - // Are we stepping a single instruction? - if (GetGPRState(true) == KERN_SUCCESS) - { - // We are single stepping, was this the primary thread? - if (m_thread->IsStepping()) - { - // This was the primary thread, we need to clear the trace - // bit if so. - success = EnableHardwareSingleStep(false) == KERN_SUCCESS; - } - else - { - // The MachThread will automatically restore the suspend count - // in ThreadDidStop(), so we don't need to do anything here if - // we weren't the primary thread the last time - } + } + + // Are we stepping a single instruction? + if (GetGPRState(true) == KERN_SUCCESS) { + // We are single stepping, was this the primary thread? + if (m_thread->IsStepping()) { + // This was the primary thread, we need to clear the trace + // bit if so. + success = EnableHardwareSingleStep(false) == KERN_SUCCESS; + } else { + // The MachThread will automatically restore the suspend count + // in ThreadDidStop(), so we don't need to do anything here if + // we weren't the primary thread the last time } - return success; + } + return success; } // Set the single step bit in the processor status register. -kern_return_t -DNBArchMachARM64::EnableHardwareSingleStep (bool enable) -{ - DNBError err; - DNBLogThreadedIf(LOG_STEP, "%s( enable = %d )", __FUNCTION__, enable); - - err = GetGPRState(false); - - if (err.Fail()) - { - err.LogThreaded("%s: failed to read the GPR registers", __FUNCTION__); - return err.Error(); - } - - err = GetDBGState(false); - - if (err.Fail()) - { - err.LogThreaded("%s: failed to read the DBG registers", __FUNCTION__); - return err.Error(); - } - - if (enable) - { - DNBLogThreadedIf(LOG_STEP, "%s: Setting MDSCR_EL1 Single Step bit at pc 0x%llx", __FUNCTION__, (uint64_t) m_state.context.gpr.__pc); - m_state.dbg.__mdscr_el1 |= SS_ENABLE; - } - else - { - DNBLogThreadedIf(LOG_STEP, "%s: Clearing MDSCR_EL1 Single Step bit at pc 0x%llx", __FUNCTION__, (uint64_t) m_state.context.gpr.__pc); - m_state.dbg.__mdscr_el1 &= ~(SS_ENABLE); - } - - return SetDBGState(false); +kern_return_t DNBArchMachARM64::EnableHardwareSingleStep(bool enable) { + DNBError err; + DNBLogThreadedIf(LOG_STEP, "%s( enable = %d )", __FUNCTION__, enable); + + err = GetGPRState(false); + + if (err.Fail()) { + err.LogThreaded("%s: failed to read the GPR registers", __FUNCTION__); + return err.Error(); + } + + err = GetDBGState(false); + + if (err.Fail()) { + err.LogThreaded("%s: failed to read the DBG registers", __FUNCTION__); + return err.Error(); + } + + if (enable) { + DNBLogThreadedIf(LOG_STEP, + "%s: Setting MDSCR_EL1 Single Step bit at pc 0x%llx", + __FUNCTION__, (uint64_t)m_state.context.gpr.__pc); + m_state.dbg.__mdscr_el1 |= SS_ENABLE; + } else { + DNBLogThreadedIf(LOG_STEP, + "%s: Clearing MDSCR_EL1 Single Step bit at pc 0x%llx", + __FUNCTION__, (uint64_t)m_state.context.gpr.__pc); + m_state.dbg.__mdscr_el1 &= ~(SS_ENABLE); + } + + return SetDBGState(false); } // return 1 if bit "BIT" is set in "value" -static inline uint32_t bit(uint32_t value, uint32_t bit) -{ - return (value >> bit) & 1u; +static inline uint32_t bit(uint32_t value, uint32_t bit) { + return (value >> bit) & 1u; } // return the bitfield "value[msbit:lsbit]". -static inline uint64_t bits(uint64_t value, uint32_t msbit, uint32_t lsbit) -{ - assert(msbit >= lsbit); - uint64_t shift_left = sizeof(value) * 8 - 1 - msbit; - value <<= shift_left; // shift anything above the msbit off of the unsigned edge - value >>= shift_left + lsbit; // shift it back again down to the lsbit (including undoing any shift from above) - return value; // return our result +static inline uint64_t bits(uint64_t value, uint32_t msbit, uint32_t lsbit) { + assert(msbit >= lsbit); + uint64_t shift_left = sizeof(value) * 8 - 1 - msbit; + value <<= + shift_left; // shift anything above the msbit off of the unsigned edge + value >>= shift_left + lsbit; // shift it back again down to the lsbit + // (including undoing any shift from above) + return value; // return our result } -uint32_t -DNBArchMachARM64::NumSupportedHardwareWatchpoints() -{ - // Set the init value to something that will let us know that we need to - // autodetect how many watchpoints are supported dynamically... - static uint32_t g_num_supported_hw_watchpoints = UINT_MAX; - if (g_num_supported_hw_watchpoints == UINT_MAX) - { - // Set this to zero in case we can't tell if there are any HW breakpoints - g_num_supported_hw_watchpoints = 0; - - - size_t len; - uint32_t n = 0; - len = sizeof (n); - if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0) - { - g_num_supported_hw_watchpoints = n; - DNBLogThreadedIf(LOG_THREAD, "hw.optional.watchpoint=%u", n); - } - else - { - // For AArch64 we would need to look at ID_AA64DFR0_EL1 but debugserver runs in EL0 so it can't - // access that reg. The kernel should have filled in the sysctls based on it though. -#if defined (__arm__) - uint32_t register_DBGDIDR; - - asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR)); - uint32_t numWRPs = bits(register_DBGDIDR, 31, 28); - // Zero is reserved for the WRP count, so don't increment it if it is zero - if (numWRPs > 0) - numWRPs++; - g_num_supported_hw_watchpoints = numWRPs; - DNBLogThreadedIf(LOG_THREAD, "Number of supported hw watchpoints via asm(): %d", g_num_supported_hw_watchpoints); +uint32_t DNBArchMachARM64::NumSupportedHardwareWatchpoints() { + // Set the init value to something that will let us know that we need to + // autodetect how many watchpoints are supported dynamically... + static uint32_t g_num_supported_hw_watchpoints = UINT_MAX; + if (g_num_supported_hw_watchpoints == UINT_MAX) { + // Set this to zero in case we can't tell if there are any HW breakpoints + g_num_supported_hw_watchpoints = 0; + + size_t len; + uint32_t n = 0; + len = sizeof(n); + if (::sysctlbyname("hw.optional.watchpoint", &n, &len, NULL, 0) == 0) { + g_num_supported_hw_watchpoints = n; + DNBLogThreadedIf(LOG_THREAD, "hw.optional.watchpoint=%u", n); + } else { +// For AArch64 we would need to look at ID_AA64DFR0_EL1 but debugserver runs in +// EL0 so it can't +// access that reg. The kernel should have filled in the sysctls based on it +// though. +#if defined(__arm__) + uint32_t register_DBGDIDR; + + asm("mrc p14, 0, %0, c0, c0, 0" : "=r"(register_DBGDIDR)); + uint32_t numWRPs = bits(register_DBGDIDR, 31, 28); + // Zero is reserved for the WRP count, so don't increment it if it is zero + if (numWRPs > 0) + numWRPs++; + g_num_supported_hw_watchpoints = numWRPs; + DNBLogThreadedIf(LOG_THREAD, + "Number of supported hw watchpoints via asm(): %d", + g_num_supported_hw_watchpoints); #endif - } } - return g_num_supported_hw_watchpoints; + } + return g_num_supported_hw_watchpoints; } -uint32_t -DNBArchMachARM64::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task) -{ - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::EnableHardwareWatchpoint(addr = 0x%8.8llx, size = %zu, read = %u, write = %u)", (uint64_t)addr, size, read, write); - - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - - // Can't watch zero bytes - if (size == 0) - return INVALID_NUB_HW_INDEX; - - // We must watch for either read or write - if (read == false && write == false) - return INVALID_NUB_HW_INDEX; - - // Otherwise, can't watch more than 8 bytes per WVR/WCR pair - if (size > 8) - return INVALID_NUB_HW_INDEX; - - // arm64 watchpoints really have an 8-byte alignment requirement. You can put a watchpoint on a 4-byte - // offset address but you can only watch 4 bytes with that watchpoint. - - // arm64 watchpoints on an 8-byte (double word) aligned addr can watch any bytes in that - // 8-byte long region of memory. They can watch the 1st byte, the 2nd byte, 3rd byte, etc, or any - // combination therein by setting the bits in the BAS [12:5] (Byte Address Select) field of - // the DBGWCRn_EL1 reg for the watchpoint. - - // If the MASK [28:24] bits in the DBGWCRn_EL1 allow a single watchpoint to monitor a larger region - // of memory (16 bytes, 32 bytes, or 2GB) but the Byte Address Select bitfield then selects a larger - // range of bytes, instead of individual bytes. See the ARMv8 Debug Architecture manual for details. - // This implementation does not currently use the MASK bits; the largest single region watched by a single - // watchpoint right now is 8-bytes. - - nub_addr_t aligned_wp_address = addr & ~0x7; - uint32_t addr_dword_offset = addr & 0x7; - - // Do we need to split up this logical watchpoint into two hardware watchpoint - // registers? - // e.g. a watchpoint of length 4 on address 6. We need do this with - // one watchpoint on address 0 with bytes 6 & 7 being monitored - // one watchpoint on address 8 with bytes 0, 1, 2, 3 being monitored - - if (addr_dword_offset + size > 8) - { - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::EnableHardwareWatchpoint(addr = 0x%8.8llx, size = %zu) needs two hardware watchpoints slots to monitor", (uint64_t)addr, size); - int low_watchpoint_size = 8 - addr_dword_offset; - int high_watchpoint_size = addr_dword_offset + size - 8; - - uint32_t lo = EnableHardwareWatchpoint(addr, low_watchpoint_size, read, write, also_set_on_task); - if (lo == INVALID_NUB_HW_INDEX) - return INVALID_NUB_HW_INDEX; - uint32_t hi = EnableHardwareWatchpoint (aligned_wp_address + 8, high_watchpoint_size, read, write, also_set_on_task); - if (hi == INVALID_NUB_HW_INDEX) - { - DisableHardwareWatchpoint (lo, also_set_on_task); - return INVALID_NUB_HW_INDEX; - } - // Tag this lo->hi mapping in our database. - LoHi[lo] = hi; - return lo; - } - - // At this point - // 1 aligned_wp_address is the requested address rounded down to 8-byte alignment - // 2 addr_dword_offset is the offset into that double word (8-byte) region that we are watching - // 3 size is the number of bytes within that 8-byte region that we are watching - - // Set the Byte Address Selects bits DBGWCRn_EL1 bits [12:5] based on the above. - // The bit shift and negation operation will give us 0b11 for 2, 0b1111 for 4, etc, up to 0b11111111 for 8. - // then we shift those bits left by the offset into this dword that we are interested in. - // e.g. if we are watching bytes 4,5,6,7 in a dword we want a BAS of 0b11110000. - uint32_t byte_address_select = ((1 << size) - 1) << addr_dword_offset; - - // Read the debug state - kern_return_t kret = GetDBGState(false); - - if (kret == KERN_SUCCESS) - { - // Check to make sure we have the needed hardware support - uint32_t i = 0; - - for (i=0; i<num_hw_watchpoints; ++i) - { - if ((m_state.dbg.__wcr[i] & WCR_ENABLE) == 0) - break; // We found an available hw watchpoint slot (in i) - } +uint32_t DNBArchMachARM64::EnableHardwareWatchpoint(nub_addr_t addr, + nub_size_t size, bool read, + bool write, + bool also_set_on_task) { + DNBLogThreadedIf(LOG_WATCHPOINTS, + "DNBArchMachARM64::EnableHardwareWatchpoint(addr = " + "0x%8.8llx, size = %zu, read = %u, write = %u)", + (uint64_t)addr, size, read, write); - // See if we found an available hw watchpoint slot above - if (i < num_hw_watchpoints) - { - //DumpDBGState(m_state.dbg); + const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - // Clear any previous LoHi joined-watchpoint that may have been in use - LoHi[i] = 0; - - // shift our Byte Address Select bits up to the correct bit range for the DBGWCRn_EL1 - byte_address_select = byte_address_select << 5; - - // Make sure bits 1:0 are clear in our address - m_state.dbg.__wvr[i] = aligned_wp_address; // DVA (Data Virtual Address) - m_state.dbg.__wcr[i] = byte_address_select | // Which bytes that follow the DVA that we will watch - S_USER | // Stop only in user mode - (read ? WCR_LOAD : 0) | // Stop on read access? - (write ? WCR_STORE : 0) | // Stop on write access? - WCR_ENABLE; // Enable this watchpoint; + // Can't watch zero bytes + if (size == 0) + return INVALID_NUB_HW_INDEX; - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::EnableHardwareWatchpoint() adding watchpoint on address 0x%llx with control register value 0x%x", (uint64_t) m_state.dbg.__wvr[i], (uint32_t) m_state.dbg.__wcr[i]); + // We must watch for either read or write + if (read == false && write == false) + return INVALID_NUB_HW_INDEX; - // The kernel will set the MDE_ENABLE bit in the MDSCR_EL1 for us automatically, don't need to do it here. + // Otherwise, can't watch more than 8 bytes per WVR/WCR pair + if (size > 8) + return INVALID_NUB_HW_INDEX; - kret = SetDBGState(also_set_on_task); - //DumpDBGState(m_state.dbg); + // arm64 watchpoints really have an 8-byte alignment requirement. You can put + // a watchpoint on a 4-byte + // offset address but you can only watch 4 bytes with that watchpoint. + + // arm64 watchpoints on an 8-byte (double word) aligned addr can watch any + // bytes in that + // 8-byte long region of memory. They can watch the 1st byte, the 2nd byte, + // 3rd byte, etc, or any + // combination therein by setting the bits in the BAS [12:5] (Byte Address + // Select) field of + // the DBGWCRn_EL1 reg for the watchpoint. + + // If the MASK [28:24] bits in the DBGWCRn_EL1 allow a single watchpoint to + // monitor a larger region + // of memory (16 bytes, 32 bytes, or 2GB) but the Byte Address Select bitfield + // then selects a larger + // range of bytes, instead of individual bytes. See the ARMv8 Debug + // Architecture manual for details. + // This implementation does not currently use the MASK bits; the largest + // single region watched by a single + // watchpoint right now is 8-bytes. + + nub_addr_t aligned_wp_address = addr & ~0x7; + uint32_t addr_dword_offset = addr & 0x7; + + // Do we need to split up this logical watchpoint into two hardware watchpoint + // registers? + // e.g. a watchpoint of length 4 on address 6. We need do this with + // one watchpoint on address 0 with bytes 6 & 7 being monitored + // one watchpoint on address 8 with bytes 0, 1, 2, 3 being monitored + + if (addr_dword_offset + size > 8) { + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::" + "EnableHardwareWatchpoint(addr = " + "0x%8.8llx, size = %zu) needs two " + "hardware watchpoints slots to monitor", + (uint64_t)addr, size); + int low_watchpoint_size = 8 - addr_dword_offset; + int high_watchpoint_size = addr_dword_offset + size - 8; + + uint32_t lo = EnableHardwareWatchpoint(addr, low_watchpoint_size, read, + write, also_set_on_task); + if (lo == INVALID_NUB_HW_INDEX) + return INVALID_NUB_HW_INDEX; + uint32_t hi = + EnableHardwareWatchpoint(aligned_wp_address + 8, high_watchpoint_size, + read, write, also_set_on_task); + if (hi == INVALID_NUB_HW_INDEX) { + DisableHardwareWatchpoint(lo, also_set_on_task); + return INVALID_NUB_HW_INDEX; + } + // Tag this lo->hi mapping in our database. + LoHi[lo] = hi; + return lo; + } + + // At this point + // 1 aligned_wp_address is the requested address rounded down to 8-byte + // alignment + // 2 addr_dword_offset is the offset into that double word (8-byte) region + // that we are watching + // 3 size is the number of bytes within that 8-byte region that we are + // watching + + // Set the Byte Address Selects bits DBGWCRn_EL1 bits [12:5] based on the + // above. + // The bit shift and negation operation will give us 0b11 for 2, 0b1111 for 4, + // etc, up to 0b11111111 for 8. + // then we shift those bits left by the offset into this dword that we are + // interested in. + // e.g. if we are watching bytes 4,5,6,7 in a dword we want a BAS of + // 0b11110000. + uint32_t byte_address_select = ((1 << size) - 1) << addr_dword_offset; + + // Read the debug state + kern_return_t kret = GetDBGState(false); + + if (kret == KERN_SUCCESS) { + // Check to make sure we have the needed hardware support + uint32_t i = 0; - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::EnableHardwareWatchpoint() SetDBGState() => 0x%8.8x.", kret); + for (i = 0; i < num_hw_watchpoints; ++i) { + if ((m_state.dbg.__wcr[i] & WCR_ENABLE) == 0) + break; // We found an available hw watchpoint slot (in i) + } - if (kret == KERN_SUCCESS) - return i; - } - else - { - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints); - } + // See if we found an available hw watchpoint slot above + if (i < num_hw_watchpoints) { + // DumpDBGState(m_state.dbg); + + // Clear any previous LoHi joined-watchpoint that may have been in use + LoHi[i] = 0; + + // shift our Byte Address Select bits up to the correct bit range for the + // DBGWCRn_EL1 + byte_address_select = byte_address_select << 5; + + // Make sure bits 1:0 are clear in our address + m_state.dbg.__wvr[i] = aligned_wp_address; // DVA (Data Virtual Address) + m_state.dbg.__wcr[i] = byte_address_select | // Which bytes that follow + // the DVA that we will watch + S_USER | // Stop only in user mode + (read ? WCR_LOAD : 0) | // Stop on read access? + (write ? WCR_STORE : 0) | // Stop on write access? + WCR_ENABLE; // Enable this watchpoint; + + DNBLogThreadedIf( + LOG_WATCHPOINTS, "DNBArchMachARM64::EnableHardwareWatchpoint() " + "adding watchpoint on address 0x%llx with control " + "register value 0x%x", + (uint64_t)m_state.dbg.__wvr[i], (uint32_t)m_state.dbg.__wcr[i]); + + // The kernel will set the MDE_ENABLE bit in the MDSCR_EL1 for us + // automatically, don't need to do it here. + + kret = SetDBGState(also_set_on_task); + // DumpDBGState(m_state.dbg); + + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::" + "EnableHardwareWatchpoint() " + "SetDBGState() => 0x%8.8x.", + kret); + + if (kret == KERN_SUCCESS) + return i; + } else { + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::" + "EnableHardwareWatchpoint(): All " + "hardware resources (%u) are in use.", + num_hw_watchpoints); } - return INVALID_NUB_HW_INDEX; + } + return INVALID_NUB_HW_INDEX; } -bool -DNBArchMachARM64::ReenableHardwareWatchpoint (uint32_t hw_index) -{ - // If this logical watchpoint # is actually implemented using - // two hardware watchpoint registers, re-enable both of them. +bool DNBArchMachARM64::ReenableHardwareWatchpoint(uint32_t hw_index) { + // If this logical watchpoint # is actually implemented using + // two hardware watchpoint registers, re-enable both of them. - if (hw_index < NumSupportedHardwareWatchpoints() && LoHi[hw_index]) - { - return ReenableHardwareWatchpoint_helper (hw_index) && ReenableHardwareWatchpoint_helper (LoHi[hw_index]); - } - else - { - return ReenableHardwareWatchpoint_helper (hw_index); - } + if (hw_index < NumSupportedHardwareWatchpoints() && LoHi[hw_index]) { + return ReenableHardwareWatchpoint_helper(hw_index) && + ReenableHardwareWatchpoint_helper(LoHi[hw_index]); + } else { + return ReenableHardwareWatchpoint_helper(hw_index); + } } -bool -DNBArchMachARM64::ReenableHardwareWatchpoint_helper (uint32_t hw_index) -{ - kern_return_t kret = GetDBGState(false); - if (kret != KERN_SUCCESS) - return false; +bool DNBArchMachARM64::ReenableHardwareWatchpoint_helper(uint32_t hw_index) { + kern_return_t kret = GetDBGState(false); + if (kret != KERN_SUCCESS) + return false; - const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); - if (hw_index >= num_hw_points) - return false; + const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); + if (hw_index >= num_hw_points) + return false; - m_state.dbg.__wvr[hw_index] = m_disabled_watchpoints[hw_index].addr; - m_state.dbg.__wcr[hw_index] = m_disabled_watchpoints[hw_index].control; + m_state.dbg.__wvr[hw_index] = m_disabled_watchpoints[hw_index].addr; + m_state.dbg.__wcr[hw_index] = m_disabled_watchpoints[hw_index].control; - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::EnableHardwareWatchpoint( %u ) - WVR%u = 0x%8.8llx WCR%u = 0x%8.8llx", - hw_index, - hw_index, - (uint64_t) m_state.dbg.__wvr[hw_index], - hw_index, - (uint64_t) m_state.dbg.__wcr[hw_index]); + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::" + "EnableHardwareWatchpoint( %u ) - WVR%u = " + "0x%8.8llx WCR%u = 0x%8.8llx", + hw_index, hw_index, (uint64_t)m_state.dbg.__wvr[hw_index], + hw_index, (uint64_t)m_state.dbg.__wcr[hw_index]); - // The kernel will set the MDE_ENABLE bit in the MDSCR_EL1 for us automatically, don't need to do it here. + // The kernel will set the MDE_ENABLE bit in the MDSCR_EL1 for us + // automatically, don't need to do it here. - kret = SetDBGState(false); + kret = SetDBGState(false); - return (kret == KERN_SUCCESS); + return (kret == KERN_SUCCESS); } -bool -DNBArchMachARM64::DisableHardwareWatchpoint (uint32_t hw_index, bool also_set_on_task) -{ - if (hw_index < NumSupportedHardwareWatchpoints() && LoHi[hw_index]) - { - return DisableHardwareWatchpoint_helper (hw_index, also_set_on_task) && DisableHardwareWatchpoint_helper (LoHi[hw_index], also_set_on_task); - } - else - { - return DisableHardwareWatchpoint_helper (hw_index, also_set_on_task); - } +bool DNBArchMachARM64::DisableHardwareWatchpoint(uint32_t hw_index, + bool also_set_on_task) { + if (hw_index < NumSupportedHardwareWatchpoints() && LoHi[hw_index]) { + return DisableHardwareWatchpoint_helper(hw_index, also_set_on_task) && + DisableHardwareWatchpoint_helper(LoHi[hw_index], also_set_on_task); + } else { + return DisableHardwareWatchpoint_helper(hw_index, also_set_on_task); + } } -bool -DNBArchMachARM64::DisableHardwareWatchpoint_helper (uint32_t hw_index, bool also_set_on_task) -{ - kern_return_t kret = GetDBGState(false); - if (kret != KERN_SUCCESS) - return false; +bool DNBArchMachARM64::DisableHardwareWatchpoint_helper(uint32_t hw_index, + bool also_set_on_task) { + kern_return_t kret = GetDBGState(false); + if (kret != KERN_SUCCESS) + return false; - const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); - if (hw_index >= num_hw_points) - return false; + const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); + if (hw_index >= num_hw_points) + return false; - m_disabled_watchpoints[hw_index].addr = m_state.dbg.__wvr[hw_index]; - m_disabled_watchpoints[hw_index].control = m_state.dbg.__wcr[hw_index]; + m_disabled_watchpoints[hw_index].addr = m_state.dbg.__wvr[hw_index]; + m_disabled_watchpoints[hw_index].control = m_state.dbg.__wcr[hw_index]; - m_state.dbg.__wcr[hw_index] &= ~((nub_addr_t)WCR_ENABLE); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::DisableHardwareWatchpoint( %u ) - WVR%u = 0x%8.8llx WCR%u = 0x%8.8llx", - hw_index, - hw_index, - (uint64_t) m_state.dbg.__wvr[hw_index], - hw_index, - (uint64_t) m_state.dbg.__wcr[hw_index]); + m_state.dbg.__wcr[hw_index] &= ~((nub_addr_t)WCR_ENABLE); + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::" + "DisableHardwareWatchpoint( %u ) - WVR%u = " + "0x%8.8llx WCR%u = 0x%8.8llx", + hw_index, hw_index, (uint64_t)m_state.dbg.__wvr[hw_index], + hw_index, (uint64_t)m_state.dbg.__wcr[hw_index]); - kret = SetDBGState(also_set_on_task); + kret = SetDBGState(also_set_on_task); - return (kret == KERN_SUCCESS); + return (kret == KERN_SUCCESS); } -// This is for checking the Byte Address Select bits in the DBRWCRn_EL1 control register. +// This is for checking the Byte Address Select bits in the DBRWCRn_EL1 control +// register. // Returns -1 if the trailing bit patterns are not one of: -// { 0b???????1, 0b??????10, 0b?????100, 0b????1000, 0b???10000, 0b??100000, 0b?1000000, 0b10000000 }. -static inline -int32_t -LowestBitSet(uint32_t val) -{ - for (unsigned i = 0; i < 8; ++i) { - if (bit(val, i)) - return i; - } - return -1; +// { 0b???????1, 0b??????10, 0b?????100, 0b????1000, 0b???10000, 0b??100000, +// 0b?1000000, 0b10000000 }. +static inline int32_t LowestBitSet(uint32_t val) { + for (unsigned i = 0; i < 8; ++i) { + if (bit(val, i)) + return i; + } + return -1; } -// Iterate through the debug registers; return the index of the first watchpoint whose address matches. -// As a side effect, the starting address as understood by the debugger is returned which could be +// Iterate through the debug registers; return the index of the first watchpoint +// whose address matches. +// As a side effect, the starting address as understood by the debugger is +// returned which could be // different from 'addr' passed as an in/out argument. -uint32_t -DNBArchMachARM64::GetHardwareWatchpointHit(nub_addr_t &addr) -{ - // Read the debug state - kern_return_t kret = GetDBGState(true); - //DumpDBGState(m_state.dbg); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::GetHardwareWatchpointHit() addr = 0x%llx", (uint64_t)addr); - - // This is the watchpoint value to match against, i.e., word address. - nub_addr_t wp_val = addr & ~((nub_addr_t)3); - if (kret == KERN_SUCCESS) - { - DBG &debug_state = m_state.dbg; - uint32_t i, num = NumSupportedHardwareWatchpoints(); - for (i = 0; i < num; ++i) - { - nub_addr_t wp_addr = GetWatchAddress(debug_state, i); - DNBLogThreadedIf(LOG_WATCHPOINTS, - "DNBArchMachARM64::GetHardwareWatchpointHit() slot: %u (addr = 0x%llx).", - i, (uint64_t)wp_addr); - if (wp_val == wp_addr) { - uint32_t byte_mask = bits(debug_state.__wcr[i], 12, 5); - - // Sanity check the byte_mask, first. - if (LowestBitSet(byte_mask) < 0) - continue; - - // Check that the watchpoint is enabled. - if (!IsWatchpointEnabled(debug_state, i)) - continue; - - // Compute the starting address (from the point of view of the debugger). - addr = wp_addr + LowestBitSet(byte_mask); - return i; - } - } +uint32_t DNBArchMachARM64::GetHardwareWatchpointHit(nub_addr_t &addr) { + // Read the debug state + kern_return_t kret = GetDBGState(true); + // DumpDBGState(m_state.dbg); + DNBLogThreadedIf( + LOG_WATCHPOINTS, + "DNBArchMachARM64::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", + kret); + DNBLogThreadedIf(LOG_WATCHPOINTS, + "DNBArchMachARM64::GetHardwareWatchpointHit() addr = 0x%llx", + (uint64_t)addr); + + // This is the watchpoint value to match against, i.e., word address. + nub_addr_t wp_val = addr & ~((nub_addr_t)3); + if (kret == KERN_SUCCESS) { + DBG &debug_state = m_state.dbg; + uint32_t i, num = NumSupportedHardwareWatchpoints(); + for (i = 0; i < num; ++i) { + nub_addr_t wp_addr = GetWatchAddress(debug_state, i); + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM64::" + "GetHardwareWatchpointHit() slot: %u " + "(addr = 0x%llx).", + i, (uint64_t)wp_addr); + if (wp_val == wp_addr) { + uint32_t byte_mask = bits(debug_state.__wcr[i], 12, 5); + + // Sanity check the byte_mask, first. + if (LowestBitSet(byte_mask) < 0) + continue; + + // Check that the watchpoint is enabled. + if (!IsWatchpointEnabled(debug_state, i)) + continue; + + // Compute the starting address (from the point of view of the + // debugger). + addr = wp_addr + LowestBitSet(byte_mask); + return i; + } } - return INVALID_NUB_HW_INDEX; + } + return INVALID_NUB_HW_INDEX; } -nub_addr_t -DNBArchMachARM64::GetWatchpointAddressByIndex (uint32_t hw_index) -{ - kern_return_t kret = GetDBGState(true); - if (kret != KERN_SUCCESS) - return INVALID_NUB_ADDRESS; - const uint32_t num = NumSupportedHardwareWatchpoints(); - if (hw_index >= num) - return INVALID_NUB_ADDRESS; - if (IsWatchpointEnabled (m_state.dbg, hw_index)) - return GetWatchAddress (m_state.dbg, hw_index); +nub_addr_t DNBArchMachARM64::GetWatchpointAddressByIndex(uint32_t hw_index) { + kern_return_t kret = GetDBGState(true); + if (kret != KERN_SUCCESS) + return INVALID_NUB_ADDRESS; + const uint32_t num = NumSupportedHardwareWatchpoints(); + if (hw_index >= num) return INVALID_NUB_ADDRESS; + if (IsWatchpointEnabled(m_state.dbg, hw_index)) + return GetWatchAddress(m_state.dbg, hw_index); + return INVALID_NUB_ADDRESS; } -bool -DNBArchMachARM64::IsWatchpointEnabled(const DBG &debug_state, uint32_t hw_index) -{ - // Watchpoint Control Registers, bitfield definitions - // ... - // Bits Value Description - // [0] 0 Watchpoint disabled - // 1 Watchpoint enabled. - return (debug_state.__wcr[hw_index] & 1u); +bool DNBArchMachARM64::IsWatchpointEnabled(const DBG &debug_state, + uint32_t hw_index) { + // Watchpoint Control Registers, bitfield definitions + // ... + // Bits Value Description + // [0] 0 Watchpoint disabled + // 1 Watchpoint enabled. + return (debug_state.__wcr[hw_index] & 1u); } -nub_addr_t -DNBArchMachARM64::GetWatchAddress(const DBG &debug_state, uint32_t hw_index) -{ - // Watchpoint Value Registers, bitfield definitions - // Bits Description - // [31:2] Watchpoint value (word address, i.e., 4-byte aligned) - // [1:0] RAZ/SBZP - return bits(debug_state.__wvr[hw_index], 63, 0); +nub_addr_t DNBArchMachARM64::GetWatchAddress(const DBG &debug_state, + uint32_t hw_index) { + // Watchpoint Value Registers, bitfield definitions + // Bits Description + // [31:2] Watchpoint value (word address, i.e., 4-byte aligned) + // [1:0] RAZ/SBZP + return bits(debug_state.__wvr[hw_index], 63, 0); } //---------------------------------------------------------------------- // Register information definitions for 64 bit ARMv8. //---------------------------------------------------------------------- -enum gpr_regnums -{ - gpr_x0 = 0, - gpr_x1, - gpr_x2, - gpr_x3, - gpr_x4, - gpr_x5, - gpr_x6, - gpr_x7, - gpr_x8, - gpr_x9, - gpr_x10, - gpr_x11, - gpr_x12, - gpr_x13, - gpr_x14, - gpr_x15, - gpr_x16, - gpr_x17, - gpr_x18, - gpr_x19, - gpr_x20, - gpr_x21, - gpr_x22, - gpr_x23, - gpr_x24, - gpr_x25, - gpr_x26, - gpr_x27, - gpr_x28, - gpr_fp, gpr_x29 = gpr_fp, - gpr_lr, gpr_x30 = gpr_lr, - gpr_sp, gpr_x31 = gpr_sp, - gpr_pc, - gpr_cpsr, - gpr_w0, - gpr_w1, - gpr_w2, - gpr_w3, - gpr_w4, - gpr_w5, - gpr_w6, - gpr_w7, - gpr_w8, - gpr_w9, - gpr_w10, - gpr_w11, - gpr_w12, - gpr_w13, - gpr_w14, - gpr_w15, - gpr_w16, - gpr_w17, - gpr_w18, - gpr_w19, - gpr_w20, - gpr_w21, - gpr_w22, - gpr_w23, - gpr_w24, - gpr_w25, - gpr_w26, - gpr_w27, - gpr_w28 +enum gpr_regnums { + gpr_x0 = 0, + gpr_x1, + gpr_x2, + gpr_x3, + gpr_x4, + gpr_x5, + gpr_x6, + gpr_x7, + gpr_x8, + gpr_x9, + gpr_x10, + gpr_x11, + gpr_x12, + gpr_x13, + gpr_x14, + gpr_x15, + gpr_x16, + gpr_x17, + gpr_x18, + gpr_x19, + gpr_x20, + gpr_x21, + gpr_x22, + gpr_x23, + gpr_x24, + gpr_x25, + gpr_x26, + gpr_x27, + gpr_x28, + gpr_fp, + gpr_x29 = gpr_fp, + gpr_lr, + gpr_x30 = gpr_lr, + gpr_sp, + gpr_x31 = gpr_sp, + gpr_pc, + gpr_cpsr, + gpr_w0, + gpr_w1, + gpr_w2, + gpr_w3, + gpr_w4, + gpr_w5, + gpr_w6, + gpr_w7, + gpr_w8, + gpr_w9, + gpr_w10, + gpr_w11, + gpr_w12, + gpr_w13, + gpr_w14, + gpr_w15, + gpr_w16, + gpr_w17, + gpr_w18, + gpr_w19, + gpr_w20, + gpr_w21, + gpr_w22, + gpr_w23, + gpr_w24, + gpr_w25, + gpr_w26, + gpr_w27, + gpr_w28 }; -enum -{ - vfp_v0 = 0, - vfp_v1, - vfp_v2, - vfp_v3, - vfp_v4, - vfp_v5, - vfp_v6, - vfp_v7, - vfp_v8, - vfp_v9, - vfp_v10, - vfp_v11, - vfp_v12, - vfp_v13, - vfp_v14, - vfp_v15, - vfp_v16, - vfp_v17, - vfp_v18, - vfp_v19, - vfp_v20, - vfp_v21, - vfp_v22, - vfp_v23, - vfp_v24, - vfp_v25, - vfp_v26, - vfp_v27, - vfp_v28, - vfp_v29, - vfp_v30, - vfp_v31, - vfp_fpsr, - vfp_fpcr, - - // lower 32 bits of the corresponding vfp_v<n> reg. - vfp_s0, - vfp_s1, - vfp_s2, - vfp_s3, - vfp_s4, - vfp_s5, - vfp_s6, - vfp_s7, - vfp_s8, - vfp_s9, - vfp_s10, - vfp_s11, - vfp_s12, - vfp_s13, - vfp_s14, - vfp_s15, - vfp_s16, - vfp_s17, - vfp_s18, - vfp_s19, - vfp_s20, - vfp_s21, - vfp_s22, - vfp_s23, - vfp_s24, - vfp_s25, - vfp_s26, - vfp_s27, - vfp_s28, - vfp_s29, - vfp_s30, - vfp_s31, - - // lower 64 bits of the corresponding vfp_v<n> reg. - vfp_d0, - vfp_d1, - vfp_d2, - vfp_d3, - vfp_d4, - vfp_d5, - vfp_d6, - vfp_d7, - vfp_d8, - vfp_d9, - vfp_d10, - vfp_d11, - vfp_d12, - vfp_d13, - vfp_d14, - vfp_d15, - vfp_d16, - vfp_d17, - vfp_d18, - vfp_d19, - vfp_d20, - vfp_d21, - vfp_d22, - vfp_d23, - vfp_d24, - vfp_d25, - vfp_d26, - vfp_d27, - vfp_d28, - vfp_d29, - vfp_d30, - vfp_d31 +enum { + vfp_v0 = 0, + vfp_v1, + vfp_v2, + vfp_v3, + vfp_v4, + vfp_v5, + vfp_v6, + vfp_v7, + vfp_v8, + vfp_v9, + vfp_v10, + vfp_v11, + vfp_v12, + vfp_v13, + vfp_v14, + vfp_v15, + vfp_v16, + vfp_v17, + vfp_v18, + vfp_v19, + vfp_v20, + vfp_v21, + vfp_v22, + vfp_v23, + vfp_v24, + vfp_v25, + vfp_v26, + vfp_v27, + vfp_v28, + vfp_v29, + vfp_v30, + vfp_v31, + vfp_fpsr, + vfp_fpcr, + + // lower 32 bits of the corresponding vfp_v<n> reg. + vfp_s0, + vfp_s1, + vfp_s2, + vfp_s3, + vfp_s4, + vfp_s5, + vfp_s6, + vfp_s7, + vfp_s8, + vfp_s9, + vfp_s10, + vfp_s11, + vfp_s12, + vfp_s13, + vfp_s14, + vfp_s15, + vfp_s16, + vfp_s17, + vfp_s18, + vfp_s19, + vfp_s20, + vfp_s21, + vfp_s22, + vfp_s23, + vfp_s24, + vfp_s25, + vfp_s26, + vfp_s27, + vfp_s28, + vfp_s29, + vfp_s30, + vfp_s31, + + // lower 64 bits of the corresponding vfp_v<n> reg. + vfp_d0, + vfp_d1, + vfp_d2, + vfp_d3, + vfp_d4, + vfp_d5, + vfp_d6, + vfp_d7, + vfp_d8, + vfp_d9, + vfp_d10, + vfp_d11, + vfp_d12, + vfp_d13, + vfp_d14, + vfp_d15, + vfp_d16, + vfp_d17, + vfp_d18, + vfp_d19, + vfp_d20, + vfp_d21, + vfp_d22, + vfp_d23, + vfp_d24, + vfp_d25, + vfp_d26, + vfp_d27, + vfp_d28, + vfp_d29, + vfp_d30, + vfp_d31 }; -enum -{ - exc_far = 0, - exc_esr, - exc_exception +enum { exc_far = 0, exc_esr, exc_exception }; + +// These numbers from the "DWARF for the ARM 64-bit Architecture (AArch64)" +// document. + +enum { + dwarf_x0 = 0, + dwarf_x1, + dwarf_x2, + dwarf_x3, + dwarf_x4, + dwarf_x5, + dwarf_x6, + dwarf_x7, + dwarf_x8, + dwarf_x9, + dwarf_x10, + dwarf_x11, + dwarf_x12, + dwarf_x13, + dwarf_x14, + dwarf_x15, + dwarf_x16, + dwarf_x17, + dwarf_x18, + dwarf_x19, + dwarf_x20, + dwarf_x21, + dwarf_x22, + dwarf_x23, + dwarf_x24, + dwarf_x25, + dwarf_x26, + dwarf_x27, + dwarf_x28, + dwarf_x29, + dwarf_x30, + dwarf_x31, + dwarf_pc = 32, + dwarf_elr_mode = 33, + dwarf_fp = dwarf_x29, + dwarf_lr = dwarf_x30, + dwarf_sp = dwarf_x31, + // 34-63 reserved + + // V0-V31 (128 bit vector registers) + dwarf_v0 = 64, + dwarf_v1, + dwarf_v2, + dwarf_v3, + dwarf_v4, + dwarf_v5, + dwarf_v6, + dwarf_v7, + dwarf_v8, + dwarf_v9, + dwarf_v10, + dwarf_v11, + dwarf_v12, + dwarf_v13, + dwarf_v14, + dwarf_v15, + dwarf_v16, + dwarf_v17, + dwarf_v18, + dwarf_v19, + dwarf_v20, + dwarf_v21, + dwarf_v22, + dwarf_v23, + dwarf_v24, + dwarf_v25, + dwarf_v26, + dwarf_v27, + dwarf_v28, + dwarf_v29, + dwarf_v30, + dwarf_v31 + + // 96-127 reserved }; -// These numbers from the "DWARF for the ARM 64-bit Architecture (AArch64)" document. - -enum -{ - dwarf_x0 = 0, - dwarf_x1, - dwarf_x2, - dwarf_x3, - dwarf_x4, - dwarf_x5, - dwarf_x6, - dwarf_x7, - dwarf_x8, - dwarf_x9, - dwarf_x10, - dwarf_x11, - dwarf_x12, - dwarf_x13, - dwarf_x14, - dwarf_x15, - dwarf_x16, - dwarf_x17, - dwarf_x18, - dwarf_x19, - dwarf_x20, - dwarf_x21, - dwarf_x22, - dwarf_x23, - dwarf_x24, - dwarf_x25, - dwarf_x26, - dwarf_x27, - dwarf_x28, - dwarf_x29, - dwarf_x30, - dwarf_x31, - dwarf_pc = 32, - dwarf_elr_mode = 33, - dwarf_fp = dwarf_x29, - dwarf_lr = dwarf_x30, - dwarf_sp = dwarf_x31, - // 34-63 reserved - - // V0-V31 (128 bit vector registers) - dwarf_v0 = 64, - dwarf_v1, - dwarf_v2, - dwarf_v3, - dwarf_v4, - dwarf_v5, - dwarf_v6, - dwarf_v7, - dwarf_v8, - dwarf_v9, - dwarf_v10, - dwarf_v11, - dwarf_v12, - dwarf_v13, - dwarf_v14, - dwarf_v15, - dwarf_v16, - dwarf_v17, - dwarf_v18, - dwarf_v19, - dwarf_v20, - dwarf_v21, - dwarf_v22, - dwarf_v23, - dwarf_v24, - dwarf_v25, - dwarf_v26, - dwarf_v27, - dwarf_v28, - dwarf_v29, - dwarf_v30, - dwarf_v31 - - // 96-127 reserved +enum { + debugserver_gpr_x0 = 0, + debugserver_gpr_x1, + debugserver_gpr_x2, + debugserver_gpr_x3, + debugserver_gpr_x4, + debugserver_gpr_x5, + debugserver_gpr_x6, + debugserver_gpr_x7, + debugserver_gpr_x8, + debugserver_gpr_x9, + debugserver_gpr_x10, + debugserver_gpr_x11, + debugserver_gpr_x12, + debugserver_gpr_x13, + debugserver_gpr_x14, + debugserver_gpr_x15, + debugserver_gpr_x16, + debugserver_gpr_x17, + debugserver_gpr_x18, + debugserver_gpr_x19, + debugserver_gpr_x20, + debugserver_gpr_x21, + debugserver_gpr_x22, + debugserver_gpr_x23, + debugserver_gpr_x24, + debugserver_gpr_x25, + debugserver_gpr_x26, + debugserver_gpr_x27, + debugserver_gpr_x28, + debugserver_gpr_fp, // x29 + debugserver_gpr_lr, // x30 + debugserver_gpr_sp, // sp aka xsp + debugserver_gpr_pc, + debugserver_gpr_cpsr, + debugserver_vfp_v0, + debugserver_vfp_v1, + debugserver_vfp_v2, + debugserver_vfp_v3, + debugserver_vfp_v4, + debugserver_vfp_v5, + debugserver_vfp_v6, + debugserver_vfp_v7, + debugserver_vfp_v8, + debugserver_vfp_v9, + debugserver_vfp_v10, + debugserver_vfp_v11, + debugserver_vfp_v12, + debugserver_vfp_v13, + debugserver_vfp_v14, + debugserver_vfp_v15, + debugserver_vfp_v16, + debugserver_vfp_v17, + debugserver_vfp_v18, + debugserver_vfp_v19, + debugserver_vfp_v20, + debugserver_vfp_v21, + debugserver_vfp_v22, + debugserver_vfp_v23, + debugserver_vfp_v24, + debugserver_vfp_v25, + debugserver_vfp_v26, + debugserver_vfp_v27, + debugserver_vfp_v28, + debugserver_vfp_v29, + debugserver_vfp_v30, + debugserver_vfp_v31, + debugserver_vfp_fpsr, + debugserver_vfp_fpcr }; -enum -{ - debugserver_gpr_x0 = 0, - debugserver_gpr_x1, - debugserver_gpr_x2, - debugserver_gpr_x3, - debugserver_gpr_x4, - debugserver_gpr_x5, - debugserver_gpr_x6, - debugserver_gpr_x7, - debugserver_gpr_x8, - debugserver_gpr_x9, - debugserver_gpr_x10, - debugserver_gpr_x11, - debugserver_gpr_x12, - debugserver_gpr_x13, - debugserver_gpr_x14, - debugserver_gpr_x15, - debugserver_gpr_x16, - debugserver_gpr_x17, - debugserver_gpr_x18, - debugserver_gpr_x19, - debugserver_gpr_x20, - debugserver_gpr_x21, - debugserver_gpr_x22, - debugserver_gpr_x23, - debugserver_gpr_x24, - debugserver_gpr_x25, - debugserver_gpr_x26, - debugserver_gpr_x27, - debugserver_gpr_x28, - debugserver_gpr_fp, // x29 - debugserver_gpr_lr, // x30 - debugserver_gpr_sp, // sp aka xsp - debugserver_gpr_pc, - debugserver_gpr_cpsr, - debugserver_vfp_v0, - debugserver_vfp_v1, - debugserver_vfp_v2, - debugserver_vfp_v3, - debugserver_vfp_v4, - debugserver_vfp_v5, - debugserver_vfp_v6, - debugserver_vfp_v7, - debugserver_vfp_v8, - debugserver_vfp_v9, - debugserver_vfp_v10, - debugserver_vfp_v11, - debugserver_vfp_v12, - debugserver_vfp_v13, - debugserver_vfp_v14, - debugserver_vfp_v15, - debugserver_vfp_v16, - debugserver_vfp_v17, - debugserver_vfp_v18, - debugserver_vfp_v19, - debugserver_vfp_v20, - debugserver_vfp_v21, - debugserver_vfp_v22, - debugserver_vfp_v23, - debugserver_vfp_v24, - debugserver_vfp_v25, - debugserver_vfp_v26, - debugserver_vfp_v27, - debugserver_vfp_v28, - debugserver_vfp_v29, - debugserver_vfp_v30, - debugserver_vfp_v31, - debugserver_vfp_fpsr, - debugserver_vfp_fpcr -}; - -const char *g_contained_x0[] {"x0", NULL }; -const char *g_contained_x1[] {"x1", NULL }; -const char *g_contained_x2[] {"x2", NULL }; -const char *g_contained_x3[] {"x3", NULL }; -const char *g_contained_x4[] {"x4", NULL }; -const char *g_contained_x5[] {"x5", NULL }; -const char *g_contained_x6[] {"x6", NULL }; -const char *g_contained_x7[] {"x7", NULL }; -const char *g_contained_x8[] {"x8", NULL }; -const char *g_contained_x9[] {"x9", NULL }; -const char *g_contained_x10[] {"x10", NULL }; -const char *g_contained_x11[] {"x11", NULL }; -const char *g_contained_x12[] {"x12", NULL }; -const char *g_contained_x13[] {"x13", NULL }; -const char *g_contained_x14[] {"x14", NULL }; -const char *g_contained_x15[] {"x15", NULL }; -const char *g_contained_x16[] {"x16", NULL }; -const char *g_contained_x17[] {"x17", NULL }; -const char *g_contained_x18[] {"x18", NULL }; -const char *g_contained_x19[] {"x19", NULL }; -const char *g_contained_x20[] {"x20", NULL }; -const char *g_contained_x21[] {"x21", NULL }; -const char *g_contained_x22[] {"x22", NULL }; -const char *g_contained_x23[] {"x23", NULL }; -const char *g_contained_x24[] {"x24", NULL }; -const char *g_contained_x25[] {"x25", NULL }; -const char *g_contained_x26[] {"x26", NULL }; -const char *g_contained_x27[] {"x27", NULL }; -const char *g_contained_x28[] {"x28", NULL }; - -const char *g_invalidate_x0[] {"x0", "w0", NULL }; -const char *g_invalidate_x1[] {"x1", "w1", NULL }; -const char *g_invalidate_x2[] {"x2", "w2", NULL }; -const char *g_invalidate_x3[] {"x3", "w3", NULL }; -const char *g_invalidate_x4[] {"x4", "w4", NULL }; -const char *g_invalidate_x5[] {"x5", "w5", NULL }; -const char *g_invalidate_x6[] {"x6", "w6", NULL }; -const char *g_invalidate_x7[] {"x7", "w7", NULL }; -const char *g_invalidate_x8[] {"x8", "w8", NULL }; -const char *g_invalidate_x9[] {"x9", "w9", NULL }; -const char *g_invalidate_x10[] {"x10", "w10", NULL }; -const char *g_invalidate_x11[] {"x11", "w11", NULL }; -const char *g_invalidate_x12[] {"x12", "w12", NULL }; -const char *g_invalidate_x13[] {"x13", "w13", NULL }; -const char *g_invalidate_x14[] {"x14", "w14", NULL }; -const char *g_invalidate_x15[] {"x15", "w15", NULL }; -const char *g_invalidate_x16[] {"x16", "w16", NULL }; -const char *g_invalidate_x17[] {"x17", "w17", NULL }; -const char *g_invalidate_x18[] {"x18", "w18", NULL }; -const char *g_invalidate_x19[] {"x19", "w19", NULL }; -const char *g_invalidate_x20[] {"x20", "w20", NULL }; -const char *g_invalidate_x21[] {"x21", "w21", NULL }; -const char *g_invalidate_x22[] {"x22", "w22", NULL }; -const char *g_invalidate_x23[] {"x23", "w23", NULL }; -const char *g_invalidate_x24[] {"x24", "w24", NULL }; -const char *g_invalidate_x25[] {"x25", "w25", NULL }; -const char *g_invalidate_x26[] {"x26", "w26", NULL }; -const char *g_invalidate_x27[] {"x27", "w27", NULL }; -const char *g_invalidate_x28[] {"x28", "w28", NULL }; - -#define GPR_OFFSET_IDX(idx) (offsetof (DNBArchMachARM64::GPR, __x[idx])) - -#define GPR_OFFSET_NAME(reg) (offsetof (DNBArchMachARM64::GPR , __##reg)) +const char *g_contained_x0[]{"x0", NULL}; +const char *g_contained_x1[]{"x1", NULL}; +const char *g_contained_x2[]{"x2", NULL}; +const char *g_contained_x3[]{"x3", NULL}; +const char *g_contained_x4[]{"x4", NULL}; +const char *g_contained_x5[]{"x5", NULL}; +const char *g_contained_x6[]{"x6", NULL}; +const char *g_contained_x7[]{"x7", NULL}; +const char *g_contained_x8[]{"x8", NULL}; +const char *g_contained_x9[]{"x9", NULL}; +const char *g_contained_x10[]{"x10", NULL}; +const char *g_contained_x11[]{"x11", NULL}; +const char *g_contained_x12[]{"x12", NULL}; +const char *g_contained_x13[]{"x13", NULL}; +const char *g_contained_x14[]{"x14", NULL}; +const char *g_contained_x15[]{"x15", NULL}; +const char *g_contained_x16[]{"x16", NULL}; +const char *g_contained_x17[]{"x17", NULL}; +const char *g_contained_x18[]{"x18", NULL}; +const char *g_contained_x19[]{"x19", NULL}; +const char *g_contained_x20[]{"x20", NULL}; +const char *g_contained_x21[]{"x21", NULL}; +const char *g_contained_x22[]{"x22", NULL}; +const char *g_contained_x23[]{"x23", NULL}; +const char *g_contained_x24[]{"x24", NULL}; +const char *g_contained_x25[]{"x25", NULL}; +const char *g_contained_x26[]{"x26", NULL}; +const char *g_contained_x27[]{"x27", NULL}; +const char *g_contained_x28[]{"x28", NULL}; + +const char *g_invalidate_x0[]{"x0", "w0", NULL}; +const char *g_invalidate_x1[]{"x1", "w1", NULL}; +const char *g_invalidate_x2[]{"x2", "w2", NULL}; +const char *g_invalidate_x3[]{"x3", "w3", NULL}; +const char *g_invalidate_x4[]{"x4", "w4", NULL}; +const char *g_invalidate_x5[]{"x5", "w5", NULL}; +const char *g_invalidate_x6[]{"x6", "w6", NULL}; +const char *g_invalidate_x7[]{"x7", "w7", NULL}; +const char *g_invalidate_x8[]{"x8", "w8", NULL}; +const char *g_invalidate_x9[]{"x9", "w9", NULL}; +const char *g_invalidate_x10[]{"x10", "w10", NULL}; +const char *g_invalidate_x11[]{"x11", "w11", NULL}; +const char *g_invalidate_x12[]{"x12", "w12", NULL}; +const char *g_invalidate_x13[]{"x13", "w13", NULL}; +const char *g_invalidate_x14[]{"x14", "w14", NULL}; +const char *g_invalidate_x15[]{"x15", "w15", NULL}; +const char *g_invalidate_x16[]{"x16", "w16", NULL}; +const char *g_invalidate_x17[]{"x17", "w17", NULL}; +const char *g_invalidate_x18[]{"x18", "w18", NULL}; +const char *g_invalidate_x19[]{"x19", "w19", NULL}; +const char *g_invalidate_x20[]{"x20", "w20", NULL}; +const char *g_invalidate_x21[]{"x21", "w21", NULL}; +const char *g_invalidate_x22[]{"x22", "w22", NULL}; +const char *g_invalidate_x23[]{"x23", "w23", NULL}; +const char *g_invalidate_x24[]{"x24", "w24", NULL}; +const char *g_invalidate_x25[]{"x25", "w25", NULL}; +const char *g_invalidate_x26[]{"x26", "w26", NULL}; +const char *g_invalidate_x27[]{"x27", "w27", NULL}; +const char *g_invalidate_x28[]{"x28", "w28", NULL}; + +#define GPR_OFFSET_IDX(idx) (offsetof(DNBArchMachARM64::GPR, __x[idx])) + +#define GPR_OFFSET_NAME(reg) (offsetof(DNBArchMachARM64::GPR, __##reg)) // These macros will auto define the register name, alt name, register size, // register offset, encoding, format and native register. This ensures that // the register state structures are defined correctly and have the correct // sizes and offsets. -#define DEFINE_GPR_IDX(idx, reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 8, GPR_OFFSET_IDX(idx) , dwarf_##reg, dwarf_##reg, gen, debugserver_gpr_##reg, NULL, g_invalidate_x##idx } -#define DEFINE_GPR_NAME(reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 8, GPR_OFFSET_NAME(reg), dwarf_##reg, dwarf_##reg, gen, debugserver_gpr_##reg, NULL, NULL } -#define DEFINE_PSEUDO_GPR_IDX(idx, reg) { e_regSetGPR, gpr_##reg, #reg, NULL, Uint, Hex, 4, 0, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_x##idx, g_invalidate_x##idx } +#define DEFINE_GPR_IDX(idx, reg, alt, gen) \ + { \ + e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 8, GPR_OFFSET_IDX(idx), \ + dwarf_##reg, dwarf_##reg, gen, debugserver_gpr_##reg, NULL, \ + g_invalidate_x##idx \ + } +#define DEFINE_GPR_NAME(reg, alt, gen) \ + { \ + e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 8, GPR_OFFSET_NAME(reg), \ + dwarf_##reg, dwarf_##reg, gen, debugserver_gpr_##reg, NULL, NULL \ + } +#define DEFINE_PSEUDO_GPR_IDX(idx, reg) \ + { \ + e_regSetGPR, gpr_##reg, #reg, NULL, Uint, Hex, 4, 0, INVALID_NUB_REGNUM, \ + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ + g_contained_x##idx, g_invalidate_x##idx \ + } //_STRUCT_ARM_THREAD_STATE64 //{ @@ -1365,268 +1375,292 @@ const char *g_invalidate_x28[] {"x28", "w28", NULL }; // uint32_t cpsr; /* Current program status register */ //}; - // General purpose registers -const DNBRegisterInfo -DNBArchMachARM64::g_gpr_registers[] = -{ - DEFINE_GPR_IDX ( 0, x0, "arg1", GENERIC_REGNUM_ARG1 ), - DEFINE_GPR_IDX ( 1, x1, "arg2", GENERIC_REGNUM_ARG2 ), - DEFINE_GPR_IDX ( 2, x2, "arg3", GENERIC_REGNUM_ARG3 ), - DEFINE_GPR_IDX ( 3, x3, "arg4", GENERIC_REGNUM_ARG4 ), - DEFINE_GPR_IDX ( 4, x4, "arg5", GENERIC_REGNUM_ARG5 ), - DEFINE_GPR_IDX ( 5, x5, "arg6", GENERIC_REGNUM_ARG6 ), - DEFINE_GPR_IDX ( 6, x6, "arg7", GENERIC_REGNUM_ARG7 ), - DEFINE_GPR_IDX ( 7, x7, "arg8", GENERIC_REGNUM_ARG8 ), - DEFINE_GPR_IDX ( 8, x8, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX ( 9, x9, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (10, x10, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (11, x11, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (12, x12, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (13, x13, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (14, x14, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (15, x15, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (16, x16, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (17, x17, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (18, x18, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (19, x19, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (20, x20, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (21, x21, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (22, x22, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (23, x23, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (24, x24, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (25, x25, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (26, x26, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (27, x27, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_IDX (28, x28, NULL, INVALID_NUB_REGNUM ), - DEFINE_GPR_NAME (fp, "x29", GENERIC_REGNUM_FP), - DEFINE_GPR_NAME (lr, "x30", GENERIC_REGNUM_RA), - DEFINE_GPR_NAME (sp, "xsp", GENERIC_REGNUM_SP), - DEFINE_GPR_NAME (pc, NULL, GENERIC_REGNUM_PC), - - // in armv7 we specify that writing to the CPSR should invalidate r8-12, sp, lr. - // this should be specified for arm64 too even though debugserver is only used for +const DNBRegisterInfo DNBArchMachARM64::g_gpr_registers[] = { + DEFINE_GPR_IDX(0, x0, "arg1", GENERIC_REGNUM_ARG1), + DEFINE_GPR_IDX(1, x1, "arg2", GENERIC_REGNUM_ARG2), + DEFINE_GPR_IDX(2, x2, "arg3", GENERIC_REGNUM_ARG3), + DEFINE_GPR_IDX(3, x3, "arg4", GENERIC_REGNUM_ARG4), + DEFINE_GPR_IDX(4, x4, "arg5", GENERIC_REGNUM_ARG5), + DEFINE_GPR_IDX(5, x5, "arg6", GENERIC_REGNUM_ARG6), + DEFINE_GPR_IDX(6, x6, "arg7", GENERIC_REGNUM_ARG7), + DEFINE_GPR_IDX(7, x7, "arg8", GENERIC_REGNUM_ARG8), + DEFINE_GPR_IDX(8, x8, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(9, x9, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(10, x10, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(11, x11, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(12, x12, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(13, x13, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(14, x14, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(15, x15, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(16, x16, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(17, x17, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(18, x18, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(19, x19, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(20, x20, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(21, x21, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(22, x22, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(23, x23, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(24, x24, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(25, x25, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(26, x26, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(27, x27, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_IDX(28, x28, NULL, INVALID_NUB_REGNUM), + DEFINE_GPR_NAME(fp, "x29", GENERIC_REGNUM_FP), + DEFINE_GPR_NAME(lr, "x30", GENERIC_REGNUM_RA), + DEFINE_GPR_NAME(sp, "xsp", GENERIC_REGNUM_SP), + DEFINE_GPR_NAME(pc, NULL, GENERIC_REGNUM_PC), + + // in armv7 we specify that writing to the CPSR should invalidate r8-12, sp, + // lr. + // this should be specified for arm64 too even though debugserver is only + // used for // userland debugging. - { e_regSetGPR, gpr_cpsr, "cpsr", "flags", Uint, Hex, 4, GPR_OFFSET_NAME(cpsr), dwarf_elr_mode, dwarf_elr_mode, INVALID_NUB_REGNUM, debugserver_gpr_cpsr, NULL, NULL }, - - DEFINE_PSEUDO_GPR_IDX ( 0, w0), - DEFINE_PSEUDO_GPR_IDX ( 1, w1), - DEFINE_PSEUDO_GPR_IDX ( 2, w2), - DEFINE_PSEUDO_GPR_IDX ( 3, w3), - DEFINE_PSEUDO_GPR_IDX ( 4, w4), - DEFINE_PSEUDO_GPR_IDX ( 5, w5), - DEFINE_PSEUDO_GPR_IDX ( 6, w6), - DEFINE_PSEUDO_GPR_IDX ( 7, w7), - DEFINE_PSEUDO_GPR_IDX ( 8, w8), - DEFINE_PSEUDO_GPR_IDX ( 9, w9), - DEFINE_PSEUDO_GPR_IDX (10, w10), - DEFINE_PSEUDO_GPR_IDX (11, w11), - DEFINE_PSEUDO_GPR_IDX (12, w12), - DEFINE_PSEUDO_GPR_IDX (13, w13), - DEFINE_PSEUDO_GPR_IDX (14, w14), - DEFINE_PSEUDO_GPR_IDX (15, w15), - DEFINE_PSEUDO_GPR_IDX (16, w16), - DEFINE_PSEUDO_GPR_IDX (17, w17), - DEFINE_PSEUDO_GPR_IDX (18, w18), - DEFINE_PSEUDO_GPR_IDX (19, w19), - DEFINE_PSEUDO_GPR_IDX (20, w20), - DEFINE_PSEUDO_GPR_IDX (21, w21), - DEFINE_PSEUDO_GPR_IDX (22, w22), - DEFINE_PSEUDO_GPR_IDX (23, w23), - DEFINE_PSEUDO_GPR_IDX (24, w24), - DEFINE_PSEUDO_GPR_IDX (25, w25), - DEFINE_PSEUDO_GPR_IDX (26, w26), - DEFINE_PSEUDO_GPR_IDX (27, w27), - DEFINE_PSEUDO_GPR_IDX (28, w28) -}; - -const char *g_contained_v0[] {"v0", NULL }; -const char *g_contained_v1[] {"v1", NULL }; -const char *g_contained_v2[] {"v2", NULL }; -const char *g_contained_v3[] {"v3", NULL }; -const char *g_contained_v4[] {"v4", NULL }; -const char *g_contained_v5[] {"v5", NULL }; -const char *g_contained_v6[] {"v6", NULL }; -const char *g_contained_v7[] {"v7", NULL }; -const char *g_contained_v8[] {"v8", NULL }; -const char *g_contained_v9[] {"v9", NULL }; -const char *g_contained_v10[] {"v10", NULL }; -const char *g_contained_v11[] {"v11", NULL }; -const char *g_contained_v12[] {"v12", NULL }; -const char *g_contained_v13[] {"v13", NULL }; -const char *g_contained_v14[] {"v14", NULL }; -const char *g_contained_v15[] {"v15", NULL }; -const char *g_contained_v16[] {"v16", NULL }; -const char *g_contained_v17[] {"v17", NULL }; -const char *g_contained_v18[] {"v18", NULL }; -const char *g_contained_v19[] {"v19", NULL }; -const char *g_contained_v20[] {"v20", NULL }; -const char *g_contained_v21[] {"v21", NULL }; -const char *g_contained_v22[] {"v22", NULL }; -const char *g_contained_v23[] {"v23", NULL }; -const char *g_contained_v24[] {"v24", NULL }; -const char *g_contained_v25[] {"v25", NULL }; -const char *g_contained_v26[] {"v26", NULL }; -const char *g_contained_v27[] {"v27", NULL }; -const char *g_contained_v28[] {"v28", NULL }; -const char *g_contained_v29[] {"v29", NULL }; -const char *g_contained_v30[] {"v30", NULL }; -const char *g_contained_v31[] {"v31", NULL }; - -const char *g_invalidate_v0[] {"v0", "d0", "s0", NULL }; -const char *g_invalidate_v1[] {"v1", "d1", "s1", NULL }; -const char *g_invalidate_v2[] {"v2", "d2", "s2", NULL }; -const char *g_invalidate_v3[] {"v3", "d3", "s3", NULL }; -const char *g_invalidate_v4[] {"v4", "d4", "s4", NULL }; -const char *g_invalidate_v5[] {"v5", "d5", "s5", NULL }; -const char *g_invalidate_v6[] {"v6", "d6", "s6", NULL }; -const char *g_invalidate_v7[] {"v7", "d7", "s7", NULL }; -const char *g_invalidate_v8[] {"v8", "d8", "s8", NULL }; -const char *g_invalidate_v9[] {"v9", "d9", "s9", NULL }; -const char *g_invalidate_v10[] {"v10", "d10", "s10", NULL }; -const char *g_invalidate_v11[] {"v11", "d11", "s11", NULL }; -const char *g_invalidate_v12[] {"v12", "d12", "s12", NULL }; -const char *g_invalidate_v13[] {"v13", "d13", "s13", NULL }; -const char *g_invalidate_v14[] {"v14", "d14", "s14", NULL }; -const char *g_invalidate_v15[] {"v15", "d15", "s15", NULL }; -const char *g_invalidate_v16[] {"v16", "d16", "s16", NULL }; -const char *g_invalidate_v17[] {"v17", "d17", "s17", NULL }; -const char *g_invalidate_v18[] {"v18", "d18", "s18", NULL }; -const char *g_invalidate_v19[] {"v19", "d19", "s19", NULL }; -const char *g_invalidate_v20[] {"v20", "d20", "s20", NULL }; -const char *g_invalidate_v21[] {"v21", "d21", "s21", NULL }; -const char *g_invalidate_v22[] {"v22", "d22", "s22", NULL }; -const char *g_invalidate_v23[] {"v23", "d23", "s23", NULL }; -const char *g_invalidate_v24[] {"v24", "d24", "s24", NULL }; -const char *g_invalidate_v25[] {"v25", "d25", "s25", NULL }; -const char *g_invalidate_v26[] {"v26", "d26", "s26", NULL }; -const char *g_invalidate_v27[] {"v27", "d27", "s27", NULL }; -const char *g_invalidate_v28[] {"v28", "d28", "s28", NULL }; -const char *g_invalidate_v29[] {"v29", "d29", "s29", NULL }; -const char *g_invalidate_v30[] {"v30", "d30", "s30", NULL }; -const char *g_invalidate_v31[] {"v31", "d31", "s31", NULL }; - -#if defined (__arm64__) || defined (__aarch64__) -#define VFP_V_OFFSET_IDX(idx) (offsetof (DNBArchMachARM64::FPU, __v) + (idx * 16) + offsetof (DNBArchMachARM64::Context, vfp)) + {e_regSetGPR, gpr_cpsr, "cpsr", "flags", Uint, Hex, 4, + GPR_OFFSET_NAME(cpsr), dwarf_elr_mode, dwarf_elr_mode, INVALID_NUB_REGNUM, + debugserver_gpr_cpsr, NULL, NULL}, + + DEFINE_PSEUDO_GPR_IDX(0, w0), + DEFINE_PSEUDO_GPR_IDX(1, w1), + DEFINE_PSEUDO_GPR_IDX(2, w2), + DEFINE_PSEUDO_GPR_IDX(3, w3), + DEFINE_PSEUDO_GPR_IDX(4, w4), + DEFINE_PSEUDO_GPR_IDX(5, w5), + DEFINE_PSEUDO_GPR_IDX(6, w6), + DEFINE_PSEUDO_GPR_IDX(7, w7), + DEFINE_PSEUDO_GPR_IDX(8, w8), + DEFINE_PSEUDO_GPR_IDX(9, w9), + DEFINE_PSEUDO_GPR_IDX(10, w10), + DEFINE_PSEUDO_GPR_IDX(11, w11), + DEFINE_PSEUDO_GPR_IDX(12, w12), + DEFINE_PSEUDO_GPR_IDX(13, w13), + DEFINE_PSEUDO_GPR_IDX(14, w14), + DEFINE_PSEUDO_GPR_IDX(15, w15), + DEFINE_PSEUDO_GPR_IDX(16, w16), + DEFINE_PSEUDO_GPR_IDX(17, w17), + DEFINE_PSEUDO_GPR_IDX(18, w18), + DEFINE_PSEUDO_GPR_IDX(19, w19), + DEFINE_PSEUDO_GPR_IDX(20, w20), + DEFINE_PSEUDO_GPR_IDX(21, w21), + DEFINE_PSEUDO_GPR_IDX(22, w22), + DEFINE_PSEUDO_GPR_IDX(23, w23), + DEFINE_PSEUDO_GPR_IDX(24, w24), + DEFINE_PSEUDO_GPR_IDX(25, w25), + DEFINE_PSEUDO_GPR_IDX(26, w26), + DEFINE_PSEUDO_GPR_IDX(27, w27), + DEFINE_PSEUDO_GPR_IDX(28, w28)}; + +const char *g_contained_v0[]{"v0", NULL}; +const char *g_contained_v1[]{"v1", NULL}; +const char *g_contained_v2[]{"v2", NULL}; +const char *g_contained_v3[]{"v3", NULL}; +const char *g_contained_v4[]{"v4", NULL}; +const char *g_contained_v5[]{"v5", NULL}; +const char *g_contained_v6[]{"v6", NULL}; +const char *g_contained_v7[]{"v7", NULL}; +const char *g_contained_v8[]{"v8", NULL}; +const char *g_contained_v9[]{"v9", NULL}; +const char *g_contained_v10[]{"v10", NULL}; +const char *g_contained_v11[]{"v11", NULL}; +const char *g_contained_v12[]{"v12", NULL}; +const char *g_contained_v13[]{"v13", NULL}; +const char *g_contained_v14[]{"v14", NULL}; +const char *g_contained_v15[]{"v15", NULL}; +const char *g_contained_v16[]{"v16", NULL}; +const char *g_contained_v17[]{"v17", NULL}; +const char *g_contained_v18[]{"v18", NULL}; +const char *g_contained_v19[]{"v19", NULL}; +const char *g_contained_v20[]{"v20", NULL}; +const char *g_contained_v21[]{"v21", NULL}; +const char *g_contained_v22[]{"v22", NULL}; +const char *g_contained_v23[]{"v23", NULL}; +const char *g_contained_v24[]{"v24", NULL}; +const char *g_contained_v25[]{"v25", NULL}; +const char *g_contained_v26[]{"v26", NULL}; +const char *g_contained_v27[]{"v27", NULL}; +const char *g_contained_v28[]{"v28", NULL}; +const char *g_contained_v29[]{"v29", NULL}; +const char *g_contained_v30[]{"v30", NULL}; +const char *g_contained_v31[]{"v31", NULL}; + +const char *g_invalidate_v0[]{"v0", "d0", "s0", NULL}; +const char *g_invalidate_v1[]{"v1", "d1", "s1", NULL}; +const char *g_invalidate_v2[]{"v2", "d2", "s2", NULL}; +const char *g_invalidate_v3[]{"v3", "d3", "s3", NULL}; +const char *g_invalidate_v4[]{"v4", "d4", "s4", NULL}; +const char *g_invalidate_v5[]{"v5", "d5", "s5", NULL}; +const char *g_invalidate_v6[]{"v6", "d6", "s6", NULL}; +const char *g_invalidate_v7[]{"v7", "d7", "s7", NULL}; +const char *g_invalidate_v8[]{"v8", "d8", "s8", NULL}; +const char *g_invalidate_v9[]{"v9", "d9", "s9", NULL}; +const char *g_invalidate_v10[]{"v10", "d10", "s10", NULL}; +const char *g_invalidate_v11[]{"v11", "d11", "s11", NULL}; +const char *g_invalidate_v12[]{"v12", "d12", "s12", NULL}; +const char *g_invalidate_v13[]{"v13", "d13", "s13", NULL}; +const char *g_invalidate_v14[]{"v14", "d14", "s14", NULL}; +const char *g_invalidate_v15[]{"v15", "d15", "s15", NULL}; +const char *g_invalidate_v16[]{"v16", "d16", "s16", NULL}; +const char *g_invalidate_v17[]{"v17", "d17", "s17", NULL}; +const char *g_invalidate_v18[]{"v18", "d18", "s18", NULL}; +const char *g_invalidate_v19[]{"v19", "d19", "s19", NULL}; +const char *g_invalidate_v20[]{"v20", "d20", "s20", NULL}; +const char *g_invalidate_v21[]{"v21", "d21", "s21", NULL}; +const char *g_invalidate_v22[]{"v22", "d22", "s22", NULL}; +const char *g_invalidate_v23[]{"v23", "d23", "s23", NULL}; +const char *g_invalidate_v24[]{"v24", "d24", "s24", NULL}; +const char *g_invalidate_v25[]{"v25", "d25", "s25", NULL}; +const char *g_invalidate_v26[]{"v26", "d26", "s26", NULL}; +const char *g_invalidate_v27[]{"v27", "d27", "s27", NULL}; +const char *g_invalidate_v28[]{"v28", "d28", "s28", NULL}; +const char *g_invalidate_v29[]{"v29", "d29", "s29", NULL}; +const char *g_invalidate_v30[]{"v30", "d30", "s30", NULL}; +const char *g_invalidate_v31[]{"v31", "d31", "s31", NULL}; + +#if defined(__arm64__) || defined(__aarch64__) +#define VFP_V_OFFSET_IDX(idx) \ + (offsetof(DNBArchMachARM64::FPU, __v) + (idx * 16) + \ + offsetof(DNBArchMachARM64::Context, vfp)) #else -#define VFP_V_OFFSET_IDX(idx) (offsetof (DNBArchMachARM64::FPU, opaque) + (idx * 16) + offsetof (DNBArchMachARM64::Context, vfp)) +#define VFP_V_OFFSET_IDX(idx) \ + (offsetof(DNBArchMachARM64::FPU, opaque) + (idx * 16) + \ + offsetof(DNBArchMachARM64::Context, vfp)) #endif -#define VFP_OFFSET_NAME(reg) (offsetof (DNBArchMachARM64::FPU, reg) + offsetof (DNBArchMachARM64::Context, vfp)) -#define EXC_OFFSET(reg) (offsetof (DNBArchMachARM64::EXC, reg) + offsetof (DNBArchMachARM64::Context, exc)) +#define VFP_OFFSET_NAME(reg) \ + (offsetof(DNBArchMachARM64::FPU, reg) + \ + offsetof(DNBArchMachARM64::Context, vfp)) +#define EXC_OFFSET(reg) \ + (offsetof(DNBArchMachARM64::EXC, reg) + \ + offsetof(DNBArchMachARM64::Context, exc)) //#define FLOAT_FORMAT Float -#define DEFINE_VFP_V_IDX(idx) { e_regSetVFP, vfp_v##idx, "v" #idx, "q" #idx, Vector, VectorOfUInt8, 16, VFP_V_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_v##idx, INVALID_NUB_REGNUM, debugserver_vfp_v##idx, NULL, g_invalidate_v##idx } -#define DEFINE_PSEUDO_VFP_S_IDX(idx) { e_regSetVFP, vfp_s##idx, "s" #idx, NULL, IEEE754, Float, 4, 0, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_v##idx, g_invalidate_v##idx } -#define DEFINE_PSEUDO_VFP_D_IDX(idx) { e_regSetVFP, vfp_d##idx, "d" #idx, NULL, IEEE754, Float, 8, 0, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_v##idx, g_invalidate_v##idx } +#define DEFINE_VFP_V_IDX(idx) \ + { \ + e_regSetVFP, vfp_v##idx, "v" #idx, "q" #idx, Vector, VectorOfUInt8, 16, \ + VFP_V_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_v##idx, \ + INVALID_NUB_REGNUM, debugserver_vfp_v##idx, NULL, g_invalidate_v##idx \ + } +#define DEFINE_PSEUDO_VFP_S_IDX(idx) \ + { \ + e_regSetVFP, vfp_s##idx, "s" #idx, NULL, IEEE754, Float, 4, 0, \ + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ + INVALID_NUB_REGNUM, g_contained_v##idx, g_invalidate_v##idx \ + } +#define DEFINE_PSEUDO_VFP_D_IDX(idx) \ + { \ + e_regSetVFP, vfp_d##idx, "d" #idx, NULL, IEEE754, Float, 8, 0, \ + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ + INVALID_NUB_REGNUM, g_contained_v##idx, g_invalidate_v##idx \ + } // Floating point registers -const DNBRegisterInfo -DNBArchMachARM64::g_vfp_registers[] = -{ - DEFINE_VFP_V_IDX ( 0), - DEFINE_VFP_V_IDX ( 1), - DEFINE_VFP_V_IDX ( 2), - DEFINE_VFP_V_IDX ( 3), - DEFINE_VFP_V_IDX ( 4), - DEFINE_VFP_V_IDX ( 5), - DEFINE_VFP_V_IDX ( 6), - DEFINE_VFP_V_IDX ( 7), - DEFINE_VFP_V_IDX ( 8), - DEFINE_VFP_V_IDX ( 9), - DEFINE_VFP_V_IDX (10), - DEFINE_VFP_V_IDX (11), - DEFINE_VFP_V_IDX (12), - DEFINE_VFP_V_IDX (13), - DEFINE_VFP_V_IDX (14), - DEFINE_VFP_V_IDX (15), - DEFINE_VFP_V_IDX (16), - DEFINE_VFP_V_IDX (17), - DEFINE_VFP_V_IDX (18), - DEFINE_VFP_V_IDX (19), - DEFINE_VFP_V_IDX (20), - DEFINE_VFP_V_IDX (21), - DEFINE_VFP_V_IDX (22), - DEFINE_VFP_V_IDX (23), - DEFINE_VFP_V_IDX (24), - DEFINE_VFP_V_IDX (25), - DEFINE_VFP_V_IDX (26), - DEFINE_VFP_V_IDX (27), - DEFINE_VFP_V_IDX (28), - DEFINE_VFP_V_IDX (29), - DEFINE_VFP_V_IDX (30), - DEFINE_VFP_V_IDX (31), - { e_regSetVFP, vfp_fpsr, "fpsr", NULL, Uint, Hex, 4, VFP_V_OFFSET_IDX (32) + 0, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, - { e_regSetVFP, vfp_fpcr, "fpcr", NULL, Uint, Hex, 4, VFP_V_OFFSET_IDX (32) + 4, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, - - DEFINE_PSEUDO_VFP_S_IDX (0), - DEFINE_PSEUDO_VFP_S_IDX (1), - DEFINE_PSEUDO_VFP_S_IDX (2), - DEFINE_PSEUDO_VFP_S_IDX (3), - DEFINE_PSEUDO_VFP_S_IDX (4), - DEFINE_PSEUDO_VFP_S_IDX (5), - DEFINE_PSEUDO_VFP_S_IDX (6), - DEFINE_PSEUDO_VFP_S_IDX (7), - DEFINE_PSEUDO_VFP_S_IDX (8), - DEFINE_PSEUDO_VFP_S_IDX (9), - DEFINE_PSEUDO_VFP_S_IDX (10), - DEFINE_PSEUDO_VFP_S_IDX (11), - DEFINE_PSEUDO_VFP_S_IDX (12), - DEFINE_PSEUDO_VFP_S_IDX (13), - DEFINE_PSEUDO_VFP_S_IDX (14), - DEFINE_PSEUDO_VFP_S_IDX (15), - DEFINE_PSEUDO_VFP_S_IDX (16), - DEFINE_PSEUDO_VFP_S_IDX (17), - DEFINE_PSEUDO_VFP_S_IDX (18), - DEFINE_PSEUDO_VFP_S_IDX (19), - DEFINE_PSEUDO_VFP_S_IDX (20), - DEFINE_PSEUDO_VFP_S_IDX (21), - DEFINE_PSEUDO_VFP_S_IDX (22), - DEFINE_PSEUDO_VFP_S_IDX (23), - DEFINE_PSEUDO_VFP_S_IDX (24), - DEFINE_PSEUDO_VFP_S_IDX (25), - DEFINE_PSEUDO_VFP_S_IDX (26), - DEFINE_PSEUDO_VFP_S_IDX (27), - DEFINE_PSEUDO_VFP_S_IDX (28), - DEFINE_PSEUDO_VFP_S_IDX (29), - DEFINE_PSEUDO_VFP_S_IDX (30), - DEFINE_PSEUDO_VFP_S_IDX (31), - - DEFINE_PSEUDO_VFP_D_IDX (0), - DEFINE_PSEUDO_VFP_D_IDX (1), - DEFINE_PSEUDO_VFP_D_IDX (2), - DEFINE_PSEUDO_VFP_D_IDX (3), - DEFINE_PSEUDO_VFP_D_IDX (4), - DEFINE_PSEUDO_VFP_D_IDX (5), - DEFINE_PSEUDO_VFP_D_IDX (6), - DEFINE_PSEUDO_VFP_D_IDX (7), - DEFINE_PSEUDO_VFP_D_IDX (8), - DEFINE_PSEUDO_VFP_D_IDX (9), - DEFINE_PSEUDO_VFP_D_IDX (10), - DEFINE_PSEUDO_VFP_D_IDX (11), - DEFINE_PSEUDO_VFP_D_IDX (12), - DEFINE_PSEUDO_VFP_D_IDX (13), - DEFINE_PSEUDO_VFP_D_IDX (14), - DEFINE_PSEUDO_VFP_D_IDX (15), - DEFINE_PSEUDO_VFP_D_IDX (16), - DEFINE_PSEUDO_VFP_D_IDX (17), - DEFINE_PSEUDO_VFP_D_IDX (18), - DEFINE_PSEUDO_VFP_D_IDX (19), - DEFINE_PSEUDO_VFP_D_IDX (20), - DEFINE_PSEUDO_VFP_D_IDX (21), - DEFINE_PSEUDO_VFP_D_IDX (22), - DEFINE_PSEUDO_VFP_D_IDX (23), - DEFINE_PSEUDO_VFP_D_IDX (24), - DEFINE_PSEUDO_VFP_D_IDX (25), - DEFINE_PSEUDO_VFP_D_IDX (26), - DEFINE_PSEUDO_VFP_D_IDX (27), - DEFINE_PSEUDO_VFP_D_IDX (28), - DEFINE_PSEUDO_VFP_D_IDX (29), - DEFINE_PSEUDO_VFP_D_IDX (30), - DEFINE_PSEUDO_VFP_D_IDX (31) +const DNBRegisterInfo DNBArchMachARM64::g_vfp_registers[] = { + DEFINE_VFP_V_IDX(0), + DEFINE_VFP_V_IDX(1), + DEFINE_VFP_V_IDX(2), + DEFINE_VFP_V_IDX(3), + DEFINE_VFP_V_IDX(4), + DEFINE_VFP_V_IDX(5), + DEFINE_VFP_V_IDX(6), + DEFINE_VFP_V_IDX(7), + DEFINE_VFP_V_IDX(8), + DEFINE_VFP_V_IDX(9), + DEFINE_VFP_V_IDX(10), + DEFINE_VFP_V_IDX(11), + DEFINE_VFP_V_IDX(12), + DEFINE_VFP_V_IDX(13), + DEFINE_VFP_V_IDX(14), + DEFINE_VFP_V_IDX(15), + DEFINE_VFP_V_IDX(16), + DEFINE_VFP_V_IDX(17), + DEFINE_VFP_V_IDX(18), + DEFINE_VFP_V_IDX(19), + DEFINE_VFP_V_IDX(20), + DEFINE_VFP_V_IDX(21), + DEFINE_VFP_V_IDX(22), + DEFINE_VFP_V_IDX(23), + DEFINE_VFP_V_IDX(24), + DEFINE_VFP_V_IDX(25), + DEFINE_VFP_V_IDX(26), + DEFINE_VFP_V_IDX(27), + DEFINE_VFP_V_IDX(28), + DEFINE_VFP_V_IDX(29), + DEFINE_VFP_V_IDX(30), + DEFINE_VFP_V_IDX(31), + {e_regSetVFP, vfp_fpsr, "fpsr", NULL, Uint, Hex, 4, + VFP_V_OFFSET_IDX(32) + 0, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetVFP, vfp_fpcr, "fpcr", NULL, Uint, Hex, 4, + VFP_V_OFFSET_IDX(32) + 4, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, + + DEFINE_PSEUDO_VFP_S_IDX(0), + DEFINE_PSEUDO_VFP_S_IDX(1), + DEFINE_PSEUDO_VFP_S_IDX(2), + DEFINE_PSEUDO_VFP_S_IDX(3), + DEFINE_PSEUDO_VFP_S_IDX(4), + DEFINE_PSEUDO_VFP_S_IDX(5), + DEFINE_PSEUDO_VFP_S_IDX(6), + DEFINE_PSEUDO_VFP_S_IDX(7), + DEFINE_PSEUDO_VFP_S_IDX(8), + DEFINE_PSEUDO_VFP_S_IDX(9), + DEFINE_PSEUDO_VFP_S_IDX(10), + DEFINE_PSEUDO_VFP_S_IDX(11), + DEFINE_PSEUDO_VFP_S_IDX(12), + DEFINE_PSEUDO_VFP_S_IDX(13), + DEFINE_PSEUDO_VFP_S_IDX(14), + DEFINE_PSEUDO_VFP_S_IDX(15), + DEFINE_PSEUDO_VFP_S_IDX(16), + DEFINE_PSEUDO_VFP_S_IDX(17), + DEFINE_PSEUDO_VFP_S_IDX(18), + DEFINE_PSEUDO_VFP_S_IDX(19), + DEFINE_PSEUDO_VFP_S_IDX(20), + DEFINE_PSEUDO_VFP_S_IDX(21), + DEFINE_PSEUDO_VFP_S_IDX(22), + DEFINE_PSEUDO_VFP_S_IDX(23), + DEFINE_PSEUDO_VFP_S_IDX(24), + DEFINE_PSEUDO_VFP_S_IDX(25), + DEFINE_PSEUDO_VFP_S_IDX(26), + DEFINE_PSEUDO_VFP_S_IDX(27), + DEFINE_PSEUDO_VFP_S_IDX(28), + DEFINE_PSEUDO_VFP_S_IDX(29), + DEFINE_PSEUDO_VFP_S_IDX(30), + DEFINE_PSEUDO_VFP_S_IDX(31), + + DEFINE_PSEUDO_VFP_D_IDX(0), + DEFINE_PSEUDO_VFP_D_IDX(1), + DEFINE_PSEUDO_VFP_D_IDX(2), + DEFINE_PSEUDO_VFP_D_IDX(3), + DEFINE_PSEUDO_VFP_D_IDX(4), + DEFINE_PSEUDO_VFP_D_IDX(5), + DEFINE_PSEUDO_VFP_D_IDX(6), + DEFINE_PSEUDO_VFP_D_IDX(7), + DEFINE_PSEUDO_VFP_D_IDX(8), + DEFINE_PSEUDO_VFP_D_IDX(9), + DEFINE_PSEUDO_VFP_D_IDX(10), + DEFINE_PSEUDO_VFP_D_IDX(11), + DEFINE_PSEUDO_VFP_D_IDX(12), + DEFINE_PSEUDO_VFP_D_IDX(13), + DEFINE_PSEUDO_VFP_D_IDX(14), + DEFINE_PSEUDO_VFP_D_IDX(15), + DEFINE_PSEUDO_VFP_D_IDX(16), + DEFINE_PSEUDO_VFP_D_IDX(17), + DEFINE_PSEUDO_VFP_D_IDX(18), + DEFINE_PSEUDO_VFP_D_IDX(19), + DEFINE_PSEUDO_VFP_D_IDX(20), + DEFINE_PSEUDO_VFP_D_IDX(21), + DEFINE_PSEUDO_VFP_D_IDX(22), + DEFINE_PSEUDO_VFP_D_IDX(23), + DEFINE_PSEUDO_VFP_D_IDX(24), + DEFINE_PSEUDO_VFP_D_IDX(25), + DEFINE_PSEUDO_VFP_D_IDX(26), + DEFINE_PSEUDO_VFP_D_IDX(27), + DEFINE_PSEUDO_VFP_D_IDX(28), + DEFINE_PSEUDO_VFP_D_IDX(29), + DEFINE_PSEUDO_VFP_D_IDX(30), + DEFINE_PSEUDO_VFP_D_IDX(31) }; - //_STRUCT_ARM_EXCEPTION_STATE64 //{ // uint64_t far; /* Virtual Fault Address */ @@ -1635,461 +1669,436 @@ DNBArchMachARM64::g_vfp_registers[] = //}; // Exception registers -const DNBRegisterInfo -DNBArchMachARM64::g_exc_registers[] = -{ - { e_regSetEXC, exc_far , "far" , NULL, Uint, Hex, 8, EXC_OFFSET(__far) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, - { e_regSetEXC, exc_esr , "esr" , NULL, Uint, Hex, 4, EXC_OFFSET(__esr) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, - { e_regSetEXC, exc_exception , "exception" , NULL, Uint, Hex, 4, EXC_OFFSET(__exception) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL } -}; +const DNBRegisterInfo DNBArchMachARM64::g_exc_registers[] = { + {e_regSetEXC, exc_far, "far", NULL, Uint, Hex, 8, EXC_OFFSET(__far), + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetEXC, exc_esr, "esr", NULL, Uint, Hex, 4, EXC_OFFSET(__esr), + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetEXC, exc_exception, "exception", NULL, Uint, Hex, 4, + EXC_OFFSET(__exception), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}}; // Number of registers in each register set -const size_t DNBArchMachARM64::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo); -const size_t DNBArchMachARM64::k_num_vfp_registers = sizeof(g_vfp_registers)/sizeof(DNBRegisterInfo); -const size_t DNBArchMachARM64::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo); -const size_t DNBArchMachARM64::k_num_all_registers = k_num_gpr_registers + k_num_vfp_registers + k_num_exc_registers; +const size_t DNBArchMachARM64::k_num_gpr_registers = + sizeof(g_gpr_registers) / sizeof(DNBRegisterInfo); +const size_t DNBArchMachARM64::k_num_vfp_registers = + sizeof(g_vfp_registers) / sizeof(DNBRegisterInfo); +const size_t DNBArchMachARM64::k_num_exc_registers = + sizeof(g_exc_registers) / sizeof(DNBRegisterInfo); +const size_t DNBArchMachARM64::k_num_all_registers = + k_num_gpr_registers + k_num_vfp_registers + k_num_exc_registers; //---------------------------------------------------------------------- // Register set definitions. The first definitions at register set index // of zero is for all registers, followed by other registers sets. The // register information for the all register set need not be filled in. //---------------------------------------------------------------------- -const DNBRegisterSetInfo -DNBArchMachARM64::g_reg_sets[] = -{ - { "ARM64 Registers", NULL, k_num_all_registers }, - { "General Purpose Registers", g_gpr_registers, k_num_gpr_registers }, - { "Floating Point Registers", g_vfp_registers, k_num_vfp_registers }, - { "Exception State Registers", g_exc_registers, k_num_exc_registers } -}; +const DNBRegisterSetInfo DNBArchMachARM64::g_reg_sets[] = { + {"ARM64 Registers", NULL, k_num_all_registers}, + {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers}, + {"Floating Point Registers", g_vfp_registers, k_num_vfp_registers}, + {"Exception State Registers", g_exc_registers, k_num_exc_registers}}; // Total number of register sets for this architecture -const size_t DNBArchMachARM64::k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo); - +const size_t DNBArchMachARM64::k_num_register_sets = + sizeof(g_reg_sets) / sizeof(DNBRegisterSetInfo); const DNBRegisterSetInfo * -DNBArchMachARM64::GetRegisterSetInfo(nub_size_t *num_reg_sets) -{ - *num_reg_sets = k_num_register_sets; - return g_reg_sets; +DNBArchMachARM64::GetRegisterSetInfo(nub_size_t *num_reg_sets) { + *num_reg_sets = k_num_register_sets; + return g_reg_sets; } -bool -DNBArchMachARM64::FixGenericRegisterNumber (uint32_t &set, uint32_t ®) -{ - if (set == REGISTER_SET_GENERIC) - { - switch (reg) - { - case GENERIC_REGNUM_PC: // Program Counter - set = e_regSetGPR; - reg = gpr_pc; - break; - - case GENERIC_REGNUM_SP: // Stack Pointer - set = e_regSetGPR; - reg = gpr_sp; - break; - - case GENERIC_REGNUM_FP: // Frame Pointer - set = e_regSetGPR; - reg = gpr_fp; - break; - - case GENERIC_REGNUM_RA: // Return Address - set = e_regSetGPR; - reg = gpr_lr; - break; - - case GENERIC_REGNUM_FLAGS: // Processor flags register - set = e_regSetGPR; - reg = gpr_cpsr; - break; - - case GENERIC_REGNUM_ARG1: - case GENERIC_REGNUM_ARG2: - case GENERIC_REGNUM_ARG3: - case GENERIC_REGNUM_ARG4: - case GENERIC_REGNUM_ARG5: - case GENERIC_REGNUM_ARG6: - set = e_regSetGPR; - reg = gpr_x0 + reg - GENERIC_REGNUM_ARG1; - break; - - default: - return false; - } +bool DNBArchMachARM64::FixGenericRegisterNumber(uint32_t &set, uint32_t ®) { + if (set == REGISTER_SET_GENERIC) { + switch (reg) { + case GENERIC_REGNUM_PC: // Program Counter + set = e_regSetGPR; + reg = gpr_pc; + break; + + case GENERIC_REGNUM_SP: // Stack Pointer + set = e_regSetGPR; + reg = gpr_sp; + break; + + case GENERIC_REGNUM_FP: // Frame Pointer + set = e_regSetGPR; + reg = gpr_fp; + break; + + case GENERIC_REGNUM_RA: // Return Address + set = e_regSetGPR; + reg = gpr_lr; + break; + + case GENERIC_REGNUM_FLAGS: // Processor flags register + set = e_regSetGPR; + reg = gpr_cpsr; + break; + + case GENERIC_REGNUM_ARG1: + case GENERIC_REGNUM_ARG2: + case GENERIC_REGNUM_ARG3: + case GENERIC_REGNUM_ARG4: + case GENERIC_REGNUM_ARG5: + case GENERIC_REGNUM_ARG6: + set = e_regSetGPR; + reg = gpr_x0 + reg - GENERIC_REGNUM_ARG1; + break; + + default: + return false; } - return true; + } + return true; } -bool -DNBArchMachARM64::GetRegisterValue(uint32_t set, uint32_t reg, DNBRegisterValue *value) -{ - if (!FixGenericRegisterNumber (set, reg)) - return false; - - if (GetRegisterState(set, false) != KERN_SUCCESS) - return false; - - const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); - if (regInfo) - { - value->info = *regInfo; - switch (set) - { - case e_regSetGPR: - if (reg <= gpr_pc) - { - value->value.uint64 = m_state.context.gpr.__x[reg]; - return true; - } - else if (reg == gpr_cpsr) - { - value->value.uint32 = m_state.context.gpr.__cpsr; - return true; - } - break; - - case e_regSetVFP: - - if (reg >= vfp_v0 && reg <= vfp_v31) - { -#if defined (__arm64__) || defined (__aarch64__) - memcpy (&value->value.v_uint8, &m_state.context.vfp.__v[reg - vfp_v0], 16); +bool DNBArchMachARM64::GetRegisterValue(uint32_t set, uint32_t reg, + DNBRegisterValue *value) { + if (!FixGenericRegisterNumber(set, reg)) + return false; + + if (GetRegisterState(set, false) != KERN_SUCCESS) + return false; + + const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); + if (regInfo) { + value->info = *regInfo; + switch (set) { + case e_regSetGPR: + if (reg <= gpr_pc) { + value->value.uint64 = m_state.context.gpr.__x[reg]; + return true; + } else if (reg == gpr_cpsr) { + value->value.uint32 = m_state.context.gpr.__cpsr; + return true; + } + break; + + case e_regSetVFP: + + if (reg >= vfp_v0 && reg <= vfp_v31) { +#if defined(__arm64__) || defined(__aarch64__) + memcpy(&value->value.v_uint8, &m_state.context.vfp.__v[reg - vfp_v0], + 16); #else - memcpy (&value->value.v_uint8, ((uint8_t *) &m_state.context.vfp.opaque) + ((reg - vfp_v0) * 16), 16); + memcpy(&value->value.v_uint8, + ((uint8_t *)&m_state.context.vfp.opaque) + ((reg - vfp_v0) * 16), + 16); #endif - return true; - } - else if (reg == vfp_fpsr) - { -#if defined (__arm64__) || defined (__aarch64__) - memcpy (&value->value.uint32, &m_state.context.vfp.__fpsr, 4); + return true; + } else if (reg == vfp_fpsr) { +#if defined(__arm64__) || defined(__aarch64__) + memcpy(&value->value.uint32, &m_state.context.vfp.__fpsr, 4); #else - memcpy (&value->value.uint32, ((uint8_t *) &m_state.context.vfp.opaque) + (32 * 16) + 0, 4); + memcpy(&value->value.uint32, + ((uint8_t *)&m_state.context.vfp.opaque) + (32 * 16) + 0, 4); #endif - return true; - } - else if (reg == vfp_fpcr) - { -#if defined (__arm64__) || defined (__aarch64__) - memcpy (&value->value.uint32, &m_state.context.vfp.__fpcr, 4); + return true; + } else if (reg == vfp_fpcr) { +#if defined(__arm64__) || defined(__aarch64__) + memcpy(&value->value.uint32, &m_state.context.vfp.__fpcr, 4); #else - memcpy (&value->value.uint32, ((uint8_t *) &m_state.context.vfp.opaque) + (32 * 16) + 4, 4); + memcpy(&value->value.uint32, + ((uint8_t *)&m_state.context.vfp.opaque) + (32 * 16) + 4, 4); #endif - return true; - } - else if (reg >= vfp_s0 && reg <= vfp_s31) - { -#if defined (__arm64__) || defined (__aarch64__) - memcpy (&value->value.v_uint8, &m_state.context.vfp.__v[reg - vfp_s0], 4); + return true; + } else if (reg >= vfp_s0 && reg <= vfp_s31) { +#if defined(__arm64__) || defined(__aarch64__) + memcpy(&value->value.v_uint8, &m_state.context.vfp.__v[reg - vfp_s0], + 4); #else - memcpy (&value->value.v_uint8, ((uint8_t *) &m_state.context.vfp.opaque) + ((reg - vfp_s0) * 16), 4); + memcpy(&value->value.v_uint8, + ((uint8_t *)&m_state.context.vfp.opaque) + ((reg - vfp_s0) * 16), + 4); #endif - return true; - } - else if (reg >= vfp_d0 && reg <= vfp_d31) - { -#if defined (__arm64__) || defined (__aarch64__) - memcpy (&value->value.v_uint8, &m_state.context.vfp.__v[reg - vfp_d0], 8); + return true; + } else if (reg >= vfp_d0 && reg <= vfp_d31) { +#if defined(__arm64__) || defined(__aarch64__) + memcpy(&value->value.v_uint8, &m_state.context.vfp.__v[reg - vfp_d0], + 8); #else - memcpy (&value->value.v_uint8, ((uint8_t *) &m_state.context.vfp.opaque) + ((reg - vfp_d0) * 16), 8); + memcpy(&value->value.v_uint8, + ((uint8_t *)&m_state.context.vfp.opaque) + ((reg - vfp_d0) * 16), + 8); #endif - return true; - } - break; - - case e_regSetEXC: - if (reg == exc_far) - { - value->value.uint64 = m_state.context.exc.__far; - return true; - } - else if (reg == exc_esr) - { - value->value.uint32 = m_state.context.exc.__esr; - return true; - } - else if (reg == exc_exception) - { - value->value.uint32 = m_state.context.exc.__exception; - return true; - } - break; - } + return true; + } + break; + + case e_regSetEXC: + if (reg == exc_far) { + value->value.uint64 = m_state.context.exc.__far; + return true; + } else if (reg == exc_esr) { + value->value.uint32 = m_state.context.exc.__esr; + return true; + } else if (reg == exc_exception) { + value->value.uint32 = m_state.context.exc.__exception; + return true; + } + break; } - return false; + } + return false; } -bool -DNBArchMachARM64::SetRegisterValue(uint32_t set, uint32_t reg, const DNBRegisterValue *value) -{ - if (!FixGenericRegisterNumber (set, reg)) - return false; - - if (GetRegisterState(set, false) != KERN_SUCCESS) - return false; - - bool success = false; - const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); - if (regInfo) - { - switch (set) - { - case e_regSetGPR: - if (reg <= gpr_pc) - { - m_state.context.gpr.__x[reg] = value->value.uint64; - success = true; - } - else if (reg == gpr_cpsr) - { - m_state.context.gpr.__cpsr = value->value.uint32; - success = true; - } - break; - - case e_regSetVFP: - if (reg >= vfp_v0 && reg <= vfp_v31) - { -#if defined (__arm64__) || defined (__aarch64__) - memcpy (&m_state.context.vfp.__v[reg - vfp_v0], &value->value.v_uint8, 16); +bool DNBArchMachARM64::SetRegisterValue(uint32_t set, uint32_t reg, + const DNBRegisterValue *value) { + if (!FixGenericRegisterNumber(set, reg)) + return false; + + if (GetRegisterState(set, false) != KERN_SUCCESS) + return false; + + bool success = false; + const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); + if (regInfo) { + switch (set) { + case e_regSetGPR: + if (reg <= gpr_pc) { + m_state.context.gpr.__x[reg] = value->value.uint64; + success = true; + } else if (reg == gpr_cpsr) { + m_state.context.gpr.__cpsr = value->value.uint32; + success = true; + } + break; + + case e_regSetVFP: + if (reg >= vfp_v0 && reg <= vfp_v31) { +#if defined(__arm64__) || defined(__aarch64__) + memcpy(&m_state.context.vfp.__v[reg - vfp_v0], &value->value.v_uint8, + 16); #else - memcpy (((uint8_t *) &m_state.context.vfp.opaque) + ((reg - vfp_v0) * 16), &value->value.v_uint8, 16); + memcpy(((uint8_t *)&m_state.context.vfp.opaque) + ((reg - vfp_v0) * 16), + &value->value.v_uint8, 16); #endif - success = true; - } - else if (reg == vfp_fpsr) - { -#if defined (__arm64__) || defined (__aarch64__) - memcpy (&m_state.context.vfp.__fpsr, &value->value.uint32, 4); + success = true; + } else if (reg == vfp_fpsr) { +#if defined(__arm64__) || defined(__aarch64__) + memcpy(&m_state.context.vfp.__fpsr, &value->value.uint32, 4); #else - memcpy (((uint8_t *) &m_state.context.vfp.opaque) + (32 * 16) + 0, &value->value.uint32, 4); + memcpy(((uint8_t *)&m_state.context.vfp.opaque) + (32 * 16) + 0, + &value->value.uint32, 4); #endif - success = true; - } - else if (reg == vfp_fpcr) - { -#if defined (__arm64__) || defined (__aarch64__) - memcpy (&m_state.context.vfp.__fpcr, &value->value.uint32, 4); + success = true; + } else if (reg == vfp_fpcr) { +#if defined(__arm64__) || defined(__aarch64__) + memcpy(&m_state.context.vfp.__fpcr, &value->value.uint32, 4); #else - memcpy (((uint8_t *) m_state.context.vfp.opaque) + (32 * 16) + 4, &value->value.uint32, 4); + memcpy(((uint8_t *)m_state.context.vfp.opaque) + (32 * 16) + 4, + &value->value.uint32, 4); #endif - success = true; - } - else if (reg >= vfp_s0 && reg <= vfp_s31) - { -#if defined (__arm64__) || defined (__aarch64__) - memcpy (&m_state.context.vfp.__v[reg - vfp_s0], &value->value.v_uint8, 4); + success = true; + } else if (reg >= vfp_s0 && reg <= vfp_s31) { +#if defined(__arm64__) || defined(__aarch64__) + memcpy(&m_state.context.vfp.__v[reg - vfp_s0], &value->value.v_uint8, + 4); #else - memcpy (((uint8_t *) &m_state.context.vfp.opaque) + ((reg - vfp_s0) * 16), &value->value.v_uint8, 4); + memcpy(((uint8_t *)&m_state.context.vfp.opaque) + ((reg - vfp_s0) * 16), + &value->value.v_uint8, 4); #endif - success = true; - } - else if (reg >= vfp_d0 && reg <= vfp_d31) - { -#if defined (__arm64__) || defined (__aarch64__) - memcpy (&m_state.context.vfp.__v[reg - vfp_d0], &value->value.v_uint8, 8); + success = true; + } else if (reg >= vfp_d0 && reg <= vfp_d31) { +#if defined(__arm64__) || defined(__aarch64__) + memcpy(&m_state.context.vfp.__v[reg - vfp_d0], &value->value.v_uint8, + 8); #else - memcpy (((uint8_t *) &m_state.context.vfp.opaque) + ((reg - vfp_d0) * 16), &value->value.v_uint8, 8); + memcpy(((uint8_t *)&m_state.context.vfp.opaque) + ((reg - vfp_d0) * 16), + &value->value.v_uint8, 8); #endif - success = true; - } - break; - - case e_regSetEXC: - if (reg == exc_far) - { - m_state.context.exc.__far = value->value.uint64; - success = true; - } - else if (reg == exc_esr) - { - m_state.context.exc.__esr = value->value.uint32; - success = true; - } - else if (reg == exc_exception) - { - m_state.context.exc.__exception = value->value.uint32; - success = true; - } - break; - } - + success = true; + } + break; + + case e_regSetEXC: + if (reg == exc_far) { + m_state.context.exc.__far = value->value.uint64; + success = true; + } else if (reg == exc_esr) { + m_state.context.exc.__esr = value->value.uint32; + success = true; + } else if (reg == exc_exception) { + m_state.context.exc.__exception = value->value.uint32; + success = true; + } + break; } - if (success) - return SetRegisterState(set) == KERN_SUCCESS; - return false; + } + if (success) + return SetRegisterState(set) == KERN_SUCCESS; + return false; } -kern_return_t -DNBArchMachARM64::GetRegisterState(int set, bool force) -{ - switch (set) - { - case e_regSetALL: return GetGPRState(force) | - GetVFPState(force) | - GetEXCState(force) | - GetDBGState(force); - case e_regSetGPR: return GetGPRState(force); - case e_regSetVFP: return GetVFPState(force); - case e_regSetEXC: return GetEXCState(force); - case e_regSetDBG: return GetDBGState(force); - default: break; - } - return KERN_INVALID_ARGUMENT; +kern_return_t DNBArchMachARM64::GetRegisterState(int set, bool force) { + switch (set) { + case e_regSetALL: + return GetGPRState(force) | GetVFPState(force) | GetEXCState(force) | + GetDBGState(force); + case e_regSetGPR: + return GetGPRState(force); + case e_regSetVFP: + return GetVFPState(force); + case e_regSetEXC: + return GetEXCState(force); + case e_regSetDBG: + return GetDBGState(force); + default: + break; + } + return KERN_INVALID_ARGUMENT; } -kern_return_t -DNBArchMachARM64::SetRegisterState(int set) -{ - // Make sure we have a valid context to set. - kern_return_t err = GetRegisterState(set, false); - if (err != KERN_SUCCESS) - return err; - - switch (set) - { - case e_regSetALL: return SetGPRState() | - SetVFPState() | - SetEXCState() | - SetDBGState(false); - case e_regSetGPR: return SetGPRState(); - case e_regSetVFP: return SetVFPState(); - case e_regSetEXC: return SetEXCState(); - case e_regSetDBG: return SetDBGState(false); - default: break; - } - return KERN_INVALID_ARGUMENT; +kern_return_t DNBArchMachARM64::SetRegisterState(int set) { + // Make sure we have a valid context to set. + kern_return_t err = GetRegisterState(set, false); + if (err != KERN_SUCCESS) + return err; + + switch (set) { + case e_regSetALL: + return SetGPRState() | SetVFPState() | SetEXCState() | SetDBGState(false); + case e_regSetGPR: + return SetGPRState(); + case e_regSetVFP: + return SetVFPState(); + case e_regSetEXC: + return SetEXCState(); + case e_regSetDBG: + return SetDBGState(false); + default: + break; + } + return KERN_INVALID_ARGUMENT; } -bool -DNBArchMachARM64::RegisterSetStateIsValid (int set) const -{ - return m_state.RegsAreValid(set); +bool DNBArchMachARM64::RegisterSetStateIsValid(int set) const { + return m_state.RegsAreValid(set); } - -nub_size_t -DNBArchMachARM64::GetRegisterContext (void *buf, nub_size_t buf_len) -{ - nub_size_t size = sizeof (m_state.context.gpr) + - sizeof (m_state.context.vfp) + - sizeof (m_state.context.exc); - - if (buf && buf_len) - { - if (size > buf_len) - size = buf_len; - - bool force = false; - if (GetGPRState(force) | GetVFPState(force) | GetEXCState(force)) - return 0; - - // Copy each struct individually to avoid any padding that might be between the structs in m_state.context - uint8_t *p = (uint8_t *)buf; - ::memcpy (p, &m_state.context.gpr, sizeof(m_state.context.gpr)); - p += sizeof(m_state.context.gpr); - ::memcpy (p, &m_state.context.vfp, sizeof(m_state.context.vfp)); - p += sizeof(m_state.context.vfp); - ::memcpy (p, &m_state.context.exc, sizeof(m_state.context.exc)); - p += sizeof(m_state.context.exc); - - size_t bytes_written = p - (uint8_t *)buf; - UNUSED_IF_ASSERT_DISABLED(bytes_written); - assert (bytes_written == size); - } - DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM64::GetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size); - // Return the size of the register context even if NULL was passed in - return size; +nub_size_t DNBArchMachARM64::GetRegisterContext(void *buf, nub_size_t buf_len) { + nub_size_t size = sizeof(m_state.context.gpr) + sizeof(m_state.context.vfp) + + sizeof(m_state.context.exc); + + if (buf && buf_len) { + if (size > buf_len) + size = buf_len; + + bool force = false; + if (GetGPRState(force) | GetVFPState(force) | GetEXCState(force)) + return 0; + + // Copy each struct individually to avoid any padding that might be between + // the structs in m_state.context + uint8_t *p = (uint8_t *)buf; + ::memcpy(p, &m_state.context.gpr, sizeof(m_state.context.gpr)); + p += sizeof(m_state.context.gpr); + ::memcpy(p, &m_state.context.vfp, sizeof(m_state.context.vfp)); + p += sizeof(m_state.context.vfp); + ::memcpy(p, &m_state.context.exc, sizeof(m_state.context.exc)); + p += sizeof(m_state.context.exc); + + size_t bytes_written = p - (uint8_t *)buf; + UNUSED_IF_ASSERT_DISABLED(bytes_written); + assert(bytes_written == size); + } + DNBLogThreadedIf( + LOG_THREAD, + "DNBArchMachARM64::GetRegisterContext (buf = %p, len = %zu) => %zu", buf, + buf_len, size); + // Return the size of the register context even if NULL was passed in + return size; } -nub_size_t -DNBArchMachARM64::SetRegisterContext (const void *buf, nub_size_t buf_len) -{ - nub_size_t size = sizeof (m_state.context.gpr) + - sizeof (m_state.context.vfp) + - sizeof (m_state.context.exc); - - if (buf == NULL || buf_len == 0) - size = 0; - - if (size) - { - if (size > buf_len) - size = buf_len; - - // Copy each struct individually to avoid any padding that might be between the structs in m_state.context - uint8_t *p = (uint8_t *)buf; - ::memcpy (&m_state.context.gpr, p, sizeof(m_state.context.gpr)); - p += sizeof(m_state.context.gpr); - ::memcpy (&m_state.context.vfp, p, sizeof(m_state.context.vfp)); - p += sizeof(m_state.context.vfp); - ::memcpy (&m_state.context.exc, p, sizeof(m_state.context.exc)); - p += sizeof(m_state.context.exc); - - size_t bytes_written = p - (uint8_t *)buf; - UNUSED_IF_ASSERT_DISABLED(bytes_written); - assert (bytes_written == size); - SetGPRState(); - SetVFPState(); - SetEXCState(); - } - DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM64::SetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size); - return size; +nub_size_t DNBArchMachARM64::SetRegisterContext(const void *buf, + nub_size_t buf_len) { + nub_size_t size = sizeof(m_state.context.gpr) + sizeof(m_state.context.vfp) + + sizeof(m_state.context.exc); + + if (buf == NULL || buf_len == 0) + size = 0; + + if (size) { + if (size > buf_len) + size = buf_len; + + // Copy each struct individually to avoid any padding that might be between + // the structs in m_state.context + uint8_t *p = (uint8_t *)buf; + ::memcpy(&m_state.context.gpr, p, sizeof(m_state.context.gpr)); + p += sizeof(m_state.context.gpr); + ::memcpy(&m_state.context.vfp, p, sizeof(m_state.context.vfp)); + p += sizeof(m_state.context.vfp); + ::memcpy(&m_state.context.exc, p, sizeof(m_state.context.exc)); + p += sizeof(m_state.context.exc); + + size_t bytes_written = p - (uint8_t *)buf; + UNUSED_IF_ASSERT_DISABLED(bytes_written); + assert(bytes_written == size); + SetGPRState(); + SetVFPState(); + SetEXCState(); + } + DNBLogThreadedIf( + LOG_THREAD, + "DNBArchMachARM64::SetRegisterContext (buf = %p, len = %zu) => %zu", buf, + buf_len, size); + return size; } -uint32_t -DNBArchMachARM64::SaveRegisterState () -{ - kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); - DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); - - // Always re-read the registers because above we call thread_abort_safely(); - bool force = true; - - if ((kret = GetGPRState(force)) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM64::SaveRegisterState () error: GPR regs failed to read: %u ", kret); - } - else if ((kret = GetVFPState(force)) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM64::SaveRegisterState () error: %s regs failed to read: %u", "VFP", kret); - } - else - { - const uint32_t save_id = GetNextRegisterStateSaveID (); - m_saved_register_states[save_id] = m_state.context; - return save_id; - } - return UINT32_MAX; +uint32_t DNBArchMachARM64::SaveRegisterState() { + kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); + DNBLogThreadedIf( + LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u " + "(SetGPRState() for stop_count = %u)", + m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); + + // Always re-read the registers because above we call thread_abort_safely(); + bool force = true; + + if ((kret = GetGPRState(force)) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchMachARM64::SaveRegisterState () " + "error: GPR regs failed to read: %u ", + kret); + } else if ((kret = GetVFPState(force)) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchMachARM64::SaveRegisterState () " + "error: %s regs failed to read: %u", + "VFP", kret); + } else { + const uint32_t save_id = GetNextRegisterStateSaveID(); + m_saved_register_states[save_id] = m_state.context; + return save_id; + } + return UINT32_MAX; } -bool -DNBArchMachARM64::RestoreRegisterState (uint32_t save_id) -{ - SaveRegisterStates::iterator pos = m_saved_register_states.find(save_id); - if (pos != m_saved_register_states.end()) - { - m_state.context.gpr = pos->second.gpr; - m_state.context.vfp = pos->second.vfp; - kern_return_t kret; - bool success = true; - if ((kret = SetGPRState()) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM64::RestoreRegisterState (save_id = %u) error: GPR regs failed to write: %u", save_id, kret); - success = false; - } - else if ((kret = SetVFPState()) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM64::RestoreRegisterState (save_id = %u) error: %s regs failed to write: %u", save_id, "VFP", kret); - success = false; - } - m_saved_register_states.erase(pos); - return success; +bool DNBArchMachARM64::RestoreRegisterState(uint32_t save_id) { + SaveRegisterStates::iterator pos = m_saved_register_states.find(save_id); + if (pos != m_saved_register_states.end()) { + m_state.context.gpr = pos->second.gpr; + m_state.context.vfp = pos->second.vfp; + kern_return_t kret; + bool success = true; + if ((kret = SetGPRState()) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchMachARM64::RestoreRegisterState " + "(save_id = %u) error: GPR regs failed to " + "write: %u", + save_id, kret); + success = false; + } else if ((kret = SetVFPState()) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchMachARM64::RestoreRegisterState " + "(save_id = %u) error: %s regs failed to " + "write: %u", + save_id, "VFP", kret); + success = false; } - return false; + m_saved_register_states.erase(pos); + return success; + } + return false; } - -#endif // #if defined (ARM_THREAD_STATE64_COUNT) -#endif // #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) +#endif // #if defined (ARM_THREAD_STATE64_COUNT) +#endif // #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) diff --git a/lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.h b/lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.h index 7e68e411a76..cde0abf42d5 100644 --- a/lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.h +++ b/lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.h @@ -7,266 +7,243 @@ // //===----------------------------------------------------------------------===// - #ifndef __DNBArchImplARM64_h__ #define __DNBArchImplARM64_h__ -#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) +#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) -#include <map> #include <mach/thread_status.h> +#include <map> -#if defined (ARM_THREAD_STATE64_COUNT) +#if defined(ARM_THREAD_STATE64_COUNT) #include "DNBArch.h" class MachThread; -class DNBArchMachARM64 : public DNBArchProtocol -{ +class DNBArchMachARM64 : public DNBArchProtocol { public: - enum { kMaxNumThumbITBreakpoints = 4 }; - - DNBArchMachARM64(MachThread *thread) : - m_thread(thread), - m_state(), - m_disabled_watchpoints(), - m_watchpoint_hw_index(-1), - m_watchpoint_did_occur(false), - m_watchpoint_resume_single_step_enabled(false), - m_saved_register_states() - { - m_disabled_watchpoints.resize (16); - memset(&m_dbg_save, 0, sizeof(m_dbg_save)); - } - - virtual ~DNBArchMachARM64() - { - } + enum { kMaxNumThumbITBreakpoints = 4 }; - static void Initialize(); - static const DNBRegisterSetInfo * - GetRegisterSetInfo(nub_size_t *num_reg_sets); - - virtual bool GetRegisterValue(uint32_t set, uint32_t reg, DNBRegisterValue *value); - virtual bool SetRegisterValue(uint32_t set, uint32_t reg, const DNBRegisterValue *value); - virtual nub_size_t GetRegisterContext (void *buf, nub_size_t buf_len); - virtual nub_size_t SetRegisterContext (const void *buf, nub_size_t buf_len); - virtual uint32_t SaveRegisterState (); - virtual bool RestoreRegisterState (uint32_t save_id); - - virtual kern_return_t GetRegisterState (int set, bool force); - virtual kern_return_t SetRegisterState (int set); - virtual bool RegisterSetStateIsValid (int set) const; - - virtual uint64_t GetPC(uint64_t failValue); // Get program counter - virtual kern_return_t SetPC(uint64_t value); - virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer - virtual void ThreadWillResume(); - virtual bool ThreadDidStop(); - virtual bool NotifyException(MachException::Data& exc); - - static DNBArchProtocol *Create (MachThread *thread); - static const uint8_t * SoftwareBreakpointOpcode (nub_size_t byte_size); - static uint32_t GetCPUType(); - - virtual uint32_t NumSupportedHardwareWatchpoints(); - virtual uint32_t EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task); - virtual bool DisableHardwareWatchpoint (uint32_t hw_break_index, bool also_set_on_task); - virtual bool DisableHardwareWatchpoint_helper (uint32_t hw_break_index, bool also_set_on_task); + DNBArchMachARM64(MachThread *thread) + : m_thread(thread), m_state(), m_disabled_watchpoints(), + m_watchpoint_hw_index(-1), m_watchpoint_did_occur(false), + m_watchpoint_resume_single_step_enabled(false), + m_saved_register_states() { + m_disabled_watchpoints.resize(16); + memset(&m_dbg_save, 0, sizeof(m_dbg_save)); + } + + virtual ~DNBArchMachARM64() {} + + static void Initialize(); + static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets); + + virtual bool GetRegisterValue(uint32_t set, uint32_t reg, + DNBRegisterValue *value); + virtual bool SetRegisterValue(uint32_t set, uint32_t reg, + const DNBRegisterValue *value); + virtual nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len); + virtual nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len); + virtual uint32_t SaveRegisterState(); + virtual bool RestoreRegisterState(uint32_t save_id); + + virtual kern_return_t GetRegisterState(int set, bool force); + virtual kern_return_t SetRegisterState(int set); + virtual bool RegisterSetStateIsValid(int set) const; + + virtual uint64_t GetPC(uint64_t failValue); // Get program counter + virtual kern_return_t SetPC(uint64_t value); + virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer + virtual void ThreadWillResume(); + virtual bool ThreadDidStop(); + virtual bool NotifyException(MachException::Data &exc); + + static DNBArchProtocol *Create(MachThread *thread); + static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size); + static uint32_t GetCPUType(); + + virtual uint32_t NumSupportedHardwareWatchpoints(); + virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, + bool read, bool write, + bool also_set_on_task); + virtual bool DisableHardwareWatchpoint(uint32_t hw_break_index, + bool also_set_on_task); + virtual bool DisableHardwareWatchpoint_helper(uint32_t hw_break_index, + bool also_set_on_task); protected: - - - kern_return_t EnableHardwareSingleStep (bool enable); - static bool FixGenericRegisterNumber (uint32_t &set, uint32_t ®); - - typedef enum RegisterSetTag - { - e_regSetALL = REGISTER_SET_ALL, - e_regSetGPR, // ARM_THREAD_STATE64, - e_regSetVFP, // ARM_NEON_STATE64, - e_regSetEXC, // ARM_EXCEPTION_STATE64, - e_regSetDBG, // ARM_DEBUG_STATE64, - kNumRegisterSets - } RegisterSet; - - enum - { - e_regSetGPRCount = ARM_THREAD_STATE64_COUNT, - e_regSetVFPCount = ARM_NEON_STATE64_COUNT, - e_regSetEXCCount = ARM_EXCEPTION_STATE64_COUNT, - e_regSetDBGCount = ARM_DEBUG_STATE64_COUNT, - }; - - enum - { - Read = 0, - Write = 1, - kNumErrors = 2 - }; - - typedef arm_thread_state64_t GPR; - typedef arm_neon_state64_t FPU; - typedef arm_exception_state64_t EXC; - - static const DNBRegisterInfo g_gpr_registers[]; - static const DNBRegisterInfo g_vfp_registers[]; - static const DNBRegisterInfo g_exc_registers[]; - static const DNBRegisterSetInfo g_reg_sets[]; - - static const size_t k_num_gpr_registers; - static const size_t k_num_vfp_registers; - static const size_t k_num_exc_registers; - static const size_t k_num_all_registers; - static const size_t k_num_register_sets; - - struct Context - { - GPR gpr; - FPU vfp; - EXC exc; - }; - - struct State - { - Context context; - arm_debug_state64_t dbg; - kern_return_t gpr_errs[2]; // Read/Write errors - kern_return_t vfp_errs[2]; // Read/Write errors - kern_return_t exc_errs[2]; // Read/Write errors - kern_return_t dbg_errs[2]; // Read/Write errors - State() - { - uint32_t i; - for (i=0; i<kNumErrors; i++) - { - gpr_errs[i] = -1; - vfp_errs[i] = -1; - exc_errs[i] = -1; - dbg_errs[i] = -1; - } - } - void InvalidateRegisterSetState(int set) - { - SetError (set, Read, -1); - } - - void - InvalidateAllRegisterStates() - { - SetError (e_regSetALL, Read, -1); - } - - kern_return_t GetError (int set, uint32_t err_idx) const - { - if (err_idx < kNumErrors) - { - switch (set) - { - // When getting all errors, just OR all values together to see if - // we got any kind of error. - case e_regSetALL: return gpr_errs[err_idx] | - vfp_errs[err_idx] | - exc_errs[err_idx] | - dbg_errs[err_idx] ; - case e_regSetGPR: return gpr_errs[err_idx]; - case e_regSetVFP: return vfp_errs[err_idx]; - case e_regSetEXC: return exc_errs[err_idx]; - //case e_regSetDBG: return dbg_errs[err_idx]; - default: break; - } - } - return -1; - } - bool SetError (int set, uint32_t err_idx, kern_return_t err) - { - if (err_idx < kNumErrors) - { - switch (set) - { - case e_regSetALL: - gpr_errs[err_idx] = err; - vfp_errs[err_idx] = err; - dbg_errs[err_idx] = err; - exc_errs[err_idx] = err; - return true; - - case e_regSetGPR: - gpr_errs[err_idx] = err; - return true; - - case e_regSetVFP: - vfp_errs[err_idx] = err; - return true; - - case e_regSetEXC: - exc_errs[err_idx] = err; - return true; - -// case e_regSetDBG: -// dbg_errs[err_idx] = err; -// return true; - default: break; - } - } - return false; + kern_return_t EnableHardwareSingleStep(bool enable); + static bool FixGenericRegisterNumber(uint32_t &set, uint32_t ®); + + typedef enum RegisterSetTag { + e_regSetALL = REGISTER_SET_ALL, + e_regSetGPR, // ARM_THREAD_STATE64, + e_regSetVFP, // ARM_NEON_STATE64, + e_regSetEXC, // ARM_EXCEPTION_STATE64, + e_regSetDBG, // ARM_DEBUG_STATE64, + kNumRegisterSets + } RegisterSet; + + enum { + e_regSetGPRCount = ARM_THREAD_STATE64_COUNT, + e_regSetVFPCount = ARM_NEON_STATE64_COUNT, + e_regSetEXCCount = ARM_EXCEPTION_STATE64_COUNT, + e_regSetDBGCount = ARM_DEBUG_STATE64_COUNT, + }; + + enum { Read = 0, Write = 1, kNumErrors = 2 }; + + typedef arm_thread_state64_t GPR; + typedef arm_neon_state64_t FPU; + typedef arm_exception_state64_t EXC; + + static const DNBRegisterInfo g_gpr_registers[]; + static const DNBRegisterInfo g_vfp_registers[]; + static const DNBRegisterInfo g_exc_registers[]; + static const DNBRegisterSetInfo g_reg_sets[]; + + static const size_t k_num_gpr_registers; + static const size_t k_num_vfp_registers; + static const size_t k_num_exc_registers; + static const size_t k_num_all_registers; + static const size_t k_num_register_sets; + + struct Context { + GPR gpr; + FPU vfp; + EXC exc; + }; + + struct State { + Context context; + arm_debug_state64_t dbg; + kern_return_t gpr_errs[2]; // Read/Write errors + kern_return_t vfp_errs[2]; // Read/Write errors + kern_return_t exc_errs[2]; // Read/Write errors + kern_return_t dbg_errs[2]; // Read/Write errors + State() { + uint32_t i; + for (i = 0; i < kNumErrors; i++) { + gpr_errs[i] = -1; + vfp_errs[i] = -1; + exc_errs[i] = -1; + dbg_errs[i] = -1; + } + } + void InvalidateRegisterSetState(int set) { SetError(set, Read, -1); } + + void InvalidateAllRegisterStates() { SetError(e_regSetALL, Read, -1); } + + kern_return_t GetError(int set, uint32_t err_idx) const { + if (err_idx < kNumErrors) { + switch (set) { + // When getting all errors, just OR all values together to see if + // we got any kind of error. + case e_regSetALL: + return gpr_errs[err_idx] | vfp_errs[err_idx] | exc_errs[err_idx] | + dbg_errs[err_idx]; + case e_regSetGPR: + return gpr_errs[err_idx]; + case e_regSetVFP: + return vfp_errs[err_idx]; + case e_regSetEXC: + return exc_errs[err_idx]; + // case e_regSetDBG: return dbg_errs[err_idx]; + default: + break; } - bool RegsAreValid (int set) const - { - return GetError(set, Read) == KERN_SUCCESS; + } + return -1; + } + bool SetError(int set, uint32_t err_idx, kern_return_t err) { + if (err_idx < kNumErrors) { + switch (set) { + case e_regSetALL: + gpr_errs[err_idx] = err; + vfp_errs[err_idx] = err; + dbg_errs[err_idx] = err; + exc_errs[err_idx] = err; + return true; + + case e_regSetGPR: + gpr_errs[err_idx] = err; + return true; + + case e_regSetVFP: + vfp_errs[err_idx] = err; + return true; + + case e_regSetEXC: + exc_errs[err_idx] = err; + return true; + + // case e_regSetDBG: + // dbg_errs[err_idx] = err; + // return true; + default: + break; } - }; - - kern_return_t GetGPRState (bool force); - kern_return_t GetVFPState (bool force); - kern_return_t GetEXCState (bool force); - kern_return_t GetDBGState (bool force); - - kern_return_t SetGPRState (); - kern_return_t SetVFPState (); - kern_return_t SetEXCState (); - kern_return_t SetDBGState (bool also_set_on_task); - - // Helper functions for watchpoint implementaions. - - typedef arm_debug_state64_t DBG; - - void ClearWatchpointOccurred(); - bool HasWatchpointOccurred(); - bool IsWatchpointEnabled(const DBG &debug_state, uint32_t hw_index); - nub_addr_t GetWatchpointAddressByIndex (uint32_t hw_index); - nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); - virtual bool ReenableHardwareWatchpoint (uint32_t hw_break_index); - virtual bool ReenableHardwareWatchpoint_helper (uint32_t hw_break_index); - virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); - - - class disabled_watchpoint { - public: - disabled_watchpoint () { addr = 0; control = 0; } - nub_addr_t addr; - uint32_t control; - }; + } + return false; + } + bool RegsAreValid(int set) const { + return GetError(set, Read) == KERN_SUCCESS; + } + }; + + kern_return_t GetGPRState(bool force); + kern_return_t GetVFPState(bool force); + kern_return_t GetEXCState(bool force); + kern_return_t GetDBGState(bool force); + + kern_return_t SetGPRState(); + kern_return_t SetVFPState(); + kern_return_t SetEXCState(); + kern_return_t SetDBGState(bool also_set_on_task); + + // Helper functions for watchpoint implementaions. + + typedef arm_debug_state64_t DBG; + + void ClearWatchpointOccurred(); + bool HasWatchpointOccurred(); + bool IsWatchpointEnabled(const DBG &debug_state, uint32_t hw_index); + nub_addr_t GetWatchpointAddressByIndex(uint32_t hw_index); + nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); + virtual bool ReenableHardwareWatchpoint(uint32_t hw_break_index); + virtual bool ReenableHardwareWatchpoint_helper(uint32_t hw_break_index); + virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); + + class disabled_watchpoint { + public: + disabled_watchpoint() { + addr = 0; + control = 0; + } + nub_addr_t addr; + uint32_t control; + }; protected: - MachThread * m_thread; - State m_state; - arm_debug_state64_t m_dbg_save; - - // arm64 doesn't keep the disabled watchpoint values in the debug register context like armv7; - // we need to save them aside when we disable them temporarily. - std::vector<disabled_watchpoint> m_disabled_watchpoints; - - // The following member variables should be updated atomically. - int32_t m_watchpoint_hw_index; - bool m_watchpoint_did_occur; - bool m_watchpoint_resume_single_step_enabled; - - typedef std::map<uint32_t, Context> SaveRegisterStates; - SaveRegisterStates m_saved_register_states; + MachThread *m_thread; + State m_state; + arm_debug_state64_t m_dbg_save; + + // arm64 doesn't keep the disabled watchpoint values in the debug register + // context like armv7; + // we need to save them aside when we disable them temporarily. + std::vector<disabled_watchpoint> m_disabled_watchpoints; + + // The following member variables should be updated atomically. + int32_t m_watchpoint_hw_index; + bool m_watchpoint_did_occur; + bool m_watchpoint_resume_single_step_enabled; + + typedef std::map<uint32_t, Context> SaveRegisterStates; + SaveRegisterStates m_saved_register_states; }; -#endif // #if defined (ARM_THREAD_STATE64_COUNT) -#endif // #if defined (__arm__) -#endif // #ifndef __DNBArchImplARM64_h__ +#endif // #if defined (ARM_THREAD_STATE64_COUNT) +#endif // #if defined (__arm__) +#endif // #ifndef __DNBArchImplARM64_h__ diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp index 93d4d894300..0974b168326 100644 --- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp +++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp @@ -11,51 +11,43 @@ // //===----------------------------------------------------------------------===// -#if defined (__i386__) || defined (__x86_64__) +#if defined(__i386__) || defined(__x86_64__) #include <sys/cdefs.h> -#include "MacOSX/i386/DNBArchImplI386.h" #include "DNBLog.h" -#include "MachThread.h" +#include "MacOSX/i386/DNBArchImplI386.h" #include "MachProcess.h" +#include "MachThread.h" extern "C" bool CPUHasAVX(); // Defined over in DNBArchImplX86_64.cpp -#if defined (LLDB_DEBUGSERVER_RELEASE) || defined (LLDB_DEBUGSERVER_DEBUG) -enum debugState { - debugStateUnknown, - debugStateOff, - debugStateOn -}; +#if defined(LLDB_DEBUGSERVER_RELEASE) || defined(LLDB_DEBUGSERVER_DEBUG) +enum debugState { debugStateUnknown, debugStateOff, debugStateOn }; static debugState sFPUDebugState = debugStateUnknown; static debugState sAVXForceState = debugStateUnknown; -static bool DebugFPURegs () -{ - if (sFPUDebugState == debugStateUnknown) - { - if (getenv("DNB_DEBUG_FPU_REGS")) - sFPUDebugState = debugStateOn; - else - sFPUDebugState = debugStateOff; - } - - return (sFPUDebugState == debugStateOn); +static bool DebugFPURegs() { + if (sFPUDebugState == debugStateUnknown) { + if (getenv("DNB_DEBUG_FPU_REGS")) + sFPUDebugState = debugStateOn; + else + sFPUDebugState = debugStateOff; + } + + return (sFPUDebugState == debugStateOn); } -static bool ForceAVXRegs () -{ - if (sFPUDebugState == debugStateUnknown) - { - if (getenv("DNB_DEBUG_X86_FORCE_AVX_REGS")) - sAVXForceState = debugStateOn; - else - sAVXForceState = debugStateOff; - } - - return (sAVXForceState == debugStateOn); +static bool ForceAVXRegs() { + if (sFPUDebugState == debugStateUnknown) { + if (getenv("DNB_DEBUG_X86_FORCE_AVX_REGS")) + sAVXForceState = debugStateOn; + else + sAVXForceState = debugStateOff; + } + + return (sAVXForceState == debugStateOn); } #define DEBUG_FPU_REGS (DebugFPURegs()) @@ -65,1837 +57,2314 @@ static bool ForceAVXRegs () #define FORCE_AVX_REGS (0) #endif -enum -{ - gpr_eax = 0, - gpr_ebx = 1, - gpr_ecx = 2, - gpr_edx = 3, - gpr_edi = 4, - gpr_esi = 5, - gpr_ebp = 6, - gpr_esp = 7, - gpr_ss = 8, - gpr_eflags = 9, - gpr_eip = 10, - gpr_cs = 11, - gpr_ds = 12, - gpr_es = 13, - gpr_fs = 14, - gpr_gs = 15, - gpr_ax , - gpr_bx , - gpr_cx , - gpr_dx , - gpr_di , - gpr_si , - gpr_bp , - gpr_sp , - gpr_ah , - gpr_bh , - gpr_ch , - gpr_dh , - gpr_al , - gpr_bl , - gpr_cl , - gpr_dl , - gpr_dil, - gpr_sil, - gpr_bpl, - gpr_spl, - k_num_gpr_regs +enum { + gpr_eax = 0, + gpr_ebx = 1, + gpr_ecx = 2, + gpr_edx = 3, + gpr_edi = 4, + gpr_esi = 5, + gpr_ebp = 6, + gpr_esp = 7, + gpr_ss = 8, + gpr_eflags = 9, + gpr_eip = 10, + gpr_cs = 11, + gpr_ds = 12, + gpr_es = 13, + gpr_fs = 14, + gpr_gs = 15, + gpr_ax, + gpr_bx, + gpr_cx, + gpr_dx, + gpr_di, + gpr_si, + gpr_bp, + gpr_sp, + gpr_ah, + gpr_bh, + gpr_ch, + gpr_dh, + gpr_al, + gpr_bl, + gpr_cl, + gpr_dl, + gpr_dil, + gpr_sil, + gpr_bpl, + gpr_spl, + k_num_gpr_regs }; enum { - fpu_fcw, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_dp, - fpu_ds, - fpu_mxcsr, - fpu_mxcsrmask, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, - fpu_ymm0, - fpu_ymm1, - fpu_ymm2, - fpu_ymm3, - fpu_ymm4, - fpu_ymm5, - fpu_ymm6, - fpu_ymm7, - k_num_fpu_regs, - - // Aliases - fpu_fctrl = fpu_fcw, - fpu_fstat = fpu_fsw, - fpu_ftag = fpu_ftw, - fpu_fiseg = fpu_cs, - fpu_fioff = fpu_ip, - fpu_foseg = fpu_ds, - fpu_fooff = fpu_dp + fpu_fcw, + fpu_fsw, + fpu_ftw, + fpu_fop, + fpu_ip, + fpu_cs, + fpu_dp, + fpu_ds, + fpu_mxcsr, + fpu_mxcsrmask, + fpu_stmm0, + fpu_stmm1, + fpu_stmm2, + fpu_stmm3, + fpu_stmm4, + fpu_stmm5, + fpu_stmm6, + fpu_stmm7, + fpu_xmm0, + fpu_xmm1, + fpu_xmm2, + fpu_xmm3, + fpu_xmm4, + fpu_xmm5, + fpu_xmm6, + fpu_xmm7, + fpu_ymm0, + fpu_ymm1, + fpu_ymm2, + fpu_ymm3, + fpu_ymm4, + fpu_ymm5, + fpu_ymm6, + fpu_ymm7, + k_num_fpu_regs, + + // Aliases + fpu_fctrl = fpu_fcw, + fpu_fstat = fpu_fsw, + fpu_ftag = fpu_ftw, + fpu_fiseg = fpu_cs, + fpu_fioff = fpu_ip, + fpu_foseg = fpu_ds, + fpu_fooff = fpu_dp }; enum { - exc_trapno, - exc_err, - exc_faultvaddr, - k_num_exc_regs, + exc_trapno, + exc_err, + exc_faultvaddr, + k_num_exc_regs, }; - -enum -{ - ehframe_eax = 0, - ehframe_ecx, - ehframe_edx, - ehframe_ebx, - - // On i386 Darwin the eh_frame register numbers for ebp and esp are reversed from DWARF. - // It's due to an ancient compiler bug in the output of the eh_frame. - // Specifically, on i386 darwin eh_frame, 4 is ebp, 5 is esp. - // On i386 darwin debug_frame (and debug_info), 4 is esp, 5 is ebp. - ehframe_ebp, - ehframe_esp, - ehframe_esi, - ehframe_edi, - ehframe_eip, - ehframe_eflags +enum { + ehframe_eax = 0, + ehframe_ecx, + ehframe_edx, + ehframe_ebx, + + // On i386 Darwin the eh_frame register numbers for ebp and esp are reversed + // from DWARF. + // It's due to an ancient compiler bug in the output of the eh_frame. + // Specifically, on i386 darwin eh_frame, 4 is ebp, 5 is esp. + // On i386 darwin debug_frame (and debug_info), 4 is esp, 5 is ebp. + ehframe_ebp, + ehframe_esp, + ehframe_esi, + ehframe_edi, + ehframe_eip, + ehframe_eflags }; -enum -{ - dwarf_eax = 0, - dwarf_ecx, - dwarf_edx, - dwarf_ebx, - dwarf_esp, - dwarf_ebp, - dwarf_esi, - dwarf_edi, - dwarf_eip, - dwarf_eflags, - dwarf_stmm0 = 11, - dwarf_stmm1, - dwarf_stmm2, - dwarf_stmm3, - dwarf_stmm4, - dwarf_stmm5, - dwarf_stmm6, - dwarf_stmm7, - dwarf_xmm0 = 21, - dwarf_xmm1, - dwarf_xmm2, - dwarf_xmm3, - dwarf_xmm4, - dwarf_xmm5, - dwarf_xmm6, - dwarf_xmm7, - dwarf_ymm0 = dwarf_xmm0, - dwarf_ymm1 = dwarf_xmm1, - dwarf_ymm2 = dwarf_xmm2, - dwarf_ymm3 = dwarf_xmm3, - dwarf_ymm4 = dwarf_xmm4, - dwarf_ymm5 = dwarf_xmm5, - dwarf_ymm6 = dwarf_xmm6, - dwarf_ymm7 = dwarf_xmm7, +enum { + dwarf_eax = 0, + dwarf_ecx, + dwarf_edx, + dwarf_ebx, + dwarf_esp, + dwarf_ebp, + dwarf_esi, + dwarf_edi, + dwarf_eip, + dwarf_eflags, + dwarf_stmm0 = 11, + dwarf_stmm1, + dwarf_stmm2, + dwarf_stmm3, + dwarf_stmm4, + dwarf_stmm5, + dwarf_stmm6, + dwarf_stmm7, + dwarf_xmm0 = 21, + dwarf_xmm1, + dwarf_xmm2, + dwarf_xmm3, + dwarf_xmm4, + dwarf_xmm5, + dwarf_xmm6, + dwarf_xmm7, + dwarf_ymm0 = dwarf_xmm0, + dwarf_ymm1 = dwarf_xmm1, + dwarf_ymm2 = dwarf_xmm2, + dwarf_ymm3 = dwarf_xmm3, + dwarf_ymm4 = dwarf_xmm4, + dwarf_ymm5 = dwarf_xmm5, + dwarf_ymm6 = dwarf_xmm6, + dwarf_ymm7 = dwarf_xmm7, }; -enum -{ - debugserver_eax = 0, - debugserver_ecx = 1, - debugserver_edx = 2, - debugserver_ebx = 3, - debugserver_esp = 4, - debugserver_ebp = 5, - debugserver_esi = 6, - debugserver_edi = 7, - debugserver_eip = 8, - debugserver_eflags = 9, - debugserver_cs = 10, - debugserver_ss = 11, - debugserver_ds = 12, - debugserver_es = 13, - debugserver_fs = 14, - debugserver_gs = 15, - debugserver_stmm0 = 16, - debugserver_stmm1 = 17, - debugserver_stmm2 = 18, - debugserver_stmm3 = 19, - debugserver_stmm4 = 20, - debugserver_stmm5 = 21, - debugserver_stmm6 = 22, - debugserver_stmm7 = 23, - debugserver_fctrl = 24, debugserver_fcw = debugserver_fctrl, - debugserver_fstat = 25, debugserver_fsw = debugserver_fstat, - debugserver_ftag = 26, debugserver_ftw = debugserver_ftag, - debugserver_fiseg = 27, debugserver_fpu_cs = debugserver_fiseg, - debugserver_fioff = 28, debugserver_ip = debugserver_fioff, - debugserver_foseg = 29, debugserver_fpu_ds = debugserver_foseg, - debugserver_fooff = 30, debugserver_dp = debugserver_fooff, - debugserver_fop = 31, - debugserver_xmm0 = 32, - debugserver_xmm1 = 33, - debugserver_xmm2 = 34, - debugserver_xmm3 = 35, - debugserver_xmm4 = 36, - debugserver_xmm5 = 37, - debugserver_xmm6 = 38, - debugserver_xmm7 = 39, - debugserver_mxcsr = 40, - debugserver_mm0 = 41, - debugserver_mm1 = 42, - debugserver_mm2 = 43, - debugserver_mm3 = 44, - debugserver_mm4 = 45, - debugserver_mm5 = 46, - debugserver_mm6 = 47, - debugserver_mm7 = 48, - debugserver_ymm0 = debugserver_xmm0, - debugserver_ymm1 = debugserver_xmm1, - debugserver_ymm2 = debugserver_xmm2, - debugserver_ymm3 = debugserver_xmm3, - debugserver_ymm4 = debugserver_xmm4, - debugserver_ymm5 = debugserver_xmm5, - debugserver_ymm6 = debugserver_xmm6, - debugserver_ymm7 = debugserver_xmm7 +enum { + debugserver_eax = 0, + debugserver_ecx = 1, + debugserver_edx = 2, + debugserver_ebx = 3, + debugserver_esp = 4, + debugserver_ebp = 5, + debugserver_esi = 6, + debugserver_edi = 7, + debugserver_eip = 8, + debugserver_eflags = 9, + debugserver_cs = 10, + debugserver_ss = 11, + debugserver_ds = 12, + debugserver_es = 13, + debugserver_fs = 14, + debugserver_gs = 15, + debugserver_stmm0 = 16, + debugserver_stmm1 = 17, + debugserver_stmm2 = 18, + debugserver_stmm3 = 19, + debugserver_stmm4 = 20, + debugserver_stmm5 = 21, + debugserver_stmm6 = 22, + debugserver_stmm7 = 23, + debugserver_fctrl = 24, + debugserver_fcw = debugserver_fctrl, + debugserver_fstat = 25, + debugserver_fsw = debugserver_fstat, + debugserver_ftag = 26, + debugserver_ftw = debugserver_ftag, + debugserver_fiseg = 27, + debugserver_fpu_cs = debugserver_fiseg, + debugserver_fioff = 28, + debugserver_ip = debugserver_fioff, + debugserver_foseg = 29, + debugserver_fpu_ds = debugserver_foseg, + debugserver_fooff = 30, + debugserver_dp = debugserver_fooff, + debugserver_fop = 31, + debugserver_xmm0 = 32, + debugserver_xmm1 = 33, + debugserver_xmm2 = 34, + debugserver_xmm3 = 35, + debugserver_xmm4 = 36, + debugserver_xmm5 = 37, + debugserver_xmm6 = 38, + debugserver_xmm7 = 39, + debugserver_mxcsr = 40, + debugserver_mm0 = 41, + debugserver_mm1 = 42, + debugserver_mm2 = 43, + debugserver_mm3 = 44, + debugserver_mm4 = 45, + debugserver_mm5 = 46, + debugserver_mm6 = 47, + debugserver_mm7 = 48, + debugserver_ymm0 = debugserver_xmm0, + debugserver_ymm1 = debugserver_xmm1, + debugserver_ymm2 = debugserver_xmm2, + debugserver_ymm3 = debugserver_xmm3, + debugserver_ymm4 = debugserver_xmm4, + debugserver_ymm5 = debugserver_xmm5, + debugserver_ymm6 = debugserver_xmm6, + debugserver_ymm7 = debugserver_xmm7 }; -uint64_t -DNBArchImplI386::GetPC(uint64_t failValue) -{ - // Get program counter - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.context.gpr.__eip; - return failValue; +uint64_t DNBArchImplI386::GetPC(uint64_t failValue) { + // Get program counter + if (GetGPRState(false) == KERN_SUCCESS) + return m_state.context.gpr.__eip; + return failValue; } -kern_return_t -DNBArchImplI386::SetPC(uint64_t value) -{ - // Get program counter - kern_return_t err = GetGPRState(false); - if (err == KERN_SUCCESS) - { - m_state.context.gpr.__eip = static_cast<uint32_t>(value); - err = SetGPRState(); - } - return err == KERN_SUCCESS; +kern_return_t DNBArchImplI386::SetPC(uint64_t value) { + // Get program counter + kern_return_t err = GetGPRState(false); + if (err == KERN_SUCCESS) { + m_state.context.gpr.__eip = static_cast<uint32_t>(value); + err = SetGPRState(); + } + return err == KERN_SUCCESS; } -uint64_t -DNBArchImplI386::GetSP(uint64_t failValue) -{ - // Get stack pointer - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.context.gpr.__esp; - return failValue; +uint64_t DNBArchImplI386::GetSP(uint64_t failValue) { + // Get stack pointer + if (GetGPRState(false) == KERN_SUCCESS) + return m_state.context.gpr.__esp; + return failValue; } // Uncomment the value below to verify the values in the debugger. //#define DEBUG_GPR_VALUES 1 // DO NOT CHECK IN WITH THIS DEFINE ENABLED //#define SET_GPR(reg) m_state.context.gpr.__##reg = gpr_##reg -kern_return_t -DNBArchImplI386::GetGPRState(bool force) -{ - if (force || m_state.GetError(e_regSetGPR, Read)) - { +kern_return_t DNBArchImplI386::GetGPRState(bool force) { + if (force || m_state.GetError(e_regSetGPR, Read)) { #if DEBUG_GPR_VALUES - SET_GPR(eax); - SET_GPR(ebx); - SET_GPR(ecx); - SET_GPR(edx); - SET_GPR(edi); - SET_GPR(esi); - SET_GPR(ebp); - SET_GPR(esp); - SET_GPR(ss); - SET_GPR(eflags); - SET_GPR(eip); - SET_GPR(cs); - SET_GPR(ds); - SET_GPR(es); - SET_GPR(fs); - SET_GPR(gs); - m_state.SetError(e_regSetGPR, Read, 0); + SET_GPR(eax); + SET_GPR(ebx); + SET_GPR(ecx); + SET_GPR(edx); + SET_GPR(edi); + SET_GPR(esi); + SET_GPR(ebp); + SET_GPR(esp); + SET_GPR(ss); + SET_GPR(eflags); + SET_GPR(eip); + SET_GPR(cs); + SET_GPR(ds); + SET_GPR(es); + SET_GPR(fs); + SET_GPR(gs); + m_state.SetError(e_regSetGPR, Read, 0); #else - mach_msg_type_number_t count = e_regSetWordSizeGPR; - m_state.SetError(e_regSetGPR, Read, ::thread_get_state(m_thread->MachPortNumber(), __i386_THREAD_STATE, (thread_state_t)&m_state.context.gpr, &count)); + mach_msg_type_number_t count = e_regSetWordSizeGPR; + m_state.SetError( + e_regSetGPR, Read, + ::thread_get_state(m_thread->MachPortNumber(), __i386_THREAD_STATE, + (thread_state_t)&m_state.context.gpr, &count)); #endif - } - return m_state.GetError(e_regSetGPR, Read); + } + return m_state.GetError(e_regSetGPR, Read); } // Uncomment the value below to verify the values in the debugger. //#define DEBUG_FPU_VALUES 1 // DO NOT CHECK IN WITH THIS DEFINE ENABLED -kern_return_t -DNBArchImplI386::GetFPUState(bool force) -{ - if (force || m_state.GetError(e_regSetFPU, Read)) - { - if (DEBUG_FPU_REGS) - { - if (CPUHasAVX() || FORCE_AVX_REGS) - { - m_state.context.fpu.avx.__fpu_reserved[0] = -1; - m_state.context.fpu.avx.__fpu_reserved[1] = -1; - *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fcw) = 0x1234; - *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fsw) = 0x5678; - m_state.context.fpu.avx.__fpu_ftw = 1; - m_state.context.fpu.avx.__fpu_rsrv1 = UINT8_MAX; - m_state.context.fpu.avx.__fpu_fop = 2; - m_state.context.fpu.avx.__fpu_ip = 3; - m_state.context.fpu.avx.__fpu_cs = 4; - m_state.context.fpu.avx.__fpu_rsrv2 = 5; - m_state.context.fpu.avx.__fpu_dp = 6; - m_state.context.fpu.avx.__fpu_ds = 7; - m_state.context.fpu.avx.__fpu_rsrv3 = UINT16_MAX; - m_state.context.fpu.avx.__fpu_mxcsr = 8; - m_state.context.fpu.avx.__fpu_mxcsrmask = 9; - int i; - for (i=0; i<16; ++i) - { - if (i<10) - { - m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = 'a'; - m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = 'b'; - m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = 'c'; - m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = 'd'; - m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = 'e'; - m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = 'f'; - m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = 'g'; - m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = 'h'; - } - else - { - m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN; - } - - m_state.context.fpu.avx.__fpu_xmm0.__xmm_reg[i] = '0'; - m_state.context.fpu.avx.__fpu_xmm1.__xmm_reg[i] = '1'; - m_state.context.fpu.avx.__fpu_xmm2.__xmm_reg[i] = '2'; - m_state.context.fpu.avx.__fpu_xmm3.__xmm_reg[i] = '3'; - m_state.context.fpu.avx.__fpu_xmm4.__xmm_reg[i] = '4'; - m_state.context.fpu.avx.__fpu_xmm5.__xmm_reg[i] = '5'; - m_state.context.fpu.avx.__fpu_xmm6.__xmm_reg[i] = '6'; - m_state.context.fpu.avx.__fpu_xmm7.__xmm_reg[i] = '7'; - } - for (i=0; i<sizeof(m_state.context.fpu.avx.__fpu_rsrv4); ++i) - m_state.context.fpu.avx.__fpu_rsrv4[i] = INT8_MIN; - m_state.context.fpu.avx.__fpu_reserved1 = -1; - for (i=0; i<sizeof(m_state.context.fpu.avx.__avx_reserved1); ++i) - m_state.context.fpu.avx.__avx_reserved1[i] = INT8_MIN; - - for (i = 0; i < 16; ++i) - { - m_state.context.fpu.avx.__fpu_ymmh0.__xmm_reg[i] = '0'; - m_state.context.fpu.avx.__fpu_ymmh1.__xmm_reg[i] = '1'; - m_state.context.fpu.avx.__fpu_ymmh2.__xmm_reg[i] = '2'; - m_state.context.fpu.avx.__fpu_ymmh3.__xmm_reg[i] = '3'; - m_state.context.fpu.avx.__fpu_ymmh4.__xmm_reg[i] = '4'; - m_state.context.fpu.avx.__fpu_ymmh5.__xmm_reg[i] = '5'; - m_state.context.fpu.avx.__fpu_ymmh6.__xmm_reg[i] = '6'; - m_state.context.fpu.avx.__fpu_ymmh7.__xmm_reg[i] = '7'; - } - } - else - { - m_state.context.fpu.no_avx.__fpu_reserved[0] = -1; - m_state.context.fpu.no_avx.__fpu_reserved[1] = -1; - *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fcw) = 0x1234; - *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fsw) = 0x5678; - m_state.context.fpu.no_avx.__fpu_ftw = 1; - m_state.context.fpu.no_avx.__fpu_rsrv1 = UINT8_MAX; - m_state.context.fpu.no_avx.__fpu_fop = 2; - m_state.context.fpu.no_avx.__fpu_ip = 3; - m_state.context.fpu.no_avx.__fpu_cs = 4; - m_state.context.fpu.no_avx.__fpu_rsrv2 = 5; - m_state.context.fpu.no_avx.__fpu_dp = 6; - m_state.context.fpu.no_avx.__fpu_ds = 7; - m_state.context.fpu.no_avx.__fpu_rsrv3 = UINT16_MAX; - m_state.context.fpu.no_avx.__fpu_mxcsr = 8; - m_state.context.fpu.no_avx.__fpu_mxcsrmask = 9; - int i; - for (i=0; i<16; ++i) - { - if (i<10) - { - m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = 'a'; - m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = 'b'; - m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = 'c'; - m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = 'd'; - m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = 'e'; - m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = 'f'; - m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = 'g'; - m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = 'h'; - } - else - { - m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN; - } - - m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg[i] = '0'; - m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg[i] = '1'; - m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg[i] = '2'; - m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg[i] = '3'; - m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg[i] = '4'; - m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg[i] = '5'; - m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg[i] = '6'; - m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg[i] = '7'; - } - for (i=0; i<sizeof(m_state.context.fpu.avx.__fpu_rsrv4); ++i) - m_state.context.fpu.no_avx.__fpu_rsrv4[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_reserved1 = -1; - } - m_state.SetError(e_regSetFPU, Read, 0); +kern_return_t DNBArchImplI386::GetFPUState(bool force) { + if (force || m_state.GetError(e_regSetFPU, Read)) { + if (DEBUG_FPU_REGS) { + if (CPUHasAVX() || FORCE_AVX_REGS) { + m_state.context.fpu.avx.__fpu_reserved[0] = -1; + m_state.context.fpu.avx.__fpu_reserved[1] = -1; + *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fcw) = 0x1234; + *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fsw) = 0x5678; + m_state.context.fpu.avx.__fpu_ftw = 1; + m_state.context.fpu.avx.__fpu_rsrv1 = UINT8_MAX; + m_state.context.fpu.avx.__fpu_fop = 2; + m_state.context.fpu.avx.__fpu_ip = 3; + m_state.context.fpu.avx.__fpu_cs = 4; + m_state.context.fpu.avx.__fpu_rsrv2 = 5; + m_state.context.fpu.avx.__fpu_dp = 6; + m_state.context.fpu.avx.__fpu_ds = 7; + m_state.context.fpu.avx.__fpu_rsrv3 = UINT16_MAX; + m_state.context.fpu.avx.__fpu_mxcsr = 8; + m_state.context.fpu.avx.__fpu_mxcsrmask = 9; + int i; + for (i = 0; i < 16; ++i) { + if (i < 10) { + m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = 'a'; + m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = 'b'; + m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = 'c'; + m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = 'd'; + m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = 'e'; + m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = 'f'; + m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = 'g'; + m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = 'h'; + } else { + m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN; + } + + m_state.context.fpu.avx.__fpu_xmm0.__xmm_reg[i] = '0'; + m_state.context.fpu.avx.__fpu_xmm1.__xmm_reg[i] = '1'; + m_state.context.fpu.avx.__fpu_xmm2.__xmm_reg[i] = '2'; + m_state.context.fpu.avx.__fpu_xmm3.__xmm_reg[i] = '3'; + m_state.context.fpu.avx.__fpu_xmm4.__xmm_reg[i] = '4'; + m_state.context.fpu.avx.__fpu_xmm5.__xmm_reg[i] = '5'; + m_state.context.fpu.avx.__fpu_xmm6.__xmm_reg[i] = '6'; + m_state.context.fpu.avx.__fpu_xmm7.__xmm_reg[i] = '7'; } - else - { - if (CPUHasAVX() || FORCE_AVX_REGS) - { - mach_msg_type_number_t count = e_regSetWordSizeAVX; - m_state.SetError (e_regSetFPU, Read, ::thread_get_state(m_thread->MachPortNumber(), __i386_AVX_STATE, (thread_state_t)&m_state.context.fpu.avx, &count)); - DNBLogThreadedIf (LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &avx, %u (%u passed in)) => 0x%8.8x", - m_thread->MachPortNumber(), __i386_AVX_STATE, count, e_regSetWordSizeAVX, - m_state.GetError(e_regSetFPU, Read)); - } - else - { - mach_msg_type_number_t count = e_regSetWordSizeFPU; - m_state.SetError(e_regSetFPU, Read, ::thread_get_state(m_thread->MachPortNumber(), __i386_FLOAT_STATE, (thread_state_t)&m_state.context.fpu.no_avx, &count)); - DNBLogThreadedIf (LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &fpu, %u (%u passed in) => 0x%8.8x", - m_thread->MachPortNumber(), __i386_FLOAT_STATE, count, e_regSetWordSizeFPU, - m_state.GetError(e_regSetFPU, Read)); - } + for (i = 0; i < sizeof(m_state.context.fpu.avx.__fpu_rsrv4); ++i) + m_state.context.fpu.avx.__fpu_rsrv4[i] = INT8_MIN; + m_state.context.fpu.avx.__fpu_reserved1 = -1; + for (i = 0; i < sizeof(m_state.context.fpu.avx.__avx_reserved1); ++i) + m_state.context.fpu.avx.__avx_reserved1[i] = INT8_MIN; + + for (i = 0; i < 16; ++i) { + m_state.context.fpu.avx.__fpu_ymmh0.__xmm_reg[i] = '0'; + m_state.context.fpu.avx.__fpu_ymmh1.__xmm_reg[i] = '1'; + m_state.context.fpu.avx.__fpu_ymmh2.__xmm_reg[i] = '2'; + m_state.context.fpu.avx.__fpu_ymmh3.__xmm_reg[i] = '3'; + m_state.context.fpu.avx.__fpu_ymmh4.__xmm_reg[i] = '4'; + m_state.context.fpu.avx.__fpu_ymmh5.__xmm_reg[i] = '5'; + m_state.context.fpu.avx.__fpu_ymmh6.__xmm_reg[i] = '6'; + m_state.context.fpu.avx.__fpu_ymmh7.__xmm_reg[i] = '7'; } + } else { + m_state.context.fpu.no_avx.__fpu_reserved[0] = -1; + m_state.context.fpu.no_avx.__fpu_reserved[1] = -1; + *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fcw) = 0x1234; + *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fsw) = 0x5678; + m_state.context.fpu.no_avx.__fpu_ftw = 1; + m_state.context.fpu.no_avx.__fpu_rsrv1 = UINT8_MAX; + m_state.context.fpu.no_avx.__fpu_fop = 2; + m_state.context.fpu.no_avx.__fpu_ip = 3; + m_state.context.fpu.no_avx.__fpu_cs = 4; + m_state.context.fpu.no_avx.__fpu_rsrv2 = 5; + m_state.context.fpu.no_avx.__fpu_dp = 6; + m_state.context.fpu.no_avx.__fpu_ds = 7; + m_state.context.fpu.no_avx.__fpu_rsrv3 = UINT16_MAX; + m_state.context.fpu.no_avx.__fpu_mxcsr = 8; + m_state.context.fpu.no_avx.__fpu_mxcsrmask = 9; + int i; + for (i = 0; i < 16; ++i) { + if (i < 10) { + m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = 'a'; + m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = 'b'; + m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = 'c'; + m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = 'd'; + m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = 'e'; + m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = 'f'; + m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = 'g'; + m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = 'h'; + } else { + m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN; + } + + m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg[i] = '0'; + m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg[i] = '1'; + m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg[i] = '2'; + m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg[i] = '3'; + m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg[i] = '4'; + m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg[i] = '5'; + m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg[i] = '6'; + m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg[i] = '7'; + } + for (i = 0; i < sizeof(m_state.context.fpu.avx.__fpu_rsrv4); ++i) + m_state.context.fpu.no_avx.__fpu_rsrv4[i] = INT8_MIN; + m_state.context.fpu.no_avx.__fpu_reserved1 = -1; + } + m_state.SetError(e_regSetFPU, Read, 0); + } else { + if (CPUHasAVX() || FORCE_AVX_REGS) { + mach_msg_type_number_t count = e_regSetWordSizeAVX; + m_state.SetError(e_regSetFPU, Read, + ::thread_get_state( + m_thread->MachPortNumber(), __i386_AVX_STATE, + (thread_state_t)&m_state.context.fpu.avx, &count)); + DNBLogThreadedIf(LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &avx, " + "%u (%u passed in)) => 0x%8.8x", + m_thread->MachPortNumber(), __i386_AVX_STATE, count, + e_regSetWordSizeAVX, + m_state.GetError(e_regSetFPU, Read)); + } else { + mach_msg_type_number_t count = e_regSetWordSizeFPU; + m_state.SetError( + e_regSetFPU, Read, + ::thread_get_state(m_thread->MachPortNumber(), __i386_FLOAT_STATE, + (thread_state_t)&m_state.context.fpu.no_avx, + &count)); + DNBLogThreadedIf(LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &fpu, " + "%u (%u passed in) => 0x%8.8x", + m_thread->MachPortNumber(), __i386_FLOAT_STATE, count, + e_regSetWordSizeFPU, + m_state.GetError(e_regSetFPU, Read)); + } } - return m_state.GetError(e_regSetFPU, Read); + } + return m_state.GetError(e_regSetFPU, Read); } -kern_return_t -DNBArchImplI386::GetEXCState(bool force) -{ - if (force || m_state.GetError(e_regSetEXC, Read)) - { - mach_msg_type_number_t count = e_regSetWordSizeEXC; - m_state.SetError(e_regSetEXC, Read, ::thread_get_state(m_thread->MachPortNumber(), __i386_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, &count)); - } - return m_state.GetError(e_regSetEXC, Read); +kern_return_t DNBArchImplI386::GetEXCState(bool force) { + if (force || m_state.GetError(e_regSetEXC, Read)) { + mach_msg_type_number_t count = e_regSetWordSizeEXC; + m_state.SetError( + e_regSetEXC, Read, + ::thread_get_state(m_thread->MachPortNumber(), __i386_EXCEPTION_STATE, + (thread_state_t)&m_state.context.exc, &count)); + } + return m_state.GetError(e_regSetEXC, Read); } -kern_return_t -DNBArchImplI386::SetGPRState() -{ - kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); - DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); - - - m_state.SetError(e_regSetGPR, Write, ::thread_set_state(m_thread->MachPortNumber(), __i386_THREAD_STATE, (thread_state_t)&m_state.context.gpr, e_regSetWordSizeGPR)); - return m_state.GetError(e_regSetGPR, Write); +kern_return_t DNBArchImplI386::SetGPRState() { + kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); + DNBLogThreadedIf( + LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u " + "(SetGPRState() for stop_count = %u)", + m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); + + m_state.SetError(e_regSetGPR, Write, + ::thread_set_state(m_thread->MachPortNumber(), + __i386_THREAD_STATE, + (thread_state_t)&m_state.context.gpr, + e_regSetWordSizeGPR)); + return m_state.GetError(e_regSetGPR, Write); } -kern_return_t -DNBArchImplI386::SetFPUState() -{ - if (DEBUG_FPU_REGS) - { - m_state.SetError(e_regSetFPU, Write, 0); - return m_state.GetError(e_regSetFPU, Write); - } +kern_return_t DNBArchImplI386::SetFPUState() { + if (DEBUG_FPU_REGS) { + m_state.SetError(e_regSetFPU, Write, 0); + return m_state.GetError(e_regSetFPU, Write); + } else { + if (CPUHasAVX() || FORCE_AVX_REGS) + m_state.SetError( + e_regSetFPU, Write, + ::thread_set_state(m_thread->MachPortNumber(), __i386_AVX_STATE, + (thread_state_t)&m_state.context.fpu.avx, + e_regSetWordSizeAVX)); else - { - if (CPUHasAVX() || FORCE_AVX_REGS) - m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->MachPortNumber(), __i386_AVX_STATE, (thread_state_t)&m_state.context.fpu.avx, e_regSetWordSizeAVX)); - else - m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->MachPortNumber(), __i386_FLOAT_STATE, (thread_state_t)&m_state.context.fpu.no_avx, e_regSetWordSizeFPU)); - return m_state.GetError(e_regSetFPU, Write); - } + m_state.SetError( + e_regSetFPU, Write, + ::thread_set_state(m_thread->MachPortNumber(), __i386_FLOAT_STATE, + (thread_state_t)&m_state.context.fpu.no_avx, + e_regSetWordSizeFPU)); + return m_state.GetError(e_regSetFPU, Write); + } } -kern_return_t -DNBArchImplI386::SetEXCState() -{ - m_state.SetError(e_regSetEXC, Write, ::thread_set_state(m_thread->MachPortNumber(), __i386_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, e_regSetWordSizeEXC)); - return m_state.GetError(e_regSetEXC, Write); +kern_return_t DNBArchImplI386::SetEXCState() { + m_state.SetError(e_regSetEXC, Write, + ::thread_set_state(m_thread->MachPortNumber(), + __i386_EXCEPTION_STATE, + (thread_state_t)&m_state.context.exc, + e_regSetWordSizeEXC)); + return m_state.GetError(e_regSetEXC, Write); } -kern_return_t -DNBArchImplI386::GetDBGState(bool force) -{ - if (force || m_state.GetError(e_regSetDBG, Read)) - { - mach_msg_type_number_t count = e_regSetWordSizeDBG; - m_state.SetError(e_regSetDBG, Read, ::thread_get_state(m_thread->MachPortNumber(), __i386_DEBUG_STATE, (thread_state_t)&m_state.context.dbg, &count)); - } - return m_state.GetError(e_regSetDBG, Read); +kern_return_t DNBArchImplI386::GetDBGState(bool force) { + if (force || m_state.GetError(e_regSetDBG, Read)) { + mach_msg_type_number_t count = e_regSetWordSizeDBG; + m_state.SetError( + e_regSetDBG, Read, + ::thread_get_state(m_thread->MachPortNumber(), __i386_DEBUG_STATE, + (thread_state_t)&m_state.context.dbg, &count)); + } + return m_state.GetError(e_regSetDBG, Read); } -kern_return_t -DNBArchImplI386::SetDBGState(bool also_set_on_task) -{ - m_state.SetError(e_regSetDBG, Write, ::thread_set_state(m_thread->MachPortNumber(), __i386_DEBUG_STATE, (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG)); - if (also_set_on_task) - { - kern_return_t kret = ::task_set_state(m_thread->Process()->Task().TaskPort(), __i386_DEBUG_STATE, (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG); - if (kret != KERN_SUCCESS) - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::SetDBGState failed to set debug control register state: 0x%8.8x.", kret); - - } - return m_state.GetError(e_regSetDBG, Write); +kern_return_t DNBArchImplI386::SetDBGState(bool also_set_on_task) { + m_state.SetError(e_regSetDBG, Write, + ::thread_set_state(m_thread->MachPortNumber(), + __i386_DEBUG_STATE, + (thread_state_t)&m_state.context.dbg, + e_regSetWordSizeDBG)); + if (also_set_on_task) { + kern_return_t kret = ::task_set_state( + m_thread->Process()->Task().TaskPort(), __i386_DEBUG_STATE, + (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG); + if (kret != KERN_SUCCESS) + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::SetDBGState failed " + "to set debug control register state: " + "0x%8.8x.", + kret); + } + return m_state.GetError(e_regSetDBG, Write); } -void -DNBArchImplI386::ThreadWillResume() -{ - // Do we need to step this thread? If so, let the mach thread tell us so. - if (m_thread->IsStepping()) - { - // This is the primary thread, let the arch do anything it needs - EnableHardwareSingleStep(true); - } - - // Reset the debug status register, if necessary, before we resume. - kern_return_t kret = GetDBGState(false); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::ThreadWillResume() GetDBGState() => 0x%8.8x.", kret); - if (kret != KERN_SUCCESS) - return; +void DNBArchImplI386::ThreadWillResume() { + // Do we need to step this thread? If so, let the mach thread tell us so. + if (m_thread->IsStepping()) { + // This is the primary thread, let the arch do anything it needs + EnableHardwareSingleStep(true); + } + + // Reset the debug status register, if necessary, before we resume. + kern_return_t kret = GetDBGState(false); + DNBLogThreadedIf( + LOG_WATCHPOINTS, + "DNBArchImplI386::ThreadWillResume() GetDBGState() => 0x%8.8x.", kret); + if (kret != KERN_SUCCESS) + return; - DBG &debug_state = m_state.context.dbg; - bool need_reset = false; - uint32_t i, num = NumSupportedHardwareWatchpoints(); - for (i = 0; i < num; ++i) - if (IsWatchpointHit(debug_state, i)) - need_reset = true; - - if (need_reset) - { - ClearWatchpointHits(debug_state); - kret = SetDBGState(false); - DNBLogThreadedIf(LOG_WATCHPOINTS,"DNBArchImplI386::ThreadWillResume() SetDBGState() => 0x%8.8x.", kret); - } + DBG &debug_state = m_state.context.dbg; + bool need_reset = false; + uint32_t i, num = NumSupportedHardwareWatchpoints(); + for (i = 0; i < num; ++i) + if (IsWatchpointHit(debug_state, i)) + need_reset = true; + + if (need_reset) { + ClearWatchpointHits(debug_state); + kret = SetDBGState(false); + DNBLogThreadedIf( + LOG_WATCHPOINTS, + "DNBArchImplI386::ThreadWillResume() SetDBGState() => 0x%8.8x.", kret); + } } -bool -DNBArchImplI386::ThreadDidStop() -{ - bool success = true; +bool DNBArchImplI386::ThreadDidStop() { + bool success = true; - m_state.InvalidateAllRegisterStates(); - - // Are we stepping a single instruction? - if (GetGPRState(true) == KERN_SUCCESS) - { - // We are single stepping, was this the primary thread? - if (m_thread->IsStepping()) - { - // This was the primary thread, we need to clear the trace - // bit if so. - success = EnableHardwareSingleStep(false) == KERN_SUCCESS; - } - else - { - // The MachThread will automatically restore the suspend count - // in ThreadDidStop(), so we don't need to do anything here if - // we weren't the primary thread the last time - } + m_state.InvalidateAllRegisterStates(); + + // Are we stepping a single instruction? + if (GetGPRState(true) == KERN_SUCCESS) { + // We are single stepping, was this the primary thread? + if (m_thread->IsStepping()) { + // This was the primary thread, we need to clear the trace + // bit if so. + success = EnableHardwareSingleStep(false) == KERN_SUCCESS; + } else { + // The MachThread will automatically restore the suspend count + // in ThreadDidStop(), so we don't need to do anything here if + // we weren't the primary thread the last time } - return success; + } + return success; } -bool -DNBArchImplI386::NotifyException(MachException::Data& exc) -{ - switch (exc.exc_type) - { - case EXC_BAD_ACCESS: - break; - case EXC_BAD_INSTRUCTION: - break; - case EXC_ARITHMETIC: - break; - case EXC_EMULATION: - break; - case EXC_SOFTWARE: - break; - case EXC_BREAKPOINT: - if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 2) - { - // exc_code = EXC_I386_BPT - // - nub_addr_t pc = GetPC(INVALID_NUB_ADDRESS); - if (pc != INVALID_NUB_ADDRESS && pc > 0) - { - pc -= 1; - // Check for a breakpoint at one byte prior to the current PC value - // since the PC will be just past the trap. - - DNBBreakpoint *bp = m_thread->Process()->Breakpoints().FindByAddress(pc); - if (bp) - { - // Backup the PC for i386 since the trap was taken and the PC - // is at the address following the single byte trap instruction. - if (m_state.context.gpr.__eip > 0) - { - m_state.context.gpr.__eip = static_cast<uint32_t>(pc); - // Write the new PC back out - SetGPRState (); - } - } - return true; - } +bool DNBArchImplI386::NotifyException(MachException::Data &exc) { + switch (exc.exc_type) { + case EXC_BAD_ACCESS: + break; + case EXC_BAD_INSTRUCTION: + break; + case EXC_ARITHMETIC: + break; + case EXC_EMULATION: + break; + case EXC_SOFTWARE: + break; + case EXC_BREAKPOINT: + if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 2) { + // exc_code = EXC_I386_BPT + // + nub_addr_t pc = GetPC(INVALID_NUB_ADDRESS); + if (pc != INVALID_NUB_ADDRESS && pc > 0) { + pc -= 1; + // Check for a breakpoint at one byte prior to the current PC value + // since the PC will be just past the trap. + + DNBBreakpoint *bp = + m_thread->Process()->Breakpoints().FindByAddress(pc); + if (bp) { + // Backup the PC for i386 since the trap was taken and the PC + // is at the address following the single byte trap instruction. + if (m_state.context.gpr.__eip > 0) { + m_state.context.gpr.__eip = static_cast<uint32_t>(pc); + // Write the new PC back out + SetGPRState(); + } } - else if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 1) - { - // exc_code = EXC_I386_SGL - // - // Check whether this corresponds to a watchpoint hit event. - // If yes, set the exc_sub_code to the data break address. - nub_addr_t addr = 0; - uint32_t hw_index = GetHardwareWatchpointHit(addr); - if (hw_index != INVALID_NUB_HW_INDEX) - { - exc.exc_data[1] = addr; - // Piggyback the hw_index in the exc.data. - exc.exc_data.push_back(hw_index); - } - - return true; - } - break; - case EXC_SYSCALL: - break; - case EXC_MACH_SYSCALL: - break; - case EXC_RPC_ALERT: - break; + return true; + } + } else if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 1) { + // exc_code = EXC_I386_SGL + // + // Check whether this corresponds to a watchpoint hit event. + // If yes, set the exc_sub_code to the data break address. + nub_addr_t addr = 0; + uint32_t hw_index = GetHardwareWatchpointHit(addr); + if (hw_index != INVALID_NUB_HW_INDEX) { + exc.exc_data[1] = addr; + // Piggyback the hw_index in the exc.data. + exc.exc_data.push_back(hw_index); + } + + return true; } - return false; + break; + case EXC_SYSCALL: + break; + case EXC_MACH_SYSCALL: + break; + case EXC_RPC_ALERT: + break; + } + return false; } -uint32_t -DNBArchImplI386::NumSupportedHardwareWatchpoints() -{ - // Available debug address registers: dr0, dr1, dr2, dr3. - return 4; +uint32_t DNBArchImplI386::NumSupportedHardwareWatchpoints() { + // Available debug address registers: dr0, dr1, dr2, dr3. + return 4; } -static uint32_t -size_and_rw_bits(nub_size_t size, bool read, bool write) -{ - uint32_t rw; - if (read) { - rw = 0x3; // READ or READ/WRITE - } else if (write) { - rw = 0x1; // WRITE - } else { - assert(0 && "read and write cannot both be false"); - } - - switch (size) { - case 1: - return rw; - case 2: - return (0x1 << 2) | rw; - case 4: - return (0x3 << 2) | rw; - case 8: - return (0x2 << 2) | rw; - } - assert(0 && "invalid size, must be one of 1, 2, 4, or 8"); - return 0; +static uint32_t size_and_rw_bits(nub_size_t size, bool read, bool write) { + uint32_t rw; + if (read) { + rw = 0x3; // READ or READ/WRITE + } else if (write) { + rw = 0x1; // WRITE + } else { + assert(0 && "read and write cannot both be false"); + } + + switch (size) { + case 1: + return rw; + case 2: + return (0x1 << 2) | rw; + case 4: + return (0x3 << 2) | rw; + case 8: + return (0x2 << 2) | rw; + } + assert(0 && "invalid size, must be one of 1, 2, 4, or 8"); + return 0; } -void -DNBArchImplI386::SetWatchpoint(DBG &debug_state, uint32_t hw_index, nub_addr_t addr, nub_size_t size, bool read, bool write) -{ - // Set both dr7 (debug control register) and dri (debug address register). - - // dr7{7-0} encodes the local/gloabl enable bits: - // global enable --. .-- local enable - // | | - // v v - // dr0 -> bits{1-0} - // dr1 -> bits{3-2} - // dr2 -> bits{5-4} - // dr3 -> bits{7-6} - // - // dr7{31-16} encodes the rw/len bits: - // b_x+3, b_x+2, b_x+1, b_x - // where bits{x+1, x} => rw - // 0b00: execute, 0b01: write, 0b11: read-or-write, 0b10: io read-or-write (unused) - // and bits{x+3, x+2} => len - // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte - // - // dr0 -> bits{19-16} - // dr1 -> bits{23-20} - // dr2 -> bits{27-24} - // dr3 -> bits{31-28} - debug_state.__dr7 |= (1 << (2*hw_index) | - size_and_rw_bits(size, read, write) << (16+4*hw_index)); - uint32_t addr_32 = addr & 0xffffffff; - switch (hw_index) { - case 0: - debug_state.__dr0 = addr_32; break; - case 1: - debug_state.__dr1 = addr_32; break; - case 2: - debug_state.__dr2 = addr_32; break; - case 3: - debug_state.__dr3 = addr_32; break; - default: - assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3"); - } - return; +void DNBArchImplI386::SetWatchpoint(DBG &debug_state, uint32_t hw_index, + nub_addr_t addr, nub_size_t size, bool read, + bool write) { + // Set both dr7 (debug control register) and dri (debug address register). + + // dr7{7-0} encodes the local/gloabl enable bits: + // global enable --. .-- local enable + // | | + // v v + // dr0 -> bits{1-0} + // dr1 -> bits{3-2} + // dr2 -> bits{5-4} + // dr3 -> bits{7-6} + // + // dr7{31-16} encodes the rw/len bits: + // b_x+3, b_x+2, b_x+1, b_x + // where bits{x+1, x} => rw + // 0b00: execute, 0b01: write, 0b11: read-or-write, 0b10: io + // read-or-write (unused) + // and bits{x+3, x+2} => len + // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte + // + // dr0 -> bits{19-16} + // dr1 -> bits{23-20} + // dr2 -> bits{27-24} + // dr3 -> bits{31-28} + debug_state.__dr7 |= + (1 << (2 * hw_index) | + size_and_rw_bits(size, read, write) << (16 + 4 * hw_index)); + uint32_t addr_32 = addr & 0xffffffff; + switch (hw_index) { + case 0: + debug_state.__dr0 = addr_32; + break; + case 1: + debug_state.__dr1 = addr_32; + break; + case 2: + debug_state.__dr2 = addr_32; + break; + case 3: + debug_state.__dr3 = addr_32; + break; + default: + assert(0 && + "invalid hardware register index, must be one of 0, 1, 2, or 3"); + } + return; } -void -DNBArchImplI386::ClearWatchpoint(DBG &debug_state, uint32_t hw_index) -{ - debug_state.__dr7 &= ~(3 << (2*hw_index)); - switch (hw_index) { - case 0: - debug_state.__dr0 = 0; break; - case 1: - debug_state.__dr1 = 0; break; - case 2: - debug_state.__dr2 = 0; break; - case 3: - debug_state.__dr3 = 0; break; - default: - assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3"); - } - return; +void DNBArchImplI386::ClearWatchpoint(DBG &debug_state, uint32_t hw_index) { + debug_state.__dr7 &= ~(3 << (2 * hw_index)); + switch (hw_index) { + case 0: + debug_state.__dr0 = 0; + break; + case 1: + debug_state.__dr1 = 0; + break; + case 2: + debug_state.__dr2 = 0; + break; + case 3: + debug_state.__dr3 = 0; + break; + default: + assert(0 && + "invalid hardware register index, must be one of 0, 1, 2, or 3"); + } + return; } -bool -DNBArchImplI386::IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index) -{ - // Check dr7 (debug control register) for local/global enable bits: - // global enable --. .-- local enable - // | | - // v v - // dr0 -> bits{1-0} - // dr1 -> bits{3-2} - // dr2 -> bits{5-4} - // dr3 -> bits{7-6} - return (debug_state.__dr7 & (3 << (2*hw_index))) == 0; +bool DNBArchImplI386::IsWatchpointVacant(const DBG &debug_state, + uint32_t hw_index) { + // Check dr7 (debug control register) for local/global enable bits: + // global enable --. .-- local enable + // | | + // v v + // dr0 -> bits{1-0} + // dr1 -> bits{3-2} + // dr2 -> bits{5-4} + // dr3 -> bits{7-6} + return (debug_state.__dr7 & (3 << (2 * hw_index))) == 0; } -// Resets local copy of debug status register to wait for the next debug exception. -void -DNBArchImplI386::ClearWatchpointHits(DBG &debug_state) -{ - // See also IsWatchpointHit(). - debug_state.__dr6 = 0; - return; +// Resets local copy of debug status register to wait for the next debug +// exception. +void DNBArchImplI386::ClearWatchpointHits(DBG &debug_state) { + // See also IsWatchpointHit(). + debug_state.__dr6 = 0; + return; } -bool -DNBArchImplI386::IsWatchpointHit(const DBG &debug_state, uint32_t hw_index) -{ - // Check dr6 (debug status register) whether a watchpoint hits: - // is watchpoint hit? - // | - // v - // dr0 -> bits{0} - // dr1 -> bits{1} - // dr2 -> bits{2} - // dr3 -> bits{3} - return (debug_state.__dr6 & (1 << hw_index)); +bool DNBArchImplI386::IsWatchpointHit(const DBG &debug_state, + uint32_t hw_index) { + // Check dr6 (debug status register) whether a watchpoint hits: + // is watchpoint hit? + // | + // v + // dr0 -> bits{0} + // dr1 -> bits{1} + // dr2 -> bits{2} + // dr3 -> bits{3} + return (debug_state.__dr6 & (1 << hw_index)); } -nub_addr_t -DNBArchImplI386::GetWatchAddress(const DBG &debug_state, uint32_t hw_index) -{ - switch (hw_index) { - case 0: - return debug_state.__dr0; - case 1: - return debug_state.__dr1; - case 2: - return debug_state.__dr2; - case 3: - return debug_state.__dr3; - } - assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3"); - return 0; +nub_addr_t DNBArchImplI386::GetWatchAddress(const DBG &debug_state, + uint32_t hw_index) { + switch (hw_index) { + case 0: + return debug_state.__dr0; + case 1: + return debug_state.__dr1; + case 2: + return debug_state.__dr2; + case 3: + return debug_state.__dr3; + } + assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3"); + return 0; } -bool -DNBArchImplI386::StartTransForHWP() -{ - if (m_2pc_trans_state != Trans_Done && m_2pc_trans_state != Trans_Rolled_Back) - DNBLogError ("%s inconsistent state detected, expected %d or %d, got: %d", __FUNCTION__, Trans_Done, Trans_Rolled_Back, m_2pc_trans_state); - m_2pc_dbg_checkpoint = m_state.context.dbg; - m_2pc_trans_state = Trans_Pending; - return true; -} -bool -DNBArchImplI386::RollbackTransForHWP() -{ - m_state.context.dbg = m_2pc_dbg_checkpoint; - if (m_2pc_trans_state != Trans_Pending) - DNBLogError ("%s inconsistent state detected, expected %d, got: %d", __FUNCTION__, Trans_Pending, m_2pc_trans_state); - m_2pc_trans_state = Trans_Rolled_Back; - kern_return_t kret = SetDBGState(false); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::RollbackTransForHWP() SetDBGState() => 0x%8.8x.", kret); - - if (kret == KERN_SUCCESS) - return true; - else - return false; +bool DNBArchImplI386::StartTransForHWP() { + if (m_2pc_trans_state != Trans_Done && m_2pc_trans_state != Trans_Rolled_Back) + DNBLogError("%s inconsistent state detected, expected %d or %d, got: %d", + __FUNCTION__, Trans_Done, Trans_Rolled_Back, m_2pc_trans_state); + m_2pc_dbg_checkpoint = m_state.context.dbg; + m_2pc_trans_state = Trans_Pending; + return true; } -bool -DNBArchImplI386::FinishTransForHWP() -{ - m_2pc_trans_state = Trans_Done; +bool DNBArchImplI386::RollbackTransForHWP() { + m_state.context.dbg = m_2pc_dbg_checkpoint; + if (m_2pc_trans_state != Trans_Pending) + DNBLogError("%s inconsistent state detected, expected %d, got: %d", + __FUNCTION__, Trans_Pending, m_2pc_trans_state); + m_2pc_trans_state = Trans_Rolled_Back; + kern_return_t kret = SetDBGState(false); + DNBLogThreadedIf( + LOG_WATCHPOINTS, + "DNBArchImplI386::RollbackTransForHWP() SetDBGState() => 0x%8.8x.", kret); + + if (kret == KERN_SUCCESS) return true; + else + return false; +} +bool DNBArchImplI386::FinishTransForHWP() { + m_2pc_trans_state = Trans_Done; + return true; } -DNBArchImplI386::DBG -DNBArchImplI386::GetDBGCheckpoint() -{ - return m_2pc_dbg_checkpoint; +DNBArchImplI386::DBG DNBArchImplI386::GetDBGCheckpoint() { + return m_2pc_dbg_checkpoint; } -uint32_t -DNBArchImplI386::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task) -{ - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::EnableHardwareWatchpoint(addr = 0x%llx, size = %llu, read = %u, write = %u)", (uint64_t)addr, (uint64_t)size, read, write); +uint32_t DNBArchImplI386::EnableHardwareWatchpoint(nub_addr_t addr, + nub_size_t size, bool read, + bool write, + bool also_set_on_task) { + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::EnableHardwareWatchpoint(" + "addr = 0x%llx, size = %llu, read = %u, " + "write = %u)", + (uint64_t)addr, (uint64_t)size, read, write); - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); + const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - // Can only watch 1, 2, 4, or 8 bytes. - if (!(size == 1 || size == 2 || size == 4 || size == 8)) - return INVALID_NUB_HW_INDEX; + // Can only watch 1, 2, 4, or 8 bytes. + if (!(size == 1 || size == 2 || size == 4 || size == 8)) + return INVALID_NUB_HW_INDEX; - // We must watch for either read or write - if (read == false && write == false) - return INVALID_NUB_HW_INDEX; + // We must watch for either read or write + if (read == false && write == false) + return INVALID_NUB_HW_INDEX; - // Read the debug state - kern_return_t kret = GetDBGState(false); + // Read the debug state + kern_return_t kret = GetDBGState(false); - if (kret == KERN_SUCCESS) - { - // Check to make sure we have the needed hardware support - uint32_t i = 0; + if (kret == KERN_SUCCESS) { + // Check to make sure we have the needed hardware support + uint32_t i = 0; - DBG &debug_state = m_state.context.dbg; - for (i = 0; i < num_hw_watchpoints; ++i) - { - if (IsWatchpointVacant(debug_state, i)) - break; - } + DBG &debug_state = m_state.context.dbg; + for (i = 0; i < num_hw_watchpoints; ++i) { + if (IsWatchpointVacant(debug_state, i)) + break; + } - // See if we found an available hw breakpoint slot above - if (i < num_hw_watchpoints) - { - StartTransForHWP(); - - // Modify our local copy of the debug state, first. - SetWatchpoint(debug_state, i, addr, size, read, write); - // Now set the watch point in the inferior. - kret = SetDBGState(also_set_on_task); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::EnableHardwareWatchpoint() SetDBGState() => 0x%8.8x.", kret); - - if (kret == KERN_SUCCESS) - return i; - else // Revert to the previous debug state voluntarily. The transaction coordinator knows that we have failed. - m_state.context.dbg = GetDBGCheckpoint(); - } - else - { - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints); - } + // See if we found an available hw breakpoint slot above + if (i < num_hw_watchpoints) { + StartTransForHWP(); + + // Modify our local copy of the debug state, first. + SetWatchpoint(debug_state, i, addr, size, read, write); + // Now set the watch point in the inferior. + kret = SetDBGState(also_set_on_task); + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::" + "EnableHardwareWatchpoint() " + "SetDBGState() => 0x%8.8x.", + kret); + + if (kret == KERN_SUCCESS) + return i; + else // Revert to the previous debug state voluntarily. The transaction + // coordinator knows that we have failed. + m_state.context.dbg = GetDBGCheckpoint(); + } else { + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::" + "EnableHardwareWatchpoint(): All " + "hardware resources (%u) are in use.", + num_hw_watchpoints); } - return INVALID_NUB_HW_INDEX; + } + return INVALID_NUB_HW_INDEX; } -bool -DNBArchImplI386::DisableHardwareWatchpoint (uint32_t hw_index, bool also_set_on_task) -{ - kern_return_t kret = GetDBGState(false); - - const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); - if (kret == KERN_SUCCESS) - { - DBG &debug_state = m_state.context.dbg; - if (hw_index < num_hw_points && !IsWatchpointVacant(debug_state, hw_index)) - { - StartTransForHWP(); - - // Modify our local copy of the debug state, first. - ClearWatchpoint(debug_state, hw_index); - // Now disable the watch point in the inferior. - kret = SetDBGState(also_set_on_task); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::DisableHardwareWatchpoint( %u )", - hw_index); - - if (kret == KERN_SUCCESS) - return true; - else // Revert to the previous debug state voluntarily. The transaction coordinator knows that we have failed. - m_state.context.dbg = GetDBGCheckpoint(); - } +bool DNBArchImplI386::DisableHardwareWatchpoint(uint32_t hw_index, + bool also_set_on_task) { + kern_return_t kret = GetDBGState(false); + + const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); + if (kret == KERN_SUCCESS) { + DBG &debug_state = m_state.context.dbg; + if (hw_index < num_hw_points && + !IsWatchpointVacant(debug_state, hw_index)) { + StartTransForHWP(); + + // Modify our local copy of the debug state, first. + ClearWatchpoint(debug_state, hw_index); + // Now disable the watch point in the inferior. + kret = SetDBGState(also_set_on_task); + DNBLogThreadedIf(LOG_WATCHPOINTS, + "DNBArchImplI386::DisableHardwareWatchpoint( %u )", + hw_index); + + if (kret == KERN_SUCCESS) + return true; + else // Revert to the previous debug state voluntarily. The transaction + // coordinator knows that we have failed. + m_state.context.dbg = GetDBGCheckpoint(); } - return false; + } + return false; } // Iterate through the debug status register; return the index of the first hit. -uint32_t -DNBArchImplI386::GetHardwareWatchpointHit(nub_addr_t &addr) -{ - // Read the debug state - kern_return_t kret = GetDBGState(true); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret); - if (kret == KERN_SUCCESS) - { - DBG &debug_state = m_state.context.dbg; - uint32_t i, num = NumSupportedHardwareWatchpoints(); - for (i = 0; i < num; ++i) - { - if (IsWatchpointHit(debug_state, i)) - { - addr = GetWatchAddress(debug_state, i); - DNBLogThreadedIf(LOG_WATCHPOINTS, - "DNBArchImplI386::GetHardwareWatchpointHit() found => %u (addr = 0x%llx).", - i, (uint64_t)addr); - return i; - } - } +uint32_t DNBArchImplI386::GetHardwareWatchpointHit(nub_addr_t &addr) { + // Read the debug state + kern_return_t kret = GetDBGState(true); + DNBLogThreadedIf( + LOG_WATCHPOINTS, + "DNBArchImplI386::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", + kret); + if (kret == KERN_SUCCESS) { + DBG &debug_state = m_state.context.dbg; + uint32_t i, num = NumSupportedHardwareWatchpoints(); + for (i = 0; i < num; ++i) { + if (IsWatchpointHit(debug_state, i)) { + addr = GetWatchAddress(debug_state, i); + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::" + "GetHardwareWatchpointHit() found => " + "%u (addr = 0x%llx).", + i, (uint64_t)addr); + return i; + } } - return INVALID_NUB_HW_INDEX; + } + return INVALID_NUB_HW_INDEX; } // Set the single step bit in the processor status register. -kern_return_t -DNBArchImplI386::EnableHardwareSingleStep (bool enable) -{ - if (GetGPRState(false) == KERN_SUCCESS) - { - const uint32_t trace_bit = 0x100u; - if (enable) - m_state.context.gpr.__eflags |= trace_bit; - else - m_state.context.gpr.__eflags &= ~trace_bit; - return SetGPRState(); - } - return m_state.GetError(e_regSetGPR, Read); +kern_return_t DNBArchImplI386::EnableHardwareSingleStep(bool enable) { + if (GetGPRState(false) == KERN_SUCCESS) { + const uint32_t trace_bit = 0x100u; + if (enable) + m_state.context.gpr.__eflags |= trace_bit; + else + m_state.context.gpr.__eflags &= ~trace_bit; + return SetGPRState(); + } + return m_state.GetError(e_regSetGPR, Read); } - //---------------------------------------------------------------------- // Register information definitions //---------------------------------------------------------------------- -#define DEFINE_GPR_PSEUDO_16(reg16,reg32) { e_regSetGPR, gpr_##reg16, #reg16, NULL, Uint, Hex, 2, 0,INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_##reg32, g_invalidate_##reg32 } -#define DEFINE_GPR_PSEUDO_8H(reg8,reg32) { e_regSetGPR, gpr_##reg8 , #reg8 , NULL, Uint, Hex, 1, 1,INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_##reg32, g_invalidate_##reg32 } -#define DEFINE_GPR_PSEUDO_8L(reg8,reg32) { e_regSetGPR, gpr_##reg8 , #reg8 , NULL, Uint, Hex, 1, 0,INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_##reg32, g_invalidate_##reg32 } - - -#define GPR_OFFSET(reg) (offsetof (DNBArchImplI386::GPR, __##reg)) -#define FPU_OFFSET(reg) (offsetof (DNBArchImplI386::FPU, __fpu_##reg) + offsetof (DNBArchImplI386::Context, fpu.no_avx)) -#define AVX_OFFSET(reg) (offsetof (DNBArchImplI386::AVX, __fpu_##reg) + offsetof (DNBArchImplI386::Context, fpu.avx)) -#define EXC_OFFSET(reg) (offsetof (DNBArchImplI386::EXC, __##reg) + offsetof (DNBArchImplI386::Context, exc)) - -#define GPR_SIZE(reg) (sizeof(((DNBArchImplI386::GPR *)NULL)->__##reg)) -#define FPU_SIZE_UINT(reg) (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg)) -#define FPU_SIZE_MMST(reg) (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg.__mmst_reg)) -#define FPU_SIZE_XMM(reg) (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg.__xmm_reg)) -#define FPU_SIZE_YMM(reg) (32) -#define EXC_SIZE(reg) (sizeof(((DNBArchImplI386::EXC *)NULL)->__##reg)) - -// This does not accurately identify the location of ymm0...7 in +#define DEFINE_GPR_PSEUDO_16(reg16, reg32) \ + { \ + e_regSetGPR, gpr_##reg16, #reg16, NULL, Uint, Hex, 2, 0, \ + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ + INVALID_NUB_REGNUM, g_contained_##reg32, g_invalidate_##reg32 \ + } +#define DEFINE_GPR_PSEUDO_8H(reg8, reg32) \ + { \ + e_regSetGPR, gpr_##reg8, #reg8, NULL, Uint, Hex, 1, 1, INVALID_NUB_REGNUM, \ + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ + g_contained_##reg32, g_invalidate_##reg32 \ + } +#define DEFINE_GPR_PSEUDO_8L(reg8, reg32) \ + { \ + e_regSetGPR, gpr_##reg8, #reg8, NULL, Uint, Hex, 1, 0, INVALID_NUB_REGNUM, \ + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ + g_contained_##reg32, g_invalidate_##reg32 \ + } + +#define GPR_OFFSET(reg) (offsetof(DNBArchImplI386::GPR, __##reg)) +#define FPU_OFFSET(reg) \ + (offsetof(DNBArchImplI386::FPU, __fpu_##reg) + \ + offsetof(DNBArchImplI386::Context, fpu.no_avx)) +#define AVX_OFFSET(reg) \ + (offsetof(DNBArchImplI386::AVX, __fpu_##reg) + \ + offsetof(DNBArchImplI386::Context, fpu.avx)) +#define EXC_OFFSET(reg) \ + (offsetof(DNBArchImplI386::EXC, __##reg) + \ + offsetof(DNBArchImplI386::Context, exc)) + +#define GPR_SIZE(reg) (sizeof(((DNBArchImplI386::GPR *)NULL)->__##reg)) +#define FPU_SIZE_UINT(reg) (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg)) +#define FPU_SIZE_MMST(reg) \ + (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg.__mmst_reg)) +#define FPU_SIZE_XMM(reg) \ + (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg.__xmm_reg)) +#define FPU_SIZE_YMM(reg) (32) +#define EXC_SIZE(reg) (sizeof(((DNBArchImplI386::EXC *)NULL)->__##reg)) + +// This does not accurately identify the location of ymm0...7 in // Context.fpu.avx. That is because there is a bunch of padding // in Context.fpu.avx that we don't need. Offset macros lay out // the register state that Debugserver transmits to the debugger // -- not to interpret the thread_get_state info. -#define AVX_OFFSET_YMM(n) (AVX_OFFSET(xmm7) + FPU_SIZE_XMM(xmm7) + (32 * n)) +#define AVX_OFFSET_YMM(n) (AVX_OFFSET(xmm7) + FPU_SIZE_XMM(xmm7) + (32 * n)) // These macros will auto define the register name, alt name, register size, // register offset, encoding, format and native register. This ensures that // the register state structures are defined correctly and have the correct // sizes and offsets. -const char * g_contained_eax[] = { "eax", NULL }; -const char * g_contained_ebx[] = { "ebx", NULL }; -const char * g_contained_ecx[] = { "ecx", NULL }; -const char * g_contained_edx[] = { "edx", NULL }; -const char * g_contained_edi[] = { "edi", NULL }; -const char * g_contained_esi[] = { "esi", NULL }; -const char * g_contained_ebp[] = { "ebp", NULL }; -const char * g_contained_esp[] = { "esp", NULL }; - -const char * g_invalidate_eax[] = { "eax", "ax", "ah", "al", NULL }; -const char * g_invalidate_ebx[] = { "ebx", "bx", "bh", "bl", NULL }; -const char * g_invalidate_ecx[] = { "ecx", "cx", "ch", "cl", NULL }; -const char * g_invalidate_edx[] = { "edx", "dx", "dh", "dl", NULL }; -const char * g_invalidate_edi[] = { "edi", "di", "dil", NULL }; -const char * g_invalidate_esi[] = { "esi", "si", "sil", NULL }; -const char * g_invalidate_ebp[] = { "ebp", "bp", "bpl", NULL }; -const char * g_invalidate_esp[] = { "esp", "sp", "spl", NULL }; +const char *g_contained_eax[] = {"eax", NULL}; +const char *g_contained_ebx[] = {"ebx", NULL}; +const char *g_contained_ecx[] = {"ecx", NULL}; +const char *g_contained_edx[] = {"edx", NULL}; +const char *g_contained_edi[] = {"edi", NULL}; +const char *g_contained_esi[] = {"esi", NULL}; +const char *g_contained_ebp[] = {"ebp", NULL}; +const char *g_contained_esp[] = {"esp", NULL}; + +const char *g_invalidate_eax[] = {"eax", "ax", "ah", "al", NULL}; +const char *g_invalidate_ebx[] = {"ebx", "bx", "bh", "bl", NULL}; +const char *g_invalidate_ecx[] = {"ecx", "cx", "ch", "cl", NULL}; +const char *g_invalidate_edx[] = {"edx", "dx", "dh", "dl", NULL}; +const char *g_invalidate_edi[] = {"edi", "di", "dil", NULL}; +const char *g_invalidate_esi[] = {"esi", "si", "sil", NULL}; +const char *g_invalidate_ebp[] = {"ebp", "bp", "bpl", NULL}; +const char *g_invalidate_esp[] = {"esp", "sp", "spl", NULL}; // General purpose registers for 64 bit -const DNBRegisterInfo -DNBArchImplI386::g_gpr_registers[] = -{ -{ e_regSetGPR, gpr_eax, "eax" , NULL , Uint, Hex, GPR_SIZE(eax), GPR_OFFSET(eax) , ehframe_eax , dwarf_eax , INVALID_NUB_REGNUM , debugserver_eax , NULL, g_invalidate_eax }, -{ e_regSetGPR, gpr_ebx, "ebx" , NULL , Uint, Hex, GPR_SIZE(ebx), GPR_OFFSET(ebx) , ehframe_ebx , dwarf_ebx , INVALID_NUB_REGNUM , debugserver_ebx , NULL, g_invalidate_ebx }, -{ e_regSetGPR, gpr_ecx, "ecx" , NULL , Uint, Hex, GPR_SIZE(ecx), GPR_OFFSET(ecx) , ehframe_ecx , dwarf_ecx , INVALID_NUB_REGNUM , debugserver_ecx , NULL, g_invalidate_ecx }, -{ e_regSetGPR, gpr_edx, "edx" , NULL , Uint, Hex, GPR_SIZE(edx), GPR_OFFSET(edx) , ehframe_edx , dwarf_edx , INVALID_NUB_REGNUM , debugserver_edx , NULL, g_invalidate_edx }, -{ e_regSetGPR, gpr_edi, "edi" , NULL , Uint, Hex, GPR_SIZE(edi), GPR_OFFSET(edi) , ehframe_edi , dwarf_edi , INVALID_NUB_REGNUM , debugserver_edi , NULL, g_invalidate_edi }, -{ e_regSetGPR, gpr_esi, "esi" , NULL , Uint, Hex, GPR_SIZE(esi), GPR_OFFSET(esi) , ehframe_esi , dwarf_esi , INVALID_NUB_REGNUM , debugserver_esi , NULL, g_invalidate_esi }, -{ e_regSetGPR, gpr_ebp, "ebp" , "fp" , Uint, Hex, GPR_SIZE(ebp), GPR_OFFSET(ebp) , ehframe_ebp , dwarf_ebp , GENERIC_REGNUM_FP , debugserver_ebp , NULL, g_invalidate_ebp }, -{ e_regSetGPR, gpr_esp, "esp" , "sp" , Uint, Hex, GPR_SIZE(esp), GPR_OFFSET(esp) , ehframe_esp , dwarf_esp , GENERIC_REGNUM_SP , debugserver_esp , NULL, g_invalidate_esp }, -{ e_regSetGPR, gpr_ss, "ss" , NULL , Uint, Hex, GPR_SIZE(ss), GPR_OFFSET(ss) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM , debugserver_ss , NULL, NULL}, -{ e_regSetGPR, gpr_eflags, "eflags", "flags" , Uint, Hex, GPR_SIZE(eflags), GPR_OFFSET(eflags) , ehframe_eflags , dwarf_eflags , GENERIC_REGNUM_FLAGS , debugserver_eflags, NULL, NULL}, -{ e_regSetGPR, gpr_eip, "eip" , "pc" , Uint, Hex, GPR_SIZE(eip), GPR_OFFSET(eip) , ehframe_eip , dwarf_eip , GENERIC_REGNUM_PC , debugserver_eip , NULL, NULL}, -{ e_regSetGPR, gpr_cs, "cs" , NULL , Uint, Hex, GPR_SIZE(cs), GPR_OFFSET(cs) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM , debugserver_cs , NULL, NULL}, -{ e_regSetGPR, gpr_ds, "ds" , NULL , Uint, Hex, GPR_SIZE(ds), GPR_OFFSET(ds) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM , debugserver_ds , NULL, NULL}, -{ e_regSetGPR, gpr_es, "es" , NULL , Uint, Hex, GPR_SIZE(es), GPR_OFFSET(es) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM , debugserver_es , NULL, NULL}, -{ e_regSetGPR, gpr_fs, "fs" , NULL , Uint, Hex, GPR_SIZE(fs), GPR_OFFSET(fs) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM , debugserver_fs , NULL, NULL}, -{ e_regSetGPR, gpr_gs, "gs" , NULL , Uint, Hex, GPR_SIZE(gs), GPR_OFFSET(gs) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM , debugserver_gs , NULL, NULL}, -DEFINE_GPR_PSEUDO_16 (ax , eax), -DEFINE_GPR_PSEUDO_16 (bx , ebx), -DEFINE_GPR_PSEUDO_16 (cx , ecx), -DEFINE_GPR_PSEUDO_16 (dx , edx), -DEFINE_GPR_PSEUDO_16 (di , edi), -DEFINE_GPR_PSEUDO_16 (si , esi), -DEFINE_GPR_PSEUDO_16 (bp , ebp), -DEFINE_GPR_PSEUDO_16 (sp , esp), -DEFINE_GPR_PSEUDO_8H (ah , eax), -DEFINE_GPR_PSEUDO_8H (bh , ebx), -DEFINE_GPR_PSEUDO_8H (ch , ecx), -DEFINE_GPR_PSEUDO_8H (dh , edx), -DEFINE_GPR_PSEUDO_8L (al , eax), -DEFINE_GPR_PSEUDO_8L (bl , ebx), -DEFINE_GPR_PSEUDO_8L (cl , ecx), -DEFINE_GPR_PSEUDO_8L (dl , edx), -DEFINE_GPR_PSEUDO_8L (dil, edi), -DEFINE_GPR_PSEUDO_8L (sil, esi), -DEFINE_GPR_PSEUDO_8L (bpl, ebp), -DEFINE_GPR_PSEUDO_8L (spl, esp) -}; - - -const DNBRegisterInfo -DNBArchImplI386::g_fpu_registers_no_avx[] = -{ -{ e_regSetFPU, fpu_fcw , "fctrl" , NULL, Uint, Hex, FPU_SIZE_UINT(fcw) , FPU_OFFSET(fcw) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetFPU, fpu_fsw , "fstat" , NULL, Uint, Hex, FPU_SIZE_UINT(fsw) , FPU_OFFSET(fsw) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetFPU, fpu_ftw , "ftag" , NULL, Uint, Hex, FPU_SIZE_UINT(ftw) , FPU_OFFSET(ftw) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetFPU, fpu_fop , "fop" , NULL, Uint, Hex, FPU_SIZE_UINT(fop) , FPU_OFFSET(fop) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetFPU, fpu_ip , "fioff" , NULL, Uint, Hex, FPU_SIZE_UINT(ip) , FPU_OFFSET(ip) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetFPU, fpu_cs , "fiseg" , NULL, Uint, Hex, FPU_SIZE_UINT(cs) , FPU_OFFSET(cs) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetFPU, fpu_dp , "fooff" , NULL, Uint, Hex, FPU_SIZE_UINT(dp) , FPU_OFFSET(dp) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetFPU, fpu_ds , "foseg" , NULL, Uint, Hex, FPU_SIZE_UINT(ds) , FPU_OFFSET(ds) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetFPU, fpu_mxcsr , "mxcsr" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr) , FPU_OFFSET(mxcsr) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetFPU, fpu_mxcsrmask, "mxcsrmask" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsrmask) , FPU_OFFSET(mxcsrmask) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, - -{ e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm0), FPU_OFFSET(stmm0), INVALID_NUB_REGNUM, dwarf_stmm0, INVALID_NUB_REGNUM, debugserver_stmm0, NULL, NULL }, -{ e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm1), FPU_OFFSET(stmm1), INVALID_NUB_REGNUM, dwarf_stmm1, INVALID_NUB_REGNUM, debugserver_stmm1, NULL, NULL }, -{ e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm2), FPU_OFFSET(stmm2), INVALID_NUB_REGNUM, dwarf_stmm2, INVALID_NUB_REGNUM, debugserver_stmm2, NULL, NULL }, -{ e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm3), FPU_OFFSET(stmm3), INVALID_NUB_REGNUM, dwarf_stmm3, INVALID_NUB_REGNUM, debugserver_stmm3, NULL, NULL }, -{ e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm4), FPU_OFFSET(stmm4), INVALID_NUB_REGNUM, dwarf_stmm4, INVALID_NUB_REGNUM, debugserver_stmm4, NULL, NULL }, -{ e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm5), FPU_OFFSET(stmm5), INVALID_NUB_REGNUM, dwarf_stmm5, INVALID_NUB_REGNUM, debugserver_stmm5, NULL, NULL }, -{ e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm6), FPU_OFFSET(stmm6), INVALID_NUB_REGNUM, dwarf_stmm6, INVALID_NUB_REGNUM, debugserver_stmm6, NULL, NULL }, -{ e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm7), FPU_OFFSET(stmm7), INVALID_NUB_REGNUM, dwarf_stmm7, INVALID_NUB_REGNUM, debugserver_stmm7, NULL, NULL }, - -{ e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm0), FPU_OFFSET(xmm0), INVALID_NUB_REGNUM, dwarf_xmm0, INVALID_NUB_REGNUM, debugserver_xmm0, NULL, NULL }, -{ e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm1), FPU_OFFSET(xmm1), INVALID_NUB_REGNUM, dwarf_xmm1, INVALID_NUB_REGNUM, debugserver_xmm1, NULL, NULL }, -{ e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm2), FPU_OFFSET(xmm2), INVALID_NUB_REGNUM, dwarf_xmm2, INVALID_NUB_REGNUM, debugserver_xmm2, NULL, NULL }, -{ e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm3), FPU_OFFSET(xmm3), INVALID_NUB_REGNUM, dwarf_xmm3, INVALID_NUB_REGNUM, debugserver_xmm3, NULL, NULL }, -{ e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm4), FPU_OFFSET(xmm4), INVALID_NUB_REGNUM, dwarf_xmm4, INVALID_NUB_REGNUM, debugserver_xmm4, NULL, NULL }, -{ e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm5), FPU_OFFSET(xmm5), INVALID_NUB_REGNUM, dwarf_xmm5, INVALID_NUB_REGNUM, debugserver_xmm5, NULL, NULL }, -{ e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm6), FPU_OFFSET(xmm6), INVALID_NUB_REGNUM, dwarf_xmm6, INVALID_NUB_REGNUM, debugserver_xmm6, NULL, NULL }, -{ e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm7), FPU_OFFSET(xmm7), INVALID_NUB_REGNUM, dwarf_xmm7, INVALID_NUB_REGNUM, debugserver_xmm7, NULL, NULL } -}; - - -static const char *g_contained_ymm0 [] = { "ymm0", NULL }; -static const char *g_contained_ymm1 [] = { "ymm1", NULL }; -static const char *g_contained_ymm2 [] = { "ymm2", NULL }; -static const char *g_contained_ymm3 [] = { "ymm3", NULL }; -static const char *g_contained_ymm4 [] = { "ymm4", NULL }; -static const char *g_contained_ymm5 [] = { "ymm5", NULL }; -static const char *g_contained_ymm6 [] = { "ymm6", NULL }; -static const char *g_contained_ymm7 [] = { "ymm7", NULL }; - - -const DNBRegisterInfo -DNBArchImplI386::g_fpu_registers_avx[] = -{ -{ e_regSetFPU, fpu_fcw , "fctrl" , NULL, Uint, Hex, FPU_SIZE_UINT(fcw) , AVX_OFFSET(fcw) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetFPU, fpu_fsw , "fstat" , NULL, Uint, Hex, FPU_SIZE_UINT(fsw) , AVX_OFFSET(fsw) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetFPU, fpu_ftw , "ftag" , NULL, Uint, Hex, FPU_SIZE_UINT(ftw) , AVX_OFFSET(ftw) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetFPU, fpu_fop , "fop" , NULL, Uint, Hex, FPU_SIZE_UINT(fop) , AVX_OFFSET(fop) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetFPU, fpu_ip , "fioff" , NULL, Uint, Hex, FPU_SIZE_UINT(ip) , AVX_OFFSET(ip) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetFPU, fpu_cs , "fiseg" , NULL, Uint, Hex, FPU_SIZE_UINT(cs) , AVX_OFFSET(cs) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetFPU, fpu_dp , "fooff" , NULL, Uint, Hex, FPU_SIZE_UINT(dp) , AVX_OFFSET(dp) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetFPU, fpu_ds , "foseg" , NULL, Uint, Hex, FPU_SIZE_UINT(ds) , AVX_OFFSET(ds) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetFPU, fpu_mxcsr , "mxcsr" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr) , AVX_OFFSET(mxcsr) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetFPU, fpu_mxcsrmask, "mxcsrmask" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsrmask) , AVX_OFFSET(mxcsrmask) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, - -{ e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm0), AVX_OFFSET(stmm0), INVALID_NUB_REGNUM, dwarf_stmm0, INVALID_NUB_REGNUM, debugserver_stmm0, NULL, NULL }, -{ e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm1), AVX_OFFSET(stmm1), INVALID_NUB_REGNUM, dwarf_stmm1, INVALID_NUB_REGNUM, debugserver_stmm1, NULL, NULL }, -{ e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm2), AVX_OFFSET(stmm2), INVALID_NUB_REGNUM, dwarf_stmm2, INVALID_NUB_REGNUM, debugserver_stmm2, NULL, NULL }, -{ e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm3), AVX_OFFSET(stmm3), INVALID_NUB_REGNUM, dwarf_stmm3, INVALID_NUB_REGNUM, debugserver_stmm3, NULL, NULL }, -{ e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm4), AVX_OFFSET(stmm4), INVALID_NUB_REGNUM, dwarf_stmm4, INVALID_NUB_REGNUM, debugserver_stmm4, NULL, NULL }, -{ e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm5), AVX_OFFSET(stmm5), INVALID_NUB_REGNUM, dwarf_stmm5, INVALID_NUB_REGNUM, debugserver_stmm5, NULL, NULL }, -{ e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm6), AVX_OFFSET(stmm6), INVALID_NUB_REGNUM, dwarf_stmm6, INVALID_NUB_REGNUM, debugserver_stmm6, NULL, NULL }, -{ e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm7), AVX_OFFSET(stmm7), INVALID_NUB_REGNUM, dwarf_stmm7, INVALID_NUB_REGNUM, debugserver_stmm7, NULL, NULL }, - -{ e_regSetFPU, fpu_ymm0, "ymm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm0), AVX_OFFSET_YMM(0), INVALID_NUB_REGNUM, dwarf_ymm0, INVALID_NUB_REGNUM, debugserver_ymm0, NULL, NULL }, -{ e_regSetFPU, fpu_ymm1, "ymm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm1), AVX_OFFSET_YMM(1), INVALID_NUB_REGNUM, dwarf_ymm1, INVALID_NUB_REGNUM, debugserver_ymm1, NULL, NULL }, -{ e_regSetFPU, fpu_ymm2, "ymm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm2), AVX_OFFSET_YMM(2), INVALID_NUB_REGNUM, dwarf_ymm2, INVALID_NUB_REGNUM, debugserver_ymm2, NULL, NULL }, -{ e_regSetFPU, fpu_ymm3, "ymm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm3), AVX_OFFSET_YMM(3), INVALID_NUB_REGNUM, dwarf_ymm3, INVALID_NUB_REGNUM, debugserver_ymm3, NULL, NULL }, -{ e_regSetFPU, fpu_ymm4, "ymm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm4), AVX_OFFSET_YMM(4), INVALID_NUB_REGNUM, dwarf_ymm4, INVALID_NUB_REGNUM, debugserver_ymm4, NULL, NULL }, -{ e_regSetFPU, fpu_ymm5, "ymm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm5), AVX_OFFSET_YMM(5), INVALID_NUB_REGNUM, dwarf_ymm5, INVALID_NUB_REGNUM, debugserver_ymm5, NULL, NULL }, -{ e_regSetFPU, fpu_ymm6, "ymm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm6), AVX_OFFSET_YMM(6), INVALID_NUB_REGNUM, dwarf_ymm6, INVALID_NUB_REGNUM, debugserver_ymm6, NULL, NULL }, -{ e_regSetFPU, fpu_ymm7, "ymm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm7), AVX_OFFSET_YMM(7), INVALID_NUB_REGNUM, dwarf_ymm7, INVALID_NUB_REGNUM, debugserver_ymm7, NULL, NULL }, - -{ e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm0), 0, INVALID_NUB_REGNUM, dwarf_xmm0, INVALID_NUB_REGNUM, debugserver_xmm0, g_contained_ymm0, NULL }, -{ e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm1), 0, INVALID_NUB_REGNUM, dwarf_xmm1, INVALID_NUB_REGNUM, debugserver_xmm1, g_contained_ymm1, NULL }, -{ e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm2), 0, INVALID_NUB_REGNUM, dwarf_xmm2, INVALID_NUB_REGNUM, debugserver_xmm2, g_contained_ymm2, NULL }, -{ e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm3), 0, INVALID_NUB_REGNUM, dwarf_xmm3, INVALID_NUB_REGNUM, debugserver_xmm3, g_contained_ymm3, NULL }, -{ e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm4), 0, INVALID_NUB_REGNUM, dwarf_xmm4, INVALID_NUB_REGNUM, debugserver_xmm4, g_contained_ymm4, NULL }, -{ e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm5), 0, INVALID_NUB_REGNUM, dwarf_xmm5, INVALID_NUB_REGNUM, debugserver_xmm5, g_contained_ymm5, NULL }, -{ e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm6), 0, INVALID_NUB_REGNUM, dwarf_xmm6, INVALID_NUB_REGNUM, debugserver_xmm6, g_contained_ymm6, NULL }, -{ e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm7), 0, INVALID_NUB_REGNUM, dwarf_xmm7, INVALID_NUB_REGNUM, debugserver_xmm7, g_contained_ymm7, NULL }, +const DNBRegisterInfo DNBArchImplI386::g_gpr_registers[] = { + {e_regSetGPR, gpr_eax, "eax", NULL, Uint, Hex, GPR_SIZE(eax), + GPR_OFFSET(eax), ehframe_eax, dwarf_eax, INVALID_NUB_REGNUM, + debugserver_eax, NULL, g_invalidate_eax}, + {e_regSetGPR, gpr_ebx, "ebx", NULL, Uint, Hex, GPR_SIZE(ebx), + GPR_OFFSET(ebx), ehframe_ebx, dwarf_ebx, INVALID_NUB_REGNUM, + debugserver_ebx, NULL, g_invalidate_ebx}, + {e_regSetGPR, gpr_ecx, "ecx", NULL, Uint, Hex, GPR_SIZE(ecx), + GPR_OFFSET(ecx), ehframe_ecx, dwarf_ecx, INVALID_NUB_REGNUM, + debugserver_ecx, NULL, g_invalidate_ecx}, + {e_regSetGPR, gpr_edx, "edx", NULL, Uint, Hex, GPR_SIZE(edx), + GPR_OFFSET(edx), ehframe_edx, dwarf_edx, INVALID_NUB_REGNUM, + debugserver_edx, NULL, g_invalidate_edx}, + {e_regSetGPR, gpr_edi, "edi", NULL, Uint, Hex, GPR_SIZE(edi), + GPR_OFFSET(edi), ehframe_edi, dwarf_edi, INVALID_NUB_REGNUM, + debugserver_edi, NULL, g_invalidate_edi}, + {e_regSetGPR, gpr_esi, "esi", NULL, Uint, Hex, GPR_SIZE(esi), + GPR_OFFSET(esi), ehframe_esi, dwarf_esi, INVALID_NUB_REGNUM, + debugserver_esi, NULL, g_invalidate_esi}, + {e_regSetGPR, gpr_ebp, "ebp", "fp", Uint, Hex, GPR_SIZE(ebp), + GPR_OFFSET(ebp), ehframe_ebp, dwarf_ebp, GENERIC_REGNUM_FP, + debugserver_ebp, NULL, g_invalidate_ebp}, + {e_regSetGPR, gpr_esp, "esp", "sp", Uint, Hex, GPR_SIZE(esp), + GPR_OFFSET(esp), ehframe_esp, dwarf_esp, GENERIC_REGNUM_SP, + debugserver_esp, NULL, g_invalidate_esp}, + {e_regSetGPR, gpr_ss, "ss", NULL, Uint, Hex, GPR_SIZE(ss), GPR_OFFSET(ss), + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_ss, + NULL, NULL}, + {e_regSetGPR, gpr_eflags, "eflags", "flags", Uint, Hex, GPR_SIZE(eflags), + GPR_OFFSET(eflags), ehframe_eflags, dwarf_eflags, GENERIC_REGNUM_FLAGS, + debugserver_eflags, NULL, NULL}, + {e_regSetGPR, gpr_eip, "eip", "pc", Uint, Hex, GPR_SIZE(eip), + GPR_OFFSET(eip), ehframe_eip, dwarf_eip, GENERIC_REGNUM_PC, + debugserver_eip, NULL, NULL}, + {e_regSetGPR, gpr_cs, "cs", NULL, Uint, Hex, GPR_SIZE(cs), GPR_OFFSET(cs), + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_cs, + NULL, NULL}, + {e_regSetGPR, gpr_ds, "ds", NULL, Uint, Hex, GPR_SIZE(ds), GPR_OFFSET(ds), + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_ds, + NULL, NULL}, + {e_regSetGPR, gpr_es, "es", NULL, Uint, Hex, GPR_SIZE(es), GPR_OFFSET(es), + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_es, + NULL, NULL}, + {e_regSetGPR, gpr_fs, "fs", NULL, Uint, Hex, GPR_SIZE(fs), GPR_OFFSET(fs), + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_fs, + NULL, NULL}, + {e_regSetGPR, gpr_gs, "gs", NULL, Uint, Hex, GPR_SIZE(gs), GPR_OFFSET(gs), + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_gs, + NULL, NULL}, + DEFINE_GPR_PSEUDO_16(ax, eax), + DEFINE_GPR_PSEUDO_16(bx, ebx), + DEFINE_GPR_PSEUDO_16(cx, ecx), + DEFINE_GPR_PSEUDO_16(dx, edx), + DEFINE_GPR_PSEUDO_16(di, edi), + DEFINE_GPR_PSEUDO_16(si, esi), + DEFINE_GPR_PSEUDO_16(bp, ebp), + DEFINE_GPR_PSEUDO_16(sp, esp), + DEFINE_GPR_PSEUDO_8H(ah, eax), + DEFINE_GPR_PSEUDO_8H(bh, ebx), + DEFINE_GPR_PSEUDO_8H(ch, ecx), + DEFINE_GPR_PSEUDO_8H(dh, edx), + DEFINE_GPR_PSEUDO_8L(al, eax), + DEFINE_GPR_PSEUDO_8L(bl, ebx), + DEFINE_GPR_PSEUDO_8L(cl, ecx), + DEFINE_GPR_PSEUDO_8L(dl, edx), + DEFINE_GPR_PSEUDO_8L(dil, edi), + DEFINE_GPR_PSEUDO_8L(sil, esi), + DEFINE_GPR_PSEUDO_8L(bpl, ebp), + DEFINE_GPR_PSEUDO_8L(spl, esp)}; + +const DNBRegisterInfo DNBArchImplI386::g_fpu_registers_no_avx[] = { + {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw), + FPU_OFFSET(fcw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw), + FPU_OFFSET(fsw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, FPU_SIZE_UINT(ftw), + FPU_OFFSET(ftw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop), + FPU_OFFSET(fop), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip), + FPU_OFFSET(ip), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs), + FPU_OFFSET(cs), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp), + FPU_OFFSET(dp), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds), + FPU_OFFSET(ds), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr), + FPU_OFFSET(mxcsr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex, + FPU_SIZE_UINT(mxcsrmask), FPU_OFFSET(mxcsrmask), INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, + + {e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm0), FPU_OFFSET(stmm0), INVALID_NUB_REGNUM, dwarf_stmm0, + INVALID_NUB_REGNUM, debugserver_stmm0, NULL, NULL}, + {e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm1), FPU_OFFSET(stmm1), INVALID_NUB_REGNUM, dwarf_stmm1, + INVALID_NUB_REGNUM, debugserver_stmm1, NULL, NULL}, + {e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm2), FPU_OFFSET(stmm2), INVALID_NUB_REGNUM, dwarf_stmm2, + INVALID_NUB_REGNUM, debugserver_stmm2, NULL, NULL}, + {e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm3), FPU_OFFSET(stmm3), INVALID_NUB_REGNUM, dwarf_stmm3, + INVALID_NUB_REGNUM, debugserver_stmm3, NULL, NULL}, + {e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm4), FPU_OFFSET(stmm4), INVALID_NUB_REGNUM, dwarf_stmm4, + INVALID_NUB_REGNUM, debugserver_stmm4, NULL, NULL}, + {e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm5), FPU_OFFSET(stmm5), INVALID_NUB_REGNUM, dwarf_stmm5, + INVALID_NUB_REGNUM, debugserver_stmm5, NULL, NULL}, + {e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm6), FPU_OFFSET(stmm6), INVALID_NUB_REGNUM, dwarf_stmm6, + INVALID_NUB_REGNUM, debugserver_stmm6, NULL, NULL}, + {e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm7), FPU_OFFSET(stmm7), INVALID_NUB_REGNUM, dwarf_stmm7, + INVALID_NUB_REGNUM, debugserver_stmm7, NULL, NULL}, + + {e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm0), FPU_OFFSET(xmm0), INVALID_NUB_REGNUM, dwarf_xmm0, + INVALID_NUB_REGNUM, debugserver_xmm0, NULL, NULL}, + {e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm1), FPU_OFFSET(xmm1), INVALID_NUB_REGNUM, dwarf_xmm1, + INVALID_NUB_REGNUM, debugserver_xmm1, NULL, NULL}, + {e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm2), FPU_OFFSET(xmm2), INVALID_NUB_REGNUM, dwarf_xmm2, + INVALID_NUB_REGNUM, debugserver_xmm2, NULL, NULL}, + {e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm3), FPU_OFFSET(xmm3), INVALID_NUB_REGNUM, dwarf_xmm3, + INVALID_NUB_REGNUM, debugserver_xmm3, NULL, NULL}, + {e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm4), FPU_OFFSET(xmm4), INVALID_NUB_REGNUM, dwarf_xmm4, + INVALID_NUB_REGNUM, debugserver_xmm4, NULL, NULL}, + {e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm5), FPU_OFFSET(xmm5), INVALID_NUB_REGNUM, dwarf_xmm5, + INVALID_NUB_REGNUM, debugserver_xmm5, NULL, NULL}, + {e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm6), FPU_OFFSET(xmm6), INVALID_NUB_REGNUM, dwarf_xmm6, + INVALID_NUB_REGNUM, debugserver_xmm6, NULL, NULL}, + {e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm7), FPU_OFFSET(xmm7), INVALID_NUB_REGNUM, dwarf_xmm7, + INVALID_NUB_REGNUM, debugserver_xmm7, NULL, NULL}}; + +static const char *g_contained_ymm0[] = {"ymm0", NULL}; +static const char *g_contained_ymm1[] = {"ymm1", NULL}; +static const char *g_contained_ymm2[] = {"ymm2", NULL}; +static const char *g_contained_ymm3[] = {"ymm3", NULL}; +static const char *g_contained_ymm4[] = {"ymm4", NULL}; +static const char *g_contained_ymm5[] = {"ymm5", NULL}; +static const char *g_contained_ymm6[] = {"ymm6", NULL}; +static const char *g_contained_ymm7[] = {"ymm7", NULL}; + +const DNBRegisterInfo DNBArchImplI386::g_fpu_registers_avx[] = { + {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw), + AVX_OFFSET(fcw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw), + AVX_OFFSET(fsw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, FPU_SIZE_UINT(ftw), + AVX_OFFSET(ftw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop), + AVX_OFFSET(fop), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip), + AVX_OFFSET(ip), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs), + AVX_OFFSET(cs), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp), + AVX_OFFSET(dp), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds), + AVX_OFFSET(ds), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr), + AVX_OFFSET(mxcsr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex, + FPU_SIZE_UINT(mxcsrmask), AVX_OFFSET(mxcsrmask), INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, + + {e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm0), AVX_OFFSET(stmm0), INVALID_NUB_REGNUM, dwarf_stmm0, + INVALID_NUB_REGNUM, debugserver_stmm0, NULL, NULL}, + {e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm1), AVX_OFFSET(stmm1), INVALID_NUB_REGNUM, dwarf_stmm1, + INVALID_NUB_REGNUM, debugserver_stmm1, NULL, NULL}, + {e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm2), AVX_OFFSET(stmm2), INVALID_NUB_REGNUM, dwarf_stmm2, + INVALID_NUB_REGNUM, debugserver_stmm2, NULL, NULL}, + {e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm3), AVX_OFFSET(stmm3), INVALID_NUB_REGNUM, dwarf_stmm3, + INVALID_NUB_REGNUM, debugserver_stmm3, NULL, NULL}, + {e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm4), AVX_OFFSET(stmm4), INVALID_NUB_REGNUM, dwarf_stmm4, + INVALID_NUB_REGNUM, debugserver_stmm4, NULL, NULL}, + {e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm5), AVX_OFFSET(stmm5), INVALID_NUB_REGNUM, dwarf_stmm5, + INVALID_NUB_REGNUM, debugserver_stmm5, NULL, NULL}, + {e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm6), AVX_OFFSET(stmm6), INVALID_NUB_REGNUM, dwarf_stmm6, + INVALID_NUB_REGNUM, debugserver_stmm6, NULL, NULL}, + {e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm7), AVX_OFFSET(stmm7), INVALID_NUB_REGNUM, dwarf_stmm7, + INVALID_NUB_REGNUM, debugserver_stmm7, NULL, NULL}, + + {e_regSetFPU, fpu_ymm0, "ymm0", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm0), AVX_OFFSET_YMM(0), INVALID_NUB_REGNUM, dwarf_ymm0, + INVALID_NUB_REGNUM, debugserver_ymm0, NULL, NULL}, + {e_regSetFPU, fpu_ymm1, "ymm1", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm1), AVX_OFFSET_YMM(1), INVALID_NUB_REGNUM, dwarf_ymm1, + INVALID_NUB_REGNUM, debugserver_ymm1, NULL, NULL}, + {e_regSetFPU, fpu_ymm2, "ymm2", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm2), AVX_OFFSET_YMM(2), INVALID_NUB_REGNUM, dwarf_ymm2, + INVALID_NUB_REGNUM, debugserver_ymm2, NULL, NULL}, + {e_regSetFPU, fpu_ymm3, "ymm3", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm3), AVX_OFFSET_YMM(3), INVALID_NUB_REGNUM, dwarf_ymm3, + INVALID_NUB_REGNUM, debugserver_ymm3, NULL, NULL}, + {e_regSetFPU, fpu_ymm4, "ymm4", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm4), AVX_OFFSET_YMM(4), INVALID_NUB_REGNUM, dwarf_ymm4, + INVALID_NUB_REGNUM, debugserver_ymm4, NULL, NULL}, + {e_regSetFPU, fpu_ymm5, "ymm5", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm5), AVX_OFFSET_YMM(5), INVALID_NUB_REGNUM, dwarf_ymm5, + INVALID_NUB_REGNUM, debugserver_ymm5, NULL, NULL}, + {e_regSetFPU, fpu_ymm6, "ymm6", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm6), AVX_OFFSET_YMM(6), INVALID_NUB_REGNUM, dwarf_ymm6, + INVALID_NUB_REGNUM, debugserver_ymm6, NULL, NULL}, + {e_regSetFPU, fpu_ymm7, "ymm7", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm7), AVX_OFFSET_YMM(7), INVALID_NUB_REGNUM, dwarf_ymm7, + INVALID_NUB_REGNUM, debugserver_ymm7, NULL, NULL}, + + {e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm0), 0, INVALID_NUB_REGNUM, dwarf_xmm0, INVALID_NUB_REGNUM, + debugserver_xmm0, g_contained_ymm0, NULL}, + {e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm1), 0, INVALID_NUB_REGNUM, dwarf_xmm1, INVALID_NUB_REGNUM, + debugserver_xmm1, g_contained_ymm1, NULL}, + {e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm2), 0, INVALID_NUB_REGNUM, dwarf_xmm2, INVALID_NUB_REGNUM, + debugserver_xmm2, g_contained_ymm2, NULL}, + {e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm3), 0, INVALID_NUB_REGNUM, dwarf_xmm3, INVALID_NUB_REGNUM, + debugserver_xmm3, g_contained_ymm3, NULL}, + {e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm4), 0, INVALID_NUB_REGNUM, dwarf_xmm4, INVALID_NUB_REGNUM, + debugserver_xmm4, g_contained_ymm4, NULL}, + {e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm5), 0, INVALID_NUB_REGNUM, dwarf_xmm5, INVALID_NUB_REGNUM, + debugserver_xmm5, g_contained_ymm5, NULL}, + {e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm6), 0, INVALID_NUB_REGNUM, dwarf_xmm6, INVALID_NUB_REGNUM, + debugserver_xmm6, g_contained_ymm6, NULL}, + {e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm7), 0, INVALID_NUB_REGNUM, dwarf_xmm7, INVALID_NUB_REGNUM, + debugserver_xmm7, g_contained_ymm7, NULL}, }; -const DNBRegisterInfo -DNBArchImplI386::g_exc_registers[] = -{ -{ e_regSetEXC, exc_trapno, "trapno" , NULL, Uint, Hex, EXC_SIZE (trapno) , EXC_OFFSET (trapno) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetEXC, exc_err, "err" , NULL, Uint, Hex, EXC_SIZE (err) , EXC_OFFSET (err) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }, -{ e_regSetEXC, exc_faultvaddr, "faultvaddr", NULL, Uint, Hex, EXC_SIZE (faultvaddr), EXC_OFFSET (faultvaddr) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL } -}; +const DNBRegisterInfo DNBArchImplI386::g_exc_registers[] = { + {e_regSetEXC, exc_trapno, "trapno", NULL, Uint, Hex, EXC_SIZE(trapno), + EXC_OFFSET(trapno), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetEXC, exc_err, "err", NULL, Uint, Hex, EXC_SIZE(err), + EXC_OFFSET(err), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}, + {e_regSetEXC, exc_faultvaddr, "faultvaddr", NULL, Uint, Hex, + EXC_SIZE(faultvaddr), EXC_OFFSET(faultvaddr), INVALID_NUB_REGNUM, + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}}; // Number of registers in each register set -const size_t DNBArchImplI386::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo); -const size_t DNBArchImplI386::k_num_fpu_registers_no_avx = sizeof(g_fpu_registers_no_avx)/sizeof(DNBRegisterInfo); -const size_t DNBArchImplI386::k_num_fpu_registers_avx = sizeof(g_fpu_registers_avx)/sizeof(DNBRegisterInfo); -const size_t DNBArchImplI386::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo); -const size_t DNBArchImplI386::k_num_all_registers_no_avx = k_num_gpr_registers + k_num_fpu_registers_no_avx + k_num_exc_registers; -const size_t DNBArchImplI386::k_num_all_registers_avx = k_num_gpr_registers + k_num_fpu_registers_avx + k_num_exc_registers; +const size_t DNBArchImplI386::k_num_gpr_registers = + sizeof(g_gpr_registers) / sizeof(DNBRegisterInfo); +const size_t DNBArchImplI386::k_num_fpu_registers_no_avx = + sizeof(g_fpu_registers_no_avx) / sizeof(DNBRegisterInfo); +const size_t DNBArchImplI386::k_num_fpu_registers_avx = + sizeof(g_fpu_registers_avx) / sizeof(DNBRegisterInfo); +const size_t DNBArchImplI386::k_num_exc_registers = + sizeof(g_exc_registers) / sizeof(DNBRegisterInfo); +const size_t DNBArchImplI386::k_num_all_registers_no_avx = + k_num_gpr_registers + k_num_fpu_registers_no_avx + k_num_exc_registers; +const size_t DNBArchImplI386::k_num_all_registers_avx = + k_num_gpr_registers + k_num_fpu_registers_avx + k_num_exc_registers; //---------------------------------------------------------------------- // Register set definitions. The first definitions at register set index // of zero is for all registers, followed by other registers sets. The // register information for the all register set need not be filled in. //---------------------------------------------------------------------- -const DNBRegisterSetInfo -DNBArchImplI386::g_reg_sets_no_avx[] = -{ - { "i386 Registers", NULL, k_num_all_registers_no_avx }, - { "General Purpose Registers", g_gpr_registers, k_num_gpr_registers }, - { "Floating Point Registers", g_fpu_registers_no_avx, k_num_fpu_registers_no_avx }, - { "Exception State Registers", g_exc_registers, k_num_exc_registers } -}; - -const DNBRegisterSetInfo -DNBArchImplI386::g_reg_sets_avx[] = -{ - { "i386 Registers", NULL, k_num_all_registers_avx }, - { "General Purpose Registers", g_gpr_registers, k_num_gpr_registers }, - { "Floating Point Registers", g_fpu_registers_avx, k_num_fpu_registers_avx }, - { "Exception State Registers", g_exc_registers, k_num_exc_registers } -}; +const DNBRegisterSetInfo DNBArchImplI386::g_reg_sets_no_avx[] = { + {"i386 Registers", NULL, k_num_all_registers_no_avx}, + {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers}, + {"Floating Point Registers", g_fpu_registers_no_avx, + k_num_fpu_registers_no_avx}, + {"Exception State Registers", g_exc_registers, k_num_exc_registers}}; + +const DNBRegisterSetInfo DNBArchImplI386::g_reg_sets_avx[] = { + {"i386 Registers", NULL, k_num_all_registers_avx}, + {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers}, + {"Floating Point Registers", g_fpu_registers_avx, k_num_fpu_registers_avx}, + {"Exception State Registers", g_exc_registers, k_num_exc_registers}}; // Total number of register sets for this architecture -const size_t DNBArchImplI386::k_num_register_sets = sizeof(g_reg_sets_no_avx)/sizeof(DNBRegisterSetInfo); +const size_t DNBArchImplI386::k_num_register_sets = + sizeof(g_reg_sets_no_avx) / sizeof(DNBRegisterSetInfo); -DNBArchProtocol * -DNBArchImplI386::Create (MachThread *thread) -{ - DNBArchImplI386 *obj = new DNBArchImplI386 (thread); - return obj; +DNBArchProtocol *DNBArchImplI386::Create(MachThread *thread) { + DNBArchImplI386 *obj = new DNBArchImplI386(thread); + return obj; } -const uint8_t * -DNBArchImplI386::SoftwareBreakpointOpcode (nub_size_t byte_size) -{ - static const uint8_t g_breakpoint_opcode[] = { 0xCC }; - if (byte_size == 1) - return g_breakpoint_opcode; - return NULL; +const uint8_t *DNBArchImplI386::SoftwareBreakpointOpcode(nub_size_t byte_size) { + static const uint8_t g_breakpoint_opcode[] = {0xCC}; + if (byte_size == 1) + return g_breakpoint_opcode; + return NULL; } const DNBRegisterSetInfo * -DNBArchImplI386::GetRegisterSetInfo(nub_size_t *num_reg_sets) -{ - *num_reg_sets = k_num_register_sets; - if (CPUHasAVX() || FORCE_AVX_REGS) - return g_reg_sets_avx; - else - return g_reg_sets_no_avx; +DNBArchImplI386::GetRegisterSetInfo(nub_size_t *num_reg_sets) { + *num_reg_sets = k_num_register_sets; + if (CPUHasAVX() || FORCE_AVX_REGS) + return g_reg_sets_avx; + else + return g_reg_sets_no_avx; } +void DNBArchImplI386::Initialize() { + DNBArchPluginInfo arch_plugin_info = { + CPU_TYPE_I386, DNBArchImplI386::Create, + DNBArchImplI386::GetRegisterSetInfo, + DNBArchImplI386::SoftwareBreakpointOpcode}; -void -DNBArchImplI386::Initialize() -{ - DNBArchPluginInfo arch_plugin_info = - { - CPU_TYPE_I386, - DNBArchImplI386::Create, - DNBArchImplI386::GetRegisterSetInfo, - DNBArchImplI386::SoftwareBreakpointOpcode - }; - - // Register this arch plug-in with the main protocol class - DNBArchProtocol::RegisterArchPlugin (arch_plugin_info); + // Register this arch plug-in with the main protocol class + DNBArchProtocol::RegisterArchPlugin(arch_plugin_info); } -bool -DNBArchImplI386::GetRegisterValue(uint32_t set, uint32_t reg, DNBRegisterValue *value) -{ - if (set == REGISTER_SET_GENERIC) - { - switch (reg) - { - case GENERIC_REGNUM_PC: // Program Counter - set = e_regSetGPR; - reg = gpr_eip; - break; - - case GENERIC_REGNUM_SP: // Stack Pointer - set = e_regSetGPR; - reg = gpr_esp; - break; - - case GENERIC_REGNUM_FP: // Frame Pointer - set = e_regSetGPR; - reg = gpr_ebp; - break; - - case GENERIC_REGNUM_FLAGS: // Processor flags register - set = e_regSetGPR; - reg = gpr_eflags; - break; - - case GENERIC_REGNUM_RA: // Return Address - default: - return false; - } +bool DNBArchImplI386::GetRegisterValue(uint32_t set, uint32_t reg, + DNBRegisterValue *value) { + if (set == REGISTER_SET_GENERIC) { + switch (reg) { + case GENERIC_REGNUM_PC: // Program Counter + set = e_regSetGPR; + reg = gpr_eip; + break; + + case GENERIC_REGNUM_SP: // Stack Pointer + set = e_regSetGPR; + reg = gpr_esp; + break; + + case GENERIC_REGNUM_FP: // Frame Pointer + set = e_regSetGPR; + reg = gpr_ebp; + break; + + case GENERIC_REGNUM_FLAGS: // Processor flags register + set = e_regSetGPR; + reg = gpr_eflags; + break; + + case GENERIC_REGNUM_RA: // Return Address + default: + return false; } + } + + if (GetRegisterState(set, false) != KERN_SUCCESS) + return false; - if (GetRegisterState(set, false) != KERN_SUCCESS) - return false; - - const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); - if (regInfo) - { - value->info = *regInfo; - switch (set) - { - case e_regSetGPR: - if (reg < k_num_gpr_registers) - { - value->value.uint32 = ((uint32_t*)(&m_state.context.gpr))[reg]; - return true; - } - break; - - case e_regSetFPU: - if (CPUHasAVX() || FORCE_AVX_REGS) - { - switch (reg) - { - case fpu_fcw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw)); return true; - case fpu_fsw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw)); return true; - case fpu_ftw: value->value.uint8 = m_state.context.fpu.avx.__fpu_ftw; return true; - case fpu_fop: value->value.uint16 = m_state.context.fpu.avx.__fpu_fop; return true; - case fpu_ip: value->value.uint32 = m_state.context.fpu.avx.__fpu_ip; return true; - case fpu_cs: value->value.uint16 = m_state.context.fpu.avx.__fpu_cs; return true; - case fpu_dp: value->value.uint32 = m_state.context.fpu.avx.__fpu_dp; return true; - case fpu_ds: value->value.uint16 = m_state.context.fpu.avx.__fpu_ds; return true; - case fpu_mxcsr: value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsr; return true; - case fpu_mxcsrmask: value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsrmask; return true; - - case fpu_stmm0: memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg, 10); return true; - case fpu_stmm1: memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg, 10); return true; - case fpu_stmm2: memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg, 10); return true; - case fpu_stmm3: memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg, 10); return true; - case fpu_stmm4: memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg, 10); return true; - case fpu_stmm5: memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg, 10); return true; - case fpu_stmm6: memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg, 10); return true; - case fpu_stmm7: memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg, 10); return true; - - case fpu_xmm0: memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm0.__xmm_reg, 16); return true; - case fpu_xmm1: memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm1.__xmm_reg, 16); return true; - case fpu_xmm2: memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm2.__xmm_reg, 16); return true; - case fpu_xmm3: memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm3.__xmm_reg, 16); return true; - case fpu_xmm4: memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm4.__xmm_reg, 16); return true; - case fpu_xmm5: memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm5.__xmm_reg, 16); return true; - case fpu_xmm6: memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm6.__xmm_reg, 16); return true; - case fpu_xmm7: memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm7.__xmm_reg, 16); return true; - -#define MEMCPY_YMM(n) \ - memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm##n.__xmm_reg, 16); \ - memcpy((&value->value.uint8) + 16, m_state.context.fpu.avx.__fpu_ymmh##n.__xmm_reg, 16); - case fpu_ymm0: MEMCPY_YMM(0); return true; - case fpu_ymm1: MEMCPY_YMM(1); return true; - case fpu_ymm2: MEMCPY_YMM(2); return true; - case fpu_ymm3: MEMCPY_YMM(3); return true; - case fpu_ymm4: MEMCPY_YMM(4); return true; - case fpu_ymm5: MEMCPY_YMM(5); return true; - case fpu_ymm6: MEMCPY_YMM(6); return true; - case fpu_ymm7: MEMCPY_YMM(7); return true; + const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); + if (regInfo) { + value->info = *regInfo; + switch (set) { + case e_regSetGPR: + if (reg < k_num_gpr_registers) { + value->value.uint32 = ((uint32_t *)(&m_state.context.gpr))[reg]; + return true; + } + break; + + case e_regSetFPU: + if (CPUHasAVX() || FORCE_AVX_REGS) { + switch (reg) { + case fpu_fcw: + value->value.uint16 = + *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw)); + return true; + case fpu_fsw: + value->value.uint16 = + *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw)); + return true; + case fpu_ftw: + value->value.uint8 = m_state.context.fpu.avx.__fpu_ftw; + return true; + case fpu_fop: + value->value.uint16 = m_state.context.fpu.avx.__fpu_fop; + return true; + case fpu_ip: + value->value.uint32 = m_state.context.fpu.avx.__fpu_ip; + return true; + case fpu_cs: + value->value.uint16 = m_state.context.fpu.avx.__fpu_cs; + return true; + case fpu_dp: + value->value.uint32 = m_state.context.fpu.avx.__fpu_dp; + return true; + case fpu_ds: + value->value.uint16 = m_state.context.fpu.avx.__fpu_ds; + return true; + case fpu_mxcsr: + value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsr; + return true; + case fpu_mxcsrmask: + value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsrmask; + return true; + + case fpu_stmm0: + memcpy(&value->value.uint8, + m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg, 10); + return true; + case fpu_stmm1: + memcpy(&value->value.uint8, + m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg, 10); + return true; + case fpu_stmm2: + memcpy(&value->value.uint8, + m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg, 10); + return true; + case fpu_stmm3: + memcpy(&value->value.uint8, + m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg, 10); + return true; + case fpu_stmm4: + memcpy(&value->value.uint8, + m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg, 10); + return true; + case fpu_stmm5: + memcpy(&value->value.uint8, + m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg, 10); + return true; + case fpu_stmm6: + memcpy(&value->value.uint8, + m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg, 10); + return true; + case fpu_stmm7: + memcpy(&value->value.uint8, + m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg, 10); + return true; + + case fpu_xmm0: + memcpy(&value->value.uint8, + m_state.context.fpu.avx.__fpu_xmm0.__xmm_reg, 16); + return true; + case fpu_xmm1: + memcpy(&value->value.uint8, + m_state.context.fpu.avx.__fpu_xmm1.__xmm_reg, 16); + return true; + case fpu_xmm2: + memcpy(&value->value.uint8, + m_state.context.fpu.avx.__fpu_xmm2.__xmm_reg, 16); + return true; + case fpu_xmm3: + memcpy(&value->value.uint8, + m_state.context.fpu.avx.__fpu_xmm3.__xmm_reg, 16); + return true; + case fpu_xmm4: + memcpy(&value->value.uint8, + m_state.context.fpu.avx.__fpu_xmm4.__xmm_reg, 16); + return true; + case fpu_xmm5: + memcpy(&value->value.uint8, + m_state.context.fpu.avx.__fpu_xmm5.__xmm_reg, 16); + return true; + case fpu_xmm6: + memcpy(&value->value.uint8, + m_state.context.fpu.avx.__fpu_xmm6.__xmm_reg, 16); + return true; + case fpu_xmm7: + memcpy(&value->value.uint8, + m_state.context.fpu.avx.__fpu_xmm7.__xmm_reg, 16); + return true; + +#define MEMCPY_YMM(n) \ + memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm##n.__xmm_reg, \ + 16); \ + memcpy((&value->value.uint8) + 16, \ + m_state.context.fpu.avx.__fpu_ymmh##n.__xmm_reg, 16); + case fpu_ymm0: + MEMCPY_YMM(0); + return true; + case fpu_ymm1: + MEMCPY_YMM(1); + return true; + case fpu_ymm2: + MEMCPY_YMM(2); + return true; + case fpu_ymm3: + MEMCPY_YMM(3); + return true; + case fpu_ymm4: + MEMCPY_YMM(4); + return true; + case fpu_ymm5: + MEMCPY_YMM(5); + return true; + case fpu_ymm6: + MEMCPY_YMM(6); + return true; + case fpu_ymm7: + MEMCPY_YMM(7); + return true; #undef MEMCPY_YMM - } - } - else - { - switch (reg) - { - case fpu_fcw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)); return true; - case fpu_fsw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)); return true; - case fpu_ftw: value->value.uint8 = m_state.context.fpu.no_avx.__fpu_ftw; return true; - case fpu_fop: value->value.uint16 = m_state.context.fpu.no_avx.__fpu_fop; return true; - case fpu_ip: value->value.uint32 = m_state.context.fpu.no_avx.__fpu_ip; return true; - case fpu_cs: value->value.uint16 = m_state.context.fpu.no_avx.__fpu_cs; return true; - case fpu_dp: value->value.uint32 = m_state.context.fpu.no_avx.__fpu_dp; return true; - case fpu_ds: value->value.uint16 = m_state.context.fpu.no_avx.__fpu_ds; return true; - case fpu_mxcsr: value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsr; return true; - case fpu_mxcsrmask: value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsrmask; return true; - - case fpu_stmm0: memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg, 10); return true; - case fpu_stmm1: memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg, 10); return true; - case fpu_stmm2: memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg, 10); return true; - case fpu_stmm3: memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg, 10); return true; - case fpu_stmm4: memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg, 10); return true; - case fpu_stmm5: memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg, 10); return true; - case fpu_stmm6: memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg, 10); return true; - case fpu_stmm7: memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg, 10); return true; - - case fpu_xmm0: memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg, 16); return true; - case fpu_xmm1: memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg, 16); return true; - case fpu_xmm2: memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg, 16); return true; - case fpu_xmm3: memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg, 16); return true; - case fpu_xmm4: memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg, 16); return true; - case fpu_xmm5: memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg, 16); return true; - case fpu_xmm6: memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg, 16); return true; - case fpu_xmm7: memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg, 16); return true; - } - } - break; - - case e_regSetEXC: - if (reg < k_num_exc_registers) - { - value->value.uint32 = (&m_state.context.exc.__trapno)[reg]; - return true; - } - break; } + } else { + switch (reg) { + case fpu_fcw: + value->value.uint16 = + *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)); + return true; + case fpu_fsw: + value->value.uint16 = + *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)); + return true; + case fpu_ftw: + value->value.uint8 = m_state.context.fpu.no_avx.__fpu_ftw; + return true; + case fpu_fop: + value->value.uint16 = m_state.context.fpu.no_avx.__fpu_fop; + return true; + case fpu_ip: + value->value.uint32 = m_state.context.fpu.no_avx.__fpu_ip; + return true; + case fpu_cs: + value->value.uint16 = m_state.context.fpu.no_avx.__fpu_cs; + return true; + case fpu_dp: + value->value.uint32 = m_state.context.fpu.no_avx.__fpu_dp; + return true; + case fpu_ds: + value->value.uint16 = m_state.context.fpu.no_avx.__fpu_ds; + return true; + case fpu_mxcsr: + value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsr; + return true; + case fpu_mxcsrmask: + value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsrmask; + return true; + + case fpu_stmm0: + memcpy(&value->value.uint8, + m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg, 10); + return true; + case fpu_stmm1: + memcpy(&value->value.uint8, + m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg, 10); + return true; + case fpu_stmm2: + memcpy(&value->value.uint8, + m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg, 10); + return true; + case fpu_stmm3: + memcpy(&value->value.uint8, + m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg, 10); + return true; + case fpu_stmm4: + memcpy(&value->value.uint8, + m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg, 10); + return true; + case fpu_stmm5: + memcpy(&value->value.uint8, + m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg, 10); + return true; + case fpu_stmm6: + memcpy(&value->value.uint8, + m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg, 10); + return true; + case fpu_stmm7: + memcpy(&value->value.uint8, + m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg, 10); + return true; + + case fpu_xmm0: + memcpy(&value->value.uint8, + m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg, 16); + return true; + case fpu_xmm1: + memcpy(&value->value.uint8, + m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg, 16); + return true; + case fpu_xmm2: + memcpy(&value->value.uint8, + m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg, 16); + return true; + case fpu_xmm3: + memcpy(&value->value.uint8, + m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg, 16); + return true; + case fpu_xmm4: + memcpy(&value->value.uint8, + m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg, 16); + return true; + case fpu_xmm5: + memcpy(&value->value.uint8, + m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg, 16); + return true; + case fpu_xmm6: + memcpy(&value->value.uint8, + m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg, 16); + return true; + case fpu_xmm7: + memcpy(&value->value.uint8, + m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg, 16); + return true; + } + } + break; + + case e_regSetEXC: + if (reg < k_num_exc_registers) { + value->value.uint32 = (&m_state.context.exc.__trapno)[reg]; + return true; + } + break; } - return false; + } + return false; } - -bool -DNBArchImplI386::SetRegisterValue(uint32_t set, uint32_t reg, const DNBRegisterValue *value) -{ - if (set == REGISTER_SET_GENERIC) - { - switch (reg) - { - case GENERIC_REGNUM_PC: // Program Counter - set = e_regSetGPR; - reg = gpr_eip; - break; - - case GENERIC_REGNUM_SP: // Stack Pointer - set = e_regSetGPR; - reg = gpr_esp; - break; - - case GENERIC_REGNUM_FP: // Frame Pointer - set = e_regSetGPR; - reg = gpr_ebp; - break; - - case GENERIC_REGNUM_FLAGS: // Processor flags register - set = e_regSetGPR; - reg = gpr_eflags; - break; - - case GENERIC_REGNUM_RA: // Return Address - default: - return false; - } +bool DNBArchImplI386::SetRegisterValue(uint32_t set, uint32_t reg, + const DNBRegisterValue *value) { + if (set == REGISTER_SET_GENERIC) { + switch (reg) { + case GENERIC_REGNUM_PC: // Program Counter + set = e_regSetGPR; + reg = gpr_eip; + break; + + case GENERIC_REGNUM_SP: // Stack Pointer + set = e_regSetGPR; + reg = gpr_esp; + break; + + case GENERIC_REGNUM_FP: // Frame Pointer + set = e_regSetGPR; + reg = gpr_ebp; + break; + + case GENERIC_REGNUM_FLAGS: // Processor flags register + set = e_regSetGPR; + reg = gpr_eflags; + break; + + case GENERIC_REGNUM_RA: // Return Address + default: + return false; } + } + + if (GetRegisterState(set, false) != KERN_SUCCESS) + return false; - if (GetRegisterState(set, false) != KERN_SUCCESS) - return false; - - bool success = false; - const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); - if (regInfo) - { - switch (set) - { - case e_regSetGPR: - if (reg < k_num_gpr_registers) - { - ((uint32_t*)(&m_state.context.gpr))[reg] = value->value.uint32; - success = true; - } - break; - - case e_regSetFPU: - if (CPUHasAVX() || FORCE_AVX_REGS) - { - switch (reg) - { - case fpu_fcw: *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw)) = value->value.uint16; success = true; break; - case fpu_fsw: *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw)) = value->value.uint16; success = true; break; - case fpu_ftw: m_state.context.fpu.avx.__fpu_ftw = value->value.uint8; success = true; break; - case fpu_fop: m_state.context.fpu.avx.__fpu_fop = value->value.uint16; success = true; break; - case fpu_ip: m_state.context.fpu.avx.__fpu_ip = value->value.uint32; success = true; break; - case fpu_cs: m_state.context.fpu.avx.__fpu_cs = value->value.uint16; success = true; break; - case fpu_dp: m_state.context.fpu.avx.__fpu_dp = value->value.uint32; success = true; break; - case fpu_ds: m_state.context.fpu.avx.__fpu_ds = value->value.uint16; success = true; break; - case fpu_mxcsr: m_state.context.fpu.avx.__fpu_mxcsr = value->value.uint32; success = true; break; - case fpu_mxcsrmask: m_state.context.fpu.avx.__fpu_mxcsrmask = value->value.uint32; success = true; break; - - case fpu_stmm0: memcpy (m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg, &value->value.uint8, 10); success = true; break; - case fpu_stmm1: memcpy (m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg, &value->value.uint8, 10); success = true; break; - case fpu_stmm2: memcpy (m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg, &value->value.uint8, 10); success = true; break; - case fpu_stmm3: memcpy (m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg, &value->value.uint8, 10); success = true; break; - case fpu_stmm4: memcpy (m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg, &value->value.uint8, 10); success = true; break; - case fpu_stmm5: memcpy (m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg, &value->value.uint8, 10); success = true; break; - case fpu_stmm6: memcpy (m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg, &value->value.uint8, 10); success = true; break; - case fpu_stmm7: memcpy (m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg, &value->value.uint8, 10); success = true; break; - - case fpu_xmm0: memcpy(m_state.context.fpu.avx.__fpu_xmm0.__xmm_reg, &value->value.uint8, 16); success = true; break; - case fpu_xmm1: memcpy(m_state.context.fpu.avx.__fpu_xmm1.__xmm_reg, &value->value.uint8, 16); success = true; break; - case fpu_xmm2: memcpy(m_state.context.fpu.avx.__fpu_xmm2.__xmm_reg, &value->value.uint8, 16); success = true; break; - case fpu_xmm3: memcpy(m_state.context.fpu.avx.__fpu_xmm3.__xmm_reg, &value->value.uint8, 16); success = true; break; - case fpu_xmm4: memcpy(m_state.context.fpu.avx.__fpu_xmm4.__xmm_reg, &value->value.uint8, 16); success = true; break; - case fpu_xmm5: memcpy(m_state.context.fpu.avx.__fpu_xmm5.__xmm_reg, &value->value.uint8, 16); success = true; break; - case fpu_xmm6: memcpy(m_state.context.fpu.avx.__fpu_xmm6.__xmm_reg, &value->value.uint8, 16); success = true; break; - case fpu_xmm7: memcpy(m_state.context.fpu.avx.__fpu_xmm7.__xmm_reg, &value->value.uint8, 16); success = true; break; - -#define MEMCPY_YMM(n) \ - memcpy(m_state.context.fpu.avx.__fpu_xmm##n.__xmm_reg, &value->value.uint8, 16); \ - memcpy(m_state.context.fpu.avx.__fpu_ymmh##n.__xmm_reg, (&value->value.uint8) + 16, 16); - case fpu_ymm0: MEMCPY_YMM(0); return true; - case fpu_ymm1: MEMCPY_YMM(1); return true; - case fpu_ymm2: MEMCPY_YMM(2); return true; - case fpu_ymm3: MEMCPY_YMM(3); return true; - case fpu_ymm4: MEMCPY_YMM(4); return true; - case fpu_ymm5: MEMCPY_YMM(5); return true; - case fpu_ymm6: MEMCPY_YMM(6); return true; - case fpu_ymm7: MEMCPY_YMM(7); return true; + bool success = false; + const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); + if (regInfo) { + switch (set) { + case e_regSetGPR: + if (reg < k_num_gpr_registers) { + ((uint32_t *)(&m_state.context.gpr))[reg] = value->value.uint32; + success = true; + } + break; + + case e_regSetFPU: + if (CPUHasAVX() || FORCE_AVX_REGS) { + switch (reg) { + case fpu_fcw: + *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw)) = + value->value.uint16; + success = true; + break; + case fpu_fsw: + *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw)) = + value->value.uint16; + success = true; + break; + case fpu_ftw: + m_state.context.fpu.avx.__fpu_ftw = value->value.uint8; + success = true; + break; + case fpu_fop: + m_state.context.fpu.avx.__fpu_fop = value->value.uint16; + success = true; + break; + case fpu_ip: + m_state.context.fpu.avx.__fpu_ip = value->value.uint32; + success = true; + break; + case fpu_cs: + m_state.context.fpu.avx.__fpu_cs = value->value.uint16; + success = true; + break; + case fpu_dp: + m_state.context.fpu.avx.__fpu_dp = value->value.uint32; + success = true; + break; + case fpu_ds: + m_state.context.fpu.avx.__fpu_ds = value->value.uint16; + success = true; + break; + case fpu_mxcsr: + m_state.context.fpu.avx.__fpu_mxcsr = value->value.uint32; + success = true; + break; + case fpu_mxcsrmask: + m_state.context.fpu.avx.__fpu_mxcsrmask = value->value.uint32; + success = true; + break; + + case fpu_stmm0: + memcpy(m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg, + &value->value.uint8, 10); + success = true; + break; + case fpu_stmm1: + memcpy(m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg, + &value->value.uint8, 10); + success = true; + break; + case fpu_stmm2: + memcpy(m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg, + &value->value.uint8, 10); + success = true; + break; + case fpu_stmm3: + memcpy(m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg, + &value->value.uint8, 10); + success = true; + break; + case fpu_stmm4: + memcpy(m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg, + &value->value.uint8, 10); + success = true; + break; + case fpu_stmm5: + memcpy(m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg, + &value->value.uint8, 10); + success = true; + break; + case fpu_stmm6: + memcpy(m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg, + &value->value.uint8, 10); + success = true; + break; + case fpu_stmm7: + memcpy(m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg, + &value->value.uint8, 10); + success = true; + break; + + case fpu_xmm0: + memcpy(m_state.context.fpu.avx.__fpu_xmm0.__xmm_reg, + &value->value.uint8, 16); + success = true; + break; + case fpu_xmm1: + memcpy(m_state.context.fpu.avx.__fpu_xmm1.__xmm_reg, + &value->value.uint8, 16); + success = true; + break; + case fpu_xmm2: + memcpy(m_state.context.fpu.avx.__fpu_xmm2.__xmm_reg, + &value->value.uint8, 16); + success = true; + break; + case fpu_xmm3: + memcpy(m_state.context.fpu.avx.__fpu_xmm3.__xmm_reg, + &value->value.uint8, 16); + success = true; + break; + case fpu_xmm4: + memcpy(m_state.context.fpu.avx.__fpu_xmm4.__xmm_reg, + &value->value.uint8, 16); + success = true; + break; + case fpu_xmm5: + memcpy(m_state.context.fpu.avx.__fpu_xmm5.__xmm_reg, + &value->value.uint8, 16); + success = true; + break; + case fpu_xmm6: + memcpy(m_state.context.fpu.avx.__fpu_xmm6.__xmm_reg, + &value->value.uint8, 16); + success = true; + break; + case fpu_xmm7: + memcpy(m_state.context.fpu.avx.__fpu_xmm7.__xmm_reg, + &value->value.uint8, 16); + success = true; + break; + +#define MEMCPY_YMM(n) \ + memcpy(m_state.context.fpu.avx.__fpu_xmm##n.__xmm_reg, &value->value.uint8, \ + 16); \ + memcpy(m_state.context.fpu.avx.__fpu_ymmh##n.__xmm_reg, \ + (&value->value.uint8) + 16, 16); + case fpu_ymm0: + MEMCPY_YMM(0); + return true; + case fpu_ymm1: + MEMCPY_YMM(1); + return true; + case fpu_ymm2: + MEMCPY_YMM(2); + return true; + case fpu_ymm3: + MEMCPY_YMM(3); + return true; + case fpu_ymm4: + MEMCPY_YMM(4); + return true; + case fpu_ymm5: + MEMCPY_YMM(5); + return true; + case fpu_ymm6: + MEMCPY_YMM(6); + return true; + case fpu_ymm7: + MEMCPY_YMM(7); + return true; #undef MEMCPY_YMM - } - } - else - { - switch (reg) - { - case fpu_fcw: *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)) = value->value.uint16; success = true; break; - case fpu_fsw: *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)) = value->value.uint16; success = true; break; - case fpu_ftw: m_state.context.fpu.no_avx.__fpu_ftw = value->value.uint8; success = true; break; - case fpu_fop: m_state.context.fpu.no_avx.__fpu_fop = value->value.uint16; success = true; break; - case fpu_ip: m_state.context.fpu.no_avx.__fpu_ip = value->value.uint32; success = true; break; - case fpu_cs: m_state.context.fpu.no_avx.__fpu_cs = value->value.uint16; success = true; break; - case fpu_dp: m_state.context.fpu.no_avx.__fpu_dp = value->value.uint32; success = true; break; - case fpu_ds: m_state.context.fpu.no_avx.__fpu_ds = value->value.uint16; success = true; break; - case fpu_mxcsr: m_state.context.fpu.no_avx.__fpu_mxcsr = value->value.uint32; success = true; break; - case fpu_mxcsrmask: m_state.context.fpu.no_avx.__fpu_mxcsrmask = value->value.uint32; success = true; break; - - case fpu_stmm0: memcpy (m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg, &value->value.uint8, 10); success = true; break; - case fpu_stmm1: memcpy (m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg, &value->value.uint8, 10); success = true; break; - case fpu_stmm2: memcpy (m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg, &value->value.uint8, 10); success = true; break; - case fpu_stmm3: memcpy (m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg, &value->value.uint8, 10); success = true; break; - case fpu_stmm4: memcpy (m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg, &value->value.uint8, 10); success = true; break; - case fpu_stmm5: memcpy (m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg, &value->value.uint8, 10); success = true; break; - case fpu_stmm6: memcpy (m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg, &value->value.uint8, 10); success = true; break; - case fpu_stmm7: memcpy (m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg, &value->value.uint8, 10); success = true; break; - - case fpu_xmm0: memcpy(m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg, &value->value.uint8, 16); success = true; break; - case fpu_xmm1: memcpy(m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg, &value->value.uint8, 16); success = true; break; - case fpu_xmm2: memcpy(m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg, &value->value.uint8, 16); success = true; break; - case fpu_xmm3: memcpy(m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg, &value->value.uint8, 16); success = true; break; - case fpu_xmm4: memcpy(m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg, &value->value.uint8, 16); success = true; break; - case fpu_xmm5: memcpy(m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg, &value->value.uint8, 16); success = true; break; - case fpu_xmm6: memcpy(m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg, &value->value.uint8, 16); success = true; break; - case fpu_xmm7: memcpy(m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg, &value->value.uint8, 16); success = true; break; - } - } - break; - - case e_regSetEXC: - if (reg < k_num_exc_registers) - { - (&m_state.context.exc.__trapno)[reg] = value->value.uint32; - success = true; - } - break; } + } else { + switch (reg) { + case fpu_fcw: + *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)) = + value->value.uint16; + success = true; + break; + case fpu_fsw: + *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)) = + value->value.uint16; + success = true; + break; + case fpu_ftw: + m_state.context.fpu.no_avx.__fpu_ftw = value->value.uint8; + success = true; + break; + case fpu_fop: + m_state.context.fpu.no_avx.__fpu_fop = value->value.uint16; + success = true; + break; + case fpu_ip: + m_state.context.fpu.no_avx.__fpu_ip = value->value.uint32; + success = true; + break; + case fpu_cs: + m_state.context.fpu.no_avx.__fpu_cs = value->value.uint16; + success = true; + break; + case fpu_dp: + m_state.context.fpu.no_avx.__fpu_dp = value->value.uint32; + success = true; + break; + case fpu_ds: + m_state.context.fpu.no_avx.__fpu_ds = value->value.uint16; + success = true; + break; + case fpu_mxcsr: + m_state.context.fpu.no_avx.__fpu_mxcsr = value->value.uint32; + success = true; + break; + case fpu_mxcsrmask: + m_state.context.fpu.no_avx.__fpu_mxcsrmask = value->value.uint32; + success = true; + break; + + case fpu_stmm0: + memcpy(m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg, + &value->value.uint8, 10); + success = true; + break; + case fpu_stmm1: + memcpy(m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg, + &value->value.uint8, 10); + success = true; + break; + case fpu_stmm2: + memcpy(m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg, + &value->value.uint8, 10); + success = true; + break; + case fpu_stmm3: + memcpy(m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg, + &value->value.uint8, 10); + success = true; + break; + case fpu_stmm4: + memcpy(m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg, + &value->value.uint8, 10); + success = true; + break; + case fpu_stmm5: + memcpy(m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg, + &value->value.uint8, 10); + success = true; + break; + case fpu_stmm6: + memcpy(m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg, + &value->value.uint8, 10); + success = true; + break; + case fpu_stmm7: + memcpy(m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg, + &value->value.uint8, 10); + success = true; + break; + + case fpu_xmm0: + memcpy(m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg, + &value->value.uint8, 16); + success = true; + break; + case fpu_xmm1: + memcpy(m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg, + &value->value.uint8, 16); + success = true; + break; + case fpu_xmm2: + memcpy(m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg, + &value->value.uint8, 16); + success = true; + break; + case fpu_xmm3: + memcpy(m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg, + &value->value.uint8, 16); + success = true; + break; + case fpu_xmm4: + memcpy(m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg, + &value->value.uint8, 16); + success = true; + break; + case fpu_xmm5: + memcpy(m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg, + &value->value.uint8, 16); + success = true; + break; + case fpu_xmm6: + memcpy(m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg, + &value->value.uint8, 16); + success = true; + break; + case fpu_xmm7: + memcpy(m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg, + &value->value.uint8, 16); + success = true; + break; + } + } + break; + + case e_regSetEXC: + if (reg < k_num_exc_registers) { + (&m_state.context.exc.__trapno)[reg] = value->value.uint32; + success = true; + } + break; } + } - if (success) - return SetRegisterState(set) == KERN_SUCCESS; - return false; + if (success) + return SetRegisterState(set) == KERN_SUCCESS; + return false; } - -uint32_t -DNBArchImplI386::GetRegisterContextSize() -{ - static uint32_t g_cached_size = 0; - if (g_cached_size == 0) - { - if (CPUHasAVX() || FORCE_AVX_REGS) - { - for (size_t i=0; i<k_num_fpu_registers_avx; ++i) - { - if (g_fpu_registers_avx[i].value_regs == NULL) - g_cached_size += g_fpu_registers_avx[i].size; - } - } - else - { - for (size_t i=0; i<k_num_fpu_registers_no_avx; ++i) - { - if (g_fpu_registers_no_avx[i].value_regs == NULL) - g_cached_size += g_fpu_registers_no_avx[i].size; - } - } - DNBLogThreaded ("DNBArchImplX86_64::GetRegisterContextSize() - GPR = %zu, FPU = %u, EXC = %zu", sizeof(GPR), g_cached_size, sizeof(EXC)); - g_cached_size += sizeof(GPR); - g_cached_size += sizeof(EXC); - DNBLogThreaded ("DNBArchImplX86_64::GetRegisterContextSize() - GPR + FPU + EXC = %u", g_cached_size); +uint32_t DNBArchImplI386::GetRegisterContextSize() { + static uint32_t g_cached_size = 0; + if (g_cached_size == 0) { + if (CPUHasAVX() || FORCE_AVX_REGS) { + for (size_t i = 0; i < k_num_fpu_registers_avx; ++i) { + if (g_fpu_registers_avx[i].value_regs == NULL) + g_cached_size += g_fpu_registers_avx[i].size; + } + } else { + for (size_t i = 0; i < k_num_fpu_registers_no_avx; ++i) { + if (g_fpu_registers_no_avx[i].value_regs == NULL) + g_cached_size += g_fpu_registers_no_avx[i].size; + } } - return g_cached_size; + DNBLogThreaded("DNBArchImplX86_64::GetRegisterContextSize() - GPR = %zu, " + "FPU = %u, EXC = %zu", + sizeof(GPR), g_cached_size, sizeof(EXC)); + g_cached_size += sizeof(GPR); + g_cached_size += sizeof(EXC); + DNBLogThreaded( + "DNBArchImplX86_64::GetRegisterContextSize() - GPR + FPU + EXC = %u", + g_cached_size); + } + return g_cached_size; } - -nub_size_t -DNBArchImplI386::GetRegisterContext (void *buf, nub_size_t buf_len) -{ - uint32_t size = GetRegisterContextSize(); - - if (buf && buf_len) - { - if (size > buf_len) - size = static_cast<uint32_t>(buf_len); - - bool force = false; - kern_return_t kret; - if ((kret = GetGPRState(force)) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = %p, len = %llu) error: GPR regs failed to read: %u ", buf, (uint64_t)buf_len, kret); - size = 0; - } - else if ((kret = GetFPUState(force)) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = %p, len = %llu) error: %s regs failed to read: %u", buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret); - size = 0; - } - else if ((kret = GetEXCState(force)) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = %p, len = %llu) error: EXC regs failed to read: %u", buf, (uint64_t)buf_len, kret); - size = 0; - } - else - { - uint8_t *p = (uint8_t *)buf; - // Copy the GPR registers - memcpy(p, &m_state.context.gpr, sizeof(GPR)); - p += sizeof(GPR); - - if (CPUHasAVX() || FORCE_AVX_REGS) - { - // Walk around the gaps in the FPU regs - memcpy(p, &m_state.context.fpu.avx.__fpu_fcw, 5); - p += 5; - memcpy(p, &m_state.context.fpu.avx.__fpu_fop, 8); - p += 8; - memcpy(p, &m_state.context.fpu.avx.__fpu_dp, 6); - p += 6; - memcpy(p, &m_state.context.fpu.avx.__fpu_mxcsr, 8); - p += 8; - - // Work around the padding between the stmm registers as they are 16 - // byte structs with 10 bytes of the value in each - for (size_t i=0; i<8; ++i) - { - memcpy(p, &m_state.context.fpu.avx.__fpu_stmm0 + i, 10); - p += 10; - } - - // Interleave the XMM and YMMH registers to make the YMM registers - for (size_t i=0; i<8; ++i) - { - memcpy(p, &m_state.context.fpu.avx.__fpu_xmm0 + i, 16); - p += 16; - memcpy(p, &m_state.context.fpu.avx.__fpu_ymmh0 + i, 16); - p += 16; - } - } - else - { - // Walk around the gaps in the FPU regs - memcpy(p, &m_state.context.fpu.no_avx.__fpu_fcw, 5); - p += 5; - memcpy(p, &m_state.context.fpu.no_avx.__fpu_fop, 8); - p += 8; - memcpy(p, &m_state.context.fpu.no_avx.__fpu_dp, 6); - p += 6; - memcpy(p, &m_state.context.fpu.no_avx.__fpu_mxcsr, 8); - p += 8; - - // Work around the padding between the stmm registers as they are 16 - // byte structs with 10 bytes of the value in each - for (size_t i=0; i<8; ++i) - { - memcpy(p, &m_state.context.fpu.no_avx.__fpu_stmm0 + i, 10); - p += 10; - } - - // Copy the XMM registers in a single block - memcpy(p, &m_state.context.fpu.no_avx.__fpu_xmm0, 8 * 16); - p += 8 * 16; - } - - // Copy the exception registers - memcpy(p, &m_state.context.exc, sizeof(EXC)); - p += sizeof(EXC); - - // make sure we end up with exactly what we think we should have - size_t bytes_written = p - (uint8_t *)buf; - UNUSED_IF_ASSERT_DISABLED(bytes_written); - assert (bytes_written == size); +nub_size_t DNBArchImplI386::GetRegisterContext(void *buf, nub_size_t buf_len) { + uint32_t size = GetRegisterContextSize(); + + if (buf && buf_len) { + if (size > buf_len) + size = static_cast<uint32_t>(buf_len); + + bool force = false; + kern_return_t kret; + if ((kret = GetGPRState(force)) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = " + "%p, len = %llu) error: GPR regs failed to " + "read: %u ", + buf, (uint64_t)buf_len, kret); + size = 0; + } else if ((kret = GetFPUState(force)) != KERN_SUCCESS) { + DNBLogThreadedIf( + LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = %p, len = " + "%llu) error: %s regs failed to read: %u", + buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret); + size = 0; + } else if ((kret = GetEXCState(force)) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = " + "%p, len = %llu) error: EXC regs failed to " + "read: %u", + buf, (uint64_t)buf_len, kret); + size = 0; + } else { + uint8_t *p = (uint8_t *)buf; + // Copy the GPR registers + memcpy(p, &m_state.context.gpr, sizeof(GPR)); + p += sizeof(GPR); + + if (CPUHasAVX() || FORCE_AVX_REGS) { + // Walk around the gaps in the FPU regs + memcpy(p, &m_state.context.fpu.avx.__fpu_fcw, 5); + p += 5; + memcpy(p, &m_state.context.fpu.avx.__fpu_fop, 8); + p += 8; + memcpy(p, &m_state.context.fpu.avx.__fpu_dp, 6); + p += 6; + memcpy(p, &m_state.context.fpu.avx.__fpu_mxcsr, 8); + p += 8; + + // Work around the padding between the stmm registers as they are 16 + // byte structs with 10 bytes of the value in each + for (size_t i = 0; i < 8; ++i) { + memcpy(p, &m_state.context.fpu.avx.__fpu_stmm0 + i, 10); + p += 10; } - } - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = %p, len = %llu) => %llu", buf, (uint64_t)buf_len, (uint64_t)size); - // Return the size of the register context even if NULL was passed in - return size; -} -nub_size_t -DNBArchImplI386::SetRegisterContext (const void *buf, nub_size_t buf_len) -{ - nub_size_t size = sizeof (m_state.context); - if (buf == NULL || buf_len == 0) - size = 0; - - if (size) - { - if (size > buf_len) - size = buf_len; - - uint8_t *p = (uint8_t *)buf; - // Copy the GPR registers - memcpy(&m_state.context.gpr, p, sizeof(GPR)); - p += sizeof(GPR); - - if (CPUHasAVX() || FORCE_AVX_REGS) - { - // Walk around the gaps in the FPU regs - memcpy(&m_state.context.fpu.avx.__fpu_fcw, p, 5); - p += 5; - memcpy(&m_state.context.fpu.avx.__fpu_fop, p, 8); - p += 8; - memcpy(&m_state.context.fpu.avx.__fpu_dp, p, 6); - p += 6; - memcpy(&m_state.context.fpu.avx.__fpu_mxcsr, p, 8); - p += 8; - - // Work around the padding between the stmm registers as they are 16 - // byte structs with 10 bytes of the value in each - for (size_t i=0; i<8; ++i) - { - memcpy(&m_state.context.fpu.avx.__fpu_stmm0 + i, p, 10); - p += 10; - } - - // Interleave the XMM and YMMH registers to make the YMM registers - for (size_t i=0; i<8; ++i) - { - memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + i, p, 16); - p += 16; - memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + i, p, 16); - p += 16; - } + // Interleave the XMM and YMMH registers to make the YMM registers + for (size_t i = 0; i < 8; ++i) { + memcpy(p, &m_state.context.fpu.avx.__fpu_xmm0 + i, 16); + p += 16; + memcpy(p, &m_state.context.fpu.avx.__fpu_ymmh0 + i, 16); + p += 16; } - else - { - // Copy fcw through mxcsrmask as there is no padding - memcpy(&m_state.context.fpu.no_avx.__fpu_fcw, p, 5); - p += 5; - memcpy(&m_state.context.fpu.no_avx.__fpu_fop, p, 8); - p += 8; - memcpy(&m_state.context.fpu.no_avx.__fpu_dp, p, 6); - p += 6; - memcpy(&m_state.context.fpu.no_avx.__fpu_mxcsr, p, 8); - p += 8; - - // Work around the padding between the stmm registers as they are 16 - // byte structs with 10 bytes of the value in each - for (size_t i=0; i<8; ++i) - { - memcpy(&m_state.context.fpu.no_avx.__fpu_stmm0 + i, p, 10); - p += 10; - } - - // Copy the XMM registers in a single block - memcpy(&m_state.context.fpu.no_avx.__fpu_xmm0, p, 8 * 16); - p += 8 * 16; + } else { + // Walk around the gaps in the FPU regs + memcpy(p, &m_state.context.fpu.no_avx.__fpu_fcw, 5); + p += 5; + memcpy(p, &m_state.context.fpu.no_avx.__fpu_fop, 8); + p += 8; + memcpy(p, &m_state.context.fpu.no_avx.__fpu_dp, 6); + p += 6; + memcpy(p, &m_state.context.fpu.no_avx.__fpu_mxcsr, 8); + p += 8; + + // Work around the padding between the stmm registers as they are 16 + // byte structs with 10 bytes of the value in each + for (size_t i = 0; i < 8; ++i) { + memcpy(p, &m_state.context.fpu.no_avx.__fpu_stmm0 + i, 10); + p += 10; } - - // Copy the exception registers - memcpy(&m_state.context.exc, p, sizeof(EXC)); - p += sizeof(EXC); - - // make sure we end up with exactly what we think we should have - size_t bytes_written = p - (uint8_t *)buf; - UNUSED_IF_ASSERT_DISABLED(bytes_written); - assert (bytes_written == size); - kern_return_t kret; - if ((kret = SetGPRState()) != KERN_SUCCESS) - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = %p, len = %llu) error: GPR regs failed to write: %u", buf, (uint64_t)buf_len, kret); - if ((kret = SetFPUState()) != KERN_SUCCESS) - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = %p, len = %llu) error: %s regs failed to write: %u", buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret); - if ((kret = SetEXCState()) != KERN_SUCCESS) - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = %p, len = %llu) error: EXP regs failed to write: %u", buf, (uint64_t)buf_len, kret); - } - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = %p, len = %llu) => %llu", buf, (uint64_t)buf_len, (uint64_t)size); - return size; -} + // Copy the XMM registers in a single block + memcpy(p, &m_state.context.fpu.no_avx.__fpu_xmm0, 8 * 16); + p += 8 * 16; + } -uint32_t -DNBArchImplI386::SaveRegisterState () -{ - kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); - DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); + // Copy the exception registers + memcpy(p, &m_state.context.exc, sizeof(EXC)); + p += sizeof(EXC); - bool force = true; - - if ((kret = GetGPRState(force)) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SaveRegisterState () error: GPR regs failed to read: %u ", kret); - } - else if ((kret = GetFPUState(force)) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SaveRegisterState () error: %s regs failed to read: %u", CPUHasAVX() ? "AVX" : "FPU", kret); - } - else - { - const uint32_t save_id = GetNextRegisterStateSaveID (); - m_saved_register_states[save_id] = m_state.context; - return save_id; + // make sure we end up with exactly what we think we should have + size_t bytes_written = p - (uint8_t *)buf; + UNUSED_IF_ASSERT_DISABLED(bytes_written); + assert(bytes_written == size); } - return 0; + } + DNBLogThreadedIf( + LOG_THREAD, + "DNBArchImplI386::GetRegisterContext (buf = %p, len = %llu) => %llu", buf, + (uint64_t)buf_len, (uint64_t)size); + // Return the size of the register context even if NULL was passed in + return size; } -bool -DNBArchImplI386::RestoreRegisterState (uint32_t save_id) -{ - SaveRegisterStates::iterator pos = m_saved_register_states.find(save_id); - if (pos != m_saved_register_states.end()) - { - m_state.context.gpr = pos->second.gpr; - m_state.context.fpu = pos->second.fpu; - m_state.context.exc = pos->second.exc; - m_state.SetError(e_regSetGPR, Read, 0); - m_state.SetError(e_regSetFPU, Read, 0); - m_state.SetError(e_regSetEXC, Read, 0); - kern_return_t kret; - bool success = true; - if ((kret = SetGPRState()) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::RestoreRegisterState (save_id = %u) error: GPR regs failed to write: %u", save_id, kret); - success = false; - } - else if ((kret = SetFPUState()) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::RestoreRegisterState (save_id = %u) error: %s regs failed to write: %u", save_id, CPUHasAVX() ? "AVX" : "FPU", kret); - success = false; - } - m_saved_register_states.erase(pos); - return success; + +nub_size_t DNBArchImplI386::SetRegisterContext(const void *buf, + nub_size_t buf_len) { + nub_size_t size = sizeof(m_state.context); + if (buf == NULL || buf_len == 0) + size = 0; + + if (size) { + if (size > buf_len) + size = buf_len; + + uint8_t *p = (uint8_t *)buf; + // Copy the GPR registers + memcpy(&m_state.context.gpr, p, sizeof(GPR)); + p += sizeof(GPR); + + if (CPUHasAVX() || FORCE_AVX_REGS) { + // Walk around the gaps in the FPU regs + memcpy(&m_state.context.fpu.avx.__fpu_fcw, p, 5); + p += 5; + memcpy(&m_state.context.fpu.avx.__fpu_fop, p, 8); + p += 8; + memcpy(&m_state.context.fpu.avx.__fpu_dp, p, 6); + p += 6; + memcpy(&m_state.context.fpu.avx.__fpu_mxcsr, p, 8); + p += 8; + + // Work around the padding between the stmm registers as they are 16 + // byte structs with 10 bytes of the value in each + for (size_t i = 0; i < 8; ++i) { + memcpy(&m_state.context.fpu.avx.__fpu_stmm0 + i, p, 10); + p += 10; + } + + // Interleave the XMM and YMMH registers to make the YMM registers + for (size_t i = 0; i < 8; ++i) { + memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + i, p, 16); + p += 16; + memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + i, p, 16); + p += 16; + } + } else { + // Copy fcw through mxcsrmask as there is no padding + memcpy(&m_state.context.fpu.no_avx.__fpu_fcw, p, 5); + p += 5; + memcpy(&m_state.context.fpu.no_avx.__fpu_fop, p, 8); + p += 8; + memcpy(&m_state.context.fpu.no_avx.__fpu_dp, p, 6); + p += 6; + memcpy(&m_state.context.fpu.no_avx.__fpu_mxcsr, p, 8); + p += 8; + + // Work around the padding between the stmm registers as they are 16 + // byte structs with 10 bytes of the value in each + for (size_t i = 0; i < 8; ++i) { + memcpy(&m_state.context.fpu.no_avx.__fpu_stmm0 + i, p, 10); + p += 10; + } + + // Copy the XMM registers in a single block + memcpy(&m_state.context.fpu.no_avx.__fpu_xmm0, p, 8 * 16); + p += 8 * 16; } - return false; -} + // Copy the exception registers + memcpy(&m_state.context.exc, p, sizeof(EXC)); + p += sizeof(EXC); + + // make sure we end up with exactly what we think we should have + size_t bytes_written = p - (uint8_t *)buf; + UNUSED_IF_ASSERT_DISABLED(bytes_written); + assert(bytes_written == size); + kern_return_t kret; + if ((kret = SetGPRState()) != KERN_SUCCESS) + DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = " + "%p, len = %llu) error: GPR regs failed to " + "write: %u", + buf, (uint64_t)buf_len, kret); + if ((kret = SetFPUState()) != KERN_SUCCESS) + DNBLogThreadedIf( + LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = %p, len = " + "%llu) error: %s regs failed to write: %u", + buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret); + if ((kret = SetEXCState()) != KERN_SUCCESS) + DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = " + "%p, len = %llu) error: EXP regs failed to " + "write: %u", + buf, (uint64_t)buf_len, kret); + } + DNBLogThreadedIf( + LOG_THREAD, + "DNBArchImplI386::SetRegisterContext (buf = %p, len = %llu) => %llu", buf, + (uint64_t)buf_len, (uint64_t)size); + return size; +} -kern_return_t -DNBArchImplI386::GetRegisterState(int set, bool force) -{ - switch (set) - { - case e_regSetALL: return GetGPRState(force) | GetFPUState(force) | GetEXCState(force); - case e_regSetGPR: return GetGPRState(force); - case e_regSetFPU: return GetFPUState(force); - case e_regSetEXC: return GetEXCState(force); - default: break; +uint32_t DNBArchImplI386::SaveRegisterState() { + kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); + DNBLogThreadedIf( + LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u " + "(SetGPRState() for stop_count = %u)", + m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); + + bool force = true; + + if ((kret = GetGPRState(force)) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::SaveRegisterState () error: " + "GPR regs failed to read: %u ", + kret); + } else if ((kret = GetFPUState(force)) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::SaveRegisterState () error: " + "%s regs failed to read: %u", + CPUHasAVX() ? "AVX" : "FPU", kret); + } else { + const uint32_t save_id = GetNextRegisterStateSaveID(); + m_saved_register_states[save_id] = m_state.context; + return save_id; + } + return 0; +} +bool DNBArchImplI386::RestoreRegisterState(uint32_t save_id) { + SaveRegisterStates::iterator pos = m_saved_register_states.find(save_id); + if (pos != m_saved_register_states.end()) { + m_state.context.gpr = pos->second.gpr; + m_state.context.fpu = pos->second.fpu; + m_state.context.exc = pos->second.exc; + m_state.SetError(e_regSetGPR, Read, 0); + m_state.SetError(e_regSetFPU, Read, 0); + m_state.SetError(e_regSetEXC, Read, 0); + kern_return_t kret; + bool success = true; + if ((kret = SetGPRState()) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::RestoreRegisterState " + "(save_id = %u) error: GPR regs failed to " + "write: %u", + save_id, kret); + success = false; + } else if ((kret = SetFPUState()) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::RestoreRegisterState " + "(save_id = %u) error: %s regs failed to " + "write: %u", + save_id, CPUHasAVX() ? "AVX" : "FPU", kret); + success = false; } - return KERN_INVALID_ARGUMENT; + m_saved_register_states.erase(pos); + return success; + } + return false; } -kern_return_t -DNBArchImplI386::SetRegisterState(int set) -{ - // Make sure we have a valid context to set. - if (RegisterSetStateIsValid(set)) - { - switch (set) - { - case e_regSetALL: return SetGPRState() | SetFPUState() | SetEXCState(); - case e_regSetGPR: return SetGPRState(); - case e_regSetFPU: return SetFPUState(); - case e_regSetEXC: return SetEXCState(); - default: break; - } +kern_return_t DNBArchImplI386::GetRegisterState(int set, bool force) { + switch (set) { + case e_regSetALL: + return GetGPRState(force) | GetFPUState(force) | GetEXCState(force); + case e_regSetGPR: + return GetGPRState(force); + case e_regSetFPU: + return GetFPUState(force); + case e_regSetEXC: + return GetEXCState(force); + default: + break; + } + return KERN_INVALID_ARGUMENT; +} + +kern_return_t DNBArchImplI386::SetRegisterState(int set) { + // Make sure we have a valid context to set. + if (RegisterSetStateIsValid(set)) { + switch (set) { + case e_regSetALL: + return SetGPRState() | SetFPUState() | SetEXCState(); + case e_regSetGPR: + return SetGPRState(); + case e_regSetFPU: + return SetFPUState(); + case e_regSetEXC: + return SetEXCState(); + default: + break; } - return KERN_INVALID_ARGUMENT; + } + return KERN_INVALID_ARGUMENT; } -bool -DNBArchImplI386::RegisterSetStateIsValid (int set) const -{ - return m_state.RegsAreValid(set); +bool DNBArchImplI386::RegisterSetStateIsValid(int set) const { + return m_state.RegsAreValid(set); } -#endif // #if defined (__i386__) +#endif // #if defined (__i386__) diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h index 6b4252151fe..5b042668818 100644 --- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h +++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h @@ -14,242 +14,219 @@ #ifndef __DNBArchImplI386_h__ #define __DNBArchImplI386_h__ -#if defined (__i386__) || defined (__x86_64__) +#if defined(__i386__) || defined(__x86_64__) -#include "DNBArch.h" #include "../HasAVX.h" +#include "DNBArch.h" #include "MachRegisterStatesI386.h" #include <map> class MachThread; -class DNBArchImplI386 : public DNBArchProtocol -{ +class DNBArchImplI386 : public DNBArchProtocol { public: - DNBArchImplI386(MachThread *thread) : - DNBArchProtocol(), - m_thread(thread), - m_state(), - m_2pc_dbg_checkpoint(), - m_2pc_trans_state(Trans_Done), - m_saved_register_states() - { - } - virtual ~DNBArchImplI386() - { - } - - static void Initialize(); - - virtual bool GetRegisterValue(uint32_t set, uint32_t reg, DNBRegisterValue *value); - virtual bool SetRegisterValue(uint32_t set, uint32_t reg, const DNBRegisterValue *value); - virtual nub_size_t GetRegisterContext (void *buf, nub_size_t buf_len); - virtual nub_size_t SetRegisterContext (const void *buf, nub_size_t buf_len); - virtual uint32_t SaveRegisterState (); - virtual bool RestoreRegisterState (uint32_t save_id); - - virtual kern_return_t GetRegisterState (int set, bool force); - virtual kern_return_t SetRegisterState (int set); - virtual bool RegisterSetStateIsValid (int set) const; - - virtual uint64_t GetPC(uint64_t failValue); // Get program counter - virtual kern_return_t SetPC(uint64_t value); - virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer - virtual void ThreadWillResume(); - virtual bool ThreadDidStop(); - virtual bool NotifyException(MachException::Data& exc); - - virtual uint32_t NumSupportedHardwareWatchpoints(); - virtual uint32_t EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task); - virtual bool DisableHardwareWatchpoint (uint32_t hw_break_index, bool also_set_on_task); - virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); + DNBArchImplI386(MachThread *thread) + : DNBArchProtocol(), m_thread(thread), m_state(), m_2pc_dbg_checkpoint(), + m_2pc_trans_state(Trans_Done), m_saved_register_states() {} + virtual ~DNBArchImplI386() {} + + static void Initialize(); + + virtual bool GetRegisterValue(uint32_t set, uint32_t reg, + DNBRegisterValue *value); + virtual bool SetRegisterValue(uint32_t set, uint32_t reg, + const DNBRegisterValue *value); + virtual nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len); + virtual nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len); + virtual uint32_t SaveRegisterState(); + virtual bool RestoreRegisterState(uint32_t save_id); + + virtual kern_return_t GetRegisterState(int set, bool force); + virtual kern_return_t SetRegisterState(int set); + virtual bool RegisterSetStateIsValid(int set) const; + + virtual uint64_t GetPC(uint64_t failValue); // Get program counter + virtual kern_return_t SetPC(uint64_t value); + virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer + virtual void ThreadWillResume(); + virtual bool ThreadDidStop(); + virtual bool NotifyException(MachException::Data &exc); + + virtual uint32_t NumSupportedHardwareWatchpoints(); + virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, + bool read, bool write, + bool also_set_on_task); + virtual bool DisableHardwareWatchpoint(uint32_t hw_break_index, + bool also_set_on_task); + virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); protected: - kern_return_t EnableHardwareSingleStep (bool enable); - - typedef __i386_thread_state_t GPR; - typedef __i386_float_state_t FPU; - typedef __i386_exception_state_t EXC; - typedef __i386_avx_state_t AVX; - typedef __i386_debug_state_t DBG; - - static const DNBRegisterInfo g_gpr_registers[]; - static const DNBRegisterInfo g_fpu_registers_no_avx[]; - static const DNBRegisterInfo g_fpu_registers_avx[]; - static const DNBRegisterInfo g_exc_registers[]; - static const DNBRegisterSetInfo g_reg_sets_no_avx[]; - static const DNBRegisterSetInfo g_reg_sets_avx[]; - static const size_t k_num_gpr_registers; - static const size_t k_num_fpu_registers_no_avx; - static const size_t k_num_fpu_registers_avx; - static const size_t k_num_exc_registers; - static const size_t k_num_all_registers_no_avx; - static const size_t k_num_all_registers_avx; - static const size_t k_num_register_sets; - - typedef enum RegisterSetTag - { - e_regSetALL = REGISTER_SET_ALL, - e_regSetGPR, - e_regSetFPU, - e_regSetEXC, - e_regSetDBG, - kNumRegisterSets - } RegisterSet; - - typedef enum RegisterSetWordSizeTag - { - e_regSetWordSizeGPR = sizeof(GPR) / sizeof(int), - e_regSetWordSizeFPU = sizeof(FPU) / sizeof(int), - e_regSetWordSizeEXC = sizeof(EXC) / sizeof(int), - e_regSetWordSizeAVX = sizeof(AVX) / sizeof(int), - e_regSetWordSizeDBG = sizeof(DBG) / sizeof(int) - } RegisterSetWordSize; - - enum - { - Read = 0, - Write = 1, - kNumErrors = 2 - }; - - struct Context - { - GPR gpr; - union { - FPU no_avx; - AVX avx; - } fpu; - EXC exc; - DBG dbg; - }; - - struct State - { - Context context; - kern_return_t gpr_errs[2]; // Read/Write errors - kern_return_t fpu_errs[2]; // Read/Write errors - kern_return_t exc_errs[2]; // Read/Write errors - kern_return_t dbg_errs[2]; // Read/Write errors - - State() - { - uint32_t i; - for (i=0; i<kNumErrors; i++) - { - gpr_errs[i] = -1; - fpu_errs[i] = -1; - exc_errs[i] = -1; - dbg_errs[i] = -1; - } - } - void InvalidateAllRegisterStates() - { - SetError (e_regSetALL, Read, -1); - } - kern_return_t GetError (int flavor, uint32_t err_idx) const - { - if (err_idx < kNumErrors) - { - switch (flavor) - { - // When getting all errors, just OR all values together to see if - // we got any kind of error. - case e_regSetALL: return gpr_errs[err_idx] | - fpu_errs[err_idx] | - exc_errs[err_idx]; - case e_regSetGPR: return gpr_errs[err_idx]; - case e_regSetFPU: return fpu_errs[err_idx]; - case e_regSetEXC: return exc_errs[err_idx]; - case e_regSetDBG: return dbg_errs[err_idx]; - default: break; - } - } - return -1; - } - bool SetError (int flavor, uint32_t err_idx, kern_return_t err) - { - if (err_idx < kNumErrors) - { - switch (flavor) - { - case e_regSetALL: - gpr_errs[err_idx] = - fpu_errs[err_idx] = - exc_errs[err_idx] = - dbg_errs[err_idx] = err; - return true; - - case e_regSetGPR: - gpr_errs[err_idx] = err; - return true; - - case e_regSetFPU: - fpu_errs[err_idx] = err; - return true; - - case e_regSetEXC: - exc_errs[err_idx] = err; - return true; - - case e_regSetDBG: - dbg_errs[err_idx] = err; - return true; - - default: break; - } - } - return false; + kern_return_t EnableHardwareSingleStep(bool enable); + + typedef __i386_thread_state_t GPR; + typedef __i386_float_state_t FPU; + typedef __i386_exception_state_t EXC; + typedef __i386_avx_state_t AVX; + typedef __i386_debug_state_t DBG; + + static const DNBRegisterInfo g_gpr_registers[]; + static const DNBRegisterInfo g_fpu_registers_no_avx[]; + static const DNBRegisterInfo g_fpu_registers_avx[]; + static const DNBRegisterInfo g_exc_registers[]; + static const DNBRegisterSetInfo g_reg_sets_no_avx[]; + static const DNBRegisterSetInfo g_reg_sets_avx[]; + static const size_t k_num_gpr_registers; + static const size_t k_num_fpu_registers_no_avx; + static const size_t k_num_fpu_registers_avx; + static const size_t k_num_exc_registers; + static const size_t k_num_all_registers_no_avx; + static const size_t k_num_all_registers_avx; + static const size_t k_num_register_sets; + + typedef enum RegisterSetTag { + e_regSetALL = REGISTER_SET_ALL, + e_regSetGPR, + e_regSetFPU, + e_regSetEXC, + e_regSetDBG, + kNumRegisterSets + } RegisterSet; + + typedef enum RegisterSetWordSizeTag { + e_regSetWordSizeGPR = sizeof(GPR) / sizeof(int), + e_regSetWordSizeFPU = sizeof(FPU) / sizeof(int), + e_regSetWordSizeEXC = sizeof(EXC) / sizeof(int), + e_regSetWordSizeAVX = sizeof(AVX) / sizeof(int), + e_regSetWordSizeDBG = sizeof(DBG) / sizeof(int) + } RegisterSetWordSize; + + enum { Read = 0, Write = 1, kNumErrors = 2 }; + + struct Context { + GPR gpr; + union { + FPU no_avx; + AVX avx; + } fpu; + EXC exc; + DBG dbg; + }; + + struct State { + Context context; + kern_return_t gpr_errs[2]; // Read/Write errors + kern_return_t fpu_errs[2]; // Read/Write errors + kern_return_t exc_errs[2]; // Read/Write errors + kern_return_t dbg_errs[2]; // Read/Write errors + + State() { + uint32_t i; + for (i = 0; i < kNumErrors; i++) { + gpr_errs[i] = -1; + fpu_errs[i] = -1; + exc_errs[i] = -1; + dbg_errs[i] = -1; + } + } + void InvalidateAllRegisterStates() { SetError(e_regSetALL, Read, -1); } + kern_return_t GetError(int flavor, uint32_t err_idx) const { + if (err_idx < kNumErrors) { + switch (flavor) { + // When getting all errors, just OR all values together to see if + // we got any kind of error. + case e_regSetALL: + return gpr_errs[err_idx] | fpu_errs[err_idx] | exc_errs[err_idx]; + case e_regSetGPR: + return gpr_errs[err_idx]; + case e_regSetFPU: + return fpu_errs[err_idx]; + case e_regSetEXC: + return exc_errs[err_idx]; + case e_regSetDBG: + return dbg_errs[err_idx]; + default: + break; } - bool RegsAreValid (int flavor) const - { - return GetError(flavor, Read) == KERN_SUCCESS; + } + return -1; + } + bool SetError(int flavor, uint32_t err_idx, kern_return_t err) { + if (err_idx < kNumErrors) { + switch (flavor) { + case e_regSetALL: + gpr_errs[err_idx] = fpu_errs[err_idx] = exc_errs[err_idx] = + dbg_errs[err_idx] = err; + return true; + + case e_regSetGPR: + gpr_errs[err_idx] = err; + return true; + + case e_regSetFPU: + fpu_errs[err_idx] = err; + return true; + + case e_regSetEXC: + exc_errs[err_idx] = err; + return true; + + case e_regSetDBG: + dbg_errs[err_idx] = err; + return true; + + default: + break; } - }; - - kern_return_t GetGPRState (bool force); - kern_return_t GetFPUState (bool force); - kern_return_t GetEXCState (bool force); - kern_return_t GetDBGState (bool force); - - kern_return_t SetGPRState (); - kern_return_t SetFPUState (); - kern_return_t SetEXCState (); - kern_return_t SetDBGState (bool also_set_on_task); - - static DNBArchProtocol * - Create (MachThread *thread); - - static const uint8_t * - SoftwareBreakpointOpcode (nub_size_t byte_size); - - static const DNBRegisterSetInfo * - GetRegisterSetInfo(nub_size_t *num_reg_sets); - - static uint32_t - GetRegisterContextSize(); - - // Helper functions for watchpoint manipulations. - static void SetWatchpoint(DBG &debug_state, uint32_t hw_index, nub_addr_t addr, nub_size_t size, bool read, bool write); - static void ClearWatchpoint(DBG &debug_state, uint32_t hw_index); - static bool IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index); - static void ClearWatchpointHits(DBG &debug_state); - static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index); - static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); - - virtual bool StartTransForHWP(); - virtual bool RollbackTransForHWP(); - virtual bool FinishTransForHWP(); - DBG GetDBGCheckpoint(); - - MachThread *m_thread; - State m_state; - DBG m_2pc_dbg_checkpoint; - uint32_t m_2pc_trans_state; // Is transaction of DBG state change: Pedning (0), Done (1), or Rolled Back (2)? - typedef std::map<uint32_t, Context> SaveRegisterStates; - SaveRegisterStates m_saved_register_states; + } + return false; + } + bool RegsAreValid(int flavor) const { + return GetError(flavor, Read) == KERN_SUCCESS; + } + }; + + kern_return_t GetGPRState(bool force); + kern_return_t GetFPUState(bool force); + kern_return_t GetEXCState(bool force); + kern_return_t GetDBGState(bool force); + + kern_return_t SetGPRState(); + kern_return_t SetFPUState(); + kern_return_t SetEXCState(); + kern_return_t SetDBGState(bool also_set_on_task); + + static DNBArchProtocol *Create(MachThread *thread); + + static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size); + + static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets); + + static uint32_t GetRegisterContextSize(); + + // Helper functions for watchpoint manipulations. + static void SetWatchpoint(DBG &debug_state, uint32_t hw_index, + nub_addr_t addr, nub_size_t size, bool read, + bool write); + static void ClearWatchpoint(DBG &debug_state, uint32_t hw_index); + static bool IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index); + static void ClearWatchpointHits(DBG &debug_state); + static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index); + static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); + + virtual bool StartTransForHWP(); + virtual bool RollbackTransForHWP(); + virtual bool FinishTransForHWP(); + DBG GetDBGCheckpoint(); + + MachThread *m_thread; + State m_state; + DBG m_2pc_dbg_checkpoint; + uint32_t m_2pc_trans_state; // Is transaction of DBG state change: Pedning + // (0), Done (1), or Rolled Back (2)? + typedef std::map<uint32_t, Context> SaveRegisterStates; + SaveRegisterStates m_saved_register_states; }; -#endif // #if defined (__i386__) || defined (__x86_64__) -#endif // #ifndef __DNBArchImplI386_h__ +#endif // #if defined (__i386__) || defined (__x86_64__) +#endif // #ifndef __DNBArchImplI386_h__ diff --git a/lldb/tools/debugserver/source/MacOSX/i386/MachRegisterStatesI386.h b/lldb/tools/debugserver/source/MacOSX/i386/MachRegisterStatesI386.h index 59cfbe055a3..900aa15a75d 100644 --- a/lldb/tools/debugserver/source/MacOSX/i386/MachRegisterStatesI386.h +++ b/lldb/tools/debugserver/source/MacOSX/i386/MachRegisterStatesI386.h @@ -16,165 +16,163 @@ #include <inttypes.h> -#define __i386_THREAD_STATE 1 -#define __i386_FLOAT_STATE 2 -#define __i386_EXCEPTION_STATE 3 -#define __i386_DEBUG_STATE 10 -#define __i386_AVX_STATE 16 +#define __i386_THREAD_STATE 1 +#define __i386_FLOAT_STATE 2 +#define __i386_EXCEPTION_STATE 3 +#define __i386_DEBUG_STATE 10 +#define __i386_AVX_STATE 16 typedef struct { - uint32_t __eax; - uint32_t __ebx; - uint32_t __ecx; - uint32_t __edx; - uint32_t __edi; - uint32_t __esi; - uint32_t __ebp; - uint32_t __esp; - uint32_t __ss; - uint32_t __eflags; - uint32_t __eip; - uint32_t __cs; - uint32_t __ds; - uint32_t __es; - uint32_t __fs; - uint32_t __gs; + uint32_t __eax; + uint32_t __ebx; + uint32_t __ecx; + uint32_t __edx; + uint32_t __edi; + uint32_t __esi; + uint32_t __ebp; + uint32_t __esp; + uint32_t __ss; + uint32_t __eflags; + uint32_t __eip; + uint32_t __cs; + uint32_t __ds; + uint32_t __es; + uint32_t __fs; + uint32_t __gs; } __i386_thread_state_t; typedef struct { - uint16_t __invalid : 1; - uint16_t __denorm : 1; - uint16_t __zdiv : 1; - uint16_t __ovrfl : 1; - uint16_t __undfl : 1; - uint16_t __precis : 1; - uint16_t __PAD1 : 2; - uint16_t __pc : 2; - uint16_t __rc : 2; - uint16_t __PAD2 : 1; - uint16_t __PAD3 : 3; + uint16_t __invalid : 1; + uint16_t __denorm : 1; + uint16_t __zdiv : 1; + uint16_t __ovrfl : 1; + uint16_t __undfl : 1; + uint16_t __precis : 1; + uint16_t __PAD1 : 2; + uint16_t __pc : 2; + uint16_t __rc : 2; + uint16_t __PAD2 : 1; + uint16_t __PAD3 : 3; } __i386_fp_control_t; typedef struct { - uint16_t __invalid : 1; - uint16_t __denorm : 1; - uint16_t __zdiv : 1; - uint16_t __ovrfl : 1; - uint16_t __undfl : 1; - uint16_t __precis : 1; - uint16_t __stkflt : 1; - uint16_t __errsumm : 1; - uint16_t __c0 : 1; - uint16_t __c1 : 1; - uint16_t __c2 : 1; - uint16_t __tos : 3; - uint16_t __c3 : 1; - uint16_t __busy : 1; + uint16_t __invalid : 1; + uint16_t __denorm : 1; + uint16_t __zdiv : 1; + uint16_t __ovrfl : 1; + uint16_t __undfl : 1; + uint16_t __precis : 1; + uint16_t __stkflt : 1; + uint16_t __errsumm : 1; + uint16_t __c0 : 1; + uint16_t __c1 : 1; + uint16_t __c2 : 1; + uint16_t __tos : 3; + uint16_t __c3 : 1; + uint16_t __busy : 1; } __i386_fp_status_t; typedef struct { - uint8_t __mmst_reg[10]; - uint8_t __mmst_rsrv[6]; + uint8_t __mmst_reg[10]; + uint8_t __mmst_rsrv[6]; } __i386_mmst_reg; -typedef struct { - uint8_t __xmm_reg[16]; -} __i386_xmm_reg; +typedef struct { uint8_t __xmm_reg[16]; } __i386_xmm_reg; typedef struct { - uint32_t __fpu_reserved[2]; - __i386_fp_control_t __fpu_fcw; - __i386_fp_status_t __fpu_fsw; - uint8_t __fpu_ftw; - uint8_t __fpu_rsrv1; - uint16_t __fpu_fop; - uint32_t __fpu_ip; - uint16_t __fpu_cs; - uint16_t __fpu_rsrv2; - uint32_t __fpu_dp; - uint16_t __fpu_ds; - uint16_t __fpu_rsrv3; - uint32_t __fpu_mxcsr; - uint32_t __fpu_mxcsrmask; - __i386_mmst_reg __fpu_stmm0; - __i386_mmst_reg __fpu_stmm1; - __i386_mmst_reg __fpu_stmm2; - __i386_mmst_reg __fpu_stmm3; - __i386_mmst_reg __fpu_stmm4; - __i386_mmst_reg __fpu_stmm5; - __i386_mmst_reg __fpu_stmm6; - __i386_mmst_reg __fpu_stmm7; - __i386_xmm_reg __fpu_xmm0; - __i386_xmm_reg __fpu_xmm1; - __i386_xmm_reg __fpu_xmm2; - __i386_xmm_reg __fpu_xmm3; - __i386_xmm_reg __fpu_xmm4; - __i386_xmm_reg __fpu_xmm5; - __i386_xmm_reg __fpu_xmm6; - __i386_xmm_reg __fpu_xmm7; - uint8_t __fpu_rsrv4[14*16]; - uint32_t __fpu_reserved1; + uint32_t __fpu_reserved[2]; + __i386_fp_control_t __fpu_fcw; + __i386_fp_status_t __fpu_fsw; + uint8_t __fpu_ftw; + uint8_t __fpu_rsrv1; + uint16_t __fpu_fop; + uint32_t __fpu_ip; + uint16_t __fpu_cs; + uint16_t __fpu_rsrv2; + uint32_t __fpu_dp; + uint16_t __fpu_ds; + uint16_t __fpu_rsrv3; + uint32_t __fpu_mxcsr; + uint32_t __fpu_mxcsrmask; + __i386_mmst_reg __fpu_stmm0; + __i386_mmst_reg __fpu_stmm1; + __i386_mmst_reg __fpu_stmm2; + __i386_mmst_reg __fpu_stmm3; + __i386_mmst_reg __fpu_stmm4; + __i386_mmst_reg __fpu_stmm5; + __i386_mmst_reg __fpu_stmm6; + __i386_mmst_reg __fpu_stmm7; + __i386_xmm_reg __fpu_xmm0; + __i386_xmm_reg __fpu_xmm1; + __i386_xmm_reg __fpu_xmm2; + __i386_xmm_reg __fpu_xmm3; + __i386_xmm_reg __fpu_xmm4; + __i386_xmm_reg __fpu_xmm5; + __i386_xmm_reg __fpu_xmm6; + __i386_xmm_reg __fpu_xmm7; + uint8_t __fpu_rsrv4[14 * 16]; + uint32_t __fpu_reserved1; } __i386_float_state_t; typedef struct { - uint32_t __fpu_reserved[2]; - __i386_fp_control_t __fpu_fcw; - __i386_fp_status_t __fpu_fsw; - uint8_t __fpu_ftw; - uint8_t __fpu_rsrv1; - uint16_t __fpu_fop; - uint32_t __fpu_ip; - uint16_t __fpu_cs; - uint16_t __fpu_rsrv2; - uint32_t __fpu_dp; - uint16_t __fpu_ds; - uint16_t __fpu_rsrv3; - uint32_t __fpu_mxcsr; - uint32_t __fpu_mxcsrmask; - __i386_mmst_reg __fpu_stmm0; - __i386_mmst_reg __fpu_stmm1; - __i386_mmst_reg __fpu_stmm2; - __i386_mmst_reg __fpu_stmm3; - __i386_mmst_reg __fpu_stmm4; - __i386_mmst_reg __fpu_stmm5; - __i386_mmst_reg __fpu_stmm6; - __i386_mmst_reg __fpu_stmm7; - __i386_xmm_reg __fpu_xmm0; - __i386_xmm_reg __fpu_xmm1; - __i386_xmm_reg __fpu_xmm2; - __i386_xmm_reg __fpu_xmm3; - __i386_xmm_reg __fpu_xmm4; - __i386_xmm_reg __fpu_xmm5; - __i386_xmm_reg __fpu_xmm6; - __i386_xmm_reg __fpu_xmm7; - uint8_t __fpu_rsrv4[14*16]; - uint32_t __fpu_reserved1; - uint8_t __avx_reserved1[64]; - __i386_xmm_reg __fpu_ymmh0; - __i386_xmm_reg __fpu_ymmh1; - __i386_xmm_reg __fpu_ymmh2; - __i386_xmm_reg __fpu_ymmh3; - __i386_xmm_reg __fpu_ymmh4; - __i386_xmm_reg __fpu_ymmh5; - __i386_xmm_reg __fpu_ymmh6; - __i386_xmm_reg __fpu_ymmh7; + uint32_t __fpu_reserved[2]; + __i386_fp_control_t __fpu_fcw; + __i386_fp_status_t __fpu_fsw; + uint8_t __fpu_ftw; + uint8_t __fpu_rsrv1; + uint16_t __fpu_fop; + uint32_t __fpu_ip; + uint16_t __fpu_cs; + uint16_t __fpu_rsrv2; + uint32_t __fpu_dp; + uint16_t __fpu_ds; + uint16_t __fpu_rsrv3; + uint32_t __fpu_mxcsr; + uint32_t __fpu_mxcsrmask; + __i386_mmst_reg __fpu_stmm0; + __i386_mmst_reg __fpu_stmm1; + __i386_mmst_reg __fpu_stmm2; + __i386_mmst_reg __fpu_stmm3; + __i386_mmst_reg __fpu_stmm4; + __i386_mmst_reg __fpu_stmm5; + __i386_mmst_reg __fpu_stmm6; + __i386_mmst_reg __fpu_stmm7; + __i386_xmm_reg __fpu_xmm0; + __i386_xmm_reg __fpu_xmm1; + __i386_xmm_reg __fpu_xmm2; + __i386_xmm_reg __fpu_xmm3; + __i386_xmm_reg __fpu_xmm4; + __i386_xmm_reg __fpu_xmm5; + __i386_xmm_reg __fpu_xmm6; + __i386_xmm_reg __fpu_xmm7; + uint8_t __fpu_rsrv4[14 * 16]; + uint32_t __fpu_reserved1; + uint8_t __avx_reserved1[64]; + __i386_xmm_reg __fpu_ymmh0; + __i386_xmm_reg __fpu_ymmh1; + __i386_xmm_reg __fpu_ymmh2; + __i386_xmm_reg __fpu_ymmh3; + __i386_xmm_reg __fpu_ymmh4; + __i386_xmm_reg __fpu_ymmh5; + __i386_xmm_reg __fpu_ymmh6; + __i386_xmm_reg __fpu_ymmh7; } __i386_avx_state_t; typedef struct { - uint32_t __trapno; - uint32_t __err; - uint32_t __faultvaddr; + uint32_t __trapno; + uint32_t __err; + uint32_t __faultvaddr; } __i386_exception_state_t; typedef struct { - uint32_t __dr0; - uint32_t __dr1; - uint32_t __dr2; - uint32_t __dr3; - uint32_t __dr4; - uint32_t __dr5; - uint32_t __dr6; - uint32_t __dr7; + uint32_t __dr0; + uint32_t __dr1; + uint32_t __dr2; + uint32_t __dr3; + uint32_t __dr4; + uint32_t __dr5; + uint32_t __dr6; + uint32_t __dr7; } __i386_debug_state_t; #endif diff --git a/lldb/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.cpp b/lldb/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.cpp index c6f1a718ac9..1653287430a 100644 --- a/lldb/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.cpp +++ b/lldb/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.cpp @@ -11,7 +11,7 @@ // //===----------------------------------------------------------------------===// -#if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) +#if defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) #if __DARWIN_UNIX03 #define PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(reg) __##reg @@ -20,550 +20,473 @@ #endif #include "MacOSX/ppc/DNBArchImpl.h" -#include "MacOSX/MachThread.h" #include "DNBBreakpoint.h" #include "DNBLog.h" #include "DNBRegisterInfo.h" +#include "MacOSX/MachThread.h" -static const uint8_t g_breakpoint_opcode[] = { 0x7F, 0xC0, 0x00, 0x08 }; +static const uint8_t g_breakpoint_opcode[] = {0x7F, 0xC0, 0x00, 0x08}; -const uint8_t * -DNBArchMachPPC::SoftwareBreakpointOpcode (nub_size_t size) -{ - if (size == 4) - return g_breakpoint_opcode; - return NULL; +const uint8_t *DNBArchMachPPC::SoftwareBreakpointOpcode(nub_size_t size) { + if (size == 4) + return g_breakpoint_opcode; + return NULL; } -uint32_t -DNBArchMachPPC::GetCPUType() -{ - return CPU_TYPE_POWERPC; -} +uint32_t DNBArchMachPPC::GetCPUType() { return CPU_TYPE_POWERPC; } -uint64_t -DNBArchMachPPC::GetPC(uint64_t failValue) -{ - // Get program counter - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr0); - return failValue; +uint64_t DNBArchMachPPC::GetPC(uint64_t failValue) { + // Get program counter + if (GetGPRState(false) == KERN_SUCCESS) + return m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr0); + return failValue; } -kern_return_t -DNBArchMachPPC::SetPC(uint64_t value) -{ - // Get program counter - kern_return_t err = GetGPRState(false); - if (err == KERN_SUCCESS) - { - m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr0) = value; - err = SetGPRState(); - } - return err == KERN_SUCCESS; +kern_return_t DNBArchMachPPC::SetPC(uint64_t value) { + // Get program counter + kern_return_t err = GetGPRState(false); + if (err == KERN_SUCCESS) { + m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr0) = value; + err = SetGPRState(); + } + return err == KERN_SUCCESS; } -uint64_t -DNBArchMachPPC::GetSP(uint64_t failValue) -{ - // Get stack pointer - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(r1); - return failValue; +uint64_t DNBArchMachPPC::GetSP(uint64_t failValue) { + // Get stack pointer + if (GetGPRState(false) == KERN_SUCCESS) + return m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(r1); + return failValue; } -kern_return_t -DNBArchMachPPC::GetGPRState(bool force) -{ - if (force || m_state.GetError(e_regSetGPR, Read)) - { - mach_msg_type_number_t count = e_regSetWordSizeGPR; - m_state.SetError(e_regSetGPR, Read, ::thread_get_state(m_thread->MachPortNumber(), e_regSetGPR, (thread_state_t)&m_state.gpr, &count)); - } - return m_state.GetError(e_regSetGPR, Read); +kern_return_t DNBArchMachPPC::GetGPRState(bool force) { + if (force || m_state.GetError(e_regSetGPR, Read)) { + mach_msg_type_number_t count = e_regSetWordSizeGPR; + m_state.SetError(e_regSetGPR, Read, + ::thread_get_state(m_thread->MachPortNumber(), e_regSetGPR, + (thread_state_t)&m_state.gpr, &count)); + } + return m_state.GetError(e_regSetGPR, Read); } -kern_return_t -DNBArchMachPPC::GetFPRState(bool force) -{ - if (force || m_state.GetError(e_regSetFPR, Read)) - { - mach_msg_type_number_t count = e_regSetWordSizeFPR; - m_state.SetError(e_regSetFPR, Read, ::thread_get_state(m_thread->MachPortNumber(), e_regSetFPR, (thread_state_t)&m_state.fpr, &count)); - } - return m_state.GetError(e_regSetFPR, Read); +kern_return_t DNBArchMachPPC::GetFPRState(bool force) { + if (force || m_state.GetError(e_regSetFPR, Read)) { + mach_msg_type_number_t count = e_regSetWordSizeFPR; + m_state.SetError(e_regSetFPR, Read, + ::thread_get_state(m_thread->MachPortNumber(), e_regSetFPR, + (thread_state_t)&m_state.fpr, &count)); + } + return m_state.GetError(e_regSetFPR, Read); } -kern_return_t -DNBArchMachPPC::GetEXCState(bool force) -{ - if (force || m_state.GetError(e_regSetEXC, Read)) - { - mach_msg_type_number_t count = e_regSetWordSizeEXC; - m_state.SetError(e_regSetEXC, Read, ::thread_get_state(m_thread->MachPortNumber(), e_regSetEXC, (thread_state_t)&m_state.exc, &count)); - } - return m_state.GetError(e_regSetEXC, Read); +kern_return_t DNBArchMachPPC::GetEXCState(bool force) { + if (force || m_state.GetError(e_regSetEXC, Read)) { + mach_msg_type_number_t count = e_regSetWordSizeEXC; + m_state.SetError(e_regSetEXC, Read, + ::thread_get_state(m_thread->MachPortNumber(), e_regSetEXC, + (thread_state_t)&m_state.exc, &count)); + } + return m_state.GetError(e_regSetEXC, Read); } -kern_return_t -DNBArchMachPPC::GetVECState(bool force) -{ - if (force || m_state.GetError(e_regSetVEC, Read)) - { - mach_msg_type_number_t count = e_regSetWordSizeVEC; - m_state.SetError(e_regSetVEC, Read, ::thread_get_state(m_thread->MachPortNumber(), e_regSetVEC, (thread_state_t)&m_state.vec, &count)); - } - return m_state.GetError(e_regSetVEC, Read); +kern_return_t DNBArchMachPPC::GetVECState(bool force) { + if (force || m_state.GetError(e_regSetVEC, Read)) { + mach_msg_type_number_t count = e_regSetWordSizeVEC; + m_state.SetError(e_regSetVEC, Read, + ::thread_get_state(m_thread->MachPortNumber(), e_regSetVEC, + (thread_state_t)&m_state.vec, &count)); + } + return m_state.GetError(e_regSetVEC, Read); } -kern_return_t -DNBArchMachPPC::SetGPRState() -{ - m_state.SetError(e_regSetGPR, Write, ::thread_set_state(m_thread->MachPortNumber(), e_regSetGPR, (thread_state_t)&m_state.gpr, e_regSetWordSizeGPR)); - return m_state.GetError(e_regSetGPR, Write); +kern_return_t DNBArchMachPPC::SetGPRState() { + m_state.SetError(e_regSetGPR, Write, + ::thread_set_state(m_thread->MachPortNumber(), e_regSetGPR, + (thread_state_t)&m_state.gpr, + e_regSetWordSizeGPR)); + return m_state.GetError(e_regSetGPR, Write); } -kern_return_t -DNBArchMachPPC::SetFPRState() -{ - m_state.SetError(e_regSetFPR, Write, ::thread_set_state(m_thread->MachPortNumber(), e_regSetFPR, (thread_state_t)&m_state.fpr, e_regSetWordSizeFPR)); - return m_state.GetError(e_regSetFPR, Write); +kern_return_t DNBArchMachPPC::SetFPRState() { + m_state.SetError(e_regSetFPR, Write, + ::thread_set_state(m_thread->MachPortNumber(), e_regSetFPR, + (thread_state_t)&m_state.fpr, + e_regSetWordSizeFPR)); + return m_state.GetError(e_regSetFPR, Write); } -kern_return_t -DNBArchMachPPC::SetEXCState() -{ - m_state.SetError(e_regSetEXC, Write, ::thread_set_state(m_thread->MachPortNumber(), e_regSetEXC, (thread_state_t)&m_state.exc, e_regSetWordSizeEXC)); - return m_state.GetError(e_regSetEXC, Write); +kern_return_t DNBArchMachPPC::SetEXCState() { + m_state.SetError(e_regSetEXC, Write, + ::thread_set_state(m_thread->MachPortNumber(), e_regSetEXC, + (thread_state_t)&m_state.exc, + e_regSetWordSizeEXC)); + return m_state.GetError(e_regSetEXC, Write); } -kern_return_t -DNBArchMachPPC::SetVECState() -{ - m_state.SetError(e_regSetVEC, Write, ::thread_set_state(m_thread->MachPortNumber(), e_regSetVEC, (thread_state_t)&m_state.vec, e_regSetWordSizeVEC)); - return m_state.GetError(e_regSetVEC, Write); +kern_return_t DNBArchMachPPC::SetVECState() { + m_state.SetError(e_regSetVEC, Write, + ::thread_set_state(m_thread->MachPortNumber(), e_regSetVEC, + (thread_state_t)&m_state.vec, + e_regSetWordSizeVEC)); + return m_state.GetError(e_regSetVEC, Write); } -bool -DNBArchMachPPC::ThreadWillResume() -{ - bool success = true; +bool DNBArchMachPPC::ThreadWillResume() { + bool success = true; - // Do we need to step this thread? If so, let the mach thread tell us so. - if (m_thread->IsStepping()) - { - // This is the primary thread, let the arch do anything it needs - success = EnableHardwareSingleStep(true) == KERN_SUCCESS; - } - return success; + // Do we need to step this thread? If so, let the mach thread tell us so. + if (m_thread->IsStepping()) { + // This is the primary thread, let the arch do anything it needs + success = EnableHardwareSingleStep(true) == KERN_SUCCESS; + } + return success; } -bool -DNBArchMachPPC::ThreadDidStop() -{ - bool success = true; - - m_state.InvalidateAllRegisterStates(); - - // Are we stepping a single instruction? - if (GetGPRState(true) == KERN_SUCCESS) - { - // We are single stepping, was this the primary thread? - if (m_thread->IsStepping()) - { - // This was the primary thread, we need to clear the trace - // bit if so. - success = EnableHardwareSingleStep(false) == KERN_SUCCESS; - } - else - { - // The MachThread will automatically restore the suspend count - // in ThreadDidStop(), so we don't need to do anything here if - // we weren't the primary thread the last time - } +bool DNBArchMachPPC::ThreadDidStop() { + bool success = true; + + m_state.InvalidateAllRegisterStates(); + + // Are we stepping a single instruction? + if (GetGPRState(true) == KERN_SUCCESS) { + // We are single stepping, was this the primary thread? + if (m_thread->IsStepping()) { + // This was the primary thread, we need to clear the trace + // bit if so. + success = EnableHardwareSingleStep(false) == KERN_SUCCESS; + } else { + // The MachThread will automatically restore the suspend count + // in ThreadDidStop(), so we don't need to do anything here if + // we weren't the primary thread the last time } - return success; + } + return success; } - // Set the single step bit in the processor status register. -kern_return_t -DNBArchMachPPC::EnableHardwareSingleStep (bool enable) -{ - DNBLogThreadedIf(LOG_STEP, "DNBArchMachPPC::EnableHardwareSingleStep( enable = %d )", enable); - if (GetGPRState(false) == KERN_SUCCESS) - { - const uint32_t trace_bit = 0x400; - if (enable) - m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr1) |= trace_bit; - else - m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr1) &= ~trace_bit; - return SetGPRState(); - } - return m_state.GetError(e_regSetGPR, Read); +kern_return_t DNBArchMachPPC::EnableHardwareSingleStep(bool enable) { + DNBLogThreadedIf(LOG_STEP, + "DNBArchMachPPC::EnableHardwareSingleStep( enable = %d )", + enable); + if (GetGPRState(false) == KERN_SUCCESS) { + const uint32_t trace_bit = 0x400; + if (enable) + m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr1) |= trace_bit; + else + m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr1) &= ~trace_bit; + return SetGPRState(); + } + return m_state.GetError(e_regSetGPR, Read); } //---------------------------------------------------------------------- // Register information definitions for 32 bit PowerPC. //---------------------------------------------------------------------- -enum gpr_regnums -{ - e_regNumGPR_srr0, - e_regNumGPR_srr1, - e_regNumGPR_r0, - e_regNumGPR_r1, - e_regNumGPR_r2, - e_regNumGPR_r3, - e_regNumGPR_r4, - e_regNumGPR_r5, - e_regNumGPR_r6, - e_regNumGPR_r7, - e_regNumGPR_r8, - e_regNumGPR_r9, - e_regNumGPR_r10, - e_regNumGPR_r11, - e_regNumGPR_r12, - e_regNumGPR_r13, - e_regNumGPR_r14, - e_regNumGPR_r15, - e_regNumGPR_r16, - e_regNumGPR_r17, - e_regNumGPR_r18, - e_regNumGPR_r19, - e_regNumGPR_r20, - e_regNumGPR_r21, - e_regNumGPR_r22, - e_regNumGPR_r23, - e_regNumGPR_r24, - e_regNumGPR_r25, - e_regNumGPR_r26, - e_regNumGPR_r27, - e_regNumGPR_r28, - e_regNumGPR_r29, - e_regNumGPR_r30, - e_regNumGPR_r31, - e_regNumGPR_cr, - e_regNumGPR_xer, - e_regNumGPR_lr, - e_regNumGPR_ctr, - e_regNumGPR_mq, - e_regNumGPR_vrsave +enum gpr_regnums { + e_regNumGPR_srr0, + e_regNumGPR_srr1, + e_regNumGPR_r0, + e_regNumGPR_r1, + e_regNumGPR_r2, + e_regNumGPR_r3, + e_regNumGPR_r4, + e_regNumGPR_r5, + e_regNumGPR_r6, + e_regNumGPR_r7, + e_regNumGPR_r8, + e_regNumGPR_r9, + e_regNumGPR_r10, + e_regNumGPR_r11, + e_regNumGPR_r12, + e_regNumGPR_r13, + e_regNumGPR_r14, + e_regNumGPR_r15, + e_regNumGPR_r16, + e_regNumGPR_r17, + e_regNumGPR_r18, + e_regNumGPR_r19, + e_regNumGPR_r20, + e_regNumGPR_r21, + e_regNumGPR_r22, + e_regNumGPR_r23, + e_regNumGPR_r24, + e_regNumGPR_r25, + e_regNumGPR_r26, + e_regNumGPR_r27, + e_regNumGPR_r28, + e_regNumGPR_r29, + e_regNumGPR_r30, + e_regNumGPR_r31, + e_regNumGPR_cr, + e_regNumGPR_xer, + e_regNumGPR_lr, + e_regNumGPR_ctr, + e_regNumGPR_mq, + e_regNumGPR_vrsave }; - - - // General purpose registers -static DNBRegisterInfo g_gpr_registers[] = -{ - { "srr0" , Uint, 4, Hex }, - { "srr1" , Uint, 4, Hex }, - { "r0" , Uint, 4, Hex }, - { "r1" , Uint, 4, Hex }, - { "r2" , Uint, 4, Hex }, - { "r3" , Uint, 4, Hex }, - { "r4" , Uint, 4, Hex }, - { "r5" , Uint, 4, Hex }, - { "r6" , Uint, 4, Hex }, - { "r7" , Uint, 4, Hex }, - { "r8" , Uint, 4, Hex }, - { "r9" , Uint, 4, Hex }, - { "r10" , Uint, 4, Hex }, - { "r11" , Uint, 4, Hex }, - { "r12" , Uint, 4, Hex }, - { "r13" , Uint, 4, Hex }, - { "r14" , Uint, 4, Hex }, - { "r15" , Uint, 4, Hex }, - { "r16" , Uint, 4, Hex }, - { "r17" , Uint, 4, Hex }, - { "r18" , Uint, 4, Hex }, - { "r19" , Uint, 4, Hex }, - { "r20" , Uint, 4, Hex }, - { "r21" , Uint, 4, Hex }, - { "r22" , Uint, 4, Hex }, - { "r23" , Uint, 4, Hex }, - { "r24" , Uint, 4, Hex }, - { "r25" , Uint, 4, Hex }, - { "r26" , Uint, 4, Hex }, - { "r27" , Uint, 4, Hex }, - { "r28" , Uint, 4, Hex }, - { "r29" , Uint, 4, Hex }, - { "r30" , Uint, 4, Hex }, - { "r31" , Uint, 4, Hex }, - { "cr" , Uint, 4, Hex }, - { "xer" , Uint, 4, Hex }, - { "lr" , Uint, 4, Hex }, - { "ctr" , Uint, 4, Hex }, - { "mq" , Uint, 4, Hex }, - { "vrsave", Uint, 4, Hex }, +static DNBRegisterInfo g_gpr_registers[] = { + {"srr0", Uint, 4, Hex}, {"srr1", Uint, 4, Hex}, {"r0", Uint, 4, Hex}, + {"r1", Uint, 4, Hex}, {"r2", Uint, 4, Hex}, {"r3", Uint, 4, Hex}, + {"r4", Uint, 4, Hex}, {"r5", Uint, 4, Hex}, {"r6", Uint, 4, Hex}, + {"r7", Uint, 4, Hex}, {"r8", Uint, 4, Hex}, {"r9", Uint, 4, Hex}, + {"r10", Uint, 4, Hex}, {"r11", Uint, 4, Hex}, {"r12", Uint, 4, Hex}, + {"r13", Uint, 4, Hex}, {"r14", Uint, 4, Hex}, {"r15", Uint, 4, Hex}, + {"r16", Uint, 4, Hex}, {"r17", Uint, 4, Hex}, {"r18", Uint, 4, Hex}, + {"r19", Uint, 4, Hex}, {"r20", Uint, 4, Hex}, {"r21", Uint, 4, Hex}, + {"r22", Uint, 4, Hex}, {"r23", Uint, 4, Hex}, {"r24", Uint, 4, Hex}, + {"r25", Uint, 4, Hex}, {"r26", Uint, 4, Hex}, {"r27", Uint, 4, Hex}, + {"r28", Uint, 4, Hex}, {"r29", Uint, 4, Hex}, {"r30", Uint, 4, Hex}, + {"r31", Uint, 4, Hex}, {"cr", Uint, 4, Hex}, {"xer", Uint, 4, Hex}, + {"lr", Uint, 4, Hex}, {"ctr", Uint, 4, Hex}, {"mq", Uint, 4, Hex}, + {"vrsave", Uint, 4, Hex}, }; // Floating point registers -static DNBRegisterInfo g_fpr_registers[] = -{ - { "fp0" , IEEE754, 8, Float }, - { "fp1" , IEEE754, 8, Float }, - { "fp2" , IEEE754, 8, Float }, - { "fp3" , IEEE754, 8, Float }, - { "fp4" , IEEE754, 8, Float }, - { "fp5" , IEEE754, 8, Float }, - { "fp6" , IEEE754, 8, Float }, - { "fp7" , IEEE754, 8, Float }, - { "fp8" , IEEE754, 8, Float }, - { "fp9" , IEEE754, 8, Float }, - { "fp10" , IEEE754, 8, Float }, - { "fp11" , IEEE754, 8, Float }, - { "fp12" , IEEE754, 8, Float }, - { "fp13" , IEEE754, 8, Float }, - { "fp14" , IEEE754, 8, Float }, - { "fp15" , IEEE754, 8, Float }, - { "fp16" , IEEE754, 8, Float }, - { "fp17" , IEEE754, 8, Float }, - { "fp18" , IEEE754, 8, Float }, - { "fp19" , IEEE754, 8, Float }, - { "fp20" , IEEE754, 8, Float }, - { "fp21" , IEEE754, 8, Float }, - { "fp22" , IEEE754, 8, Float }, - { "fp23" , IEEE754, 8, Float }, - { "fp24" , IEEE754, 8, Float }, - { "fp25" , IEEE754, 8, Float }, - { "fp26" , IEEE754, 8, Float }, - { "fp27" , IEEE754, 8, Float }, - { "fp28" , IEEE754, 8, Float }, - { "fp29" , IEEE754, 8, Float }, - { "fp30" , IEEE754, 8, Float }, - { "fp31" , IEEE754, 8, Float }, - { "fpscr" , Uint, 4, Hex } -}; +static DNBRegisterInfo g_fpr_registers[] = { + {"fp0", IEEE754, 8, Float}, {"fp1", IEEE754, 8, Float}, + {"fp2", IEEE754, 8, Float}, {"fp3", IEEE754, 8, Float}, + {"fp4", IEEE754, 8, Float}, {"fp5", IEEE754, 8, Float}, + {"fp6", IEEE754, 8, Float}, {"fp7", IEEE754, 8, Float}, + {"fp8", IEEE754, 8, Float}, {"fp9", IEEE754, 8, Float}, + {"fp10", IEEE754, 8, Float}, {"fp11", IEEE754, 8, Float}, + {"fp12", IEEE754, 8, Float}, {"fp13", IEEE754, 8, Float}, + {"fp14", IEEE754, 8, Float}, {"fp15", IEEE754, 8, Float}, + {"fp16", IEEE754, 8, Float}, {"fp17", IEEE754, 8, Float}, + {"fp18", IEEE754, 8, Float}, {"fp19", IEEE754, 8, Float}, + {"fp20", IEEE754, 8, Float}, {"fp21", IEEE754, 8, Float}, + {"fp22", IEEE754, 8, Float}, {"fp23", IEEE754, 8, Float}, + {"fp24", IEEE754, 8, Float}, {"fp25", IEEE754, 8, Float}, + {"fp26", IEEE754, 8, Float}, {"fp27", IEEE754, 8, Float}, + {"fp28", IEEE754, 8, Float}, {"fp29", IEEE754, 8, Float}, + {"fp30", IEEE754, 8, Float}, {"fp31", IEEE754, 8, Float}, + {"fpscr", Uint, 4, Hex}}; // Exception registers -static DNBRegisterInfo g_exc_registers[] = -{ - { "dar" , Uint, 4, Hex }, - { "dsisr" , Uint, 4, Hex }, - { "exception" , Uint, 4, Hex } -}; +static DNBRegisterInfo g_exc_registers[] = {{"dar", Uint, 4, Hex}, + {"dsisr", Uint, 4, Hex}, + {"exception", Uint, 4, Hex}}; // Altivec registers -static DNBRegisterInfo g_vec_registers[] = -{ - { "vr0" , Vector, 16, VectorOfFloat32 }, - { "vr1" , Vector, 16, VectorOfFloat32 }, - { "vr2" , Vector, 16, VectorOfFloat32 }, - { "vr3" , Vector, 16, VectorOfFloat32 }, - { "vr4" , Vector, 16, VectorOfFloat32 }, - { "vr5" , Vector, 16, VectorOfFloat32 }, - { "vr6" , Vector, 16, VectorOfFloat32 }, - { "vr7" , Vector, 16, VectorOfFloat32 }, - { "vr8" , Vector, 16, VectorOfFloat32 }, - { "vr9" , Vector, 16, VectorOfFloat32 }, - { "vr10" , Vector, 16, VectorOfFloat32 }, - { "vr11" , Vector, 16, VectorOfFloat32 }, - { "vr12" , Vector, 16, VectorOfFloat32 }, - { "vr13" , Vector, 16, VectorOfFloat32 }, - { "vr14" , Vector, 16, VectorOfFloat32 }, - { "vr15" , Vector, 16, VectorOfFloat32 }, - { "vr16" , Vector, 16, VectorOfFloat32 }, - { "vr17" , Vector, 16, VectorOfFloat32 }, - { "vr18" , Vector, 16, VectorOfFloat32 }, - { "vr19" , Vector, 16, VectorOfFloat32 }, - { "vr20" , Vector, 16, VectorOfFloat32 }, - { "vr21" , Vector, 16, VectorOfFloat32 }, - { "vr22" , Vector, 16, VectorOfFloat32 }, - { "vr23" , Vector, 16, VectorOfFloat32 }, - { "vr24" , Vector, 16, VectorOfFloat32 }, - { "vr25" , Vector, 16, VectorOfFloat32 }, - { "vr26" , Vector, 16, VectorOfFloat32 }, - { "vr27" , Vector, 16, VectorOfFloat32 }, - { "vr28" , Vector, 16, VectorOfFloat32 }, - { "vr29" , Vector, 16, VectorOfFloat32 }, - { "vr30" , Vector, 16, VectorOfFloat32 }, - { "vr31" , Vector, 16, VectorOfFloat32 }, - { "vscr" , Uint, 16, Hex }, - { "vrvalid" , Uint, 4, Hex } -}; +static DNBRegisterInfo g_vec_registers[] = { + {"vr0", Vector, 16, VectorOfFloat32}, + {"vr1", Vector, 16, VectorOfFloat32}, + {"vr2", Vector, 16, VectorOfFloat32}, + {"vr3", Vector, 16, VectorOfFloat32}, + {"vr4", Vector, 16, VectorOfFloat32}, + {"vr5", Vector, 16, VectorOfFloat32}, + {"vr6", Vector, 16, VectorOfFloat32}, + {"vr7", Vector, 16, VectorOfFloat32}, + {"vr8", Vector, 16, VectorOfFloat32}, + {"vr9", Vector, 16, VectorOfFloat32}, + {"vr10", Vector, 16, VectorOfFloat32}, + {"vr11", Vector, 16, VectorOfFloat32}, + {"vr12", Vector, 16, VectorOfFloat32}, + {"vr13", Vector, 16, VectorOfFloat32}, + {"vr14", Vector, 16, VectorOfFloat32}, + {"vr15", Vector, 16, VectorOfFloat32}, + {"vr16", Vector, 16, VectorOfFloat32}, + {"vr17", Vector, 16, VectorOfFloat32}, + {"vr18", Vector, 16, VectorOfFloat32}, + {"vr19", Vector, 16, VectorOfFloat32}, + {"vr20", Vector, 16, VectorOfFloat32}, + {"vr21", Vector, 16, VectorOfFloat32}, + {"vr22", Vector, 16, VectorOfFloat32}, + {"vr23", Vector, 16, VectorOfFloat32}, + {"vr24", Vector, 16, VectorOfFloat32}, + {"vr25", Vector, 16, VectorOfFloat32}, + {"vr26", Vector, 16, VectorOfFloat32}, + {"vr27", Vector, 16, VectorOfFloat32}, + {"vr28", Vector, 16, VectorOfFloat32}, + {"vr29", Vector, 16, VectorOfFloat32}, + {"vr30", Vector, 16, VectorOfFloat32}, + {"vr31", Vector, 16, VectorOfFloat32}, + {"vscr", Uint, 16, Hex}, + {"vrvalid", Uint, 4, Hex}}; // Number of registers in each register set -const size_t k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo); -const size_t k_num_fpr_registers = sizeof(g_fpr_registers)/sizeof(DNBRegisterInfo); -const size_t k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo); -const size_t k_num_vec_registers = sizeof(g_vec_registers)/sizeof(DNBRegisterInfo); +const size_t k_num_gpr_registers = + sizeof(g_gpr_registers) / sizeof(DNBRegisterInfo); +const size_t k_num_fpr_registers = + sizeof(g_fpr_registers) / sizeof(DNBRegisterInfo); +const size_t k_num_exc_registers = + sizeof(g_exc_registers) / sizeof(DNBRegisterInfo); +const size_t k_num_vec_registers = + sizeof(g_vec_registers) / sizeof(DNBRegisterInfo); // Total number of registers for this architecture -const size_t k_num_ppc_registers = k_num_gpr_registers + k_num_fpr_registers + k_num_exc_registers + k_num_vec_registers; +const size_t k_num_ppc_registers = k_num_gpr_registers + k_num_fpr_registers + + k_num_exc_registers + k_num_vec_registers; //---------------------------------------------------------------------- // Register set definitions. The first definitions at register set index // of zero is for all registers, followed by other registers sets. The // register information for the all register set need not be filled in. //---------------------------------------------------------------------- -static const DNBRegisterSetInfo g_reg_sets[] = -{ - { "PowerPC Registers", NULL, k_num_ppc_registers }, - { "General Purpose Registers", g_gpr_registers, k_num_gpr_registers }, - { "Floating Point Registers", g_fpr_registers, k_num_fpr_registers }, - { "Exception State Registers", g_exc_registers, k_num_exc_registers }, - { "Altivec Registers", g_vec_registers, k_num_vec_registers } -}; +static const DNBRegisterSetInfo g_reg_sets[] = { + {"PowerPC Registers", NULL, k_num_ppc_registers}, + {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers}, + {"Floating Point Registers", g_fpr_registers, k_num_fpr_registers}, + {"Exception State Registers", g_exc_registers, k_num_exc_registers}, + {"Altivec Registers", g_vec_registers, k_num_vec_registers}}; // Total number of register sets for this architecture -const size_t k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo); - +const size_t k_num_register_sets = + sizeof(g_reg_sets) / sizeof(DNBRegisterSetInfo); const DNBRegisterSetInfo * -DNBArchMachPPC::GetRegisterSetInfo(nub_size_t *num_reg_sets) const -{ - *num_reg_sets = k_num_register_sets; - return g_reg_sets; +DNBArchMachPPC::GetRegisterSetInfo(nub_size_t *num_reg_sets) const { + *num_reg_sets = k_num_register_sets; + return g_reg_sets; } -bool -DNBArchMachPPC::GetRegisterValue(uint32_t set, uint32_t reg, DNBRegisterValue *value) const -{ - if (set == REGISTER_SET_GENERIC) - { - switch (reg) - { - case GENERIC_REGNUM_PC: // Program Counter - set = e_regSetGPR; - reg = e_regNumGPR_srr0; - break; - - case GENERIC_REGNUM_SP: // Stack Pointer - set = e_regSetGPR; - reg = e_regNumGPR_r1; - break; - - case GENERIC_REGNUM_FP: // Frame Pointer - // Return false for now instead of returning r30 as gcc 3.x would - // use a variety of registers for the FP and it takes inspecting - // the stack to make sure there is a frame pointer before we can - // determine the FP. - return false; - - case GENERIC_REGNUM_RA: // Return Address - set = e_regSetGPR; - reg = e_regNumGPR_lr; - break; - - case GENERIC_REGNUM_FLAGS: // Processor flags register - set = e_regSetGPR; - reg = e_regNumGPR_srr1; - break; - - default: - return false; - } +bool DNBArchMachPPC::GetRegisterValue(uint32_t set, uint32_t reg, + DNBRegisterValue *value) const { + if (set == REGISTER_SET_GENERIC) { + switch (reg) { + case GENERIC_REGNUM_PC: // Program Counter + set = e_regSetGPR; + reg = e_regNumGPR_srr0; + break; + + case GENERIC_REGNUM_SP: // Stack Pointer + set = e_regSetGPR; + reg = e_regNumGPR_r1; + break; + + case GENERIC_REGNUM_FP: // Frame Pointer + // Return false for now instead of returning r30 as gcc 3.x would + // use a variety of registers for the FP and it takes inspecting + // the stack to make sure there is a frame pointer before we can + // determine the FP. + return false; + + case GENERIC_REGNUM_RA: // Return Address + set = e_regSetGPR; + reg = e_regNumGPR_lr; + break; + + case GENERIC_REGNUM_FLAGS: // Processor flags register + set = e_regSetGPR; + reg = e_regNumGPR_srr1; + break; + + default: + return false; } + } - if (!m_state.RegsAreValid(set)) - return false; + if (!m_state.RegsAreValid(set)) + return false; - const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); - if (regInfo) - { - value->info = *regInfo; - switch (set) + const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); + if (regInfo) { + value->info = *regInfo; + switch (set) { + case e_regSetGPR: + if (reg < k_num_gpr_registers) { + value->value.uint32 = + (&m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr0))[reg]; + return true; + } + break; + + case e_regSetFPR: + if (reg < 32) { + value->value.float64 = + m_state.fpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(fpregs)[reg]; + return true; + } else if (reg == 32) { + value->value.uint32 = + m_state.fpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(fpscr); + return true; + } + break; + + case e_regSetEXC: + if (reg < k_num_exc_registers) { + value->value.uint32 = + (&m_state.exc.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(dar))[reg]; + return true; + } + break; + + case e_regSetVEC: + if (reg < k_num_vec_registers) { + if (reg < 33) // FP0 - FP31 and VSCR + { + // Copy all 4 uint32 values for this vector register + value->value.v_uint32[0] = + m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg] + [0]; + value->value.v_uint32[1] = + m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg] + [1]; + value->value.v_uint32[2] = + m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg] + [2]; + value->value.v_uint32[3] = + m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg] + [3]; + return true; + } else if (reg == 34) // VRVALID { - case e_regSetGPR: - if (reg < k_num_gpr_registers) - { - value->value.uint32 = (&m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr0))[reg]; - return true; - } - break; - - case e_regSetFPR: - if (reg < 32) - { - value->value.float64 = m_state.fpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(fpregs)[reg]; - return true; - } - else if (reg == 32) - { - value->value.uint32 = m_state.fpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(fpscr); - return true; - } - break; - - case e_regSetEXC: - if (reg < k_num_exc_registers) - { - value->value.uint32 = (&m_state.exc.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(dar))[reg]; - return true; - } - break; - - case e_regSetVEC: - if (reg < k_num_vec_registers) - { - if (reg < 33) // FP0 - FP31 and VSCR - { - // Copy all 4 uint32 values for this vector register - value->value.v_uint32[0] = m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg][0]; - value->value.v_uint32[1] = m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg][1]; - value->value.v_uint32[2] = m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg][2]; - value->value.v_uint32[3] = m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg][3]; - return true; - } - else if (reg == 34) // VRVALID - { - value->value.uint32 = m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vrvalid); - return true; - } - } - break; + value->value.uint32 = + m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vrvalid); + return true; } + } + break; } - return false; + } + return false; } - -kern_return_t -DNBArchMachPPC::GetRegisterState(int set, bool force) -{ - switch (set) - { - case e_regSetALL: - return GetGPRState(force) | - GetFPRState(force) | - GetEXCState(force) | - GetVECState(force); - case e_regSetGPR: return GetGPRState(force); - case e_regSetFPR: return GetFPRState(force); - case e_regSetEXC: return GetEXCState(force); - case e_regSetVEC: return GetVECState(force); - default: break; - } - return KERN_INVALID_ARGUMENT; +kern_return_t DNBArchMachPPC::GetRegisterState(int set, bool force) { + switch (set) { + case e_regSetALL: + return GetGPRState(force) | GetFPRState(force) | GetEXCState(force) | + GetVECState(force); + case e_regSetGPR: + return GetGPRState(force); + case e_regSetFPR: + return GetFPRState(force); + case e_regSetEXC: + return GetEXCState(force); + case e_regSetVEC: + return GetVECState(force); + default: + break; + } + return KERN_INVALID_ARGUMENT; } -kern_return_t -DNBArchMachPPC::SetRegisterState(int set) -{ - // Make sure we have a valid context to set. - kern_return_t err = GetRegisterState(set, false); - if (err != KERN_SUCCESS) - return err; - - switch (set) - { - case e_regSetALL: return SetGPRState() | SetFPRState() | SetEXCState() | SetVECState(); - case e_regSetGPR: return SetGPRState(); - case e_regSetFPR: return SetFPRState(); - case e_regSetEXC: return SetEXCState(); - case e_regSetVEC: return SetVECState(); - default: break; - } - return KERN_INVALID_ARGUMENT; +kern_return_t DNBArchMachPPC::SetRegisterState(int set) { + // Make sure we have a valid context to set. + kern_return_t err = GetRegisterState(set, false); + if (err != KERN_SUCCESS) + return err; + + switch (set) { + case e_regSetALL: + return SetGPRState() | SetFPRState() | SetEXCState() | SetVECState(); + case e_regSetGPR: + return SetGPRState(); + case e_regSetFPR: + return SetFPRState(); + case e_regSetEXC: + return SetEXCState(); + case e_regSetVEC: + return SetVECState(); + default: + break; + } + return KERN_INVALID_ARGUMENT; } -bool -DNBArchMachPPC::RegisterSetStateIsValid (int set) const -{ - return m_state.RegsAreValid(set); +bool DNBArchMachPPC::RegisterSetStateIsValid(int set) const { + return m_state.RegsAreValid(set); } - -#endif // #if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) - +#endif // #if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) diff --git a/lldb/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.h b/lldb/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.h index 8ea81538dc4..8aed9fc0f80 100644 --- a/lldb/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.h +++ b/lldb/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.h @@ -14,166 +14,147 @@ #ifndef __DebugNubArchMachPPC_h__ #define __DebugNubArchMachPPC_h__ -#if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) +#if defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) #include "DNBArch.h" class MachThread; -class DNBArchMachPPC : public DNBArchProtocol -{ +class DNBArchMachPPC : public DNBArchProtocol { public: - DNBArchMachPPC(MachThread *thread) : - m_thread(thread), - m_state() - { - } + DNBArchMachPPC(MachThread *thread) : m_thread(thread), m_state() {} - virtual ~DNBArchMachPPC() - { - } + virtual ~DNBArchMachPPC() {} - virtual const DNBRegisterSetInfo * - GetRegisterSetInfo(nub_size_t *num_reg_sets) const; - virtual bool GetRegisterValue(uint32_t set, uint32_t reg, DNBRegisterValue *value) const; - virtual kern_return_t GetRegisterState (int set, bool force); - virtual kern_return_t SetRegisterState (int set); - virtual bool RegisterSetStateIsValid (int set) const; + virtual const DNBRegisterSetInfo * + GetRegisterSetInfo(nub_size_t *num_reg_sets) const; + virtual bool GetRegisterValue(uint32_t set, uint32_t reg, + DNBRegisterValue *value) const; + virtual kern_return_t GetRegisterState(int set, bool force); + virtual kern_return_t SetRegisterState(int set); + virtual bool RegisterSetStateIsValid(int set) const; - virtual uint64_t GetPC(uint64_t failValue); // Get program counter - virtual kern_return_t SetPC(uint64_t value); - virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer - virtual bool ThreadWillResume(); - virtual bool ThreadDidStop(); + virtual uint64_t GetPC(uint64_t failValue); // Get program counter + virtual kern_return_t SetPC(uint64_t value); + virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer + virtual bool ThreadWillResume(); + virtual bool ThreadDidStop(); - static const uint8_t * SoftwareBreakpointOpcode (nub_size_t byte_size); - static uint32_t GetCPUType(); + static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size); + static uint32_t GetCPUType(); protected: - - - kern_return_t EnableHardwareSingleStep (bool enable); - - typedef enum RegisterSetTag - { - e_regSetALL = REGISTER_SET_ALL, - e_regSetGPR, - e_regSetFPR, - e_regSetEXC, - e_regSetVEC, - kNumRegisterSets - } RegisterSet; - - typedef enum RegisterSetWordSizeTag - { - e_regSetWordSizeGPR = PPC_THREAD_STATE_COUNT, - e_regSetWordSizeFPR = PPC_FLOAT_STATE_COUNT, - e_regSetWordSizeEXC = PPC_EXCEPTION_STATE_COUNT, - e_regSetWordSizeVEC = PPC_VECTOR_STATE_COUNT - } RegisterSetWordSize; - - enum - { - Read = 0, - Write = 1, - kNumErrors = 2 - }; - - struct State - { - ppc_thread_state_t gpr; - ppc_float_state_t fpr; - ppc_exception_state_t exc; - ppc_vector_state_t vec; - kern_return_t gpr_errs[2]; // Read/Write errors - kern_return_t fpr_errs[2]; // Read/Write errors - kern_return_t exc_errs[2]; // Read/Write errors - kern_return_t vec_errs[2]; // Read/Write errors - - State() - { - uint32_t i; - for (i=0; i<kNumErrors; i++) - { - gpr_errs[i] = -1; - fpr_errs[i] = -1; - exc_errs[i] = -1; - vec_errs[i] = -1; - } - } - void InvalidateAllRegisterStates() - { - SetError (e_regSetALL, Read, -1); - } - kern_return_t GetError (int set, uint32_t err_idx) const - { - if (err_idx < kNumErrors) - { - switch (set) - { - // When getting all errors, just OR all values together to see if - // we got any kind of error. - case e_regSetALL: return gpr_errs[err_idx] | fpr_errs[err_idx] | exc_errs[err_idx] | vec_errs[err_idx]; - case e_regSetGPR: return gpr_errs[err_idx]; - case e_regSetFPR: return fpr_errs[err_idx]; - case e_regSetEXC: return exc_errs[err_idx]; - case e_regSetVEC: return vec_errs[err_idx]; - default: break; - } - } - return -1; - } - bool SetError (int set, uint32_t err_idx, kern_return_t err) - { - if (err_idx < kNumErrors) - { - switch (set) - { - case e_regSetALL: - gpr_errs[err_idx] = fpr_errs[err_idx] = exc_errs[err_idx] = vec_errs[err_idx] = err; - return true; - - case e_regSetGPR: - gpr_errs[err_idx] = err; - return true; - - case e_regSetFPR: - fpr_errs[err_idx] = err; - return true; - - case e_regSetEXC: - exc_errs[err_idx] = err; - return true; - - case e_regSetVEC: - vec_errs[err_idx] = err; - return true; - - default: break; - } - } - return false; + kern_return_t EnableHardwareSingleStep(bool enable); + + typedef enum RegisterSetTag { + e_regSetALL = REGISTER_SET_ALL, + e_regSetGPR, + e_regSetFPR, + e_regSetEXC, + e_regSetVEC, + kNumRegisterSets + } RegisterSet; + + typedef enum RegisterSetWordSizeTag { + e_regSetWordSizeGPR = PPC_THREAD_STATE_COUNT, + e_regSetWordSizeFPR = PPC_FLOAT_STATE_COUNT, + e_regSetWordSizeEXC = PPC_EXCEPTION_STATE_COUNT, + e_regSetWordSizeVEC = PPC_VECTOR_STATE_COUNT + } RegisterSetWordSize; + + enum { Read = 0, Write = 1, kNumErrors = 2 }; + + struct State { + ppc_thread_state_t gpr; + ppc_float_state_t fpr; + ppc_exception_state_t exc; + ppc_vector_state_t vec; + kern_return_t gpr_errs[2]; // Read/Write errors + kern_return_t fpr_errs[2]; // Read/Write errors + kern_return_t exc_errs[2]; // Read/Write errors + kern_return_t vec_errs[2]; // Read/Write errors + + State() { + uint32_t i; + for (i = 0; i < kNumErrors; i++) { + gpr_errs[i] = -1; + fpr_errs[i] = -1; + exc_errs[i] = -1; + vec_errs[i] = -1; + } + } + void InvalidateAllRegisterStates() { SetError(e_regSetALL, Read, -1); } + kern_return_t GetError(int set, uint32_t err_idx) const { + if (err_idx < kNumErrors) { + switch (set) { + // When getting all errors, just OR all values together to see if + // we got any kind of error. + case e_regSetALL: + return gpr_errs[err_idx] | fpr_errs[err_idx] | exc_errs[err_idx] | + vec_errs[err_idx]; + case e_regSetGPR: + return gpr_errs[err_idx]; + case e_regSetFPR: + return fpr_errs[err_idx]; + case e_regSetEXC: + return exc_errs[err_idx]; + case e_regSetVEC: + return vec_errs[err_idx]; + default: + break; } - bool RegsAreValid (int set) const - { - return GetError(set, Read) == KERN_SUCCESS; + } + return -1; + } + bool SetError(int set, uint32_t err_idx, kern_return_t err) { + if (err_idx < kNumErrors) { + switch (set) { + case e_regSetALL: + gpr_errs[err_idx] = fpr_errs[err_idx] = exc_errs[err_idx] = + vec_errs[err_idx] = err; + return true; + + case e_regSetGPR: + gpr_errs[err_idx] = err; + return true; + + case e_regSetFPR: + fpr_errs[err_idx] = err; + return true; + + case e_regSetEXC: + exc_errs[err_idx] = err; + return true; + + case e_regSetVEC: + vec_errs[err_idx] = err; + return true; + + default: + break; } - }; + } + return false; + } + bool RegsAreValid(int set) const { + return GetError(set, Read) == KERN_SUCCESS; + } + }; - kern_return_t GetGPRState (bool force); - kern_return_t GetFPRState (bool force); - kern_return_t GetEXCState (bool force); - kern_return_t GetVECState (bool force); + kern_return_t GetGPRState(bool force); + kern_return_t GetFPRState(bool force); + kern_return_t GetEXCState(bool force); + kern_return_t GetVECState(bool force); - kern_return_t SetGPRState (); - kern_return_t SetFPRState (); - kern_return_t SetEXCState (); - kern_return_t SetVECState (); + kern_return_t SetGPRState(); + kern_return_t SetFPRState(); + kern_return_t SetEXCState(); + kern_return_t SetVECState(); protected: - MachThread * m_thread; - State m_state; + MachThread *m_thread; + State m_state; }; -#endif // #if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) -#endif // #ifndef __DebugNubArchMachPPC_h__ +#endif // #if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) +#endif // #ifndef __DebugNubArchMachPPC_h__ diff --git a/lldb/tools/debugserver/source/MacOSX/stack_logging.h b/lldb/tools/debugserver/source/MacOSX/stack_logging.h index 5b0a3080349..5209e38a08e 100644 --- a/lldb/tools/debugserver/source/MacOSX/stack_logging.h +++ b/lldb/tools/debugserver/source/MacOSX/stack_logging.h @@ -2,14 +2,14 @@ * Copyright (c) 1999-2007 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ */ @@ -26,96 +26,132 @@ #import <malloc/malloc.h> -#define stack_logging_type_free 0 -#define stack_logging_type_generic 1 /* anything that is not allocation/deallocation */ -#define stack_logging_type_alloc 2 /* malloc, realloc, etc... */ -#define stack_logging_type_dealloc 4 /* free, realloc, etc... */ +#define stack_logging_type_free 0 +#define stack_logging_type_generic \ + 1 /* anything that is not allocation/deallocation */ +#define stack_logging_type_alloc 2 /* malloc, realloc, etc... */ +#define stack_logging_type_dealloc 4 /* free, realloc, etc... */ // Following flags are absorbed by stack_logging_log_stack() -#define stack_logging_flag_zone 8 /* NSZoneMalloc, etc... */ -#define stack_logging_flag_calloc 16 /* multiply arguments to get the size */ -#define stack_logging_flag_object 32 /* NSAllocateObject(Class, extraBytes, zone) */ -#define stack_logging_flag_cleared 64 /* for NewEmptyHandle */ -#define stack_logging_flag_handle 128 /* for Handle (de-)allocation routines */ -#define stack_logging_flag_set_handle_size 256 /* (Handle, newSize) treated specially */ +#define stack_logging_flag_zone 8 /* NSZoneMalloc, etc... */ +#define stack_logging_flag_calloc 16 /* multiply arguments to get the size */ +#define stack_logging_flag_object \ + 32 /* NSAllocateObject(Class, extraBytes, zone) */ +#define stack_logging_flag_cleared 64 /* for NewEmptyHandle */ +#define stack_logging_flag_handle 128 /* for Handle (de-)allocation routines \ + */ +#define stack_logging_flag_set_handle_size \ + 256 /* (Handle, newSize) treated specially */ /* Macro used to disguise addresses so that leak finding can work */ -#define STACK_LOGGING_DISGUISE(address) ((address) ^ 0x00005555) /* nicely idempotent */ - -extern "C" int stack_logging_enable_logging; /* when clear, no logging takes place */ -extern "C" int stack_logging_dontcompact; /* default is to compact; when set does not compact alloc/free logs; useful for tracing history */ - - -extern "C" void stack_logging_log_stack(unsigned type, unsigned arg1, unsigned arg2, unsigned arg3, unsigned result, unsigned num_hot_to_skip); -/* This is the old log-to-memory logger, which is now deprecated. It remains for compatibility with performance tools that haven't been updated to disk_stack_logging_log_stack() yet. */ - -extern "C" void __disk_stack_logging_log_stack(uint32_t type_flags, uintptr_t zone_ptr, uintptr_t size, uintptr_t ptr_arg, uintptr_t return_val, uint32_t num_hot_to_skip); -/* Fits as the malloc_logger; logs malloc/free/realloc events and can log custom events if called directly */ - +#define STACK_LOGGING_DISGUISE(address) \ + ((address) ^ 0x00005555) /* nicely idempotent */ + +extern "C" int + stack_logging_enable_logging; /* when clear, no logging takes place */ +extern "C" int stack_logging_dontcompact; /* default is to compact; when set + does not compact alloc/free logs; + useful for tracing history */ + +extern "C" void stack_logging_log_stack(unsigned type, unsigned arg1, + unsigned arg2, unsigned arg3, + unsigned result, + unsigned num_hot_to_skip); +/* This is the old log-to-memory logger, which is now deprecated. It remains + * for compatibility with performance tools that haven't been updated to + * disk_stack_logging_log_stack() yet. */ + +extern "C" void +__disk_stack_logging_log_stack(uint32_t type_flags, uintptr_t zone_ptr, + uintptr_t size, uintptr_t ptr_arg, + uintptr_t return_val, uint32_t num_hot_to_skip); +/* Fits as the malloc_logger; logs malloc/free/realloc events and can log custom + * events if called directly */ /* 64-bit-aware stack log access. */ typedef struct { - uint32_t type_flags; - uint64_t stack_identifier; - uint64_t argument; - mach_vm_address_t address; + uint32_t type_flags; + uint64_t stack_identifier; + uint64_t argument; + mach_vm_address_t address; } mach_stack_logging_record_t; -extern "C" kern_return_t __mach_stack_logging_get_frames(task_t task, mach_vm_address_t address, mach_vm_address_t *stack_frames_buffer, uint32_t max_stack_frames, uint32_t *count); +extern "C" kern_return_t +__mach_stack_logging_get_frames(task_t task, mach_vm_address_t address, + mach_vm_address_t *stack_frames_buffer, + uint32_t max_stack_frames, uint32_t *count); /* Gets the last allocation record (malloc, realloc, or free) about address */ -extern "C" kern_return_t __mach_stack_logging_enumerate_records(task_t task, mach_vm_address_t address, void enumerator(mach_stack_logging_record_t, void *), void *context); -/* Applies enumerator to all records involving address sending context as enumerator's second parameter; if !address, applies enumerator to all records */ +extern "C" kern_return_t __mach_stack_logging_enumerate_records( + task_t task, mach_vm_address_t address, + void enumerator(mach_stack_logging_record_t, void *), void *context); +/* Applies enumerator to all records involving address sending context as + * enumerator's second parameter; if !address, applies enumerator to all records + */ -extern "C" kern_return_t __mach_stack_logging_frames_for_uniqued_stack(task_t task, uint64_t stack_identifier, mach_vm_address_t *stack_frames_buffer, uint32_t max_stack_frames, uint32_t *count); +extern "C" kern_return_t __mach_stack_logging_frames_for_uniqued_stack( + task_t task, uint64_t stack_identifier, + mach_vm_address_t *stack_frames_buffer, uint32_t max_stack_frames, + uint32_t *count); /* Given a uniqued_stack fills stack_frames_buffer */ - #pragma mark - #pragma mark Legacy -/* The following is the old 32-bit-only, in-process-memory stack logging. This is deprecated and clients should move to the above 64-bit-aware disk stack logging SPI. */ +/* The following is the old 32-bit-only, in-process-memory stack logging. This + * is deprecated and clients should move to the above 64-bit-aware disk stack + * logging SPI. */ typedef struct { - unsigned type; - unsigned uniqued_stack; - unsigned argument; - unsigned address; /* disguised, to avoid confusing leaks */ + unsigned type; + unsigned uniqued_stack; + unsigned argument; + unsigned address; /* disguised, to avoid confusing leaks */ } stack_logging_record_t; typedef struct { - unsigned overall_num_bytes; - unsigned num_records; - unsigned lock; /* 0 means OK to lock; used for inter-process locking */ - unsigned *uniquing_table; /* allocated using vm_allocate() */ - /* hashtable organized as (PC, uniqued parent) - Only the second half of the table is active - To enable us to grow dynamically */ - unsigned uniquing_table_num_pages; /* number of pages of the table */ - unsigned extra_retain_count; /* not used by stack_logging_log_stack */ - unsigned filler[2]; /* align to cache lines for better performance */ - stack_logging_record_t records[0]; /* records follow here */ + unsigned overall_num_bytes; + unsigned num_records; + unsigned lock; /* 0 means OK to lock; used for inter-process locking */ + unsigned *uniquing_table; /* allocated using vm_allocate() */ + /* hashtable organized as (PC, uniqued parent) + Only the second half of the table is active + To enable us to grow dynamically */ + unsigned uniquing_table_num_pages; /* number of pages of the table */ + unsigned extra_retain_count; /* not used by stack_logging_log_stack */ + unsigned filler[2]; /* align to cache lines for better performance */ + stack_logging_record_t records[0]; /* records follow here */ } stack_logging_record_list_t; extern "C" stack_logging_record_list_t *stack_logging_the_record_list; /* This is the global variable containing all logs */ -extern "C" kern_return_t stack_logging_get_frames(task_t task, memory_reader_t reader, vm_address_t address, vm_address_t *stack_frames_buffer, unsigned max_stack_frames, unsigned *num_frames); +extern "C" kern_return_t +stack_logging_get_frames(task_t task, memory_reader_t reader, + vm_address_t address, + vm_address_t *stack_frames_buffer, + unsigned max_stack_frames, unsigned *num_frames); /* Gets the last record in stack_logging_the_record_list about address */ -#define STACK_LOGGING_ENUMERATION_PROVIDED 1 // temporary to avoid dependencies between projects +#define STACK_LOGGING_ENUMERATION_PROVIDED \ + 1 // temporary to avoid dependencies between projects -extern "C" kern_return_t stack_logging_enumerate_records(task_t task, memory_reader_t reader, vm_address_t address, void enumerator(stack_logging_record_t, void *), void *context); +extern "C" kern_return_t stack_logging_enumerate_records( + task_t task, memory_reader_t reader, vm_address_t address, + void enumerator(stack_logging_record_t, void *), void *context); /* Gets all the records about address; If !address, gets all records */ -extern "C" kern_return_t stack_logging_frames_for_uniqued_stack(task_t task, memory_reader_t reader, unsigned uniqued_stack, vm_address_t *stack_frames_buffer, unsigned max_stack_frames, unsigned *num_frames); +extern "C" kern_return_t stack_logging_frames_for_uniqued_stack( + task_t task, memory_reader_t reader, unsigned uniqued_stack, + vm_address_t *stack_frames_buffer, unsigned max_stack_frames, + unsigned *num_frames); /* Given a uniqued_stack fills stack_frames_buffer */ - - -extern "C" void thread_stack_pcs(vm_address_t *buffer, unsigned max, unsigned *num); -/* Convenience to fill buffer with the PCs of the frames, starting with the hot frames; +extern "C" void thread_stack_pcs(vm_address_t *buffer, unsigned max, + unsigned *num); +/* Convenience to fill buffer with the PCs of the frames, starting with the hot + frames; num: returned number of frames */ diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp index 3d2805cddb9..b8d35fe2f7c 100644 --- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp +++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp @@ -11,54 +11,46 @@ // //===----------------------------------------------------------------------===// -#if defined (__i386__) || defined (__x86_64__) +#if defined(__i386__) || defined(__x86_64__) #include <sys/cdefs.h> -#include <sys/types.h> #include <sys/sysctl.h> +#include <sys/types.h> -#include "MacOSX/x86_64/DNBArchImplX86_64.h" #include "../HasAVX.h" #include "DNBLog.h" -#include "MachThread.h" +#include "MacOSX/x86_64/DNBArchImplX86_64.h" #include "MachProcess.h" +#include "MachThread.h" #include <mach/mach.h> #include <stdlib.h> -#if defined (LLDB_DEBUGSERVER_RELEASE) || defined (LLDB_DEBUGSERVER_DEBUG) -enum debugState { - debugStateUnknown, - debugStateOff, - debugStateOn -}; +#if defined(LLDB_DEBUGSERVER_RELEASE) || defined(LLDB_DEBUGSERVER_DEBUG) +enum debugState { debugStateUnknown, debugStateOff, debugStateOn }; static debugState sFPUDebugState = debugStateUnknown; static debugState sAVXForceState = debugStateUnknown; -static bool DebugFPURegs () -{ - if (sFPUDebugState == debugStateUnknown) - { - if (getenv("DNB_DEBUG_FPU_REGS")) - sFPUDebugState = debugStateOn; - else - sFPUDebugState = debugStateOff; - } - - return (sFPUDebugState == debugStateOn); +static bool DebugFPURegs() { + if (sFPUDebugState == debugStateUnknown) { + if (getenv("DNB_DEBUG_FPU_REGS")) + sFPUDebugState = debugStateOn; + else + sFPUDebugState = debugStateOff; + } + + return (sFPUDebugState == debugStateOn); } -static bool ForceAVXRegs () -{ - if (sFPUDebugState == debugStateUnknown) - { - if (getenv("DNB_DEBUG_X86_FORCE_AVX_REGS")) - sAVXForceState = debugStateOn; - else - sAVXForceState = debugStateOff; - } - - return (sAVXForceState == debugStateOn); +static bool ForceAVXRegs() { + if (sFPUDebugState == debugStateUnknown) { + if (getenv("DNB_DEBUG_X86_FORCE_AVX_REGS")) + sAVXForceState = debugStateOn; + else + sAVXForceState = debugStateOff; + } + + return (sAVXForceState == debugStateOn); } #define DEBUG_FPU_REGS (DebugFPURegs()) @@ -68,2222 +60,2501 @@ static bool ForceAVXRegs () #define FORCE_AVX_REGS (0) #endif - -extern "C" bool -CPUHasAVX() -{ - enum AVXPresence - { - eAVXUnknown = -1, - eAVXNotPresent = 0, - eAVXPresent = 1 - }; - - static AVXPresence g_has_avx = eAVXUnknown; - if (g_has_avx == eAVXUnknown) - { - g_has_avx = eAVXNotPresent; - - // Only xnu-2020 or later has AVX support, any versions before - // this have a busted thread_get_state RPC where it would truncate - // the thread state buffer (<rdar://problem/10122874>). So we need to - // verify the kernel version number manually or disable AVX support. - int mib[2]; - char buffer[1024]; - size_t length = sizeof(buffer); - uint64_t xnu_version = 0; - mib[0] = CTL_KERN; - mib[1] = KERN_VERSION; - int err = ::sysctl(mib, 2, &buffer, &length, NULL, 0); - if (err == 0) - { - const char *xnu = strstr (buffer, "xnu-"); - if (xnu) - { - const char *xnu_version_cstr = xnu + 4; - xnu_version = strtoull (xnu_version_cstr, NULL, 0); - if (xnu_version >= 2020 && xnu_version != ULLONG_MAX) - { - if (::HasAVX()) - { - g_has_avx = eAVXPresent; - } - } - } +extern "C" bool CPUHasAVX() { + enum AVXPresence { eAVXUnknown = -1, eAVXNotPresent = 0, eAVXPresent = 1 }; + + static AVXPresence g_has_avx = eAVXUnknown; + if (g_has_avx == eAVXUnknown) { + g_has_avx = eAVXNotPresent; + + // Only xnu-2020 or later has AVX support, any versions before + // this have a busted thread_get_state RPC where it would truncate + // the thread state buffer (<rdar://problem/10122874>). So we need to + // verify the kernel version number manually or disable AVX support. + int mib[2]; + char buffer[1024]; + size_t length = sizeof(buffer); + uint64_t xnu_version = 0; + mib[0] = CTL_KERN; + mib[1] = KERN_VERSION; + int err = ::sysctl(mib, 2, &buffer, &length, NULL, 0); + if (err == 0) { + const char *xnu = strstr(buffer, "xnu-"); + if (xnu) { + const char *xnu_version_cstr = xnu + 4; + xnu_version = strtoull(xnu_version_cstr, NULL, 0); + if (xnu_version >= 2020 && xnu_version != ULLONG_MAX) { + if (::HasAVX()) { + g_has_avx = eAVXPresent; + } } - DNBLogThreadedIf (LOG_THREAD, "CPUHasAVX(): g_has_avx = %i (err = %i, errno = %i, xnu_version = %llu)", g_has_avx, err, errno, xnu_version); + } } - - return (g_has_avx == eAVXPresent); + DNBLogThreadedIf(LOG_THREAD, "CPUHasAVX(): g_has_avx = %i (err = %i, errno " + "= %i, xnu_version = %llu)", + g_has_avx, err, errno, xnu_version); + } + + return (g_has_avx == eAVXPresent); } -uint64_t -DNBArchImplX86_64::GetPC(uint64_t failValue) -{ - // Get program counter - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.context.gpr.__rip; - return failValue; +uint64_t DNBArchImplX86_64::GetPC(uint64_t failValue) { + // Get program counter + if (GetGPRState(false) == KERN_SUCCESS) + return m_state.context.gpr.__rip; + return failValue; } -kern_return_t -DNBArchImplX86_64::SetPC(uint64_t value) -{ - // Get program counter - kern_return_t err = GetGPRState(false); - if (err == KERN_SUCCESS) - { - m_state.context.gpr.__rip = value; - err = SetGPRState(); - } - return err == KERN_SUCCESS; +kern_return_t DNBArchImplX86_64::SetPC(uint64_t value) { + // Get program counter + kern_return_t err = GetGPRState(false); + if (err == KERN_SUCCESS) { + m_state.context.gpr.__rip = value; + err = SetGPRState(); + } + return err == KERN_SUCCESS; } -uint64_t -DNBArchImplX86_64::GetSP(uint64_t failValue) -{ - // Get stack pointer - if (GetGPRState(false) == KERN_SUCCESS) - return m_state.context.gpr.__rsp; - return failValue; +uint64_t DNBArchImplX86_64::GetSP(uint64_t failValue) { + // Get stack pointer + if (GetGPRState(false) == KERN_SUCCESS) + return m_state.context.gpr.__rsp; + return failValue; } // Uncomment the value below to verify the values in the debugger. //#define DEBUG_GPR_VALUES 1 // DO NOT CHECK IN WITH THIS DEFINE ENABLED -kern_return_t -DNBArchImplX86_64::GetGPRState(bool force) -{ - if (force || m_state.GetError(e_regSetGPR, Read)) - { +kern_return_t DNBArchImplX86_64::GetGPRState(bool force) { + if (force || m_state.GetError(e_regSetGPR, Read)) { #if DEBUG_GPR_VALUES - m_state.context.gpr.__rax = ('a' << 8) + 'x'; - m_state.context.gpr.__rbx = ('b' << 8) + 'x'; - m_state.context.gpr.__rcx = ('c' << 8) + 'x'; - m_state.context.gpr.__rdx = ('d' << 8) + 'x'; - m_state.context.gpr.__rdi = ('d' << 8) + 'i'; - m_state.context.gpr.__rsi = ('s' << 8) + 'i'; - m_state.context.gpr.__rbp = ('b' << 8) + 'p'; - m_state.context.gpr.__rsp = ('s' << 8) + 'p'; - m_state.context.gpr.__r8 = ('r' << 8) + '8'; - m_state.context.gpr.__r9 = ('r' << 8) + '9'; - m_state.context.gpr.__r10 = ('r' << 8) + 'a'; - m_state.context.gpr.__r11 = ('r' << 8) + 'b'; - m_state.context.gpr.__r12 = ('r' << 8) + 'c'; - m_state.context.gpr.__r13 = ('r' << 8) + 'd'; - m_state.context.gpr.__r14 = ('r' << 8) + 'e'; - m_state.context.gpr.__r15 = ('r' << 8) + 'f'; - m_state.context.gpr.__rip = ('i' << 8) + 'p'; - m_state.context.gpr.__rflags = ('f' << 8) + 'l'; - m_state.context.gpr.__cs = ('c' << 8) + 's'; - m_state.context.gpr.__fs = ('f' << 8) + 's'; - m_state.context.gpr.__gs = ('g' << 8) + 's'; - m_state.SetError(e_regSetGPR, Read, 0); + m_state.context.gpr.__rax = ('a' << 8) + 'x'; + m_state.context.gpr.__rbx = ('b' << 8) + 'x'; + m_state.context.gpr.__rcx = ('c' << 8) + 'x'; + m_state.context.gpr.__rdx = ('d' << 8) + 'x'; + m_state.context.gpr.__rdi = ('d' << 8) + 'i'; + m_state.context.gpr.__rsi = ('s' << 8) + 'i'; + m_state.context.gpr.__rbp = ('b' << 8) + 'p'; + m_state.context.gpr.__rsp = ('s' << 8) + 'p'; + m_state.context.gpr.__r8 = ('r' << 8) + '8'; + m_state.context.gpr.__r9 = ('r' << 8) + '9'; + m_state.context.gpr.__r10 = ('r' << 8) + 'a'; + m_state.context.gpr.__r11 = ('r' << 8) + 'b'; + m_state.context.gpr.__r12 = ('r' << 8) + 'c'; + m_state.context.gpr.__r13 = ('r' << 8) + 'd'; + m_state.context.gpr.__r14 = ('r' << 8) + 'e'; + m_state.context.gpr.__r15 = ('r' << 8) + 'f'; + m_state.context.gpr.__rip = ('i' << 8) + 'p'; + m_state.context.gpr.__rflags = ('f' << 8) + 'l'; + m_state.context.gpr.__cs = ('c' << 8) + 's'; + m_state.context.gpr.__fs = ('f' << 8) + 's'; + m_state.context.gpr.__gs = ('g' << 8) + 's'; + m_state.SetError(e_regSetGPR, Read, 0); #else - mach_msg_type_number_t count = e_regSetWordSizeGPR; - m_state.SetError(e_regSetGPR, Read, ::thread_get_state(m_thread->MachPortNumber(), __x86_64_THREAD_STATE, (thread_state_t)&m_state.context.gpr, &count)); - DNBLogThreadedIf (LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x" - "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx" - "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx" - "\n\t r8 = %16.16llx r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx" - "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx" - "\n\trip = %16.16llx" - "\n\tflg = %16.16llx cs = %16.16llx fs = %16.16llx gs = %16.16llx", - m_thread->MachPortNumber(), x86_THREAD_STATE64, x86_THREAD_STATE64_COUNT, - m_state.GetError(e_regSetGPR, Read), - m_state.context.gpr.__rax,m_state.context.gpr.__rbx,m_state.context.gpr.__rcx, - m_state.context.gpr.__rdx,m_state.context.gpr.__rdi,m_state.context.gpr.__rsi, - m_state.context.gpr.__rbp,m_state.context.gpr.__rsp,m_state.context.gpr.__r8, - m_state.context.gpr.__r9, m_state.context.gpr.__r10,m_state.context.gpr.__r11, - m_state.context.gpr.__r12,m_state.context.gpr.__r13,m_state.context.gpr.__r14, - m_state.context.gpr.__r15,m_state.context.gpr.__rip,m_state.context.gpr.__rflags, - m_state.context.gpr.__cs,m_state.context.gpr.__fs, m_state.context.gpr.__gs); - - // DNBLogThreadedIf (LOG_THREAD, "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x" - // "\n\trax = %16.16llx" - // "\n\trbx = %16.16llx" - // "\n\trcx = %16.16llx" - // "\n\trdx = %16.16llx" - // "\n\trdi = %16.16llx" - // "\n\trsi = %16.16llx" - // "\n\trbp = %16.16llx" - // "\n\trsp = %16.16llx" - // "\n\t r8 = %16.16llx" - // "\n\t r9 = %16.16llx" - // "\n\tr10 = %16.16llx" - // "\n\tr11 = %16.16llx" - // "\n\tr12 = %16.16llx" - // "\n\tr13 = %16.16llx" - // "\n\tr14 = %16.16llx" - // "\n\tr15 = %16.16llx" - // "\n\trip = %16.16llx" - // "\n\tflg = %16.16llx" - // "\n\t cs = %16.16llx" - // "\n\t fs = %16.16llx" - // "\n\t gs = %16.16llx", - // m_thread->MachPortNumber(), - // x86_THREAD_STATE64, - // x86_THREAD_STATE64_COUNT, - // m_state.GetError(e_regSetGPR, Read), - // m_state.context.gpr.__rax, - // m_state.context.gpr.__rbx, - // m_state.context.gpr.__rcx, - // m_state.context.gpr.__rdx, - // m_state.context.gpr.__rdi, - // m_state.context.gpr.__rsi, - // m_state.context.gpr.__rbp, - // m_state.context.gpr.__rsp, - // m_state.context.gpr.__r8, - // m_state.context.gpr.__r9, - // m_state.context.gpr.__r10, - // m_state.context.gpr.__r11, - // m_state.context.gpr.__r12, - // m_state.context.gpr.__r13, - // m_state.context.gpr.__r14, - // m_state.context.gpr.__r15, - // m_state.context.gpr.__rip, - // m_state.context.gpr.__rflags, - // m_state.context.gpr.__cs, - // m_state.context.gpr.__fs, - // m_state.context.gpr.__gs); + mach_msg_type_number_t count = e_regSetWordSizeGPR; + m_state.SetError( + e_regSetGPR, Read, + ::thread_get_state(m_thread->MachPortNumber(), __x86_64_THREAD_STATE, + (thread_state_t)&m_state.context.gpr, &count)); + DNBLogThreadedIf( + LOG_THREAD, + "::thread_get_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x" + "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx" + "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx" + "\n\t r8 = %16.16llx r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx" + "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx" + "\n\trip = %16.16llx" + "\n\tflg = %16.16llx cs = %16.16llx fs = %16.16llx gs = %16.16llx", + m_thread->MachPortNumber(), x86_THREAD_STATE64, + x86_THREAD_STATE64_COUNT, m_state.GetError(e_regSetGPR, Read), + m_state.context.gpr.__rax, m_state.context.gpr.__rbx, + m_state.context.gpr.__rcx, m_state.context.gpr.__rdx, + m_state.context.gpr.__rdi, m_state.context.gpr.__rsi, + m_state.context.gpr.__rbp, m_state.context.gpr.__rsp, + m_state.context.gpr.__r8, m_state.context.gpr.__r9, + m_state.context.gpr.__r10, m_state.context.gpr.__r11, + m_state.context.gpr.__r12, m_state.context.gpr.__r13, + m_state.context.gpr.__r14, m_state.context.gpr.__r15, + m_state.context.gpr.__rip, m_state.context.gpr.__rflags, + m_state.context.gpr.__cs, m_state.context.gpr.__fs, + m_state.context.gpr.__gs); + +// DNBLogThreadedIf (LOG_THREAD, "thread_get_state(0x%4.4x, %u, &gpr, %u) +// => 0x%8.8x" +// "\n\trax = %16.16llx" +// "\n\trbx = %16.16llx" +// "\n\trcx = %16.16llx" +// "\n\trdx = %16.16llx" +// "\n\trdi = %16.16llx" +// "\n\trsi = %16.16llx" +// "\n\trbp = %16.16llx" +// "\n\trsp = %16.16llx" +// "\n\t r8 = %16.16llx" +// "\n\t r9 = %16.16llx" +// "\n\tr10 = %16.16llx" +// "\n\tr11 = %16.16llx" +// "\n\tr12 = %16.16llx" +// "\n\tr13 = %16.16llx" +// "\n\tr14 = %16.16llx" +// "\n\tr15 = %16.16llx" +// "\n\trip = %16.16llx" +// "\n\tflg = %16.16llx" +// "\n\t cs = %16.16llx" +// "\n\t fs = %16.16llx" +// "\n\t gs = %16.16llx", +// m_thread->MachPortNumber(), +// x86_THREAD_STATE64, +// x86_THREAD_STATE64_COUNT, +// m_state.GetError(e_regSetGPR, Read), +// m_state.context.gpr.__rax, +// m_state.context.gpr.__rbx, +// m_state.context.gpr.__rcx, +// m_state.context.gpr.__rdx, +// m_state.context.gpr.__rdi, +// m_state.context.gpr.__rsi, +// m_state.context.gpr.__rbp, +// m_state.context.gpr.__rsp, +// m_state.context.gpr.__r8, +// m_state.context.gpr.__r9, +// m_state.context.gpr.__r10, +// m_state.context.gpr.__r11, +// m_state.context.gpr.__r12, +// m_state.context.gpr.__r13, +// m_state.context.gpr.__r14, +// m_state.context.gpr.__r15, +// m_state.context.gpr.__rip, +// m_state.context.gpr.__rflags, +// m_state.context.gpr.__cs, +// m_state.context.gpr.__fs, +// m_state.context.gpr.__gs); #endif - } - return m_state.GetError(e_regSetGPR, Read); + } + return m_state.GetError(e_regSetGPR, Read); } // Uncomment the value below to verify the values in the debugger. //#define DEBUG_FPU_REGS 1 // DO NOT CHECK IN WITH THIS DEFINE ENABLED -kern_return_t -DNBArchImplX86_64::GetFPUState(bool force) -{ - if (force || m_state.GetError(e_regSetFPU, Read)) - { - if (DEBUG_FPU_REGS) { - if (CPUHasAVX() || FORCE_AVX_REGS) - { - m_state.context.fpu.avx.__fpu_reserved[0] = -1; - m_state.context.fpu.avx.__fpu_reserved[1] = -1; - *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fcw) = 0x1234; - *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fsw) = 0x5678; - m_state.context.fpu.avx.__fpu_ftw = 1; - m_state.context.fpu.avx.__fpu_rsrv1 = UINT8_MAX; - m_state.context.fpu.avx.__fpu_fop = 2; - m_state.context.fpu.avx.__fpu_ip = 3; - m_state.context.fpu.avx.__fpu_cs = 4; - m_state.context.fpu.avx.__fpu_rsrv2 = UINT8_MAX; - m_state.context.fpu.avx.__fpu_dp = 5; - m_state.context.fpu.avx.__fpu_ds = 6; - m_state.context.fpu.avx.__fpu_rsrv3 = UINT16_MAX; - m_state.context.fpu.avx.__fpu_mxcsr = 8; - m_state.context.fpu.avx.__fpu_mxcsrmask = 9; - int i; - for (i=0; i<16; ++i) - { - if (i<10) - { - m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = 'a'; - m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = 'b'; - m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = 'c'; - m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = 'd'; - m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = 'e'; - m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = 'f'; - m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = 'g'; - m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = 'h'; - } - else - { - m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN; - } - - m_state.context.fpu.avx.__fpu_xmm0.__xmm_reg[i] = '0' + 2 * i; - m_state.context.fpu.avx.__fpu_xmm1.__xmm_reg[i] = '1' + 2 * i; - m_state.context.fpu.avx.__fpu_xmm2.__xmm_reg[i] = '2' + 2 * i; - m_state.context.fpu.avx.__fpu_xmm3.__xmm_reg[i] = '3' + 2 * i; - m_state.context.fpu.avx.__fpu_xmm4.__xmm_reg[i] = '4' + 2 * i; - m_state.context.fpu.avx.__fpu_xmm5.__xmm_reg[i] = '5' + 2 * i; - m_state.context.fpu.avx.__fpu_xmm6.__xmm_reg[i] = '6' + 2 * i; - m_state.context.fpu.avx.__fpu_xmm7.__xmm_reg[i] = '7' + 2 * i; - m_state.context.fpu.avx.__fpu_xmm8.__xmm_reg[i] = '8' + 2 * i; - m_state.context.fpu.avx.__fpu_xmm9.__xmm_reg[i] = '9' + 2 * i; - m_state.context.fpu.avx.__fpu_xmm10.__xmm_reg[i] = 'A' + 2 * i; - m_state.context.fpu.avx.__fpu_xmm11.__xmm_reg[i] = 'B' + 2 * i; - m_state.context.fpu.avx.__fpu_xmm12.__xmm_reg[i] = 'C' + 2 * i; - m_state.context.fpu.avx.__fpu_xmm13.__xmm_reg[i] = 'D' + 2 * i; - m_state.context.fpu.avx.__fpu_xmm14.__xmm_reg[i] = 'E' + 2 * i; - m_state.context.fpu.avx.__fpu_xmm15.__xmm_reg[i] = 'F' + 2 * i; - - m_state.context.fpu.avx.__fpu_ymmh0.__xmm_reg[i] = '0' + i; - m_state.context.fpu.avx.__fpu_ymmh1.__xmm_reg[i] = '1' + i; - m_state.context.fpu.avx.__fpu_ymmh2.__xmm_reg[i] = '2' + i; - m_state.context.fpu.avx.__fpu_ymmh3.__xmm_reg[i] = '3' + i; - m_state.context.fpu.avx.__fpu_ymmh4.__xmm_reg[i] = '4' + i; - m_state.context.fpu.avx.__fpu_ymmh5.__xmm_reg[i] = '5' + i; - m_state.context.fpu.avx.__fpu_ymmh6.__xmm_reg[i] = '6' + i; - m_state.context.fpu.avx.__fpu_ymmh7.__xmm_reg[i] = '7' + i; - m_state.context.fpu.avx.__fpu_ymmh8.__xmm_reg[i] = '8' + i; - m_state.context.fpu.avx.__fpu_ymmh9.__xmm_reg[i] = '9' + i; - m_state.context.fpu.avx.__fpu_ymmh10.__xmm_reg[i] = 'A' + i; - m_state.context.fpu.avx.__fpu_ymmh11.__xmm_reg[i] = 'B' + i; - m_state.context.fpu.avx.__fpu_ymmh12.__xmm_reg[i] = 'C' + i; - m_state.context.fpu.avx.__fpu_ymmh13.__xmm_reg[i] = 'D' + i; - m_state.context.fpu.avx.__fpu_ymmh14.__xmm_reg[i] = 'E' + i; - m_state.context.fpu.avx.__fpu_ymmh15.__xmm_reg[i] = 'F' + i; - } - for (i=0; i<sizeof(m_state.context.fpu.avx.__fpu_rsrv4); ++i) - m_state.context.fpu.avx.__fpu_rsrv4[i] = INT8_MIN; - m_state.context.fpu.avx.__fpu_reserved1 = -1; - for (i=0; i<sizeof(m_state.context.fpu.avx.__avx_reserved1); ++i) - m_state.context.fpu.avx.__avx_reserved1[i] = INT8_MIN; - m_state.SetError(e_regSetFPU, Read, 0); - } - else - { - m_state.context.fpu.no_avx.__fpu_reserved[0] = -1; - m_state.context.fpu.no_avx.__fpu_reserved[1] = -1; - *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fcw) = 0x1234; - *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fsw) = 0x5678; - m_state.context.fpu.no_avx.__fpu_ftw = 1; - m_state.context.fpu.no_avx.__fpu_rsrv1 = UINT8_MAX; - m_state.context.fpu.no_avx.__fpu_fop = 2; - m_state.context.fpu.no_avx.__fpu_ip = 3; - m_state.context.fpu.no_avx.__fpu_cs = 4; - m_state.context.fpu.no_avx.__fpu_rsrv2 = 5; - m_state.context.fpu.no_avx.__fpu_dp = 6; - m_state.context.fpu.no_avx.__fpu_ds = 7; - m_state.context.fpu.no_avx.__fpu_rsrv3 = UINT16_MAX; - m_state.context.fpu.no_avx.__fpu_mxcsr = 8; - m_state.context.fpu.no_avx.__fpu_mxcsrmask = 9; - int i; - for (i=0; i<16; ++i) - { - if (i<10) - { - m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = 'a'; - m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = 'b'; - m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = 'c'; - m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = 'd'; - m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = 'e'; - m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = 'f'; - m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = 'g'; - m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = 'h'; - } - else - { - m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN; - } - - m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg[i] = '0'; - m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg[i] = '1'; - m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg[i] = '2'; - m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg[i] = '3'; - m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg[i] = '4'; - m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg[i] = '5'; - m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg[i] = '6'; - m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg[i] = '7'; - m_state.context.fpu.no_avx.__fpu_xmm8.__xmm_reg[i] = '8'; - m_state.context.fpu.no_avx.__fpu_xmm9.__xmm_reg[i] = '9'; - m_state.context.fpu.no_avx.__fpu_xmm10.__xmm_reg[i] = 'A'; - m_state.context.fpu.no_avx.__fpu_xmm11.__xmm_reg[i] = 'B'; - m_state.context.fpu.no_avx.__fpu_xmm12.__xmm_reg[i] = 'C'; - m_state.context.fpu.no_avx.__fpu_xmm13.__xmm_reg[i] = 'D'; - m_state.context.fpu.no_avx.__fpu_xmm14.__xmm_reg[i] = 'E'; - m_state.context.fpu.no_avx.__fpu_xmm15.__xmm_reg[i] = 'F'; - } - for (i=0; i<sizeof(m_state.context.fpu.no_avx.__fpu_rsrv4); ++i) - m_state.context.fpu.no_avx.__fpu_rsrv4[i] = INT8_MIN; - m_state.context.fpu.no_avx.__fpu_reserved1 = -1; - m_state.SetError(e_regSetFPU, Read, 0); - } +kern_return_t DNBArchImplX86_64::GetFPUState(bool force) { + if (force || m_state.GetError(e_regSetFPU, Read)) { + if (DEBUG_FPU_REGS) { + if (CPUHasAVX() || FORCE_AVX_REGS) { + m_state.context.fpu.avx.__fpu_reserved[0] = -1; + m_state.context.fpu.avx.__fpu_reserved[1] = -1; + *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fcw) = 0x1234; + *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fsw) = 0x5678; + m_state.context.fpu.avx.__fpu_ftw = 1; + m_state.context.fpu.avx.__fpu_rsrv1 = UINT8_MAX; + m_state.context.fpu.avx.__fpu_fop = 2; + m_state.context.fpu.avx.__fpu_ip = 3; + m_state.context.fpu.avx.__fpu_cs = 4; + m_state.context.fpu.avx.__fpu_rsrv2 = UINT8_MAX; + m_state.context.fpu.avx.__fpu_dp = 5; + m_state.context.fpu.avx.__fpu_ds = 6; + m_state.context.fpu.avx.__fpu_rsrv3 = UINT16_MAX; + m_state.context.fpu.avx.__fpu_mxcsr = 8; + m_state.context.fpu.avx.__fpu_mxcsrmask = 9; + int i; + for (i = 0; i < 16; ++i) { + if (i < 10) { + m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = 'a'; + m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = 'b'; + m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = 'c'; + m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = 'd'; + m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = 'e'; + m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = 'f'; + m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = 'g'; + m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = 'h'; + } else { + m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN; + } + + m_state.context.fpu.avx.__fpu_xmm0.__xmm_reg[i] = '0' + 2 * i; + m_state.context.fpu.avx.__fpu_xmm1.__xmm_reg[i] = '1' + 2 * i; + m_state.context.fpu.avx.__fpu_xmm2.__xmm_reg[i] = '2' + 2 * i; + m_state.context.fpu.avx.__fpu_xmm3.__xmm_reg[i] = '3' + 2 * i; + m_state.context.fpu.avx.__fpu_xmm4.__xmm_reg[i] = '4' + 2 * i; + m_state.context.fpu.avx.__fpu_xmm5.__xmm_reg[i] = '5' + 2 * i; + m_state.context.fpu.avx.__fpu_xmm6.__xmm_reg[i] = '6' + 2 * i; + m_state.context.fpu.avx.__fpu_xmm7.__xmm_reg[i] = '7' + 2 * i; + m_state.context.fpu.avx.__fpu_xmm8.__xmm_reg[i] = '8' + 2 * i; + m_state.context.fpu.avx.__fpu_xmm9.__xmm_reg[i] = '9' + 2 * i; + m_state.context.fpu.avx.__fpu_xmm10.__xmm_reg[i] = 'A' + 2 * i; + m_state.context.fpu.avx.__fpu_xmm11.__xmm_reg[i] = 'B' + 2 * i; + m_state.context.fpu.avx.__fpu_xmm12.__xmm_reg[i] = 'C' + 2 * i; + m_state.context.fpu.avx.__fpu_xmm13.__xmm_reg[i] = 'D' + 2 * i; + m_state.context.fpu.avx.__fpu_xmm14.__xmm_reg[i] = 'E' + 2 * i; + m_state.context.fpu.avx.__fpu_xmm15.__xmm_reg[i] = 'F' + 2 * i; + + m_state.context.fpu.avx.__fpu_ymmh0.__xmm_reg[i] = '0' + i; + m_state.context.fpu.avx.__fpu_ymmh1.__xmm_reg[i] = '1' + i; + m_state.context.fpu.avx.__fpu_ymmh2.__xmm_reg[i] = '2' + i; + m_state.context.fpu.avx.__fpu_ymmh3.__xmm_reg[i] = '3' + i; + m_state.context.fpu.avx.__fpu_ymmh4.__xmm_reg[i] = '4' + i; + m_state.context.fpu.avx.__fpu_ymmh5.__xmm_reg[i] = '5' + i; + m_state.context.fpu.avx.__fpu_ymmh6.__xmm_reg[i] = '6' + i; + m_state.context.fpu.avx.__fpu_ymmh7.__xmm_reg[i] = '7' + i; + m_state.context.fpu.avx.__fpu_ymmh8.__xmm_reg[i] = '8' + i; + m_state.context.fpu.avx.__fpu_ymmh9.__xmm_reg[i] = '9' + i; + m_state.context.fpu.avx.__fpu_ymmh10.__xmm_reg[i] = 'A' + i; + m_state.context.fpu.avx.__fpu_ymmh11.__xmm_reg[i] = 'B' + i; + m_state.context.fpu.avx.__fpu_ymmh12.__xmm_reg[i] = 'C' + i; + m_state.context.fpu.avx.__fpu_ymmh13.__xmm_reg[i] = 'D' + i; + m_state.context.fpu.avx.__fpu_ymmh14.__xmm_reg[i] = 'E' + i; + m_state.context.fpu.avx.__fpu_ymmh15.__xmm_reg[i] = 'F' + i; + } + for (i = 0; i < sizeof(m_state.context.fpu.avx.__fpu_rsrv4); ++i) + m_state.context.fpu.avx.__fpu_rsrv4[i] = INT8_MIN; + m_state.context.fpu.avx.__fpu_reserved1 = -1; + for (i = 0; i < sizeof(m_state.context.fpu.avx.__avx_reserved1); ++i) + m_state.context.fpu.avx.__avx_reserved1[i] = INT8_MIN; + m_state.SetError(e_regSetFPU, Read, 0); + } else { + m_state.context.fpu.no_avx.__fpu_reserved[0] = -1; + m_state.context.fpu.no_avx.__fpu_reserved[1] = -1; + *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fcw) = 0x1234; + *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fsw) = 0x5678; + m_state.context.fpu.no_avx.__fpu_ftw = 1; + m_state.context.fpu.no_avx.__fpu_rsrv1 = UINT8_MAX; + m_state.context.fpu.no_avx.__fpu_fop = 2; + m_state.context.fpu.no_avx.__fpu_ip = 3; + m_state.context.fpu.no_avx.__fpu_cs = 4; + m_state.context.fpu.no_avx.__fpu_rsrv2 = 5; + m_state.context.fpu.no_avx.__fpu_dp = 6; + m_state.context.fpu.no_avx.__fpu_ds = 7; + m_state.context.fpu.no_avx.__fpu_rsrv3 = UINT16_MAX; + m_state.context.fpu.no_avx.__fpu_mxcsr = 8; + m_state.context.fpu.no_avx.__fpu_mxcsrmask = 9; + int i; + for (i = 0; i < 16; ++i) { + if (i < 10) { + m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = 'a'; + m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = 'b'; + m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = 'c'; + m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = 'd'; + m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = 'e'; + m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = 'f'; + m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = 'g'; + m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = 'h'; + } else { + m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN; + m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN; + } + + m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg[i] = '0'; + m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg[i] = '1'; + m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg[i] = '2'; + m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg[i] = '3'; + m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg[i] = '4'; + m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg[i] = '5'; + m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg[i] = '6'; + m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg[i] = '7'; + m_state.context.fpu.no_avx.__fpu_xmm8.__xmm_reg[i] = '8'; + m_state.context.fpu.no_avx.__fpu_xmm9.__xmm_reg[i] = '9'; + m_state.context.fpu.no_avx.__fpu_xmm10.__xmm_reg[i] = 'A'; + m_state.context.fpu.no_avx.__fpu_xmm11.__xmm_reg[i] = 'B'; + m_state.context.fpu.no_avx.__fpu_xmm12.__xmm_reg[i] = 'C'; + m_state.context.fpu.no_avx.__fpu_xmm13.__xmm_reg[i] = 'D'; + m_state.context.fpu.no_avx.__fpu_xmm14.__xmm_reg[i] = 'E'; + m_state.context.fpu.no_avx.__fpu_xmm15.__xmm_reg[i] = 'F'; } - else - { - if (CPUHasAVX() || FORCE_AVX_REGS) - { - mach_msg_type_number_t count = e_regSetWordSizeAVX; - m_state.SetError(e_regSetFPU, Read, ::thread_get_state(m_thread->MachPortNumber(), __x86_64_AVX_STATE, (thread_state_t)&m_state.context.fpu.avx, &count)); - DNBLogThreadedIf (LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &avx, %u (%u passed in) carp) => 0x%8.8x", - m_thread->MachPortNumber(), __x86_64_AVX_STATE, (uint32_t)count, - e_regSetWordSizeAVX, m_state.GetError(e_regSetFPU, Read)); - } - else - { - mach_msg_type_number_t count = e_regSetWordSizeFPU; - m_state.SetError(e_regSetFPU, Read, ::thread_get_state(m_thread->MachPortNumber(), __x86_64_FLOAT_STATE, (thread_state_t)&m_state.context.fpu.no_avx, &count)); - DNBLogThreadedIf (LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &fpu, %u (%u passed in) => 0x%8.8x", - m_thread->MachPortNumber(), __x86_64_FLOAT_STATE, (uint32_t)count, - e_regSetWordSizeFPU, m_state.GetError(e_regSetFPU, Read)); - } - } + for (i = 0; i < sizeof(m_state.context.fpu.no_avx.__fpu_rsrv4); ++i) + m_state.context.fpu.no_avx.__fpu_rsrv4[i] = INT8_MIN; + m_state.context.fpu.no_avx.__fpu_reserved1 = -1; + m_state.SetError(e_regSetFPU, Read, 0); + } + } else { + if (CPUHasAVX() || FORCE_AVX_REGS) { + mach_msg_type_number_t count = e_regSetWordSizeAVX; + m_state.SetError(e_regSetFPU, Read, + ::thread_get_state( + m_thread->MachPortNumber(), __x86_64_AVX_STATE, + (thread_state_t)&m_state.context.fpu.avx, &count)); + DNBLogThreadedIf(LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &avx, " + "%u (%u passed in) carp) => 0x%8.8x", + m_thread->MachPortNumber(), __x86_64_AVX_STATE, + (uint32_t)count, e_regSetWordSizeAVX, + m_state.GetError(e_regSetFPU, Read)); + } else { + mach_msg_type_number_t count = e_regSetWordSizeFPU; + m_state.SetError( + e_regSetFPU, Read, + ::thread_get_state(m_thread->MachPortNumber(), __x86_64_FLOAT_STATE, + (thread_state_t)&m_state.context.fpu.no_avx, + &count)); + DNBLogThreadedIf(LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &fpu, " + "%u (%u passed in) => 0x%8.8x", + m_thread->MachPortNumber(), __x86_64_FLOAT_STATE, + (uint32_t)count, e_regSetWordSizeFPU, + m_state.GetError(e_regSetFPU, Read)); + } } - return m_state.GetError(e_regSetFPU, Read); + } + return m_state.GetError(e_regSetFPU, Read); } -kern_return_t -DNBArchImplX86_64::GetEXCState(bool force) -{ - if (force || m_state.GetError(e_regSetEXC, Read)) - { - mach_msg_type_number_t count = e_regSetWordSizeEXC; - m_state.SetError(e_regSetEXC, Read, ::thread_get_state(m_thread->MachPortNumber(), __x86_64_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, &count)); - } - return m_state.GetError(e_regSetEXC, Read); +kern_return_t DNBArchImplX86_64::GetEXCState(bool force) { + if (force || m_state.GetError(e_regSetEXC, Read)) { + mach_msg_type_number_t count = e_regSetWordSizeEXC; + m_state.SetError( + e_regSetEXC, Read, + ::thread_get_state(m_thread->MachPortNumber(), __x86_64_EXCEPTION_STATE, + (thread_state_t)&m_state.context.exc, &count)); + } + return m_state.GetError(e_regSetEXC, Read); } -kern_return_t -DNBArchImplX86_64::SetGPRState() -{ - kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); - DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); - - m_state.SetError(e_regSetGPR, Write, ::thread_set_state(m_thread->MachPortNumber(), __x86_64_THREAD_STATE, (thread_state_t)&m_state.context.gpr, e_regSetWordSizeGPR)); - DNBLogThreadedIf (LOG_THREAD, "::thread_set_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x" - "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx" - "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx" - "\n\t r8 = %16.16llx r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx" - "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx" - "\n\trip = %16.16llx" - "\n\tflg = %16.16llx cs = %16.16llx fs = %16.16llx gs = %16.16llx", - m_thread->MachPortNumber(), __x86_64_THREAD_STATE, e_regSetWordSizeGPR, - m_state.GetError(e_regSetGPR, Write), - m_state.context.gpr.__rax,m_state.context.gpr.__rbx,m_state.context.gpr.__rcx, - m_state.context.gpr.__rdx,m_state.context.gpr.__rdi,m_state.context.gpr.__rsi, - m_state.context.gpr.__rbp,m_state.context.gpr.__rsp,m_state.context.gpr.__r8, - m_state.context.gpr.__r9, m_state.context.gpr.__r10,m_state.context.gpr.__r11, - m_state.context.gpr.__r12,m_state.context.gpr.__r13,m_state.context.gpr.__r14, - m_state.context.gpr.__r15,m_state.context.gpr.__rip,m_state.context.gpr.__rflags, - m_state.context.gpr.__cs, m_state.context.gpr.__fs, m_state.context.gpr.__gs); - return m_state.GetError(e_regSetGPR, Write); +kern_return_t DNBArchImplX86_64::SetGPRState() { + kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); + DNBLogThreadedIf( + LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u " + "(SetGPRState() for stop_count = %u)", + m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); + + m_state.SetError(e_regSetGPR, Write, + ::thread_set_state(m_thread->MachPortNumber(), + __x86_64_THREAD_STATE, + (thread_state_t)&m_state.context.gpr, + e_regSetWordSizeGPR)); + DNBLogThreadedIf( + LOG_THREAD, + "::thread_set_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x" + "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx" + "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx" + "\n\t r8 = %16.16llx r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx" + "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx" + "\n\trip = %16.16llx" + "\n\tflg = %16.16llx cs = %16.16llx fs = %16.16llx gs = %16.16llx", + m_thread->MachPortNumber(), __x86_64_THREAD_STATE, e_regSetWordSizeGPR, + m_state.GetError(e_regSetGPR, Write), m_state.context.gpr.__rax, + m_state.context.gpr.__rbx, m_state.context.gpr.__rcx, + m_state.context.gpr.__rdx, m_state.context.gpr.__rdi, + m_state.context.gpr.__rsi, m_state.context.gpr.__rbp, + m_state.context.gpr.__rsp, m_state.context.gpr.__r8, + m_state.context.gpr.__r9, m_state.context.gpr.__r10, + m_state.context.gpr.__r11, m_state.context.gpr.__r12, + m_state.context.gpr.__r13, m_state.context.gpr.__r14, + m_state.context.gpr.__r15, m_state.context.gpr.__rip, + m_state.context.gpr.__rflags, m_state.context.gpr.__cs, + m_state.context.gpr.__fs, m_state.context.gpr.__gs); + return m_state.GetError(e_regSetGPR, Write); } -kern_return_t -DNBArchImplX86_64::SetFPUState() -{ - if (DEBUG_FPU_REGS) - { - m_state.SetError(e_regSetFPU, Write, 0); - return m_state.GetError(e_regSetFPU, Write); - } - else - { - if (CPUHasAVX() || FORCE_AVX_REGS) - { - m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->MachPortNumber(), __x86_64_AVX_STATE, (thread_state_t)&m_state.context.fpu.avx, e_regSetWordSizeAVX)); - return m_state.GetError(e_regSetFPU, Write); - } - else - { - m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->MachPortNumber(), __x86_64_FLOAT_STATE, (thread_state_t)&m_state.context.fpu.no_avx, e_regSetWordSizeFPU)); - return m_state.GetError(e_regSetFPU, Write); - } +kern_return_t DNBArchImplX86_64::SetFPUState() { + if (DEBUG_FPU_REGS) { + m_state.SetError(e_regSetFPU, Write, 0); + return m_state.GetError(e_regSetFPU, Write); + } else { + if (CPUHasAVX() || FORCE_AVX_REGS) { + m_state.SetError( + e_regSetFPU, Write, + ::thread_set_state(m_thread->MachPortNumber(), __x86_64_AVX_STATE, + (thread_state_t)&m_state.context.fpu.avx, + e_regSetWordSizeAVX)); + return m_state.GetError(e_regSetFPU, Write); + } else { + m_state.SetError( + e_regSetFPU, Write, + ::thread_set_state(m_thread->MachPortNumber(), __x86_64_FLOAT_STATE, + (thread_state_t)&m_state.context.fpu.no_avx, + e_regSetWordSizeFPU)); + return m_state.GetError(e_regSetFPU, Write); } + } } -kern_return_t -DNBArchImplX86_64::SetEXCState() -{ - m_state.SetError(e_regSetEXC, Write, ::thread_set_state(m_thread->MachPortNumber(), __x86_64_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, e_regSetWordSizeEXC)); - return m_state.GetError(e_regSetEXC, Write); +kern_return_t DNBArchImplX86_64::SetEXCState() { + m_state.SetError(e_regSetEXC, Write, + ::thread_set_state(m_thread->MachPortNumber(), + __x86_64_EXCEPTION_STATE, + (thread_state_t)&m_state.context.exc, + e_regSetWordSizeEXC)); + return m_state.GetError(e_regSetEXC, Write); } -kern_return_t -DNBArchImplX86_64::GetDBGState(bool force) -{ - if (force || m_state.GetError(e_regSetDBG, Read)) - { - mach_msg_type_number_t count = e_regSetWordSizeDBG; - m_state.SetError(e_regSetDBG, Read, ::thread_get_state(m_thread->MachPortNumber(), __x86_64_DEBUG_STATE, (thread_state_t)&m_state.context.dbg, &count)); - } - return m_state.GetError(e_regSetDBG, Read); +kern_return_t DNBArchImplX86_64::GetDBGState(bool force) { + if (force || m_state.GetError(e_regSetDBG, Read)) { + mach_msg_type_number_t count = e_regSetWordSizeDBG; + m_state.SetError( + e_regSetDBG, Read, + ::thread_get_state(m_thread->MachPortNumber(), __x86_64_DEBUG_STATE, + (thread_state_t)&m_state.context.dbg, &count)); + } + return m_state.GetError(e_regSetDBG, Read); } -kern_return_t -DNBArchImplX86_64::SetDBGState(bool also_set_on_task) -{ - m_state.SetError(e_regSetDBG, Write, ::thread_set_state(m_thread->MachPortNumber(), __x86_64_DEBUG_STATE, (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG)); - if (also_set_on_task) - { - kern_return_t kret = ::task_set_state(m_thread->Process()->Task().TaskPort(), __x86_64_DEBUG_STATE, (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG); - if (kret != KERN_SUCCESS) - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::SetDBGState failed to set debug control register state: 0x%8.8x.", kret); - } - return m_state.GetError(e_regSetDBG, Write); +kern_return_t DNBArchImplX86_64::SetDBGState(bool also_set_on_task) { + m_state.SetError(e_regSetDBG, Write, + ::thread_set_state(m_thread->MachPortNumber(), + __x86_64_DEBUG_STATE, + (thread_state_t)&m_state.context.dbg, + e_regSetWordSizeDBG)); + if (also_set_on_task) { + kern_return_t kret = ::task_set_state( + m_thread->Process()->Task().TaskPort(), __x86_64_DEBUG_STATE, + (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG); + if (kret != KERN_SUCCESS) + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::SetDBGState failed " + "to set debug control register state: " + "0x%8.8x.", + kret); + } + return m_state.GetError(e_regSetDBG, Write); } -void -DNBArchImplX86_64::ThreadWillResume() -{ - // Do we need to step this thread? If so, let the mach thread tell us so. - if (m_thread->IsStepping()) - { - // This is the primary thread, let the arch do anything it needs - EnableHardwareSingleStep(true); - } - - // Reset the debug status register, if necessary, before we resume. - kern_return_t kret = GetDBGState(false); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::ThreadWillResume() GetDBGState() => 0x%8.8x.", kret); - if (kret != KERN_SUCCESS) - return; +void DNBArchImplX86_64::ThreadWillResume() { + // Do we need to step this thread? If so, let the mach thread tell us so. + if (m_thread->IsStepping()) { + // This is the primary thread, let the arch do anything it needs + EnableHardwareSingleStep(true); + } + + // Reset the debug status register, if necessary, before we resume. + kern_return_t kret = GetDBGState(false); + DNBLogThreadedIf( + LOG_WATCHPOINTS, + "DNBArchImplX86_64::ThreadWillResume() GetDBGState() => 0x%8.8x.", kret); + if (kret != KERN_SUCCESS) + return; - DBG &debug_state = m_state.context.dbg; - bool need_reset = false; - uint32_t i, num = NumSupportedHardwareWatchpoints(); - for (i = 0; i < num; ++i) - if (IsWatchpointHit(debug_state, i)) - need_reset = true; - - if (need_reset) - { - ClearWatchpointHits(debug_state); - kret = SetDBGState(false); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::ThreadWillResume() SetDBGState() => 0x%8.8x.", kret); - } + DBG &debug_state = m_state.context.dbg; + bool need_reset = false; + uint32_t i, num = NumSupportedHardwareWatchpoints(); + for (i = 0; i < num; ++i) + if (IsWatchpointHit(debug_state, i)) + need_reset = true; + + if (need_reset) { + ClearWatchpointHits(debug_state); + kret = SetDBGState(false); + DNBLogThreadedIf( + LOG_WATCHPOINTS, + "DNBArchImplX86_64::ThreadWillResume() SetDBGState() => 0x%8.8x.", + kret); + } } -bool -DNBArchImplX86_64::ThreadDidStop() -{ - bool success = true; - - m_state.InvalidateAllRegisterStates(); - - // Are we stepping a single instruction? - if (GetGPRState(true) == KERN_SUCCESS) - { - // We are single stepping, was this the primary thread? - if (m_thread->IsStepping()) - { - // This was the primary thread, we need to clear the trace - // bit if so. - success = EnableHardwareSingleStep(false) == KERN_SUCCESS; - } - else - { - // The MachThread will automatically restore the suspend count - // in ThreadDidStop(), so we don't need to do anything here if - // we weren't the primary thread the last time - } +bool DNBArchImplX86_64::ThreadDidStop() { + bool success = true; + + m_state.InvalidateAllRegisterStates(); + + // Are we stepping a single instruction? + if (GetGPRState(true) == KERN_SUCCESS) { + // We are single stepping, was this the primary thread? + if (m_thread->IsStepping()) { + // This was the primary thread, we need to clear the trace + // bit if so. + success = EnableHardwareSingleStep(false) == KERN_SUCCESS; + } else { + // The MachThread will automatically restore the suspend count + // in ThreadDidStop(), so we don't need to do anything here if + // we weren't the primary thread the last time } - return success; + } + return success; } -bool -DNBArchImplX86_64::NotifyException(MachException::Data& exc) -{ - switch (exc.exc_type) - { - case EXC_BAD_ACCESS: - break; - case EXC_BAD_INSTRUCTION: - break; - case EXC_ARITHMETIC: - break; - case EXC_EMULATION: - break; - case EXC_SOFTWARE: - break; - case EXC_BREAKPOINT: - if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 2) - { - // exc_code = EXC_I386_BPT - // - nub_addr_t pc = GetPC(INVALID_NUB_ADDRESS); - if (pc != INVALID_NUB_ADDRESS && pc > 0) - { - pc -= 1; - // Check for a breakpoint at one byte prior to the current PC value - // since the PC will be just past the trap. - - DNBBreakpoint *bp = m_thread->Process()->Breakpoints().FindByAddress(pc); - if (bp) - { - // Backup the PC for i386 since the trap was taken and the PC - // is at the address following the single byte trap instruction. - if (m_state.context.gpr.__rip > 0) - { - m_state.context.gpr.__rip = pc; - // Write the new PC back out - SetGPRState (); - } - } - return true; - } - } - else if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 1) - { - // exc_code = EXC_I386_SGL - // - // Check whether this corresponds to a watchpoint hit event. - // If yes, set the exc_sub_code to the data break address. - nub_addr_t addr = 0; - uint32_t hw_index = GetHardwareWatchpointHit(addr); - if (hw_index != INVALID_NUB_HW_INDEX) - { - exc.exc_data[1] = addr; - // Piggyback the hw_index in the exc.data. - exc.exc_data.push_back(hw_index); - } - - return true; - } - break; - case EXC_SYSCALL: - break; - case EXC_MACH_SYSCALL: - break; - case EXC_RPC_ALERT: - break; +bool DNBArchImplX86_64::NotifyException(MachException::Data &exc) { + switch (exc.exc_type) { + case EXC_BAD_ACCESS: + break; + case EXC_BAD_INSTRUCTION: + break; + case EXC_ARITHMETIC: + break; + case EXC_EMULATION: + break; + case EXC_SOFTWARE: + break; + case EXC_BREAKPOINT: + if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 2) { + // exc_code = EXC_I386_BPT + // + nub_addr_t pc = GetPC(INVALID_NUB_ADDRESS); + if (pc != INVALID_NUB_ADDRESS && pc > 0) { + pc -= 1; + // Check for a breakpoint at one byte prior to the current PC value + // since the PC will be just past the trap. + + DNBBreakpoint *bp = + m_thread->Process()->Breakpoints().FindByAddress(pc); + if (bp) { + // Backup the PC for i386 since the trap was taken and the PC + // is at the address following the single byte trap instruction. + if (m_state.context.gpr.__rip > 0) { + m_state.context.gpr.__rip = pc; + // Write the new PC back out + SetGPRState(); + } + } + return true; + } + } else if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 1) { + // exc_code = EXC_I386_SGL + // + // Check whether this corresponds to a watchpoint hit event. + // If yes, set the exc_sub_code to the data break address. + nub_addr_t addr = 0; + uint32_t hw_index = GetHardwareWatchpointHit(addr); + if (hw_index != INVALID_NUB_HW_INDEX) { + exc.exc_data[1] = addr; + // Piggyback the hw_index in the exc.data. + exc.exc_data.push_back(hw_index); + } + + return true; } - return false; + break; + case EXC_SYSCALL: + break; + case EXC_MACH_SYSCALL: + break; + case EXC_RPC_ALERT: + break; + } + return false; } -uint32_t -DNBArchImplX86_64::NumSupportedHardwareWatchpoints() -{ - // Available debug address registers: dr0, dr1, dr2, dr3. - return 4; +uint32_t DNBArchImplX86_64::NumSupportedHardwareWatchpoints() { + // Available debug address registers: dr0, dr1, dr2, dr3. + return 4; } -static uint32_t -size_and_rw_bits(nub_size_t size, bool read, bool write) -{ - uint32_t rw; - if (read) { - rw = 0x3; // READ or READ/WRITE - } else if (write) { - rw = 0x1; // WRITE - } else { - assert(0 && "read and write cannot both be false"); - } - - switch (size) { - case 1: - return rw; - case 2: - return (0x1 << 2) | rw; - case 4: - return (0x3 << 2) | rw; - case 8: - return (0x2 << 2) | rw; - } - assert(0 && "invalid size, must be one of 1, 2, 4, or 8"); - return 0; +static uint32_t size_and_rw_bits(nub_size_t size, bool read, bool write) { + uint32_t rw; + if (read) { + rw = 0x3; // READ or READ/WRITE + } else if (write) { + rw = 0x1; // WRITE + } else { + assert(0 && "read and write cannot both be false"); + } + + switch (size) { + case 1: + return rw; + case 2: + return (0x1 << 2) | rw; + case 4: + return (0x3 << 2) | rw; + case 8: + return (0x2 << 2) | rw; + } + assert(0 && "invalid size, must be one of 1, 2, 4, or 8"); + return 0; } -void -DNBArchImplX86_64::SetWatchpoint(DBG &debug_state, uint32_t hw_index, nub_addr_t addr, nub_size_t size, bool read, bool write) -{ - // Set both dr7 (debug control register) and dri (debug address register). - - // dr7{7-0} encodes the local/gloabl enable bits: - // global enable --. .-- local enable - // | | - // v v - // dr0 -> bits{1-0} - // dr1 -> bits{3-2} - // dr2 -> bits{5-4} - // dr3 -> bits{7-6} - // - // dr7{31-16} encodes the rw/len bits: - // b_x+3, b_x+2, b_x+1, b_x - // where bits{x+1, x} => rw - // 0b00: execute, 0b01: write, 0b11: read-or-write, 0b10: io read-or-write (unused) - // and bits{x+3, x+2} => len - // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte - // - // dr0 -> bits{19-16} - // dr1 -> bits{23-20} - // dr2 -> bits{27-24} - // dr3 -> bits{31-28} - debug_state.__dr7 |= (1 << (2*hw_index) | - size_and_rw_bits(size, read, write) << (16+4*hw_index)); - switch (hw_index) { - case 0: - debug_state.__dr0 = addr; break; - case 1: - debug_state.__dr1 = addr; break; - case 2: - debug_state.__dr2 = addr; break; - case 3: - debug_state.__dr3 = addr; break; - default: - assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3"); - } - return; +void DNBArchImplX86_64::SetWatchpoint(DBG &debug_state, uint32_t hw_index, + nub_addr_t addr, nub_size_t size, + bool read, bool write) { + // Set both dr7 (debug control register) and dri (debug address register). + + // dr7{7-0} encodes the local/gloabl enable bits: + // global enable --. .-- local enable + // | | + // v v + // dr0 -> bits{1-0} + // dr1 -> bits{3-2} + // dr2 -> bits{5-4} + // dr3 -> bits{7-6} + // + // dr7{31-16} encodes the rw/len bits: + // b_x+3, b_x+2, b_x+1, b_x + // where bits{x+1, x} => rw + // 0b00: execute, 0b01: write, 0b11: read-or-write, 0b10: io + // read-or-write (unused) + // and bits{x+3, x+2} => len + // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte + // + // dr0 -> bits{19-16} + // dr1 -> bits{23-20} + // dr2 -> bits{27-24} + // dr3 -> bits{31-28} + debug_state.__dr7 |= + (1 << (2 * hw_index) | + size_and_rw_bits(size, read, write) << (16 + 4 * hw_index)); + switch (hw_index) { + case 0: + debug_state.__dr0 = addr; + break; + case 1: + debug_state.__dr1 = addr; + break; + case 2: + debug_state.__dr2 = addr; + break; + case 3: + debug_state.__dr3 = addr; + break; + default: + assert(0 && + "invalid hardware register index, must be one of 0, 1, 2, or 3"); + } + return; } -void -DNBArchImplX86_64::ClearWatchpoint(DBG &debug_state, uint32_t hw_index) -{ - debug_state.__dr7 &= ~(3 << (2*hw_index)); - switch (hw_index) { - case 0: - debug_state.__dr0 = 0; break; - case 1: - debug_state.__dr1 = 0; break; - case 2: - debug_state.__dr2 = 0; break; - case 3: - debug_state.__dr3 = 0; break; - default: - assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3"); - } - return; +void DNBArchImplX86_64::ClearWatchpoint(DBG &debug_state, uint32_t hw_index) { + debug_state.__dr7 &= ~(3 << (2 * hw_index)); + switch (hw_index) { + case 0: + debug_state.__dr0 = 0; + break; + case 1: + debug_state.__dr1 = 0; + break; + case 2: + debug_state.__dr2 = 0; + break; + case 3: + debug_state.__dr3 = 0; + break; + default: + assert(0 && + "invalid hardware register index, must be one of 0, 1, 2, or 3"); + } + return; } -bool -DNBArchImplX86_64::IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index) -{ - // Check dr7 (debug control register) for local/global enable bits: - // global enable --. .-- local enable - // | | - // v v - // dr0 -> bits{1-0} - // dr1 -> bits{3-2} - // dr2 -> bits{5-4} - // dr3 -> bits{7-6} - return (debug_state.__dr7 & (3 << (2*hw_index))) == 0; +bool DNBArchImplX86_64::IsWatchpointVacant(const DBG &debug_state, + uint32_t hw_index) { + // Check dr7 (debug control register) for local/global enable bits: + // global enable --. .-- local enable + // | | + // v v + // dr0 -> bits{1-0} + // dr1 -> bits{3-2} + // dr2 -> bits{5-4} + // dr3 -> bits{7-6} + return (debug_state.__dr7 & (3 << (2 * hw_index))) == 0; } -// Resets local copy of debug status register to wait for the next debug exception. -void -DNBArchImplX86_64::ClearWatchpointHits(DBG &debug_state) -{ - // See also IsWatchpointHit(). - debug_state.__dr6 = 0; - return; +// Resets local copy of debug status register to wait for the next debug +// exception. +void DNBArchImplX86_64::ClearWatchpointHits(DBG &debug_state) { + // See also IsWatchpointHit(). + debug_state.__dr6 = 0; + return; } -bool -DNBArchImplX86_64::IsWatchpointHit(const DBG &debug_state, uint32_t hw_index) -{ - // Check dr6 (debug status register) whether a watchpoint hits: - // is watchpoint hit? - // | - // v - // dr0 -> bits{0} - // dr1 -> bits{1} - // dr2 -> bits{2} - // dr3 -> bits{3} - return (debug_state.__dr6 & (1 << hw_index)); +bool DNBArchImplX86_64::IsWatchpointHit(const DBG &debug_state, + uint32_t hw_index) { + // Check dr6 (debug status register) whether a watchpoint hits: + // is watchpoint hit? + // | + // v + // dr0 -> bits{0} + // dr1 -> bits{1} + // dr2 -> bits{2} + // dr3 -> bits{3} + return (debug_state.__dr6 & (1 << hw_index)); } -nub_addr_t -DNBArchImplX86_64::GetWatchAddress(const DBG &debug_state, uint32_t hw_index) -{ - switch (hw_index) { - case 0: - return debug_state.__dr0; - case 1: - return debug_state.__dr1; - case 2: - return debug_state.__dr2; - case 3: - return debug_state.__dr3; - } - assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3"); - return 0; +nub_addr_t DNBArchImplX86_64::GetWatchAddress(const DBG &debug_state, + uint32_t hw_index) { + switch (hw_index) { + case 0: + return debug_state.__dr0; + case 1: + return debug_state.__dr1; + case 2: + return debug_state.__dr2; + case 3: + return debug_state.__dr3; + } + assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3"); + return 0; } -bool -DNBArchImplX86_64::StartTransForHWP() -{ - if (m_2pc_trans_state != Trans_Done && m_2pc_trans_state != Trans_Rolled_Back) - DNBLogError ("%s inconsistent state detected, expected %d or %d, got: %d", __FUNCTION__, Trans_Done, Trans_Rolled_Back, m_2pc_trans_state); - m_2pc_dbg_checkpoint = m_state.context.dbg; - m_2pc_trans_state = Trans_Pending; - return true; +bool DNBArchImplX86_64::StartTransForHWP() { + if (m_2pc_trans_state != Trans_Done && m_2pc_trans_state != Trans_Rolled_Back) + DNBLogError("%s inconsistent state detected, expected %d or %d, got: %d", + __FUNCTION__, Trans_Done, Trans_Rolled_Back, m_2pc_trans_state); + m_2pc_dbg_checkpoint = m_state.context.dbg; + m_2pc_trans_state = Trans_Pending; + return true; } -bool -DNBArchImplX86_64::RollbackTransForHWP() -{ - m_state.context.dbg = m_2pc_dbg_checkpoint; - if (m_2pc_trans_state != Trans_Pending) - DNBLogError ("%s inconsistent state detected, expected %d, got: %d", __FUNCTION__, Trans_Pending, m_2pc_trans_state); - m_2pc_trans_state = Trans_Rolled_Back; - kern_return_t kret = SetDBGState(false); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::RollbackTransForHWP() SetDBGState() => 0x%8.8x.", kret); - - if (kret == KERN_SUCCESS) - return true; - else - return false; -} -bool -DNBArchImplX86_64::FinishTransForHWP() -{ - m_2pc_trans_state = Trans_Done; +bool DNBArchImplX86_64::RollbackTransForHWP() { + m_state.context.dbg = m_2pc_dbg_checkpoint; + if (m_2pc_trans_state != Trans_Pending) + DNBLogError("%s inconsistent state detected, expected %d, got: %d", + __FUNCTION__, Trans_Pending, m_2pc_trans_state); + m_2pc_trans_state = Trans_Rolled_Back; + kern_return_t kret = SetDBGState(false); + DNBLogThreadedIf( + LOG_WATCHPOINTS, + "DNBArchImplX86_64::RollbackTransForHWP() SetDBGState() => 0x%8.8x.", + kret); + + if (kret == KERN_SUCCESS) return true; + else + return false; +} +bool DNBArchImplX86_64::FinishTransForHWP() { + m_2pc_trans_state = Trans_Done; + return true; } -DNBArchImplX86_64::DBG -DNBArchImplX86_64::GetDBGCheckpoint() -{ - return m_2pc_dbg_checkpoint; +DNBArchImplX86_64::DBG DNBArchImplX86_64::GetDBGCheckpoint() { + return m_2pc_dbg_checkpoint; } -uint32_t -DNBArchImplX86_64::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task) -{ - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::EnableHardwareWatchpoint(addr = 0x%llx, size = %llu, read = %u, write = %u)", (uint64_t)addr, (uint64_t)size, read, write); +uint32_t DNBArchImplX86_64::EnableHardwareWatchpoint(nub_addr_t addr, + nub_size_t size, bool read, + bool write, + bool also_set_on_task) { + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::" + "EnableHardwareWatchpoint(addr = 0x%llx, " + "size = %llu, read = %u, write = %u)", + (uint64_t)addr, (uint64_t)size, read, write); - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); + const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - // Can only watch 1, 2, 4, or 8 bytes. - if (!(size == 1 || size == 2 || size == 4 || size == 8)) - return INVALID_NUB_HW_INDEX; + // Can only watch 1, 2, 4, or 8 bytes. + if (!(size == 1 || size == 2 || size == 4 || size == 8)) + return INVALID_NUB_HW_INDEX; - // We must watch for either read or write - if (read == false && write == false) - return INVALID_NUB_HW_INDEX; + // We must watch for either read or write + if (read == false && write == false) + return INVALID_NUB_HW_INDEX; - // Read the debug state - kern_return_t kret = GetDBGState(false); + // Read the debug state + kern_return_t kret = GetDBGState(false); - if (kret == KERN_SUCCESS) - { - // Check to make sure we have the needed hardware support - uint32_t i = 0; + if (kret == KERN_SUCCESS) { + // Check to make sure we have the needed hardware support + uint32_t i = 0; - DBG &debug_state = m_state.context.dbg; - for (i = 0; i < num_hw_watchpoints; ++i) - { - if (IsWatchpointVacant(debug_state, i)) - break; - } + DBG &debug_state = m_state.context.dbg; + for (i = 0; i < num_hw_watchpoints; ++i) { + if (IsWatchpointVacant(debug_state, i)) + break; + } - // See if we found an available hw breakpoint slot above - if (i < num_hw_watchpoints) - { - StartTransForHWP(); - - // Modify our local copy of the debug state, first. - SetWatchpoint(debug_state, i, addr, size, read, write); - // Now set the watch point in the inferior. - kret = SetDBGState(also_set_on_task); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::EnableHardwareWatchpoint() SetDBGState() => 0x%8.8x.", kret); - - if (kret == KERN_SUCCESS) - return i; - else // Revert to the previous debug state voluntarily. The transaction coordinator knows that we have failed. - m_state.context.dbg = GetDBGCheckpoint(); - } - else - { - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints); - } + // See if we found an available hw breakpoint slot above + if (i < num_hw_watchpoints) { + StartTransForHWP(); + + // Modify our local copy of the debug state, first. + SetWatchpoint(debug_state, i, addr, size, read, write); + // Now set the watch point in the inferior. + kret = SetDBGState(also_set_on_task); + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::" + "EnableHardwareWatchpoint() " + "SetDBGState() => 0x%8.8x.", + kret); + + if (kret == KERN_SUCCESS) + return i; + else // Revert to the previous debug state voluntarily. The transaction + // coordinator knows that we have failed. + m_state.context.dbg = GetDBGCheckpoint(); + } else { + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::" + "EnableHardwareWatchpoint(): All " + "hardware resources (%u) are in use.", + num_hw_watchpoints); } - return INVALID_NUB_HW_INDEX; + } + return INVALID_NUB_HW_INDEX; } -bool -DNBArchImplX86_64::DisableHardwareWatchpoint (uint32_t hw_index, bool also_set_on_task) -{ - kern_return_t kret = GetDBGState(false); - - const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); - if (kret == KERN_SUCCESS) - { - DBG &debug_state = m_state.context.dbg; - if (hw_index < num_hw_points && !IsWatchpointVacant(debug_state, hw_index)) - { - StartTransForHWP(); - - // Modify our local copy of the debug state, first. - ClearWatchpoint(debug_state, hw_index); - // Now disable the watch point in the inferior. - kret = SetDBGState(also_set_on_task); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::DisableHardwareWatchpoint( %u )", - hw_index); - - if (kret == KERN_SUCCESS) - return true; - else // Revert to the previous debug state voluntarily. The transaction coordinator knows that we have failed. - m_state.context.dbg = GetDBGCheckpoint(); - } +bool DNBArchImplX86_64::DisableHardwareWatchpoint(uint32_t hw_index, + bool also_set_on_task) { + kern_return_t kret = GetDBGState(false); + + const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); + if (kret == KERN_SUCCESS) { + DBG &debug_state = m_state.context.dbg; + if (hw_index < num_hw_points && + !IsWatchpointVacant(debug_state, hw_index)) { + StartTransForHWP(); + + // Modify our local copy of the debug state, first. + ClearWatchpoint(debug_state, hw_index); + // Now disable the watch point in the inferior. + kret = SetDBGState(also_set_on_task); + DNBLogThreadedIf(LOG_WATCHPOINTS, + "DNBArchImplX86_64::DisableHardwareWatchpoint( %u )", + hw_index); + + if (kret == KERN_SUCCESS) + return true; + else // Revert to the previous debug state voluntarily. The transaction + // coordinator knows that we have failed. + m_state.context.dbg = GetDBGCheckpoint(); } - return false; + } + return false; } // Iterate through the debug status register; return the index of the first hit. -uint32_t -DNBArchImplX86_64::GetHardwareWatchpointHit(nub_addr_t &addr) -{ - // Read the debug state - kern_return_t kret = GetDBGState(true); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret); - if (kret == KERN_SUCCESS) - { - DBG &debug_state = m_state.context.dbg; - uint32_t i, num = NumSupportedHardwareWatchpoints(); - for (i = 0; i < num; ++i) - { - if (IsWatchpointHit(debug_state, i)) - { - addr = GetWatchAddress(debug_state, i); - DNBLogThreadedIf(LOG_WATCHPOINTS, - "DNBArchImplX86_64::GetHardwareWatchpointHit() found => %u (addr = 0x%llx).", - i, - (uint64_t)addr); - return i; - } - } +uint32_t DNBArchImplX86_64::GetHardwareWatchpointHit(nub_addr_t &addr) { + // Read the debug state + kern_return_t kret = GetDBGState(true); + DNBLogThreadedIf( + LOG_WATCHPOINTS, + "DNBArchImplX86_64::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", + kret); + if (kret == KERN_SUCCESS) { + DBG &debug_state = m_state.context.dbg; + uint32_t i, num = NumSupportedHardwareWatchpoints(); + for (i = 0; i < num; ++i) { + if (IsWatchpointHit(debug_state, i)) { + addr = GetWatchAddress(debug_state, i); + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::" + "GetHardwareWatchpointHit() found => " + "%u (addr = 0x%llx).", + i, (uint64_t)addr); + return i; + } } - return INVALID_NUB_HW_INDEX; + } + return INVALID_NUB_HW_INDEX; } // Set the single step bit in the processor status register. -kern_return_t -DNBArchImplX86_64::EnableHardwareSingleStep (bool enable) -{ - if (GetGPRState(false) == KERN_SUCCESS) - { - const uint32_t trace_bit = 0x100u; - if (enable) - m_state.context.gpr.__rflags |= trace_bit; - else - m_state.context.gpr.__rflags &= ~trace_bit; - return SetGPRState(); - } - return m_state.GetError(e_regSetGPR, Read); +kern_return_t DNBArchImplX86_64::EnableHardwareSingleStep(bool enable) { + if (GetGPRState(false) == KERN_SUCCESS) { + const uint32_t trace_bit = 0x100u; + if (enable) + m_state.context.gpr.__rflags |= trace_bit; + else + m_state.context.gpr.__rflags &= ~trace_bit; + return SetGPRState(); + } + return m_state.GetError(e_regSetGPR, Read); } - //---------------------------------------------------------------------- // Register information definitions //---------------------------------------------------------------------- -enum -{ - gpr_rax = 0, - gpr_rbx, - gpr_rcx, - gpr_rdx, - gpr_rdi, - gpr_rsi, - gpr_rbp, - gpr_rsp, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_r13, - gpr_r14, - gpr_r15, - gpr_rip, - gpr_rflags, - gpr_cs, - gpr_fs, - gpr_gs, - gpr_eax, - gpr_ebx, - gpr_ecx, - gpr_edx, - gpr_edi, - gpr_esi, - gpr_ebp, - gpr_esp, - gpr_r8d, // Low 32 bits or r8 - gpr_r9d, // Low 32 bits or r9 - gpr_r10d, // Low 32 bits or r10 - gpr_r11d, // Low 32 bits or r11 - gpr_r12d, // Low 32 bits or r12 - gpr_r13d, // Low 32 bits or r13 - gpr_r14d, // Low 32 bits or r14 - gpr_r15d, // Low 32 bits or r15 - gpr_ax , - gpr_bx , - gpr_cx , - gpr_dx , - gpr_di , - gpr_si , - gpr_bp , - gpr_sp , - gpr_r8w, // Low 16 bits or r8 - gpr_r9w, // Low 16 bits or r9 - gpr_r10w, // Low 16 bits or r10 - gpr_r11w, // Low 16 bits or r11 - gpr_r12w, // Low 16 bits or r12 - gpr_r13w, // Low 16 bits or r13 - gpr_r14w, // Low 16 bits or r14 - gpr_r15w, // Low 16 bits or r15 - gpr_ah , - gpr_bh , - gpr_ch , - gpr_dh , - gpr_al , - gpr_bl , - gpr_cl , - gpr_dl , - gpr_dil, - gpr_sil, - gpr_bpl, - gpr_spl, - gpr_r8l, // Low 8 bits or r8 - gpr_r9l, // Low 8 bits or r9 - gpr_r10l, // Low 8 bits or r10 - gpr_r11l, // Low 8 bits or r11 - gpr_r12l, // Low 8 bits or r12 - gpr_r13l, // Low 8 bits or r13 - gpr_r14l, // Low 8 bits or r14 - gpr_r15l, // Low 8 bits or r15 - k_num_gpr_regs +enum { + gpr_rax = 0, + gpr_rbx, + gpr_rcx, + gpr_rdx, + gpr_rdi, + gpr_rsi, + gpr_rbp, + gpr_rsp, + gpr_r8, + gpr_r9, + gpr_r10, + gpr_r11, + gpr_r12, + gpr_r13, + gpr_r14, + gpr_r15, + gpr_rip, + gpr_rflags, + gpr_cs, + gpr_fs, + gpr_gs, + gpr_eax, + gpr_ebx, + gpr_ecx, + gpr_edx, + gpr_edi, + gpr_esi, + gpr_ebp, + gpr_esp, + gpr_r8d, // Low 32 bits or r8 + gpr_r9d, // Low 32 bits or r9 + gpr_r10d, // Low 32 bits or r10 + gpr_r11d, // Low 32 bits or r11 + gpr_r12d, // Low 32 bits or r12 + gpr_r13d, // Low 32 bits or r13 + gpr_r14d, // Low 32 bits or r14 + gpr_r15d, // Low 32 bits or r15 + gpr_ax, + gpr_bx, + gpr_cx, + gpr_dx, + gpr_di, + gpr_si, + gpr_bp, + gpr_sp, + gpr_r8w, // Low 16 bits or r8 + gpr_r9w, // Low 16 bits or r9 + gpr_r10w, // Low 16 bits or r10 + gpr_r11w, // Low 16 bits or r11 + gpr_r12w, // Low 16 bits or r12 + gpr_r13w, // Low 16 bits or r13 + gpr_r14w, // Low 16 bits or r14 + gpr_r15w, // Low 16 bits or r15 + gpr_ah, + gpr_bh, + gpr_ch, + gpr_dh, + gpr_al, + gpr_bl, + gpr_cl, + gpr_dl, + gpr_dil, + gpr_sil, + gpr_bpl, + gpr_spl, + gpr_r8l, // Low 8 bits or r8 + gpr_r9l, // Low 8 bits or r9 + gpr_r10l, // Low 8 bits or r10 + gpr_r11l, // Low 8 bits or r11 + gpr_r12l, // Low 8 bits or r12 + gpr_r13l, // Low 8 bits or r13 + gpr_r14l, // Low 8 bits or r14 + gpr_r15l, // Low 8 bits or r15 + k_num_gpr_regs }; enum { - fpu_fcw, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_dp, - fpu_ds, - fpu_mxcsr, - fpu_mxcsrmask, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, - fpu_xmm8, - fpu_xmm9, - fpu_xmm10, - fpu_xmm11, - fpu_xmm12, - fpu_xmm13, - fpu_xmm14, - fpu_xmm15, - fpu_ymm0, - fpu_ymm1, - fpu_ymm2, - fpu_ymm3, - fpu_ymm4, - fpu_ymm5, - fpu_ymm6, - fpu_ymm7, - fpu_ymm8, - fpu_ymm9, - fpu_ymm10, - fpu_ymm11, - fpu_ymm12, - fpu_ymm13, - fpu_ymm14, - fpu_ymm15, - k_num_fpu_regs, - - // Aliases - fpu_fctrl = fpu_fcw, - fpu_fstat = fpu_fsw, - fpu_ftag = fpu_ftw, - fpu_fiseg = fpu_cs, - fpu_fioff = fpu_ip, - fpu_foseg = fpu_ds, - fpu_fooff = fpu_dp + fpu_fcw, + fpu_fsw, + fpu_ftw, + fpu_fop, + fpu_ip, + fpu_cs, + fpu_dp, + fpu_ds, + fpu_mxcsr, + fpu_mxcsrmask, + fpu_stmm0, + fpu_stmm1, + fpu_stmm2, + fpu_stmm3, + fpu_stmm4, + fpu_stmm5, + fpu_stmm6, + fpu_stmm7, + fpu_xmm0, + fpu_xmm1, + fpu_xmm2, + fpu_xmm3, + fpu_xmm4, + fpu_xmm5, + fpu_xmm6, + fpu_xmm7, + fpu_xmm8, + fpu_xmm9, + fpu_xmm10, + fpu_xmm11, + fpu_xmm12, + fpu_xmm13, + fpu_xmm14, + fpu_xmm15, + fpu_ymm0, + fpu_ymm1, + fpu_ymm2, + fpu_ymm3, + fpu_ymm4, + fpu_ymm5, + fpu_ymm6, + fpu_ymm7, + fpu_ymm8, + fpu_ymm9, + fpu_ymm10, + fpu_ymm11, + fpu_ymm12, + fpu_ymm13, + fpu_ymm14, + fpu_ymm15, + k_num_fpu_regs, + + // Aliases + fpu_fctrl = fpu_fcw, + fpu_fstat = fpu_fsw, + fpu_ftag = fpu_ftw, + fpu_fiseg = fpu_cs, + fpu_fioff = fpu_ip, + fpu_foseg = fpu_ds, + fpu_fooff = fpu_dp }; enum { - exc_trapno, - exc_err, - exc_faultvaddr, - k_num_exc_regs, + exc_trapno, + exc_err, + exc_faultvaddr, + k_num_exc_regs, }; - -enum ehframe_dwarf_regnums -{ - ehframe_dwarf_rax = 0, - ehframe_dwarf_rdx = 1, - ehframe_dwarf_rcx = 2, - ehframe_dwarf_rbx = 3, - ehframe_dwarf_rsi = 4, - ehframe_dwarf_rdi = 5, - ehframe_dwarf_rbp = 6, - ehframe_dwarf_rsp = 7, - ehframe_dwarf_r8, - ehframe_dwarf_r9, - ehframe_dwarf_r10, - ehframe_dwarf_r11, - ehframe_dwarf_r12, - ehframe_dwarf_r13, - ehframe_dwarf_r14, - ehframe_dwarf_r15, - ehframe_dwarf_rip, - ehframe_dwarf_xmm0, - ehframe_dwarf_xmm1, - ehframe_dwarf_xmm2, - ehframe_dwarf_xmm3, - ehframe_dwarf_xmm4, - ehframe_dwarf_xmm5, - ehframe_dwarf_xmm6, - ehframe_dwarf_xmm7, - ehframe_dwarf_xmm8, - ehframe_dwarf_xmm9, - ehframe_dwarf_xmm10, - ehframe_dwarf_xmm11, - ehframe_dwarf_xmm12, - ehframe_dwarf_xmm13, - ehframe_dwarf_xmm14, - ehframe_dwarf_xmm15, - ehframe_dwarf_stmm0, - ehframe_dwarf_stmm1, - ehframe_dwarf_stmm2, - ehframe_dwarf_stmm3, - ehframe_dwarf_stmm4, - ehframe_dwarf_stmm5, - ehframe_dwarf_stmm6, - ehframe_dwarf_stmm7, - ehframe_dwarf_ymm0 = ehframe_dwarf_xmm0, - ehframe_dwarf_ymm1 = ehframe_dwarf_xmm1, - ehframe_dwarf_ymm2 = ehframe_dwarf_xmm2, - ehframe_dwarf_ymm3 = ehframe_dwarf_xmm3, - ehframe_dwarf_ymm4 = ehframe_dwarf_xmm4, - ehframe_dwarf_ymm5 = ehframe_dwarf_xmm5, - ehframe_dwarf_ymm6 = ehframe_dwarf_xmm6, - ehframe_dwarf_ymm7 = ehframe_dwarf_xmm7, - ehframe_dwarf_ymm8 = ehframe_dwarf_xmm8, - ehframe_dwarf_ymm9 = ehframe_dwarf_xmm9, - ehframe_dwarf_ymm10 = ehframe_dwarf_xmm10, - ehframe_dwarf_ymm11 = ehframe_dwarf_xmm11, - ehframe_dwarf_ymm12 = ehframe_dwarf_xmm12, - ehframe_dwarf_ymm13 = ehframe_dwarf_xmm13, - ehframe_dwarf_ymm14 = ehframe_dwarf_xmm14, - ehframe_dwarf_ymm15 = ehframe_dwarf_xmm15 +enum ehframe_dwarf_regnums { + ehframe_dwarf_rax = 0, + ehframe_dwarf_rdx = 1, + ehframe_dwarf_rcx = 2, + ehframe_dwarf_rbx = 3, + ehframe_dwarf_rsi = 4, + ehframe_dwarf_rdi = 5, + ehframe_dwarf_rbp = 6, + ehframe_dwarf_rsp = 7, + ehframe_dwarf_r8, + ehframe_dwarf_r9, + ehframe_dwarf_r10, + ehframe_dwarf_r11, + ehframe_dwarf_r12, + ehframe_dwarf_r13, + ehframe_dwarf_r14, + ehframe_dwarf_r15, + ehframe_dwarf_rip, + ehframe_dwarf_xmm0, + ehframe_dwarf_xmm1, + ehframe_dwarf_xmm2, + ehframe_dwarf_xmm3, + ehframe_dwarf_xmm4, + ehframe_dwarf_xmm5, + ehframe_dwarf_xmm6, + ehframe_dwarf_xmm7, + ehframe_dwarf_xmm8, + ehframe_dwarf_xmm9, + ehframe_dwarf_xmm10, + ehframe_dwarf_xmm11, + ehframe_dwarf_xmm12, + ehframe_dwarf_xmm13, + ehframe_dwarf_xmm14, + ehframe_dwarf_xmm15, + ehframe_dwarf_stmm0, + ehframe_dwarf_stmm1, + ehframe_dwarf_stmm2, + ehframe_dwarf_stmm3, + ehframe_dwarf_stmm4, + ehframe_dwarf_stmm5, + ehframe_dwarf_stmm6, + ehframe_dwarf_stmm7, + ehframe_dwarf_ymm0 = ehframe_dwarf_xmm0, + ehframe_dwarf_ymm1 = ehframe_dwarf_xmm1, + ehframe_dwarf_ymm2 = ehframe_dwarf_xmm2, + ehframe_dwarf_ymm3 = ehframe_dwarf_xmm3, + ehframe_dwarf_ymm4 = ehframe_dwarf_xmm4, + ehframe_dwarf_ymm5 = ehframe_dwarf_xmm5, + ehframe_dwarf_ymm6 = ehframe_dwarf_xmm6, + ehframe_dwarf_ymm7 = ehframe_dwarf_xmm7, + ehframe_dwarf_ymm8 = ehframe_dwarf_xmm8, + ehframe_dwarf_ymm9 = ehframe_dwarf_xmm9, + ehframe_dwarf_ymm10 = ehframe_dwarf_xmm10, + ehframe_dwarf_ymm11 = ehframe_dwarf_xmm11, + ehframe_dwarf_ymm12 = ehframe_dwarf_xmm12, + ehframe_dwarf_ymm13 = ehframe_dwarf_xmm13, + ehframe_dwarf_ymm14 = ehframe_dwarf_xmm14, + ehframe_dwarf_ymm15 = ehframe_dwarf_xmm15 }; -enum debugserver_regnums -{ - debugserver_rax = 0, - debugserver_rbx = 1, - debugserver_rcx = 2, - debugserver_rdx = 3, - debugserver_rsi = 4, - debugserver_rdi = 5, - debugserver_rbp = 6, - debugserver_rsp = 7, - debugserver_r8 = 8, - debugserver_r9 = 9, - debugserver_r10 = 10, - debugserver_r11 = 11, - debugserver_r12 = 12, - debugserver_r13 = 13, - debugserver_r14 = 14, - debugserver_r15 = 15, - debugserver_rip = 16, - debugserver_rflags = 17, - debugserver_cs = 18, - debugserver_ss = 19, - debugserver_ds = 20, - debugserver_es = 21, - debugserver_fs = 22, - debugserver_gs = 23, - debugserver_stmm0 = 24, - debugserver_stmm1 = 25, - debugserver_stmm2 = 26, - debugserver_stmm3 = 27, - debugserver_stmm4 = 28, - debugserver_stmm5 = 29, - debugserver_stmm6 = 30, - debugserver_stmm7 = 31, - debugserver_fctrl = 32, debugserver_fcw = debugserver_fctrl, - debugserver_fstat = 33, debugserver_fsw = debugserver_fstat, - debugserver_ftag = 34, debugserver_ftw = debugserver_ftag, - debugserver_fiseg = 35, debugserver_fpu_cs = debugserver_fiseg, - debugserver_fioff = 36, debugserver_ip = debugserver_fioff, - debugserver_foseg = 37, debugserver_fpu_ds = debugserver_foseg, - debugserver_fooff = 38, debugserver_dp = debugserver_fooff, - debugserver_fop = 39, - debugserver_xmm0 = 40, - debugserver_xmm1 = 41, - debugserver_xmm2 = 42, - debugserver_xmm3 = 43, - debugserver_xmm4 = 44, - debugserver_xmm5 = 45, - debugserver_xmm6 = 46, - debugserver_xmm7 = 47, - debugserver_xmm8 = 48, - debugserver_xmm9 = 49, - debugserver_xmm10 = 50, - debugserver_xmm11 = 51, - debugserver_xmm12 = 52, - debugserver_xmm13 = 53, - debugserver_xmm14 = 54, - debugserver_xmm15 = 55, - debugserver_mxcsr = 56, - debugserver_ymm0 = debugserver_xmm0, - debugserver_ymm1 = debugserver_xmm1, - debugserver_ymm2 = debugserver_xmm2, - debugserver_ymm3 = debugserver_xmm3, - debugserver_ymm4 = debugserver_xmm4, - debugserver_ymm5 = debugserver_xmm5, - debugserver_ymm6 = debugserver_xmm6, - debugserver_ymm7 = debugserver_xmm7, - debugserver_ymm8 = debugserver_xmm8, - debugserver_ymm9 = debugserver_xmm9, - debugserver_ymm10 = debugserver_xmm10, - debugserver_ymm11 = debugserver_xmm11, - debugserver_ymm12 = debugserver_xmm12, - debugserver_ymm13 = debugserver_xmm13, - debugserver_ymm14 = debugserver_xmm14, - debugserver_ymm15 = debugserver_xmm15 +enum debugserver_regnums { + debugserver_rax = 0, + debugserver_rbx = 1, + debugserver_rcx = 2, + debugserver_rdx = 3, + debugserver_rsi = 4, + debugserver_rdi = 5, + debugserver_rbp = 6, + debugserver_rsp = 7, + debugserver_r8 = 8, + debugserver_r9 = 9, + debugserver_r10 = 10, + debugserver_r11 = 11, + debugserver_r12 = 12, + debugserver_r13 = 13, + debugserver_r14 = 14, + debugserver_r15 = 15, + debugserver_rip = 16, + debugserver_rflags = 17, + debugserver_cs = 18, + debugserver_ss = 19, + debugserver_ds = 20, + debugserver_es = 21, + debugserver_fs = 22, + debugserver_gs = 23, + debugserver_stmm0 = 24, + debugserver_stmm1 = 25, + debugserver_stmm2 = 26, + debugserver_stmm3 = 27, + debugserver_stmm4 = 28, + debugserver_stmm5 = 29, + debugserver_stmm6 = 30, + debugserver_stmm7 = 31, + debugserver_fctrl = 32, + debugserver_fcw = debugserver_fctrl, + debugserver_fstat = 33, + debugserver_fsw = debugserver_fstat, + debugserver_ftag = 34, + debugserver_ftw = debugserver_ftag, + debugserver_fiseg = 35, + debugserver_fpu_cs = debugserver_fiseg, + debugserver_fioff = 36, + debugserver_ip = debugserver_fioff, + debugserver_foseg = 37, + debugserver_fpu_ds = debugserver_foseg, + debugserver_fooff = 38, + debugserver_dp = debugserver_fooff, + debugserver_fop = 39, + debugserver_xmm0 = 40, + debugserver_xmm1 = 41, + debugserver_xmm2 = 42, + debugserver_xmm3 = 43, + debugserver_xmm4 = 44, + debugserver_xmm5 = 45, + debugserver_xmm6 = 46, + debugserver_xmm7 = 47, + debugserver_xmm8 = 48, + debugserver_xmm9 = 49, + debugserver_xmm10 = 50, + debugserver_xmm11 = 51, + debugserver_xmm12 = 52, + debugserver_xmm13 = 53, + debugserver_xmm14 = 54, + debugserver_xmm15 = 55, + debugserver_mxcsr = 56, + debugserver_ymm0 = debugserver_xmm0, + debugserver_ymm1 = debugserver_xmm1, + debugserver_ymm2 = debugserver_xmm2, + debugserver_ymm3 = debugserver_xmm3, + debugserver_ymm4 = debugserver_xmm4, + debugserver_ymm5 = debugserver_xmm5, + debugserver_ymm6 = debugserver_xmm6, + debugserver_ymm7 = debugserver_xmm7, + debugserver_ymm8 = debugserver_xmm8, + debugserver_ymm9 = debugserver_xmm9, + debugserver_ymm10 = debugserver_xmm10, + debugserver_ymm11 = debugserver_xmm11, + debugserver_ymm12 = debugserver_xmm12, + debugserver_ymm13 = debugserver_xmm13, + debugserver_ymm14 = debugserver_xmm14, + debugserver_ymm15 = debugserver_xmm15 }; -#define GPR_OFFSET(reg) (offsetof (DNBArchImplX86_64::GPR, __##reg)) -#define FPU_OFFSET(reg) (offsetof (DNBArchImplX86_64::FPU, __fpu_##reg) + offsetof (DNBArchImplX86_64::Context, fpu.no_avx)) -#define AVX_OFFSET(reg) (offsetof (DNBArchImplX86_64::AVX, __fpu_##reg) + offsetof (DNBArchImplX86_64::Context, fpu.avx)) -#define EXC_OFFSET(reg) (offsetof (DNBArchImplX86_64::EXC, __##reg) + offsetof (DNBArchImplX86_64::Context, exc)) -#define AVX_OFFSET_YMM(n) (AVX_OFFSET(ymmh0) + (32 * n)) - -#define GPR_SIZE(reg) (sizeof(((DNBArchImplX86_64::GPR *)NULL)->__##reg)) -#define FPU_SIZE_UINT(reg) (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg)) -#define FPU_SIZE_MMST(reg) (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__mmst_reg)) -#define FPU_SIZE_XMM(reg) (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__xmm_reg)) -#define FPU_SIZE_YMM(reg) (32) -#define EXC_SIZE(reg) (sizeof(((DNBArchImplX86_64::EXC *)NULL)->__##reg)) +#define GPR_OFFSET(reg) (offsetof(DNBArchImplX86_64::GPR, __##reg)) +#define FPU_OFFSET(reg) \ + (offsetof(DNBArchImplX86_64::FPU, __fpu_##reg) + \ + offsetof(DNBArchImplX86_64::Context, fpu.no_avx)) +#define AVX_OFFSET(reg) \ + (offsetof(DNBArchImplX86_64::AVX, __fpu_##reg) + \ + offsetof(DNBArchImplX86_64::Context, fpu.avx)) +#define EXC_OFFSET(reg) \ + (offsetof(DNBArchImplX86_64::EXC, __##reg) + \ + offsetof(DNBArchImplX86_64::Context, exc)) +#define AVX_OFFSET_YMM(n) (AVX_OFFSET(ymmh0) + (32 * n)) + +#define GPR_SIZE(reg) (sizeof(((DNBArchImplX86_64::GPR *)NULL)->__##reg)) +#define FPU_SIZE_UINT(reg) \ + (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg)) +#define FPU_SIZE_MMST(reg) \ + (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__mmst_reg)) +#define FPU_SIZE_XMM(reg) \ + (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__xmm_reg)) +#define FPU_SIZE_YMM(reg) (32) +#define EXC_SIZE(reg) (sizeof(((DNBArchImplX86_64::EXC *)NULL)->__##reg)) // These macros will auto define the register name, alt name, register size, // register offset, encoding, format and native register. This ensures that // the register state structures are defined correctly and have the correct // sizes and offsets. -#define DEFINE_GPR(reg) { e_regSetGPR, gpr_##reg, #reg, NULL, Uint, Hex, GPR_SIZE(reg), GPR_OFFSET(reg), ehframe_dwarf_##reg, ehframe_dwarf_##reg, INVALID_NUB_REGNUM, debugserver_##reg, NULL, g_invalidate_##reg } -#define DEFINE_GPR_ALT(reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), GPR_OFFSET(reg), ehframe_dwarf_##reg, ehframe_dwarf_##reg, gen, debugserver_##reg, NULL, g_invalidate_##reg } -#define DEFINE_GPR_ALT2(reg, alt) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), GPR_OFFSET(reg), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_##reg, NULL, NULL } -#define DEFINE_GPR_ALT3(reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), GPR_OFFSET(reg), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, gen, debugserver_##reg, NULL, NULL } -#define DEFINE_GPR_ALT4(reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), GPR_OFFSET(reg), ehframe_dwarf_##reg, ehframe_dwarf_##reg, gen, debugserver_##reg, NULL, NULL } - -#define DEFINE_GPR_PSEUDO_32(reg32,reg64) { e_regSetGPR, gpr_##reg32, #reg32, NULL, Uint, Hex, 4, 0,INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 } -#define DEFINE_GPR_PSEUDO_16(reg16,reg64) { e_regSetGPR, gpr_##reg16, #reg16, NULL, Uint, Hex, 2, 0,INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 } -#define DEFINE_GPR_PSEUDO_8H(reg8,reg64) { e_regSetGPR, gpr_##reg8 , #reg8 , NULL, Uint, Hex, 1, 1,INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 } -#define DEFINE_GPR_PSEUDO_8L(reg8,reg64) { e_regSetGPR, gpr_##reg8 , #reg8 , NULL, Uint, Hex, 1, 0,INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 } +#define DEFINE_GPR(reg) \ + { \ + e_regSetGPR, gpr_##reg, #reg, NULL, Uint, Hex, GPR_SIZE(reg), \ + GPR_OFFSET(reg), ehframe_dwarf_##reg, ehframe_dwarf_##reg, \ + INVALID_NUB_REGNUM, debugserver_##reg, NULL, g_invalidate_##reg \ + } +#define DEFINE_GPR_ALT(reg, alt, gen) \ + { \ + e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), \ + GPR_OFFSET(reg), ehframe_dwarf_##reg, ehframe_dwarf_##reg, gen, \ + debugserver_##reg, NULL, g_invalidate_##reg \ + } +#define DEFINE_GPR_ALT2(reg, alt) \ + { \ + e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), \ + GPR_OFFSET(reg), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ + INVALID_NUB_REGNUM, debugserver_##reg, NULL, NULL \ + } +#define DEFINE_GPR_ALT3(reg, alt, gen) \ + { \ + e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), \ + GPR_OFFSET(reg), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, gen, \ + debugserver_##reg, NULL, NULL \ + } +#define DEFINE_GPR_ALT4(reg, alt, gen) \ + { \ + e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), \ + GPR_OFFSET(reg), ehframe_dwarf_##reg, ehframe_dwarf_##reg, gen, \ + debugserver_##reg, NULL, NULL \ + } + +#define DEFINE_GPR_PSEUDO_32(reg32, reg64) \ + { \ + e_regSetGPR, gpr_##reg32, #reg32, NULL, Uint, Hex, 4, 0, \ + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ + INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 \ + } +#define DEFINE_GPR_PSEUDO_16(reg16, reg64) \ + { \ + e_regSetGPR, gpr_##reg16, #reg16, NULL, Uint, Hex, 2, 0, \ + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ + INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 \ + } +#define DEFINE_GPR_PSEUDO_8H(reg8, reg64) \ + { \ + e_regSetGPR, gpr_##reg8, #reg8, NULL, Uint, Hex, 1, 1, INVALID_NUB_REGNUM, \ + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ + g_contained_##reg64, g_invalidate_##reg64 \ + } +#define DEFINE_GPR_PSEUDO_8L(reg8, reg64) \ + { \ + e_regSetGPR, gpr_##reg8, #reg8, NULL, Uint, Hex, 1, 0, INVALID_NUB_REGNUM, \ + INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ + g_contained_##reg64, g_invalidate_##reg64 \ + } // General purpose registers for 64 bit -const char *g_contained_rax[] = { "rax", NULL }; -const char *g_contained_rbx[] = { "rbx", NULL }; -const char *g_contained_rcx[] = { "rcx", NULL }; -const char *g_contained_rdx[] = { "rdx", NULL }; -const char *g_contained_rdi[] = { "rdi", NULL }; -const char *g_contained_rsi[] = { "rsi", NULL }; -const char *g_contained_rbp[] = { "rbp", NULL }; -const char *g_contained_rsp[] = { "rsp", NULL }; -const char *g_contained_r8[] = { "r8", NULL }; -const char *g_contained_r9[] = { "r9", NULL }; -const char *g_contained_r10[] = { "r10", NULL }; -const char *g_contained_r11[] = { "r11", NULL }; -const char *g_contained_r12[] = { "r12", NULL }; -const char *g_contained_r13[] = { "r13", NULL }; -const char *g_contained_r14[] = { "r14", NULL }; -const char *g_contained_r15[] = { "r15", NULL }; - -const char *g_invalidate_rax[] = { "rax", "eax", "ax", "ah", "al", NULL }; -const char *g_invalidate_rbx[] = { "rbx", "ebx", "bx", "bh", "bl", NULL }; -const char *g_invalidate_rcx[] = { "rcx", "ecx", "cx", "ch", "cl", NULL }; -const char *g_invalidate_rdx[] = { "rdx", "edx", "dx", "dh", "dl", NULL }; -const char *g_invalidate_rdi[] = { "rdi", "edi", "di", "dil", NULL }; -const char *g_invalidate_rsi[] = { "rsi", "esi", "si", "sil", NULL }; -const char *g_invalidate_rbp[] = { "rbp", "ebp", "bp", "bpl", NULL }; -const char *g_invalidate_rsp[] = { "rsp", "esp", "sp", "spl", NULL }; -const char *g_invalidate_r8 [] = { "r8", "r8d", "r8w", "r8l", NULL }; -const char *g_invalidate_r9 [] = { "r9", "r9d", "r9w", "r9l", NULL }; -const char *g_invalidate_r10[] = { "r10", "r10d", "r10w", "r10l", NULL }; -const char *g_invalidate_r11[] = { "r11", "r11d", "r11w", "r11l", NULL }; -const char *g_invalidate_r12[] = { "r12", "r12d", "r12w", "r12l", NULL }; -const char *g_invalidate_r13[] = { "r13", "r13d", "r13w", "r13l", NULL }; -const char *g_invalidate_r14[] = { "r14", "r14d", "r14w", "r14l", NULL }; -const char *g_invalidate_r15[] = { "r15", "r15d", "r15w", "r15l", NULL }; - -const DNBRegisterInfo -DNBArchImplX86_64::g_gpr_registers[] = -{ - DEFINE_GPR (rax), - DEFINE_GPR (rbx), - DEFINE_GPR_ALT (rcx , "arg4", GENERIC_REGNUM_ARG4), - DEFINE_GPR_ALT (rdx , "arg3", GENERIC_REGNUM_ARG3), - DEFINE_GPR_ALT (rdi , "arg1", GENERIC_REGNUM_ARG1), - DEFINE_GPR_ALT (rsi , "arg2", GENERIC_REGNUM_ARG2), - DEFINE_GPR_ALT (rbp , "fp" , GENERIC_REGNUM_FP), - DEFINE_GPR_ALT (rsp , "sp" , GENERIC_REGNUM_SP), - DEFINE_GPR_ALT (r8 , "arg5", GENERIC_REGNUM_ARG5), - DEFINE_GPR_ALT (r9 , "arg6", GENERIC_REGNUM_ARG6), - DEFINE_GPR (r10), - DEFINE_GPR (r11), - DEFINE_GPR (r12), - DEFINE_GPR (r13), - DEFINE_GPR (r14), - DEFINE_GPR (r15), - DEFINE_GPR_ALT4 (rip , "pc", GENERIC_REGNUM_PC), - DEFINE_GPR_ALT3 (rflags, "flags", GENERIC_REGNUM_FLAGS), - DEFINE_GPR_ALT2 (cs, NULL), - DEFINE_GPR_ALT2 (fs, NULL), - DEFINE_GPR_ALT2 (gs, NULL), - DEFINE_GPR_PSEUDO_32 (eax, rax), - DEFINE_GPR_PSEUDO_32 (ebx, rbx), - DEFINE_GPR_PSEUDO_32 (ecx, rcx), - DEFINE_GPR_PSEUDO_32 (edx, rdx), - DEFINE_GPR_PSEUDO_32 (edi, rdi), - DEFINE_GPR_PSEUDO_32 (esi, rsi), - DEFINE_GPR_PSEUDO_32 (ebp, rbp), - DEFINE_GPR_PSEUDO_32 (esp, rsp), - DEFINE_GPR_PSEUDO_32 (r8d, r8), - DEFINE_GPR_PSEUDO_32 (r9d, r9), - DEFINE_GPR_PSEUDO_32 (r10d, r10), - DEFINE_GPR_PSEUDO_32 (r11d, r11), - DEFINE_GPR_PSEUDO_32 (r12d, r12), - DEFINE_GPR_PSEUDO_32 (r13d, r13), - DEFINE_GPR_PSEUDO_32 (r14d, r14), - DEFINE_GPR_PSEUDO_32 (r15d, r15), - DEFINE_GPR_PSEUDO_16 (ax , rax), - DEFINE_GPR_PSEUDO_16 (bx , rbx), - DEFINE_GPR_PSEUDO_16 (cx , rcx), - DEFINE_GPR_PSEUDO_16 (dx , rdx), - DEFINE_GPR_PSEUDO_16 (di , rdi), - DEFINE_GPR_PSEUDO_16 (si , rsi), - DEFINE_GPR_PSEUDO_16 (bp , rbp), - DEFINE_GPR_PSEUDO_16 (sp , rsp), - DEFINE_GPR_PSEUDO_16 (r8w, r8), - DEFINE_GPR_PSEUDO_16 (r9w, r9), - DEFINE_GPR_PSEUDO_16 (r10w, r10), - DEFINE_GPR_PSEUDO_16 (r11w, r11), - DEFINE_GPR_PSEUDO_16 (r12w, r12), - DEFINE_GPR_PSEUDO_16 (r13w, r13), - DEFINE_GPR_PSEUDO_16 (r14w, r14), - DEFINE_GPR_PSEUDO_16 (r15w, r15), - DEFINE_GPR_PSEUDO_8H (ah , rax), - DEFINE_GPR_PSEUDO_8H (bh , rbx), - DEFINE_GPR_PSEUDO_8H (ch , rcx), - DEFINE_GPR_PSEUDO_8H (dh , rdx), - DEFINE_GPR_PSEUDO_8L (al , rax), - DEFINE_GPR_PSEUDO_8L (bl , rbx), - DEFINE_GPR_PSEUDO_8L (cl , rcx), - DEFINE_GPR_PSEUDO_8L (dl , rdx), - DEFINE_GPR_PSEUDO_8L (dil, rdi), - DEFINE_GPR_PSEUDO_8L (sil, rsi), - DEFINE_GPR_PSEUDO_8L (bpl, rbp), - DEFINE_GPR_PSEUDO_8L (spl, rsp), - DEFINE_GPR_PSEUDO_8L (r8l, r8), - DEFINE_GPR_PSEUDO_8L (r9l, r9), - DEFINE_GPR_PSEUDO_8L (r10l, r10), - DEFINE_GPR_PSEUDO_8L (r11l, r11), - DEFINE_GPR_PSEUDO_8L (r12l, r12), - DEFINE_GPR_PSEUDO_8L (r13l, r13), - DEFINE_GPR_PSEUDO_8L (r14l, r14), - DEFINE_GPR_PSEUDO_8L (r15l, r15) -}; +const char *g_contained_rax[] = {"rax", NULL}; +const char *g_contained_rbx[] = {"rbx", NULL}; +const char *g_contained_rcx[] = {"rcx", NULL}; +const char *g_contained_rdx[] = {"rdx", NULL}; +const char *g_contained_rdi[] = {"rdi", NULL}; +const char *g_contained_rsi[] = {"rsi", NULL}; +const char *g_contained_rbp[] = {"rbp", NULL}; +const char *g_contained_rsp[] = {"rsp", NULL}; +const char *g_contained_r8[] = {"r8", NULL}; +const char *g_contained_r9[] = {"r9", NULL}; +const char *g_contained_r10[] = {"r10", NULL}; +const char *g_contained_r11[] = {"r11", NULL}; +const char *g_contained_r12[] = {"r12", NULL}; +const char *g_contained_r13[] = {"r13", NULL}; +const char *g_contained_r14[] = {"r14", NULL}; +const char *g_contained_r15[] = {"r15", NULL}; + +const char *g_invalidate_rax[] = {"rax", "eax", "ax", "ah", "al", NULL}; +const char *g_invalidate_rbx[] = {"rbx", "ebx", "bx", "bh", "bl", NULL}; +const char *g_invalidate_rcx[] = {"rcx", "ecx", "cx", "ch", "cl", NULL}; +const char *g_invalidate_rdx[] = {"rdx", "edx", "dx", "dh", "dl", NULL}; +const char *g_invalidate_rdi[] = {"rdi", "edi", "di", "dil", NULL}; +const char *g_invalidate_rsi[] = {"rsi", "esi", "si", "sil", NULL}; +const char *g_invalidate_rbp[] = {"rbp", "ebp", "bp", "bpl", NULL}; +const char *g_invalidate_rsp[] = {"rsp", "esp", "sp", "spl", NULL}; +const char *g_invalidate_r8[] = {"r8", "r8d", "r8w", "r8l", NULL}; +const char *g_invalidate_r9[] = {"r9", "r9d", "r9w", "r9l", NULL}; +const char *g_invalidate_r10[] = {"r10", "r10d", "r10w", "r10l", NULL}; +const char *g_invalidate_r11[] = {"r11", "r11d", "r11w", "r11l", NULL}; +const char *g_invalidate_r12[] = {"r12", "r12d", "r12w", "r12l", NULL}; +const char *g_invalidate_r13[] = {"r13", "r13d", "r13w", "r13l", NULL}; +const char *g_invalidate_r14[] = {"r14", "r14d", "r14w", "r14l", NULL}; +const char *g_invalidate_r15[] = {"r15", "r15d", "r15w", "r15l", NULL}; + +const DNBRegisterInfo DNBArchImplX86_64::g_gpr_registers[] = { + DEFINE_GPR(rax), + DEFINE_GPR(rbx), + DEFINE_GPR_ALT(rcx, "arg4", GENERIC_REGNUM_ARG4), + DEFINE_GPR_ALT(rdx, "arg3", GENERIC_REGNUM_ARG3), + DEFINE_GPR_ALT(rdi, "arg1", GENERIC_REGNUM_ARG1), + DEFINE_GPR_ALT(rsi, "arg2", GENERIC_REGNUM_ARG2), + DEFINE_GPR_ALT(rbp, "fp", GENERIC_REGNUM_FP), + DEFINE_GPR_ALT(rsp, "sp", GENERIC_REGNUM_SP), + DEFINE_GPR_ALT(r8, "arg5", GENERIC_REGNUM_ARG5), + DEFINE_GPR_ALT(r9, "arg6", GENERIC_REGNUM_ARG6), + DEFINE_GPR(r10), + DEFINE_GPR(r11), + DEFINE_GPR(r12), + DEFINE_GPR(r13), + DEFINE_GPR(r14), + DEFINE_GPR(r15), + DEFINE_GPR_ALT4(rip, "pc", GENERIC_REGNUM_PC), + DEFINE_GPR_ALT3(rflags, "flags", GENERIC_REGNUM_FLAGS), + DEFINE_GPR_ALT2(cs, NULL), + DEFINE_GPR_ALT2(fs, NULL), + DEFINE_GPR_ALT2(gs, NULL), + DEFINE_GPR_PSEUDO_32(eax, rax), + DEFINE_GPR_PSEUDO_32(ebx, rbx), + DEFINE_GPR_PSEUDO_32(ecx, rcx), + DEFINE_GPR_PSEUDO_32(edx, rdx), + DEFINE_GPR_PSEUDO_32(edi, rdi), + DEFINE_GPR_PSEUDO_32(esi, rsi), + DEFINE_GPR_PSEUDO_32(ebp, rbp), + DEFINE_GPR_PSEUDO_32(esp, rsp), + DEFINE_GPR_PSEUDO_32(r8d, r8), + DEFINE_GPR_PSEUDO_32(r9d, r9), + DEFINE_GPR_PSEUDO_32(r10d, r10), + DEFINE_GPR_PSEUDO_32(r11d, r11), + DEFINE_GPR_PSEUDO_32(r12d, r12), + DEFINE_GPR_PSEUDO_32(r13d, r13), + DEFINE_GPR_PSEUDO_32(r14d, r14), + DEFINE_GPR_PSEUDO_32(r15d, r15), + DEFINE_GPR_PSEUDO_16(ax, rax), + DEFINE_GPR_PSEUDO_16(bx, rbx), + DEFINE_GPR_PSEUDO_16(cx, rcx), + DEFINE_GPR_PSEUDO_16(dx, rdx), + DEFINE_GPR_PSEUDO_16(di, rdi), + DEFINE_GPR_PSEUDO_16(si, rsi), + DEFINE_GPR_PSEUDO_16(bp, rbp), + DEFINE_GPR_PSEUDO_16(sp, rsp), + DEFINE_GPR_PSEUDO_16(r8w, r8), + DEFINE_GPR_PSEUDO_16(r9w, r9), + DEFINE_GPR_PSEUDO_16(r10w, r10), + DEFINE_GPR_PSEUDO_16(r11w, r11), + DEFINE_GPR_PSEUDO_16(r12w, r12), + DEFINE_GPR_PSEUDO_16(r13w, r13), + DEFINE_GPR_PSEUDO_16(r14w, r14), + DEFINE_GPR_PSEUDO_16(r15w, r15), + DEFINE_GPR_PSEUDO_8H(ah, rax), + DEFINE_GPR_PSEUDO_8H(bh, rbx), + DEFINE_GPR_PSEUDO_8H(ch, rcx), + DEFINE_GPR_PSEUDO_8H(dh, rdx), + DEFINE_GPR_PSEUDO_8L(al, rax), + DEFINE_GPR_PSEUDO_8L(bl, rbx), + DEFINE_GPR_PSEUDO_8L(cl, rcx), + DEFINE_GPR_PSEUDO_8L(dl, rdx), + DEFINE_GPR_PSEUDO_8L(dil, rdi), + DEFINE_GPR_PSEUDO_8L(sil, rsi), + DEFINE_GPR_PSEUDO_8L(bpl, rbp), + DEFINE_GPR_PSEUDO_8L(spl, rsp), + DEFINE_GPR_PSEUDO_8L(r8l, r8), + DEFINE_GPR_PSEUDO_8L(r9l, r9), + DEFINE_GPR_PSEUDO_8L(r10l, r10), + DEFINE_GPR_PSEUDO_8L(r11l, r11), + DEFINE_GPR_PSEUDO_8L(r12l, r12), + DEFINE_GPR_PSEUDO_8L(r13l, r13), + DEFINE_GPR_PSEUDO_8L(r14l, r14), + DEFINE_GPR_PSEUDO_8L(r15l, r15)}; // Floating point registers 64 bit -const DNBRegisterInfo -DNBArchImplX86_64::g_fpu_registers_no_avx[] = -{ - { e_regSetFPU, fpu_fcw , "fctrl" , NULL, Uint, Hex, FPU_SIZE_UINT(fcw) , FPU_OFFSET(fcw) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetFPU, fpu_fsw , "fstat" , NULL, Uint, Hex, FPU_SIZE_UINT(fsw) , FPU_OFFSET(fsw) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetFPU, fpu_ftw , "ftag" , NULL, Uint, Hex, FPU_SIZE_UINT(ftw) , FPU_OFFSET(ftw) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetFPU, fpu_fop , "fop" , NULL, Uint, Hex, FPU_SIZE_UINT(fop) , FPU_OFFSET(fop) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetFPU, fpu_ip , "fioff" , NULL, Uint, Hex, FPU_SIZE_UINT(ip) , FPU_OFFSET(ip) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetFPU, fpu_cs , "fiseg" , NULL, Uint, Hex, FPU_SIZE_UINT(cs) , FPU_OFFSET(cs) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetFPU, fpu_dp , "fooff" , NULL, Uint, Hex, FPU_SIZE_UINT(dp) , FPU_OFFSET(dp) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetFPU, fpu_ds , "foseg" , NULL, Uint, Hex, FPU_SIZE_UINT(ds) , FPU_OFFSET(ds) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetFPU, fpu_mxcsr , "mxcsr" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr) , FPU_OFFSET(mxcsr) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetFPU, fpu_mxcsrmask, "mxcsrmask" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsrmask) , FPU_OFFSET(mxcsrmask) , -1U, -1U, -1U, -1U, NULL, NULL }, - - { e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm0), FPU_OFFSET(stmm0), ehframe_dwarf_stmm0, ehframe_dwarf_stmm0, -1U, debugserver_stmm0, NULL, NULL }, - { e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm1), FPU_OFFSET(stmm1), ehframe_dwarf_stmm1, ehframe_dwarf_stmm1, -1U, debugserver_stmm1, NULL, NULL }, - { e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm2), FPU_OFFSET(stmm2), ehframe_dwarf_stmm2, ehframe_dwarf_stmm2, -1U, debugserver_stmm2, NULL, NULL }, - { e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm3), FPU_OFFSET(stmm3), ehframe_dwarf_stmm3, ehframe_dwarf_stmm3, -1U, debugserver_stmm3, NULL, NULL }, - { e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm4), FPU_OFFSET(stmm4), ehframe_dwarf_stmm4, ehframe_dwarf_stmm4, -1U, debugserver_stmm4, NULL, NULL }, - { e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm5), FPU_OFFSET(stmm5), ehframe_dwarf_stmm5, ehframe_dwarf_stmm5, -1U, debugserver_stmm5, NULL, NULL }, - { e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm6), FPU_OFFSET(stmm6), ehframe_dwarf_stmm6, ehframe_dwarf_stmm6, -1U, debugserver_stmm6, NULL, NULL }, - { e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm7), FPU_OFFSET(stmm7), ehframe_dwarf_stmm7, ehframe_dwarf_stmm7, -1U, debugserver_stmm7, NULL, NULL }, - - { e_regSetFPU, fpu_xmm0 , "xmm0" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm0) , FPU_OFFSET(xmm0) , ehframe_dwarf_xmm0 , ehframe_dwarf_xmm0 , -1U, debugserver_xmm0 , NULL, NULL }, - { e_regSetFPU, fpu_xmm1 , "xmm1" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm1) , FPU_OFFSET(xmm1) , ehframe_dwarf_xmm1 , ehframe_dwarf_xmm1 , -1U, debugserver_xmm1 , NULL, NULL }, - { e_regSetFPU, fpu_xmm2 , "xmm2" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm2) , FPU_OFFSET(xmm2) , ehframe_dwarf_xmm2 , ehframe_dwarf_xmm2 , -1U, debugserver_xmm2 , NULL, NULL }, - { e_regSetFPU, fpu_xmm3 , "xmm3" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm3) , FPU_OFFSET(xmm3) , ehframe_dwarf_xmm3 , ehframe_dwarf_xmm3 , -1U, debugserver_xmm3 , NULL, NULL }, - { e_regSetFPU, fpu_xmm4 , "xmm4" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm4) , FPU_OFFSET(xmm4) , ehframe_dwarf_xmm4 , ehframe_dwarf_xmm4 , -1U, debugserver_xmm4 , NULL, NULL }, - { e_regSetFPU, fpu_xmm5 , "xmm5" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm5) , FPU_OFFSET(xmm5) , ehframe_dwarf_xmm5 , ehframe_dwarf_xmm5 , -1U, debugserver_xmm5 , NULL, NULL }, - { e_regSetFPU, fpu_xmm6 , "xmm6" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm6) , FPU_OFFSET(xmm6) , ehframe_dwarf_xmm6 , ehframe_dwarf_xmm6 , -1U, debugserver_xmm6 , NULL, NULL }, - { e_regSetFPU, fpu_xmm7 , "xmm7" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm7) , FPU_OFFSET(xmm7) , ehframe_dwarf_xmm7 , ehframe_dwarf_xmm7 , -1U, debugserver_xmm7 , NULL, NULL }, - { e_regSetFPU, fpu_xmm8 , "xmm8" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm8) , FPU_OFFSET(xmm8) , ehframe_dwarf_xmm8 , ehframe_dwarf_xmm8 , -1U, debugserver_xmm8 , NULL, NULL }, - { e_regSetFPU, fpu_xmm9 , "xmm9" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm9) , FPU_OFFSET(xmm9) , ehframe_dwarf_xmm9 , ehframe_dwarf_xmm9 , -1U, debugserver_xmm9 , NULL, NULL }, - { e_regSetFPU, fpu_xmm10, "xmm10" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm10) , FPU_OFFSET(xmm10), ehframe_dwarf_xmm10, ehframe_dwarf_xmm10, -1U, debugserver_xmm10, NULL, NULL }, - { e_regSetFPU, fpu_xmm11, "xmm11" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm11) , FPU_OFFSET(xmm11), ehframe_dwarf_xmm11, ehframe_dwarf_xmm11, -1U, debugserver_xmm11, NULL, NULL }, - { e_regSetFPU, fpu_xmm12, "xmm12" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm12) , FPU_OFFSET(xmm12), ehframe_dwarf_xmm12, ehframe_dwarf_xmm12, -1U, debugserver_xmm12, NULL, NULL }, - { e_regSetFPU, fpu_xmm13, "xmm13" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm13) , FPU_OFFSET(xmm13), ehframe_dwarf_xmm13, ehframe_dwarf_xmm13, -1U, debugserver_xmm13, NULL, NULL }, - { e_regSetFPU, fpu_xmm14, "xmm14" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm14) , FPU_OFFSET(xmm14), ehframe_dwarf_xmm14, ehframe_dwarf_xmm14, -1U, debugserver_xmm14, NULL, NULL }, - { e_regSetFPU, fpu_xmm15, "xmm15" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm15) , FPU_OFFSET(xmm15), ehframe_dwarf_xmm15, ehframe_dwarf_xmm15, -1U, debugserver_xmm15, NULL, NULL }, +const DNBRegisterInfo DNBArchImplX86_64::g_fpu_registers_no_avx[] = { + {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw), + FPU_OFFSET(fcw), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw), + FPU_OFFSET(fsw), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, FPU_SIZE_UINT(ftw), + FPU_OFFSET(ftw), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop), + FPU_OFFSET(fop), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip), + FPU_OFFSET(ip), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs), + FPU_OFFSET(cs), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp), + FPU_OFFSET(dp), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds), + FPU_OFFSET(ds), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr), + FPU_OFFSET(mxcsr), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex, + FPU_SIZE_UINT(mxcsrmask), FPU_OFFSET(mxcsrmask), -1U, -1U, -1U, -1U, NULL, + NULL}, + + {e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm0), FPU_OFFSET(stmm0), ehframe_dwarf_stmm0, + ehframe_dwarf_stmm0, -1U, debugserver_stmm0, NULL, NULL}, + {e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm1), FPU_OFFSET(stmm1), ehframe_dwarf_stmm1, + ehframe_dwarf_stmm1, -1U, debugserver_stmm1, NULL, NULL}, + {e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm2), FPU_OFFSET(stmm2), ehframe_dwarf_stmm2, + ehframe_dwarf_stmm2, -1U, debugserver_stmm2, NULL, NULL}, + {e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm3), FPU_OFFSET(stmm3), ehframe_dwarf_stmm3, + ehframe_dwarf_stmm3, -1U, debugserver_stmm3, NULL, NULL}, + {e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm4), FPU_OFFSET(stmm4), ehframe_dwarf_stmm4, + ehframe_dwarf_stmm4, -1U, debugserver_stmm4, NULL, NULL}, + {e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm5), FPU_OFFSET(stmm5), ehframe_dwarf_stmm5, + ehframe_dwarf_stmm5, -1U, debugserver_stmm5, NULL, NULL}, + {e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm6), FPU_OFFSET(stmm6), ehframe_dwarf_stmm6, + ehframe_dwarf_stmm6, -1U, debugserver_stmm6, NULL, NULL}, + {e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm7), FPU_OFFSET(stmm7), ehframe_dwarf_stmm7, + ehframe_dwarf_stmm7, -1U, debugserver_stmm7, NULL, NULL}, + + {e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm0), FPU_OFFSET(xmm0), ehframe_dwarf_xmm0, + ehframe_dwarf_xmm0, -1U, debugserver_xmm0, NULL, NULL}, + {e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm1), FPU_OFFSET(xmm1), ehframe_dwarf_xmm1, + ehframe_dwarf_xmm1, -1U, debugserver_xmm1, NULL, NULL}, + {e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm2), FPU_OFFSET(xmm2), ehframe_dwarf_xmm2, + ehframe_dwarf_xmm2, -1U, debugserver_xmm2, NULL, NULL}, + {e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm3), FPU_OFFSET(xmm3), ehframe_dwarf_xmm3, + ehframe_dwarf_xmm3, -1U, debugserver_xmm3, NULL, NULL}, + {e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm4), FPU_OFFSET(xmm4), ehframe_dwarf_xmm4, + ehframe_dwarf_xmm4, -1U, debugserver_xmm4, NULL, NULL}, + {e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm5), FPU_OFFSET(xmm5), ehframe_dwarf_xmm5, + ehframe_dwarf_xmm5, -1U, debugserver_xmm5, NULL, NULL}, + {e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm6), FPU_OFFSET(xmm6), ehframe_dwarf_xmm6, + ehframe_dwarf_xmm6, -1U, debugserver_xmm6, NULL, NULL}, + {e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm7), FPU_OFFSET(xmm7), ehframe_dwarf_xmm7, + ehframe_dwarf_xmm7, -1U, debugserver_xmm7, NULL, NULL}, + {e_regSetFPU, fpu_xmm8, "xmm8", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm8), FPU_OFFSET(xmm8), ehframe_dwarf_xmm8, + ehframe_dwarf_xmm8, -1U, debugserver_xmm8, NULL, NULL}, + {e_regSetFPU, fpu_xmm9, "xmm9", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm9), FPU_OFFSET(xmm9), ehframe_dwarf_xmm9, + ehframe_dwarf_xmm9, -1U, debugserver_xmm9, NULL, NULL}, + {e_regSetFPU, fpu_xmm10, "xmm10", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm10), FPU_OFFSET(xmm10), ehframe_dwarf_xmm10, + ehframe_dwarf_xmm10, -1U, debugserver_xmm10, NULL, NULL}, + {e_regSetFPU, fpu_xmm11, "xmm11", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm11), FPU_OFFSET(xmm11), ehframe_dwarf_xmm11, + ehframe_dwarf_xmm11, -1U, debugserver_xmm11, NULL, NULL}, + {e_regSetFPU, fpu_xmm12, "xmm12", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm12), FPU_OFFSET(xmm12), ehframe_dwarf_xmm12, + ehframe_dwarf_xmm12, -1U, debugserver_xmm12, NULL, NULL}, + {e_regSetFPU, fpu_xmm13, "xmm13", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm13), FPU_OFFSET(xmm13), ehframe_dwarf_xmm13, + ehframe_dwarf_xmm13, -1U, debugserver_xmm13, NULL, NULL}, + {e_regSetFPU, fpu_xmm14, "xmm14", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm14), FPU_OFFSET(xmm14), ehframe_dwarf_xmm14, + ehframe_dwarf_xmm14, -1U, debugserver_xmm14, NULL, NULL}, + {e_regSetFPU, fpu_xmm15, "xmm15", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm15), FPU_OFFSET(xmm15), ehframe_dwarf_xmm15, + ehframe_dwarf_xmm15, -1U, debugserver_xmm15, NULL, NULL}, }; -static const char *g_contained_ymm0 [] = { "ymm0", NULL }; -static const char *g_contained_ymm1 [] = { "ymm1", NULL }; -static const char *g_contained_ymm2 [] = { "ymm2", NULL }; -static const char *g_contained_ymm3 [] = { "ymm3", NULL }; -static const char *g_contained_ymm4 [] = { "ymm4", NULL }; -static const char *g_contained_ymm5 [] = { "ymm5", NULL }; -static const char *g_contained_ymm6 [] = { "ymm6", NULL }; -static const char *g_contained_ymm7 [] = { "ymm7", NULL }; -static const char *g_contained_ymm8 [] = { "ymm8", NULL }; -static const char *g_contained_ymm9 [] = { "ymm9", NULL }; -static const char *g_contained_ymm10[] = { "ymm10", NULL }; -static const char *g_contained_ymm11[] = { "ymm11", NULL }; -static const char *g_contained_ymm12[] = { "ymm12", NULL }; -static const char *g_contained_ymm13[] = { "ymm13", NULL }; -static const char *g_contained_ymm14[] = { "ymm14", NULL }; -static const char *g_contained_ymm15[] = { "ymm15", NULL }; - -const DNBRegisterInfo -DNBArchImplX86_64::g_fpu_registers_avx[] = -{ - { e_regSetFPU, fpu_fcw , "fctrl" , NULL, Uint, Hex, FPU_SIZE_UINT(fcw) , AVX_OFFSET(fcw) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetFPU, fpu_fsw , "fstat" , NULL, Uint, Hex, FPU_SIZE_UINT(fsw) , AVX_OFFSET(fsw) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetFPU, fpu_ftw , "ftag" , NULL, Uint, Hex, FPU_SIZE_UINT(ftw) , AVX_OFFSET(ftw) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetFPU, fpu_fop , "fop" , NULL, Uint, Hex, FPU_SIZE_UINT(fop) , AVX_OFFSET(fop) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetFPU, fpu_ip , "fioff" , NULL, Uint, Hex, FPU_SIZE_UINT(ip) , AVX_OFFSET(ip) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetFPU, fpu_cs , "fiseg" , NULL, Uint, Hex, FPU_SIZE_UINT(cs) , AVX_OFFSET(cs) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetFPU, fpu_dp , "fooff" , NULL, Uint, Hex, FPU_SIZE_UINT(dp) , AVX_OFFSET(dp) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetFPU, fpu_ds , "foseg" , NULL, Uint, Hex, FPU_SIZE_UINT(ds) , AVX_OFFSET(ds) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetFPU, fpu_mxcsr , "mxcsr" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr) , AVX_OFFSET(mxcsr) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetFPU, fpu_mxcsrmask, "mxcsrmask" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsrmask) , AVX_OFFSET(mxcsrmask) , -1U, -1U, -1U, -1U, NULL, NULL }, - - { e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm0), AVX_OFFSET(stmm0), ehframe_dwarf_stmm0, ehframe_dwarf_stmm0, -1U, debugserver_stmm0, NULL, NULL }, - { e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm1), AVX_OFFSET(stmm1), ehframe_dwarf_stmm1, ehframe_dwarf_stmm1, -1U, debugserver_stmm1, NULL, NULL }, - { e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm2), AVX_OFFSET(stmm2), ehframe_dwarf_stmm2, ehframe_dwarf_stmm2, -1U, debugserver_stmm2, NULL, NULL }, - { e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm3), AVX_OFFSET(stmm3), ehframe_dwarf_stmm3, ehframe_dwarf_stmm3, -1U, debugserver_stmm3, NULL, NULL }, - { e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm4), AVX_OFFSET(stmm4), ehframe_dwarf_stmm4, ehframe_dwarf_stmm4, -1U, debugserver_stmm4, NULL, NULL }, - { e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm5), AVX_OFFSET(stmm5), ehframe_dwarf_stmm5, ehframe_dwarf_stmm5, -1U, debugserver_stmm5, NULL, NULL }, - { e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm6), AVX_OFFSET(stmm6), ehframe_dwarf_stmm6, ehframe_dwarf_stmm6, -1U, debugserver_stmm6, NULL, NULL }, - { e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm7), AVX_OFFSET(stmm7), ehframe_dwarf_stmm7, ehframe_dwarf_stmm7, -1U, debugserver_stmm7, NULL, NULL }, - - { e_regSetFPU, fpu_ymm0 , "ymm0" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm0) , AVX_OFFSET_YMM(0) , ehframe_dwarf_ymm0 , ehframe_dwarf_ymm0 , -1U, debugserver_ymm0, NULL, NULL }, - { e_regSetFPU, fpu_ymm1 , "ymm1" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm1) , AVX_OFFSET_YMM(1) , ehframe_dwarf_ymm1 , ehframe_dwarf_ymm1 , -1U, debugserver_ymm1, NULL, NULL }, - { e_regSetFPU, fpu_ymm2 , "ymm2" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm2) , AVX_OFFSET_YMM(2) , ehframe_dwarf_ymm2 , ehframe_dwarf_ymm2 , -1U, debugserver_ymm2, NULL, NULL }, - { e_regSetFPU, fpu_ymm3 , "ymm3" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm3) , AVX_OFFSET_YMM(3) , ehframe_dwarf_ymm3 , ehframe_dwarf_ymm3 , -1U, debugserver_ymm3, NULL, NULL }, - { e_regSetFPU, fpu_ymm4 , "ymm4" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm4) , AVX_OFFSET_YMM(4) , ehframe_dwarf_ymm4 , ehframe_dwarf_ymm4 , -1U, debugserver_ymm4, NULL, NULL }, - { e_regSetFPU, fpu_ymm5 , "ymm5" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm5) , AVX_OFFSET_YMM(5) , ehframe_dwarf_ymm5 , ehframe_dwarf_ymm5 , -1U, debugserver_ymm5, NULL, NULL }, - { e_regSetFPU, fpu_ymm6 , "ymm6" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm6) , AVX_OFFSET_YMM(6) , ehframe_dwarf_ymm6 , ehframe_dwarf_ymm6 , -1U, debugserver_ymm6, NULL, NULL }, - { e_regSetFPU, fpu_ymm7 , "ymm7" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm7) , AVX_OFFSET_YMM(7) , ehframe_dwarf_ymm7 , ehframe_dwarf_ymm7 , -1U, debugserver_ymm7, NULL, NULL }, - { e_regSetFPU, fpu_ymm8 , "ymm8" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm8) , AVX_OFFSET_YMM(8) , ehframe_dwarf_ymm8 , ehframe_dwarf_ymm8 , -1U, debugserver_ymm8 , NULL, NULL }, - { e_regSetFPU, fpu_ymm9 , "ymm9" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm9) , AVX_OFFSET_YMM(9) , ehframe_dwarf_ymm9 , ehframe_dwarf_ymm9 , -1U, debugserver_ymm9 , NULL, NULL }, - { e_regSetFPU, fpu_ymm10, "ymm10" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm10) , AVX_OFFSET_YMM(10), ehframe_dwarf_ymm10, ehframe_dwarf_ymm10, -1U, debugserver_ymm10, NULL, NULL }, - { e_regSetFPU, fpu_ymm11, "ymm11" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm11) , AVX_OFFSET_YMM(11), ehframe_dwarf_ymm11, ehframe_dwarf_ymm11, -1U, debugserver_ymm11, NULL, NULL }, - { e_regSetFPU, fpu_ymm12, "ymm12" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm12) , AVX_OFFSET_YMM(12), ehframe_dwarf_ymm12, ehframe_dwarf_ymm12, -1U, debugserver_ymm12, NULL, NULL }, - { e_regSetFPU, fpu_ymm13, "ymm13" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm13) , AVX_OFFSET_YMM(13), ehframe_dwarf_ymm13, ehframe_dwarf_ymm13, -1U, debugserver_ymm13, NULL, NULL }, - { e_regSetFPU, fpu_ymm14, "ymm14" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm14) , AVX_OFFSET_YMM(14), ehframe_dwarf_ymm14, ehframe_dwarf_ymm14, -1U, debugserver_ymm14, NULL, NULL }, - { e_regSetFPU, fpu_ymm15, "ymm15" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm15) , AVX_OFFSET_YMM(15), ehframe_dwarf_ymm15, ehframe_dwarf_ymm15, -1U, debugserver_ymm15, NULL, NULL }, - - { e_regSetFPU, fpu_xmm0 , "xmm0" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm0) , 0, ehframe_dwarf_xmm0 , ehframe_dwarf_xmm0 , -1U, debugserver_xmm0 , g_contained_ymm0 , NULL }, - { e_regSetFPU, fpu_xmm1 , "xmm1" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm1) , 0, ehframe_dwarf_xmm1 , ehframe_dwarf_xmm1 , -1U, debugserver_xmm1 , g_contained_ymm1 , NULL }, - { e_regSetFPU, fpu_xmm2 , "xmm2" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm2) , 0, ehframe_dwarf_xmm2 , ehframe_dwarf_xmm2 , -1U, debugserver_xmm2 , g_contained_ymm2 , NULL }, - { e_regSetFPU, fpu_xmm3 , "xmm3" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm3) , 0, ehframe_dwarf_xmm3 , ehframe_dwarf_xmm3 , -1U, debugserver_xmm3 , g_contained_ymm3 , NULL }, - { e_regSetFPU, fpu_xmm4 , "xmm4" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm4) , 0, ehframe_dwarf_xmm4 , ehframe_dwarf_xmm4 , -1U, debugserver_xmm4 , g_contained_ymm4 , NULL }, - { e_regSetFPU, fpu_xmm5 , "xmm5" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm5) , 0, ehframe_dwarf_xmm5 , ehframe_dwarf_xmm5 , -1U, debugserver_xmm5 , g_contained_ymm5 , NULL }, - { e_regSetFPU, fpu_xmm6 , "xmm6" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm6) , 0, ehframe_dwarf_xmm6 , ehframe_dwarf_xmm6 , -1U, debugserver_xmm6 , g_contained_ymm6 , NULL }, - { e_regSetFPU, fpu_xmm7 , "xmm7" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm7) , 0, ehframe_dwarf_xmm7 , ehframe_dwarf_xmm7 , -1U, debugserver_xmm7 , g_contained_ymm7 , NULL }, - { e_regSetFPU, fpu_xmm8 , "xmm8" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm8) , 0, ehframe_dwarf_xmm8 , ehframe_dwarf_xmm8 , -1U, debugserver_xmm8 , g_contained_ymm8 , NULL }, - { e_regSetFPU, fpu_xmm9 , "xmm9" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm9) , 0, ehframe_dwarf_xmm9 , ehframe_dwarf_xmm9 , -1U, debugserver_xmm9 , g_contained_ymm9 , NULL }, - { e_regSetFPU, fpu_xmm10, "xmm10" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm10) , 0, ehframe_dwarf_xmm10, ehframe_dwarf_xmm10, -1U, debugserver_xmm10, g_contained_ymm10, NULL }, - { e_regSetFPU, fpu_xmm11, "xmm11" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm11) , 0, ehframe_dwarf_xmm11, ehframe_dwarf_xmm11, -1U, debugserver_xmm11, g_contained_ymm11, NULL }, - { e_regSetFPU, fpu_xmm12, "xmm12" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm12) , 0, ehframe_dwarf_xmm12, ehframe_dwarf_xmm12, -1U, debugserver_xmm12, g_contained_ymm12, NULL }, - { e_regSetFPU, fpu_xmm13, "xmm13" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm13) , 0, ehframe_dwarf_xmm13, ehframe_dwarf_xmm13, -1U, debugserver_xmm13, g_contained_ymm13, NULL }, - { e_regSetFPU, fpu_xmm14, "xmm14" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm14) , 0, ehframe_dwarf_xmm14, ehframe_dwarf_xmm14, -1U, debugserver_xmm14, g_contained_ymm14, NULL }, - { e_regSetFPU, fpu_xmm15, "xmm15" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm15) , 0, ehframe_dwarf_xmm15, ehframe_dwarf_xmm15, -1U, debugserver_xmm15, g_contained_ymm15, NULL } - +static const char *g_contained_ymm0[] = {"ymm0", NULL}; +static const char *g_contained_ymm1[] = {"ymm1", NULL}; +static const char *g_contained_ymm2[] = {"ymm2", NULL}; +static const char *g_contained_ymm3[] = {"ymm3", NULL}; +static const char *g_contained_ymm4[] = {"ymm4", NULL}; +static const char *g_contained_ymm5[] = {"ymm5", NULL}; +static const char *g_contained_ymm6[] = {"ymm6", NULL}; +static const char *g_contained_ymm7[] = {"ymm7", NULL}; +static const char *g_contained_ymm8[] = {"ymm8", NULL}; +static const char *g_contained_ymm9[] = {"ymm9", NULL}; +static const char *g_contained_ymm10[] = {"ymm10", NULL}; +static const char *g_contained_ymm11[] = {"ymm11", NULL}; +static const char *g_contained_ymm12[] = {"ymm12", NULL}; +static const char *g_contained_ymm13[] = {"ymm13", NULL}; +static const char *g_contained_ymm14[] = {"ymm14", NULL}; +static const char *g_contained_ymm15[] = {"ymm15", NULL}; + +const DNBRegisterInfo DNBArchImplX86_64::g_fpu_registers_avx[] = { + {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw), + AVX_OFFSET(fcw), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw), + AVX_OFFSET(fsw), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, FPU_SIZE_UINT(ftw), + AVX_OFFSET(ftw), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop), + AVX_OFFSET(fop), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip), + AVX_OFFSET(ip), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs), + AVX_OFFSET(cs), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp), + AVX_OFFSET(dp), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds), + AVX_OFFSET(ds), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr), + AVX_OFFSET(mxcsr), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex, + FPU_SIZE_UINT(mxcsrmask), AVX_OFFSET(mxcsrmask), -1U, -1U, -1U, -1U, NULL, + NULL}, + + {e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm0), AVX_OFFSET(stmm0), ehframe_dwarf_stmm0, + ehframe_dwarf_stmm0, -1U, debugserver_stmm0, NULL, NULL}, + {e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm1), AVX_OFFSET(stmm1), ehframe_dwarf_stmm1, + ehframe_dwarf_stmm1, -1U, debugserver_stmm1, NULL, NULL}, + {e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm2), AVX_OFFSET(stmm2), ehframe_dwarf_stmm2, + ehframe_dwarf_stmm2, -1U, debugserver_stmm2, NULL, NULL}, + {e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm3), AVX_OFFSET(stmm3), ehframe_dwarf_stmm3, + ehframe_dwarf_stmm3, -1U, debugserver_stmm3, NULL, NULL}, + {e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm4), AVX_OFFSET(stmm4), ehframe_dwarf_stmm4, + ehframe_dwarf_stmm4, -1U, debugserver_stmm4, NULL, NULL}, + {e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm5), AVX_OFFSET(stmm5), ehframe_dwarf_stmm5, + ehframe_dwarf_stmm5, -1U, debugserver_stmm5, NULL, NULL}, + {e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm6), AVX_OFFSET(stmm6), ehframe_dwarf_stmm6, + ehframe_dwarf_stmm6, -1U, debugserver_stmm6, NULL, NULL}, + {e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, + FPU_SIZE_MMST(stmm7), AVX_OFFSET(stmm7), ehframe_dwarf_stmm7, + ehframe_dwarf_stmm7, -1U, debugserver_stmm7, NULL, NULL}, + + {e_regSetFPU, fpu_ymm0, "ymm0", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm0), AVX_OFFSET_YMM(0), ehframe_dwarf_ymm0, + ehframe_dwarf_ymm0, -1U, debugserver_ymm0, NULL, NULL}, + {e_regSetFPU, fpu_ymm1, "ymm1", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm1), AVX_OFFSET_YMM(1), ehframe_dwarf_ymm1, + ehframe_dwarf_ymm1, -1U, debugserver_ymm1, NULL, NULL}, + {e_regSetFPU, fpu_ymm2, "ymm2", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm2), AVX_OFFSET_YMM(2), ehframe_dwarf_ymm2, + ehframe_dwarf_ymm2, -1U, debugserver_ymm2, NULL, NULL}, + {e_regSetFPU, fpu_ymm3, "ymm3", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm3), AVX_OFFSET_YMM(3), ehframe_dwarf_ymm3, + ehframe_dwarf_ymm3, -1U, debugserver_ymm3, NULL, NULL}, + {e_regSetFPU, fpu_ymm4, "ymm4", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm4), AVX_OFFSET_YMM(4), ehframe_dwarf_ymm4, + ehframe_dwarf_ymm4, -1U, debugserver_ymm4, NULL, NULL}, + {e_regSetFPU, fpu_ymm5, "ymm5", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm5), AVX_OFFSET_YMM(5), ehframe_dwarf_ymm5, + ehframe_dwarf_ymm5, -1U, debugserver_ymm5, NULL, NULL}, + {e_regSetFPU, fpu_ymm6, "ymm6", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm6), AVX_OFFSET_YMM(6), ehframe_dwarf_ymm6, + ehframe_dwarf_ymm6, -1U, debugserver_ymm6, NULL, NULL}, + {e_regSetFPU, fpu_ymm7, "ymm7", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm7), AVX_OFFSET_YMM(7), ehframe_dwarf_ymm7, + ehframe_dwarf_ymm7, -1U, debugserver_ymm7, NULL, NULL}, + {e_regSetFPU, fpu_ymm8, "ymm8", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm8), AVX_OFFSET_YMM(8), ehframe_dwarf_ymm8, + ehframe_dwarf_ymm8, -1U, debugserver_ymm8, NULL, NULL}, + {e_regSetFPU, fpu_ymm9, "ymm9", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm9), AVX_OFFSET_YMM(9), ehframe_dwarf_ymm9, + ehframe_dwarf_ymm9, -1U, debugserver_ymm9, NULL, NULL}, + {e_regSetFPU, fpu_ymm10, "ymm10", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm10), AVX_OFFSET_YMM(10), ehframe_dwarf_ymm10, + ehframe_dwarf_ymm10, -1U, debugserver_ymm10, NULL, NULL}, + {e_regSetFPU, fpu_ymm11, "ymm11", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm11), AVX_OFFSET_YMM(11), ehframe_dwarf_ymm11, + ehframe_dwarf_ymm11, -1U, debugserver_ymm11, NULL, NULL}, + {e_regSetFPU, fpu_ymm12, "ymm12", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm12), AVX_OFFSET_YMM(12), ehframe_dwarf_ymm12, + ehframe_dwarf_ymm12, -1U, debugserver_ymm12, NULL, NULL}, + {e_regSetFPU, fpu_ymm13, "ymm13", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm13), AVX_OFFSET_YMM(13), ehframe_dwarf_ymm13, + ehframe_dwarf_ymm13, -1U, debugserver_ymm13, NULL, NULL}, + {e_regSetFPU, fpu_ymm14, "ymm14", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm14), AVX_OFFSET_YMM(14), ehframe_dwarf_ymm14, + ehframe_dwarf_ymm14, -1U, debugserver_ymm14, NULL, NULL}, + {e_regSetFPU, fpu_ymm15, "ymm15", NULL, Vector, VectorOfUInt8, + FPU_SIZE_YMM(ymm15), AVX_OFFSET_YMM(15), ehframe_dwarf_ymm15, + ehframe_dwarf_ymm15, -1U, debugserver_ymm15, NULL, NULL}, + + {e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm0), 0, ehframe_dwarf_xmm0, ehframe_dwarf_xmm0, -1U, + debugserver_xmm0, g_contained_ymm0, NULL}, + {e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm1), 0, ehframe_dwarf_xmm1, ehframe_dwarf_xmm1, -1U, + debugserver_xmm1, g_contained_ymm1, NULL}, + {e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm2), 0, ehframe_dwarf_xmm2, ehframe_dwarf_xmm2, -1U, + debugserver_xmm2, g_contained_ymm2, NULL}, + {e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm3), 0, ehframe_dwarf_xmm3, ehframe_dwarf_xmm3, -1U, + debugserver_xmm3, g_contained_ymm3, NULL}, + {e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm4), 0, ehframe_dwarf_xmm4, ehframe_dwarf_xmm4, -1U, + debugserver_xmm4, g_contained_ymm4, NULL}, + {e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm5), 0, ehframe_dwarf_xmm5, ehframe_dwarf_xmm5, -1U, + debugserver_xmm5, g_contained_ymm5, NULL}, + {e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm6), 0, ehframe_dwarf_xmm6, ehframe_dwarf_xmm6, -1U, + debugserver_xmm6, g_contained_ymm6, NULL}, + {e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm7), 0, ehframe_dwarf_xmm7, ehframe_dwarf_xmm7, -1U, + debugserver_xmm7, g_contained_ymm7, NULL}, + {e_regSetFPU, fpu_xmm8, "xmm8", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm8), 0, ehframe_dwarf_xmm8, ehframe_dwarf_xmm8, -1U, + debugserver_xmm8, g_contained_ymm8, NULL}, + {e_regSetFPU, fpu_xmm9, "xmm9", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm9), 0, ehframe_dwarf_xmm9, ehframe_dwarf_xmm9, -1U, + debugserver_xmm9, g_contained_ymm9, NULL}, + {e_regSetFPU, fpu_xmm10, "xmm10", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm10), 0, ehframe_dwarf_xmm10, ehframe_dwarf_xmm10, -1U, + debugserver_xmm10, g_contained_ymm10, NULL}, + {e_regSetFPU, fpu_xmm11, "xmm11", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm11), 0, ehframe_dwarf_xmm11, ehframe_dwarf_xmm11, -1U, + debugserver_xmm11, g_contained_ymm11, NULL}, + {e_regSetFPU, fpu_xmm12, "xmm12", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm12), 0, ehframe_dwarf_xmm12, ehframe_dwarf_xmm12, -1U, + debugserver_xmm12, g_contained_ymm12, NULL}, + {e_regSetFPU, fpu_xmm13, "xmm13", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm13), 0, ehframe_dwarf_xmm13, ehframe_dwarf_xmm13, -1U, + debugserver_xmm13, g_contained_ymm13, NULL}, + {e_regSetFPU, fpu_xmm14, "xmm14", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm14), 0, ehframe_dwarf_xmm14, ehframe_dwarf_xmm14, -1U, + debugserver_xmm14, g_contained_ymm14, NULL}, + {e_regSetFPU, fpu_xmm15, "xmm15", NULL, Vector, VectorOfUInt8, + FPU_SIZE_XMM(xmm15), 0, ehframe_dwarf_xmm15, ehframe_dwarf_xmm15, -1U, + debugserver_xmm15, g_contained_ymm15, NULL} }; // Exception registers -const DNBRegisterInfo -DNBArchImplX86_64::g_exc_registers[] = -{ - { e_regSetEXC, exc_trapno, "trapno" , NULL, Uint, Hex, EXC_SIZE (trapno) , EXC_OFFSET (trapno) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetEXC, exc_err, "err" , NULL, Uint, Hex, EXC_SIZE (err) , EXC_OFFSET (err) , -1U, -1U, -1U, -1U, NULL, NULL }, - { e_regSetEXC, exc_faultvaddr, "faultvaddr", NULL, Uint, Hex, EXC_SIZE (faultvaddr), EXC_OFFSET (faultvaddr) , -1U, -1U, -1U, -1U, NULL, NULL } -}; +const DNBRegisterInfo DNBArchImplX86_64::g_exc_registers[] = { + {e_regSetEXC, exc_trapno, "trapno", NULL, Uint, Hex, EXC_SIZE(trapno), + EXC_OFFSET(trapno), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetEXC, exc_err, "err", NULL, Uint, Hex, EXC_SIZE(err), + EXC_OFFSET(err), -1U, -1U, -1U, -1U, NULL, NULL}, + {e_regSetEXC, exc_faultvaddr, "faultvaddr", NULL, Uint, Hex, + EXC_SIZE(faultvaddr), EXC_OFFSET(faultvaddr), -1U, -1U, -1U, -1U, NULL, + NULL}}; // Number of registers in each register set -const size_t DNBArchImplX86_64::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo); -const size_t DNBArchImplX86_64::k_num_fpu_registers_no_avx = sizeof(g_fpu_registers_no_avx)/sizeof(DNBRegisterInfo); -const size_t DNBArchImplX86_64::k_num_fpu_registers_avx = sizeof(g_fpu_registers_avx)/sizeof(DNBRegisterInfo); -const size_t DNBArchImplX86_64::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo); -const size_t DNBArchImplX86_64::k_num_all_registers_no_avx = k_num_gpr_registers + k_num_fpu_registers_no_avx + k_num_exc_registers; -const size_t DNBArchImplX86_64::k_num_all_registers_avx = k_num_gpr_registers + k_num_fpu_registers_avx + k_num_exc_registers; +const size_t DNBArchImplX86_64::k_num_gpr_registers = + sizeof(g_gpr_registers) / sizeof(DNBRegisterInfo); +const size_t DNBArchImplX86_64::k_num_fpu_registers_no_avx = + sizeof(g_fpu_registers_no_avx) / sizeof(DNBRegisterInfo); +const size_t DNBArchImplX86_64::k_num_fpu_registers_avx = + sizeof(g_fpu_registers_avx) / sizeof(DNBRegisterInfo); +const size_t DNBArchImplX86_64::k_num_exc_registers = + sizeof(g_exc_registers) / sizeof(DNBRegisterInfo); +const size_t DNBArchImplX86_64::k_num_all_registers_no_avx = + k_num_gpr_registers + k_num_fpu_registers_no_avx + k_num_exc_registers; +const size_t DNBArchImplX86_64::k_num_all_registers_avx = + k_num_gpr_registers + k_num_fpu_registers_avx + k_num_exc_registers; //---------------------------------------------------------------------- // Register set definitions. The first definitions at register set index // of zero is for all registers, followed by other registers sets. The // register information for the all register set need not be filled in. //---------------------------------------------------------------------- -const DNBRegisterSetInfo -DNBArchImplX86_64::g_reg_sets_no_avx[] = -{ - { "x86_64 Registers", NULL, k_num_all_registers_no_avx }, - { "General Purpose Registers", g_gpr_registers, k_num_gpr_registers }, - { "Floating Point Registers", g_fpu_registers_no_avx, k_num_fpu_registers_no_avx }, - { "Exception State Registers", g_exc_registers, k_num_exc_registers } -}; - -const DNBRegisterSetInfo -DNBArchImplX86_64::g_reg_sets_avx[] = -{ - { "x86_64 Registers", NULL, k_num_all_registers_avx }, - { "General Purpose Registers", g_gpr_registers, k_num_gpr_registers }, - { "Floating Point Registers", g_fpu_registers_avx, k_num_fpu_registers_avx }, - { "Exception State Registers", g_exc_registers, k_num_exc_registers } -}; +const DNBRegisterSetInfo DNBArchImplX86_64::g_reg_sets_no_avx[] = { + {"x86_64 Registers", NULL, k_num_all_registers_no_avx}, + {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers}, + {"Floating Point Registers", g_fpu_registers_no_avx, + k_num_fpu_registers_no_avx}, + {"Exception State Registers", g_exc_registers, k_num_exc_registers}}; + +const DNBRegisterSetInfo DNBArchImplX86_64::g_reg_sets_avx[] = { + {"x86_64 Registers", NULL, k_num_all_registers_avx}, + {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers}, + {"Floating Point Registers", g_fpu_registers_avx, k_num_fpu_registers_avx}, + {"Exception State Registers", g_exc_registers, k_num_exc_registers}}; // Total number of register sets for this architecture -const size_t DNBArchImplX86_64::k_num_register_sets = sizeof(g_reg_sets_avx)/sizeof(DNBRegisterSetInfo); - +const size_t DNBArchImplX86_64::k_num_register_sets = + sizeof(g_reg_sets_avx) / sizeof(DNBRegisterSetInfo); -DNBArchProtocol * -DNBArchImplX86_64::Create (MachThread *thread) -{ - DNBArchImplX86_64 *obj = new DNBArchImplX86_64 (thread); - return obj; +DNBArchProtocol *DNBArchImplX86_64::Create(MachThread *thread) { + DNBArchImplX86_64 *obj = new DNBArchImplX86_64(thread); + return obj; } const uint8_t * -DNBArchImplX86_64::SoftwareBreakpointOpcode (nub_size_t byte_size) -{ - static const uint8_t g_breakpoint_opcode[] = { 0xCC }; - if (byte_size == 1) - return g_breakpoint_opcode; - return NULL; +DNBArchImplX86_64::SoftwareBreakpointOpcode(nub_size_t byte_size) { + static const uint8_t g_breakpoint_opcode[] = {0xCC}; + if (byte_size == 1) + return g_breakpoint_opcode; + return NULL; } const DNBRegisterSetInfo * -DNBArchImplX86_64::GetRegisterSetInfo(nub_size_t *num_reg_sets) -{ - *num_reg_sets = k_num_register_sets; - - if (CPUHasAVX() || FORCE_AVX_REGS) - return g_reg_sets_avx; - else - return g_reg_sets_no_avx; +DNBArchImplX86_64::GetRegisterSetInfo(nub_size_t *num_reg_sets) { + *num_reg_sets = k_num_register_sets; + + if (CPUHasAVX() || FORCE_AVX_REGS) + return g_reg_sets_avx; + else + return g_reg_sets_no_avx; } -void -DNBArchImplX86_64::Initialize() -{ - DNBArchPluginInfo arch_plugin_info = - { - CPU_TYPE_X86_64, - DNBArchImplX86_64::Create, - DNBArchImplX86_64::GetRegisterSetInfo, - DNBArchImplX86_64::SoftwareBreakpointOpcode - }; - - // Register this arch plug-in with the main protocol class - DNBArchProtocol::RegisterArchPlugin (arch_plugin_info); +void DNBArchImplX86_64::Initialize() { + DNBArchPluginInfo arch_plugin_info = { + CPU_TYPE_X86_64, DNBArchImplX86_64::Create, + DNBArchImplX86_64::GetRegisterSetInfo, + DNBArchImplX86_64::SoftwareBreakpointOpcode}; + + // Register this arch plug-in with the main protocol class + DNBArchProtocol::RegisterArchPlugin(arch_plugin_info); } -bool -DNBArchImplX86_64::GetRegisterValue(uint32_t set, uint32_t reg, DNBRegisterValue *value) -{ - if (set == REGISTER_SET_GENERIC) - { - switch (reg) - { - case GENERIC_REGNUM_PC: // Program Counter - set = e_regSetGPR; - reg = gpr_rip; - break; - - case GENERIC_REGNUM_SP: // Stack Pointer - set = e_regSetGPR; - reg = gpr_rsp; - break; - - case GENERIC_REGNUM_FP: // Frame Pointer - set = e_regSetGPR; - reg = gpr_rbp; - break; - - case GENERIC_REGNUM_FLAGS: // Processor flags register - set = e_regSetGPR; - reg = gpr_rflags; - break; - - case GENERIC_REGNUM_RA: // Return Address - default: - return false; - } +bool DNBArchImplX86_64::GetRegisterValue(uint32_t set, uint32_t reg, + DNBRegisterValue *value) { + if (set == REGISTER_SET_GENERIC) { + switch (reg) { + case GENERIC_REGNUM_PC: // Program Counter + set = e_regSetGPR; + reg = gpr_rip; + break; + + case GENERIC_REGNUM_SP: // Stack Pointer + set = e_regSetGPR; + reg = gpr_rsp; + break; + + case GENERIC_REGNUM_FP: // Frame Pointer + set = e_regSetGPR; + reg = gpr_rbp; + break; + + case GENERIC_REGNUM_FLAGS: // Processor flags register + set = e_regSetGPR; + reg = gpr_rflags; + break; + + case GENERIC_REGNUM_RA: // Return Address + default: + return false; } - - if (GetRegisterState(set, false) != KERN_SUCCESS) - return false; - - const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); - if (regInfo) - { - value->info = *regInfo; - switch (set) - { - case e_regSetGPR: - if (reg < k_num_gpr_registers) - { - value->value.uint64 = ((uint64_t*)(&m_state.context.gpr))[reg]; - return true; - } - break; - - case e_regSetFPU: - if (CPUHasAVX() || FORCE_AVX_REGS) - { - switch (reg) - { - case fpu_fcw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw)); return true; - case fpu_fsw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw)); return true; - case fpu_ftw: value->value.uint8 = m_state.context.fpu.avx.__fpu_ftw; return true; - case fpu_fop: value->value.uint16 = m_state.context.fpu.avx.__fpu_fop; return true; - case fpu_ip: value->value.uint32 = m_state.context.fpu.avx.__fpu_ip; return true; - case fpu_cs: value->value.uint16 = m_state.context.fpu.avx.__fpu_cs; return true; - case fpu_dp: value->value.uint32 = m_state.context.fpu.avx.__fpu_dp; return true; - case fpu_ds: value->value.uint16 = m_state.context.fpu.avx.__fpu_ds; return true; - case fpu_mxcsr: value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsr; return true; - case fpu_mxcsrmask: value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsrmask; return true; - - case fpu_stmm0: - case fpu_stmm1: - case fpu_stmm2: - case fpu_stmm3: - case fpu_stmm4: - case fpu_stmm5: - case fpu_stmm6: - case fpu_stmm7: - memcpy(&value->value.uint8, &m_state.context.fpu.avx.__fpu_stmm0 + (reg - fpu_stmm0), 10); - return true; - - case fpu_xmm0: - case fpu_xmm1: - case fpu_xmm2: - case fpu_xmm3: - case fpu_xmm4: - case fpu_xmm5: - case fpu_xmm6: - case fpu_xmm7: - case fpu_xmm8: - case fpu_xmm9: - case fpu_xmm10: - case fpu_xmm11: - case fpu_xmm12: - case fpu_xmm13: - case fpu_xmm14: - case fpu_xmm15: - memcpy(&value->value.uint8, &m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_xmm0), 16); - return true; - - case fpu_ymm0: - case fpu_ymm1: - case fpu_ymm2: - case fpu_ymm3: - case fpu_ymm4: - case fpu_ymm5: - case fpu_ymm6: - case fpu_ymm7: - case fpu_ymm8: - case fpu_ymm9: - case fpu_ymm10: - case fpu_ymm11: - case fpu_ymm12: - case fpu_ymm13: - case fpu_ymm14: - case fpu_ymm15: - memcpy(&value->value.uint8, &m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_ymm0), 16); - memcpy((&value->value.uint8) + 16, &m_state.context.fpu.avx.__fpu_ymmh0 + (reg - fpu_ymm0), 16); - return true; - } - } - else - { - switch (reg) - { - case fpu_fcw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)); return true; - case fpu_fsw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)); return true; - case fpu_ftw: value->value.uint8 = m_state.context.fpu.no_avx.__fpu_ftw; return true; - case fpu_fop: value->value.uint16 = m_state.context.fpu.no_avx.__fpu_fop; return true; - case fpu_ip: value->value.uint32 = m_state.context.fpu.no_avx.__fpu_ip; return true; - case fpu_cs: value->value.uint16 = m_state.context.fpu.no_avx.__fpu_cs; return true; - case fpu_dp: value->value.uint32 = m_state.context.fpu.no_avx.__fpu_dp; return true; - case fpu_ds: value->value.uint16 = m_state.context.fpu.no_avx.__fpu_ds; return true; - case fpu_mxcsr: value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsr; return true; - case fpu_mxcsrmask: value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsrmask; return true; - - case fpu_stmm0: - case fpu_stmm1: - case fpu_stmm2: - case fpu_stmm3: - case fpu_stmm4: - case fpu_stmm5: - case fpu_stmm6: - case fpu_stmm7: - memcpy(&value->value.uint8, &m_state.context.fpu.no_avx.__fpu_stmm0 + (reg - fpu_stmm0), 10); - return true; - - case fpu_xmm0: - case fpu_xmm1: - case fpu_xmm2: - case fpu_xmm3: - case fpu_xmm4: - case fpu_xmm5: - case fpu_xmm6: - case fpu_xmm7: - case fpu_xmm8: - case fpu_xmm9: - case fpu_xmm10: - case fpu_xmm11: - case fpu_xmm12: - case fpu_xmm13: - case fpu_xmm14: - case fpu_xmm15: - memcpy(&value->value.uint8, &m_state.context.fpu.no_avx.__fpu_xmm0 + (reg - fpu_xmm0), 16); - return true; - } - } - break; - - case e_regSetEXC: - switch (reg) - { - case exc_trapno: value->value.uint32 = m_state.context.exc.__trapno; return true; - case exc_err: value->value.uint32 = m_state.context.exc.__err; return true; - case exc_faultvaddr:value->value.uint64 = m_state.context.exc.__faultvaddr; return true; - } - break; + } + + if (GetRegisterState(set, false) != KERN_SUCCESS) + return false; + + const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); + if (regInfo) { + value->info = *regInfo; + switch (set) { + case e_regSetGPR: + if (reg < k_num_gpr_registers) { + value->value.uint64 = ((uint64_t *)(&m_state.context.gpr))[reg]; + return true; + } + break; + + case e_regSetFPU: + if (CPUHasAVX() || FORCE_AVX_REGS) { + switch (reg) { + case fpu_fcw: + value->value.uint16 = + *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw)); + return true; + case fpu_fsw: + value->value.uint16 = + *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw)); + return true; + case fpu_ftw: + value->value.uint8 = m_state.context.fpu.avx.__fpu_ftw; + return true; + case fpu_fop: + value->value.uint16 = m_state.context.fpu.avx.__fpu_fop; + return true; + case fpu_ip: + value->value.uint32 = m_state.context.fpu.avx.__fpu_ip; + return true; + case fpu_cs: + value->value.uint16 = m_state.context.fpu.avx.__fpu_cs; + return true; + case fpu_dp: + value->value.uint32 = m_state.context.fpu.avx.__fpu_dp; + return true; + case fpu_ds: + value->value.uint16 = m_state.context.fpu.avx.__fpu_ds; + return true; + case fpu_mxcsr: + value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsr; + return true; + case fpu_mxcsrmask: + value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsrmask; + return true; + + case fpu_stmm0: + case fpu_stmm1: + case fpu_stmm2: + case fpu_stmm3: + case fpu_stmm4: + case fpu_stmm5: + case fpu_stmm6: + case fpu_stmm7: + memcpy(&value->value.uint8, + &m_state.context.fpu.avx.__fpu_stmm0 + (reg - fpu_stmm0), 10); + return true; + + case fpu_xmm0: + case fpu_xmm1: + case fpu_xmm2: + case fpu_xmm3: + case fpu_xmm4: + case fpu_xmm5: + case fpu_xmm6: + case fpu_xmm7: + case fpu_xmm8: + case fpu_xmm9: + case fpu_xmm10: + case fpu_xmm11: + case fpu_xmm12: + case fpu_xmm13: + case fpu_xmm14: + case fpu_xmm15: + memcpy(&value->value.uint8, + &m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_xmm0), 16); + return true; + + case fpu_ymm0: + case fpu_ymm1: + case fpu_ymm2: + case fpu_ymm3: + case fpu_ymm4: + case fpu_ymm5: + case fpu_ymm6: + case fpu_ymm7: + case fpu_ymm8: + case fpu_ymm9: + case fpu_ymm10: + case fpu_ymm11: + case fpu_ymm12: + case fpu_ymm13: + case fpu_ymm14: + case fpu_ymm15: + memcpy(&value->value.uint8, + &m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_ymm0), 16); + memcpy((&value->value.uint8) + 16, + &m_state.context.fpu.avx.__fpu_ymmh0 + (reg - fpu_ymm0), 16); + return true; } + } else { + switch (reg) { + case fpu_fcw: + value->value.uint16 = + *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)); + return true; + case fpu_fsw: + value->value.uint16 = + *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)); + return true; + case fpu_ftw: + value->value.uint8 = m_state.context.fpu.no_avx.__fpu_ftw; + return true; + case fpu_fop: + value->value.uint16 = m_state.context.fpu.no_avx.__fpu_fop; + return true; + case fpu_ip: + value->value.uint32 = m_state.context.fpu.no_avx.__fpu_ip; + return true; + case fpu_cs: + value->value.uint16 = m_state.context.fpu.no_avx.__fpu_cs; + return true; + case fpu_dp: + value->value.uint32 = m_state.context.fpu.no_avx.__fpu_dp; + return true; + case fpu_ds: + value->value.uint16 = m_state.context.fpu.no_avx.__fpu_ds; + return true; + case fpu_mxcsr: + value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsr; + return true; + case fpu_mxcsrmask: + value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsrmask; + return true; + + case fpu_stmm0: + case fpu_stmm1: + case fpu_stmm2: + case fpu_stmm3: + case fpu_stmm4: + case fpu_stmm5: + case fpu_stmm6: + case fpu_stmm7: + memcpy(&value->value.uint8, + &m_state.context.fpu.no_avx.__fpu_stmm0 + (reg - fpu_stmm0), + 10); + return true; + + case fpu_xmm0: + case fpu_xmm1: + case fpu_xmm2: + case fpu_xmm3: + case fpu_xmm4: + case fpu_xmm5: + case fpu_xmm6: + case fpu_xmm7: + case fpu_xmm8: + case fpu_xmm9: + case fpu_xmm10: + case fpu_xmm11: + case fpu_xmm12: + case fpu_xmm13: + case fpu_xmm14: + case fpu_xmm15: + memcpy(&value->value.uint8, + &m_state.context.fpu.no_avx.__fpu_xmm0 + (reg - fpu_xmm0), 16); + return true; + } + } + break; + + case e_regSetEXC: + switch (reg) { + case exc_trapno: + value->value.uint32 = m_state.context.exc.__trapno; + return true; + case exc_err: + value->value.uint32 = m_state.context.exc.__err; + return true; + case exc_faultvaddr: + value->value.uint64 = m_state.context.exc.__faultvaddr; + return true; + } + break; } - return false; + } + return false; } +bool DNBArchImplX86_64::SetRegisterValue(uint32_t set, uint32_t reg, + const DNBRegisterValue *value) { + if (set == REGISTER_SET_GENERIC) { + switch (reg) { + case GENERIC_REGNUM_PC: // Program Counter + set = e_regSetGPR; + reg = gpr_rip; + break; + + case GENERIC_REGNUM_SP: // Stack Pointer + set = e_regSetGPR; + reg = gpr_rsp; + break; + + case GENERIC_REGNUM_FP: // Frame Pointer + set = e_regSetGPR; + reg = gpr_rbp; + break; + + case GENERIC_REGNUM_FLAGS: // Processor flags register + set = e_regSetGPR; + reg = gpr_rflags; + break; + + case GENERIC_REGNUM_RA: // Return Address + default: + return false; + } + } -bool -DNBArchImplX86_64::SetRegisterValue(uint32_t set, uint32_t reg, const DNBRegisterValue *value) -{ - if (set == REGISTER_SET_GENERIC) - { - switch (reg) - { - case GENERIC_REGNUM_PC: // Program Counter - set = e_regSetGPR; - reg = gpr_rip; - break; - - case GENERIC_REGNUM_SP: // Stack Pointer - set = e_regSetGPR; - reg = gpr_rsp; - break; - - case GENERIC_REGNUM_FP: // Frame Pointer - set = e_regSetGPR; - reg = gpr_rbp; - break; - - case GENERIC_REGNUM_FLAGS: // Processor flags register - set = e_regSetGPR; - reg = gpr_rflags; - break; - - case GENERIC_REGNUM_RA: // Return Address - default: - return false; + if (GetRegisterState(set, false) != KERN_SUCCESS) + return false; + + bool success = false; + const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); + if (regInfo) { + switch (set) { + case e_regSetGPR: + if (reg < k_num_gpr_registers) { + ((uint64_t *)(&m_state.context.gpr))[reg] = value->value.uint64; + success = true; + } + break; + + case e_regSetFPU: + if (CPUHasAVX() || FORCE_AVX_REGS) { + switch (reg) { + case fpu_fcw: + *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw)) = + value->value.uint16; + success = true; + break; + case fpu_fsw: + *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw)) = + value->value.uint16; + success = true; + break; + case fpu_ftw: + m_state.context.fpu.avx.__fpu_ftw = value->value.uint8; + success = true; + break; + case fpu_fop: + m_state.context.fpu.avx.__fpu_fop = value->value.uint16; + success = true; + break; + case fpu_ip: + m_state.context.fpu.avx.__fpu_ip = value->value.uint32; + success = true; + break; + case fpu_cs: + m_state.context.fpu.avx.__fpu_cs = value->value.uint16; + success = true; + break; + case fpu_dp: + m_state.context.fpu.avx.__fpu_dp = value->value.uint32; + success = true; + break; + case fpu_ds: + m_state.context.fpu.avx.__fpu_ds = value->value.uint16; + success = true; + break; + case fpu_mxcsr: + m_state.context.fpu.avx.__fpu_mxcsr = value->value.uint32; + success = true; + break; + case fpu_mxcsrmask: + m_state.context.fpu.avx.__fpu_mxcsrmask = value->value.uint32; + success = true; + break; + + case fpu_stmm0: + case fpu_stmm1: + case fpu_stmm2: + case fpu_stmm3: + case fpu_stmm4: + case fpu_stmm5: + case fpu_stmm6: + case fpu_stmm7: + memcpy(&m_state.context.fpu.avx.__fpu_stmm0 + (reg - fpu_stmm0), + &value->value.uint8, 10); + success = true; + break; + + case fpu_xmm0: + case fpu_xmm1: + case fpu_xmm2: + case fpu_xmm3: + case fpu_xmm4: + case fpu_xmm5: + case fpu_xmm6: + case fpu_xmm7: + case fpu_xmm8: + case fpu_xmm9: + case fpu_xmm10: + case fpu_xmm11: + case fpu_xmm12: + case fpu_xmm13: + case fpu_xmm14: + case fpu_xmm15: + memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_xmm0), + &value->value.uint8, 16); + success = true; + break; + + case fpu_ymm0: + case fpu_ymm1: + case fpu_ymm2: + case fpu_ymm3: + case fpu_ymm4: + case fpu_ymm5: + case fpu_ymm6: + case fpu_ymm7: + case fpu_ymm8: + case fpu_ymm9: + case fpu_ymm10: + case fpu_ymm11: + case fpu_ymm12: + case fpu_ymm13: + case fpu_ymm14: + case fpu_ymm15: + memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_ymm0), + &value->value.uint8, 16); + memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + (reg - fpu_ymm0), + (&value->value.uint8) + 16, 16); + return true; } - } - - if (GetRegisterState(set, false) != KERN_SUCCESS) - return false; - - bool success = false; - const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); - if (regInfo) - { - switch (set) - { - case e_regSetGPR: - if (reg < k_num_gpr_registers) - { - ((uint64_t*)(&m_state.context.gpr))[reg] = value->value.uint64; - success = true; - } - break; - - case e_regSetFPU: - if (CPUHasAVX() || FORCE_AVX_REGS) - { - switch (reg) - { - case fpu_fcw: *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw)) = value->value.uint16; success = true; break; - case fpu_fsw: *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw)) = value->value.uint16; success = true; break; - case fpu_ftw: m_state.context.fpu.avx.__fpu_ftw = value->value.uint8; success = true; break; - case fpu_fop: m_state.context.fpu.avx.__fpu_fop = value->value.uint16; success = true; break; - case fpu_ip: m_state.context.fpu.avx.__fpu_ip = value->value.uint32; success = true; break; - case fpu_cs: m_state.context.fpu.avx.__fpu_cs = value->value.uint16; success = true; break; - case fpu_dp: m_state.context.fpu.avx.__fpu_dp = value->value.uint32; success = true; break; - case fpu_ds: m_state.context.fpu.avx.__fpu_ds = value->value.uint16; success = true; break; - case fpu_mxcsr: m_state.context.fpu.avx.__fpu_mxcsr = value->value.uint32; success = true; break; - case fpu_mxcsrmask: m_state.context.fpu.avx.__fpu_mxcsrmask = value->value.uint32; success = true; break; - - case fpu_stmm0: - case fpu_stmm1: - case fpu_stmm2: - case fpu_stmm3: - case fpu_stmm4: - case fpu_stmm5: - case fpu_stmm6: - case fpu_stmm7: - memcpy (&m_state.context.fpu.avx.__fpu_stmm0 + (reg - fpu_stmm0), &value->value.uint8, 10); - success = true; - break; - - case fpu_xmm0: - case fpu_xmm1: - case fpu_xmm2: - case fpu_xmm3: - case fpu_xmm4: - case fpu_xmm5: - case fpu_xmm6: - case fpu_xmm7: - case fpu_xmm8: - case fpu_xmm9: - case fpu_xmm10: - case fpu_xmm11: - case fpu_xmm12: - case fpu_xmm13: - case fpu_xmm14: - case fpu_xmm15: - memcpy (&m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_xmm0), &value->value.uint8, 16); - success = true; - break; - - case fpu_ymm0: - case fpu_ymm1: - case fpu_ymm2: - case fpu_ymm3: - case fpu_ymm4: - case fpu_ymm5: - case fpu_ymm6: - case fpu_ymm7: - case fpu_ymm8: - case fpu_ymm9: - case fpu_ymm10: - case fpu_ymm11: - case fpu_ymm12: - case fpu_ymm13: - case fpu_ymm14: - case fpu_ymm15: - memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_ymm0), &value->value.uint8, 16); - memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + (reg - fpu_ymm0), (&value->value.uint8) + 16, 16); - return true; - } - } - else - { - switch (reg) - { - case fpu_fcw: *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)) = value->value.uint16; success = true; break; - case fpu_fsw: *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)) = value->value.uint16; success = true; break; - case fpu_ftw: m_state.context.fpu.no_avx.__fpu_ftw = value->value.uint8; success = true; break; - case fpu_fop: m_state.context.fpu.no_avx.__fpu_fop = value->value.uint16; success = true; break; - case fpu_ip: m_state.context.fpu.no_avx.__fpu_ip = value->value.uint32; success = true; break; - case fpu_cs: m_state.context.fpu.no_avx.__fpu_cs = value->value.uint16; success = true; break; - case fpu_dp: m_state.context.fpu.no_avx.__fpu_dp = value->value.uint32; success = true; break; - case fpu_ds: m_state.context.fpu.no_avx.__fpu_ds = value->value.uint16; success = true; break; - case fpu_mxcsr: m_state.context.fpu.no_avx.__fpu_mxcsr = value->value.uint32; success = true; break; - case fpu_mxcsrmask: m_state.context.fpu.no_avx.__fpu_mxcsrmask = value->value.uint32; success = true; break; - - case fpu_stmm0: - case fpu_stmm1: - case fpu_stmm2: - case fpu_stmm3: - case fpu_stmm4: - case fpu_stmm5: - case fpu_stmm6: - case fpu_stmm7: - memcpy (&m_state.context.fpu.no_avx.__fpu_stmm0 + (reg - fpu_stmm0), &value->value.uint8, 10); - success = true; - break; - - case fpu_xmm0: - case fpu_xmm1: - case fpu_xmm2: - case fpu_xmm3: - case fpu_xmm4: - case fpu_xmm5: - case fpu_xmm6: - case fpu_xmm7: - case fpu_xmm8: - case fpu_xmm9: - case fpu_xmm10: - case fpu_xmm11: - case fpu_xmm12: - case fpu_xmm13: - case fpu_xmm14: - case fpu_xmm15: - memcpy (&m_state.context.fpu.no_avx.__fpu_xmm0 + (reg - fpu_xmm0), &value->value.uint8, 16); - success = true; - break; - } - } - break; - - case e_regSetEXC: - switch (reg) - { - case exc_trapno: m_state.context.exc.__trapno = value->value.uint32; success = true; break; - case exc_err: m_state.context.exc.__err = value->value.uint32; success = true; break; - case exc_faultvaddr:m_state.context.exc.__faultvaddr = value->value.uint64; success = true; break; - } - break; + } else { + switch (reg) { + case fpu_fcw: + *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)) = + value->value.uint16; + success = true; + break; + case fpu_fsw: + *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)) = + value->value.uint16; + success = true; + break; + case fpu_ftw: + m_state.context.fpu.no_avx.__fpu_ftw = value->value.uint8; + success = true; + break; + case fpu_fop: + m_state.context.fpu.no_avx.__fpu_fop = value->value.uint16; + success = true; + break; + case fpu_ip: + m_state.context.fpu.no_avx.__fpu_ip = value->value.uint32; + success = true; + break; + case fpu_cs: + m_state.context.fpu.no_avx.__fpu_cs = value->value.uint16; + success = true; + break; + case fpu_dp: + m_state.context.fpu.no_avx.__fpu_dp = value->value.uint32; + success = true; + break; + case fpu_ds: + m_state.context.fpu.no_avx.__fpu_ds = value->value.uint16; + success = true; + break; + case fpu_mxcsr: + m_state.context.fpu.no_avx.__fpu_mxcsr = value->value.uint32; + success = true; + break; + case fpu_mxcsrmask: + m_state.context.fpu.no_avx.__fpu_mxcsrmask = value->value.uint32; + success = true; + break; + + case fpu_stmm0: + case fpu_stmm1: + case fpu_stmm2: + case fpu_stmm3: + case fpu_stmm4: + case fpu_stmm5: + case fpu_stmm6: + case fpu_stmm7: + memcpy(&m_state.context.fpu.no_avx.__fpu_stmm0 + (reg - fpu_stmm0), + &value->value.uint8, 10); + success = true; + break; + + case fpu_xmm0: + case fpu_xmm1: + case fpu_xmm2: + case fpu_xmm3: + case fpu_xmm4: + case fpu_xmm5: + case fpu_xmm6: + case fpu_xmm7: + case fpu_xmm8: + case fpu_xmm9: + case fpu_xmm10: + case fpu_xmm11: + case fpu_xmm12: + case fpu_xmm13: + case fpu_xmm14: + case fpu_xmm15: + memcpy(&m_state.context.fpu.no_avx.__fpu_xmm0 + (reg - fpu_xmm0), + &value->value.uint8, 16); + success = true; + break; } + } + break; + + case e_regSetEXC: + switch (reg) { + case exc_trapno: + m_state.context.exc.__trapno = value->value.uint32; + success = true; + break; + case exc_err: + m_state.context.exc.__err = value->value.uint32; + success = true; + break; + case exc_faultvaddr: + m_state.context.exc.__faultvaddr = value->value.uint64; + success = true; + break; + } + break; } - - if (success) - return SetRegisterState(set) == KERN_SUCCESS; - return false; + } + + if (success) + return SetRegisterState(set) == KERN_SUCCESS; + return false; } -uint32_t -DNBArchImplX86_64::GetRegisterContextSize() -{ - static uint32_t g_cached_size = 0; - if (g_cached_size == 0) - { - if (CPUHasAVX() || FORCE_AVX_REGS) - { - for (size_t i=0; i<k_num_fpu_registers_avx; ++i) - { - if (g_fpu_registers_avx[i].value_regs == NULL) - g_cached_size += g_fpu_registers_avx[i].size; - } - } - else - { - for (size_t i=0; i<k_num_fpu_registers_no_avx; ++i) - { - if (g_fpu_registers_no_avx[i].value_regs == NULL) - g_cached_size += g_fpu_registers_no_avx[i].size; - } - } - DNBLogThreaded ("DNBArchImplX86_64::GetRegisterContextSize() - GPR = %zu, FPU = %u, EXC = %zu", sizeof(GPR), g_cached_size, sizeof(EXC)); - g_cached_size += sizeof(GPR); - g_cached_size += sizeof(EXC); - DNBLogThreaded ("DNBArchImplX86_64::GetRegisterContextSize() - GPR + FPU + EXC = %u", g_cached_size); +uint32_t DNBArchImplX86_64::GetRegisterContextSize() { + static uint32_t g_cached_size = 0; + if (g_cached_size == 0) { + if (CPUHasAVX() || FORCE_AVX_REGS) { + for (size_t i = 0; i < k_num_fpu_registers_avx; ++i) { + if (g_fpu_registers_avx[i].value_regs == NULL) + g_cached_size += g_fpu_registers_avx[i].size; + } + } else { + for (size_t i = 0; i < k_num_fpu_registers_no_avx; ++i) { + if (g_fpu_registers_no_avx[i].value_regs == NULL) + g_cached_size += g_fpu_registers_no_avx[i].size; + } } - return g_cached_size; + DNBLogThreaded("DNBArchImplX86_64::GetRegisterContextSize() - GPR = %zu, " + "FPU = %u, EXC = %zu", + sizeof(GPR), g_cached_size, sizeof(EXC)); + g_cached_size += sizeof(GPR); + g_cached_size += sizeof(EXC); + DNBLogThreaded( + "DNBArchImplX86_64::GetRegisterContextSize() - GPR + FPU + EXC = %u", + g_cached_size); + } + return g_cached_size; } -nub_size_t -DNBArchImplX86_64::GetRegisterContext (void *buf, nub_size_t buf_len) -{ - uint32_t size = GetRegisterContextSize(); - - if (buf && buf_len) - { - bool force = false; - kern_return_t kret; - - if ((kret = GetGPRState(force)) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = %llu) error: GPR regs failed to read: %u ", buf, (uint64_t)buf_len, kret); - size = 0; - } - else - if ((kret = GetFPUState(force)) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = %llu) error: %s regs failed to read: %u", buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret); - size = 0; +nub_size_t DNBArchImplX86_64::GetRegisterContext(void *buf, + nub_size_t buf_len) { + uint32_t size = GetRegisterContextSize(); + + if (buf && buf_len) { + bool force = false; + kern_return_t kret; + + if ((kret = GetGPRState(force)) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf " + "= %p, len = %llu) error: GPR regs failed " + "to read: %u ", + buf, (uint64_t)buf_len, kret); + size = 0; + } else if ((kret = GetFPUState(force)) != KERN_SUCCESS) { + DNBLogThreadedIf( + LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = " + "%llu) error: %s regs failed to read: %u", + buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret); + size = 0; + } else if ((kret = GetEXCState(force)) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf " + "= %p, len = %llu) error: EXC regs failed " + "to read: %u", + buf, (uint64_t)buf_len, kret); + size = 0; + } else { + uint8_t *p = (uint8_t *)buf; + // Copy the GPR registers + memcpy(p, &m_state.context.gpr, sizeof(GPR)); + p += sizeof(GPR); + + if (CPUHasAVX() || FORCE_AVX_REGS) { + // Walk around the gaps in the FPU regs + memcpy(p, &m_state.context.fpu.avx.__fpu_fcw, 5); + p += 5; + memcpy(p, &m_state.context.fpu.avx.__fpu_fop, 8); + p += 8; + memcpy(p, &m_state.context.fpu.avx.__fpu_dp, 6); + p += 6; + memcpy(p, &m_state.context.fpu.avx.__fpu_mxcsr, 8); + p += 8; + + // Work around the padding between the stmm registers as they are 16 + // byte structs with 10 bytes of the value in each + for (size_t i = 0; i < 8; ++i) { + memcpy(p, &m_state.context.fpu.avx.__fpu_stmm0 + i, 10); + p += 10; } - else - if ((kret = GetEXCState(force)) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = %llu) error: EXC regs failed to read: %u", buf, (uint64_t)buf_len, kret); - size = 0; + + // Interleave the XMM and YMMH registers to make the YMM registers + for (size_t i = 0; i < 16; ++i) { + memcpy(p, &m_state.context.fpu.avx.__fpu_xmm0 + i, 16); + p += 16; + memcpy(p, &m_state.context.fpu.avx.__fpu_ymmh0 + i, 16); + p += 16; } - else - { - uint8_t *p = (uint8_t *)buf; - // Copy the GPR registers - memcpy(p, &m_state.context.gpr, sizeof(GPR)); - p += sizeof(GPR); - - if (CPUHasAVX() || FORCE_AVX_REGS) - { - // Walk around the gaps in the FPU regs - memcpy(p, &m_state.context.fpu.avx.__fpu_fcw, 5); - p += 5; - memcpy(p, &m_state.context.fpu.avx.__fpu_fop, 8); - p += 8; - memcpy(p, &m_state.context.fpu.avx.__fpu_dp, 6); - p += 6; - memcpy(p, &m_state.context.fpu.avx.__fpu_mxcsr, 8); - p += 8; - - // Work around the padding between the stmm registers as they are 16 - // byte structs with 10 bytes of the value in each - for (size_t i=0; i<8; ++i) - { - memcpy(p, &m_state.context.fpu.avx.__fpu_stmm0 + i, 10); - p += 10; - } - - // Interleave the XMM and YMMH registers to make the YMM registers - for (size_t i=0; i<16; ++i) - { - memcpy(p, &m_state.context.fpu.avx.__fpu_xmm0 + i, 16); - p += 16; - memcpy(p, &m_state.context.fpu.avx.__fpu_ymmh0 + i, 16); - p += 16; - } - } - else - { - // Walk around the gaps in the FPU regs - memcpy(p, &m_state.context.fpu.no_avx.__fpu_fcw, 5); - p += 5; - memcpy(p, &m_state.context.fpu.no_avx.__fpu_fop, 8); - p += 8; - memcpy(p, &m_state.context.fpu.no_avx.__fpu_dp, 6); - p += 6; - memcpy(p, &m_state.context.fpu.no_avx.__fpu_mxcsr, 8); - p += 8; - - // Work around the padding between the stmm registers as they are 16 - // byte structs with 10 bytes of the value in each - for (size_t i=0; i<8; ++i) - { - memcpy(p, &m_state.context.fpu.no_avx.__fpu_stmm0 + i, 10); - p += 10; - } - - // Copy the XMM registers in a single block - memcpy(p, &m_state.context.fpu.no_avx.__fpu_xmm0, 16 * 16); - p += 16 * 16; - } - - // Copy the exception registers - memcpy(p, &m_state.context.exc, sizeof(EXC)); - p += sizeof(EXC); - - // make sure we end up with exactly what we think we should have - size_t bytes_written = p - (uint8_t *)buf; - UNUSED_IF_ASSERT_DISABLED(bytes_written); - assert (bytes_written == size); + } else { + // Walk around the gaps in the FPU regs + memcpy(p, &m_state.context.fpu.no_avx.__fpu_fcw, 5); + p += 5; + memcpy(p, &m_state.context.fpu.no_avx.__fpu_fop, 8); + p += 8; + memcpy(p, &m_state.context.fpu.no_avx.__fpu_dp, 6); + p += 6; + memcpy(p, &m_state.context.fpu.no_avx.__fpu_mxcsr, 8); + p += 8; + + // Work around the padding between the stmm registers as they are 16 + // byte structs with 10 bytes of the value in each + for (size_t i = 0; i < 8; ++i) { + memcpy(p, &m_state.context.fpu.no_avx.__fpu_stmm0 + i, 10); + p += 10; } - } + // Copy the XMM registers in a single block + memcpy(p, &m_state.context.fpu.no_avx.__fpu_xmm0, 16 * 16); + p += 16 * 16; + } - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = %llu) => %u", buf, (uint64_t)buf_len, size); - // Return the size of the register context even if NULL was passed in - return size; -} + // Copy the exception registers + memcpy(p, &m_state.context.exc, sizeof(EXC)); + p += sizeof(EXC); -nub_size_t -DNBArchImplX86_64::SetRegisterContext (const void *buf, nub_size_t buf_len) -{ - uint32_t size = GetRegisterContextSize(); - if (buf == NULL || buf_len == 0) - size = 0; - - if (size) - { - if (size > buf_len) - size = static_cast<uint32_t>(buf_len); - - uint8_t *p = (uint8_t *)buf; - // Copy the GPR registers - memcpy(&m_state.context.gpr, p, sizeof(GPR)); - p += sizeof(GPR); - - if (CPUHasAVX() || FORCE_AVX_REGS) - { - // Walk around the gaps in the FPU regs - memcpy(&m_state.context.fpu.avx.__fpu_fcw, p, 5); - p += 5; - memcpy(&m_state.context.fpu.avx.__fpu_fop, p, 8); - p += 8; - memcpy(&m_state.context.fpu.avx.__fpu_dp, p, 6); - p += 6; - memcpy(&m_state.context.fpu.avx.__fpu_mxcsr, p, 8); - p += 8; - - // Work around the padding between the stmm registers as they are 16 - // byte structs with 10 bytes of the value in each - for (size_t i=0; i<8; ++i) - { - memcpy(&m_state.context.fpu.avx.__fpu_stmm0 + i, p, 10); - p += 10; - } - - // Interleave the XMM and YMMH registers to make the YMM registers - for (size_t i=0; i<16; ++i) - { - memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + i, p, 16); - p += 16; - memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + i, p, 16); - p += 16; - } - } - else - { - // Copy fcw through mxcsrmask as there is no padding - memcpy(&m_state.context.fpu.no_avx.__fpu_fcw, p, 5); - p += 5; - memcpy(&m_state.context.fpu.no_avx.__fpu_fop, p, 8); - p += 8; - memcpy(&m_state.context.fpu.no_avx.__fpu_dp, p, 6); - p += 6; - memcpy(&m_state.context.fpu.no_avx.__fpu_mxcsr, p, 8); - p += 8; - - // Work around the padding between the stmm registers as they are 16 - // byte structs with 10 bytes of the value in each - for (size_t i=0; i<8; ++i) - { - memcpy(&m_state.context.fpu.no_avx.__fpu_stmm0 + i, p, 10); - p += 10; - } - - // Copy the XMM registers in a single block - memcpy(&m_state.context.fpu.no_avx.__fpu_xmm0, p, 16 * 16); - p += 16 * 16; - } - - // Copy the exception registers - memcpy(&m_state.context.exc, p, sizeof(EXC)); - p += sizeof(EXC); - - // make sure we end up with exactly what we think we should have - size_t bytes_written = p - (uint8_t *)buf; - UNUSED_IF_ASSERT_DISABLED(bytes_written); - assert (bytes_written == size); - - kern_return_t kret; - if ((kret = SetGPRState()) != KERN_SUCCESS) - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = %llu) error: GPR regs failed to write: %u", buf, (uint64_t)buf_len, kret); - if ((kret = SetFPUState()) != KERN_SUCCESS) - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = %llu) error: %s regs failed to write: %u", buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret); - if ((kret = SetEXCState()) != KERN_SUCCESS) - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = %llu) error: EXP regs failed to write: %u", buf, (uint64_t)buf_len, kret); + // make sure we end up with exactly what we think we should have + size_t bytes_written = p - (uint8_t *)buf; + UNUSED_IF_ASSERT_DISABLED(bytes_written); + assert(bytes_written == size); } - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = %llu) => %llu", buf, (uint64_t)buf_len, (uint64_t)size); - return size; + } + + DNBLogThreadedIf( + LOG_THREAD, + "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = %llu) => %u", buf, + (uint64_t)buf_len, size); + // Return the size of the register context even if NULL was passed in + return size; } -uint32_t -DNBArchImplX86_64::SaveRegisterState () -{ - kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); - DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); - - // Always re-read the registers because above we call thread_abort_safely(); - bool force = true; - - if ((kret = GetGPRState(force)) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SaveRegisterState () error: GPR regs failed to read: %u ", kret); - } - else if ((kret = GetFPUState(force)) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SaveRegisterState () error: %s regs failed to read: %u", CPUHasAVX() ? "AVX" : "FPU", kret); - } - else - { - const uint32_t save_id = GetNextRegisterStateSaveID (); - m_saved_register_states[save_id] = m_state.context; - return save_id; +nub_size_t DNBArchImplX86_64::SetRegisterContext(const void *buf, + nub_size_t buf_len) { + uint32_t size = GetRegisterContextSize(); + if (buf == NULL || buf_len == 0) + size = 0; + + if (size) { + if (size > buf_len) + size = static_cast<uint32_t>(buf_len); + + uint8_t *p = (uint8_t *)buf; + // Copy the GPR registers + memcpy(&m_state.context.gpr, p, sizeof(GPR)); + p += sizeof(GPR); + + if (CPUHasAVX() || FORCE_AVX_REGS) { + // Walk around the gaps in the FPU regs + memcpy(&m_state.context.fpu.avx.__fpu_fcw, p, 5); + p += 5; + memcpy(&m_state.context.fpu.avx.__fpu_fop, p, 8); + p += 8; + memcpy(&m_state.context.fpu.avx.__fpu_dp, p, 6); + p += 6; + memcpy(&m_state.context.fpu.avx.__fpu_mxcsr, p, 8); + p += 8; + + // Work around the padding between the stmm registers as they are 16 + // byte structs with 10 bytes of the value in each + for (size_t i = 0; i < 8; ++i) { + memcpy(&m_state.context.fpu.avx.__fpu_stmm0 + i, p, 10); + p += 10; + } + + // Interleave the XMM and YMMH registers to make the YMM registers + for (size_t i = 0; i < 16; ++i) { + memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + i, p, 16); + p += 16; + memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + i, p, 16); + p += 16; + } + } else { + // Copy fcw through mxcsrmask as there is no padding + memcpy(&m_state.context.fpu.no_avx.__fpu_fcw, p, 5); + p += 5; + memcpy(&m_state.context.fpu.no_avx.__fpu_fop, p, 8); + p += 8; + memcpy(&m_state.context.fpu.no_avx.__fpu_dp, p, 6); + p += 6; + memcpy(&m_state.context.fpu.no_avx.__fpu_mxcsr, p, 8); + p += 8; + + // Work around the padding between the stmm registers as they are 16 + // byte structs with 10 bytes of the value in each + for (size_t i = 0; i < 8; ++i) { + memcpy(&m_state.context.fpu.no_avx.__fpu_stmm0 + i, p, 10); + p += 10; + } + + // Copy the XMM registers in a single block + memcpy(&m_state.context.fpu.no_avx.__fpu_xmm0, p, 16 * 16); + p += 16 * 16; } - return 0; + + // Copy the exception registers + memcpy(&m_state.context.exc, p, sizeof(EXC)); + p += sizeof(EXC); + + // make sure we end up with exactly what we think we should have + size_t bytes_written = p - (uint8_t *)buf; + UNUSED_IF_ASSERT_DISABLED(bytes_written); + assert(bytes_written == size); + + kern_return_t kret; + if ((kret = SetGPRState()) != KERN_SUCCESS) + DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf " + "= %p, len = %llu) error: GPR regs failed " + "to write: %u", + buf, (uint64_t)buf_len, kret); + if ((kret = SetFPUState()) != KERN_SUCCESS) + DNBLogThreadedIf( + LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = " + "%llu) error: %s regs failed to write: %u", + buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret); + if ((kret = SetEXCState()) != KERN_SUCCESS) + DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf " + "= %p, len = %llu) error: EXP regs failed " + "to write: %u", + buf, (uint64_t)buf_len, kret); + } + DNBLogThreadedIf( + LOG_THREAD, + "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = %llu) => %llu", + buf, (uint64_t)buf_len, (uint64_t)size); + return size; } -bool -DNBArchImplX86_64::RestoreRegisterState (uint32_t save_id) -{ - SaveRegisterStates::iterator pos = m_saved_register_states.find(save_id); - if (pos != m_saved_register_states.end()) - { - m_state.context.gpr = pos->second.gpr; - m_state.context.fpu = pos->second.fpu; - m_state.SetError(e_regSetGPR, Read, 0); - m_state.SetError(e_regSetFPU, Read, 0); - kern_return_t kret; - bool success = true; - if ((kret = SetGPRState()) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::RestoreRegisterState (save_id = %u) error: GPR regs failed to write: %u", save_id, kret); - success = false; - } - else if ((kret = SetFPUState()) != KERN_SUCCESS) - { - DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::RestoreRegisterState (save_id = %u) error: %s regs failed to write: %u", save_id, CPUHasAVX() ? "AVX" : "FPU", kret); - success = false; - } - m_saved_register_states.erase(pos); - return success; + +uint32_t DNBArchImplX86_64::SaveRegisterState() { + kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); + DNBLogThreadedIf( + LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u " + "(SetGPRState() for stop_count = %u)", + m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); + + // Always re-read the registers because above we call thread_abort_safely(); + bool force = true; + + if ((kret = GetGPRState(force)) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::SaveRegisterState () " + "error: GPR regs failed to read: %u ", + kret); + } else if ((kret = GetFPUState(force)) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::SaveRegisterState () " + "error: %s regs failed to read: %u", + CPUHasAVX() ? "AVX" : "FPU", kret); + } else { + const uint32_t save_id = GetNextRegisterStateSaveID(); + m_saved_register_states[save_id] = m_state.context; + return save_id; + } + return 0; +} +bool DNBArchImplX86_64::RestoreRegisterState(uint32_t save_id) { + SaveRegisterStates::iterator pos = m_saved_register_states.find(save_id); + if (pos != m_saved_register_states.end()) { + m_state.context.gpr = pos->second.gpr; + m_state.context.fpu = pos->second.fpu; + m_state.SetError(e_regSetGPR, Read, 0); + m_state.SetError(e_regSetFPU, Read, 0); + kern_return_t kret; + bool success = true; + if ((kret = SetGPRState()) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::RestoreRegisterState " + "(save_id = %u) error: GPR regs failed to " + "write: %u", + save_id, kret); + success = false; + } else if ((kret = SetFPUState()) != KERN_SUCCESS) { + DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::RestoreRegisterState " + "(save_id = %u) error: %s regs failed to " + "write: %u", + save_id, CPUHasAVX() ? "AVX" : "FPU", kret); + success = false; } - return false; + m_saved_register_states.erase(pos); + return success; + } + return false; } - -kern_return_t -DNBArchImplX86_64::GetRegisterState(int set, bool force) -{ - switch (set) - { - case e_regSetALL: return GetGPRState(force) | GetFPUState(force) | GetEXCState(force); - case e_regSetGPR: return GetGPRState(force); - case e_regSetFPU: return GetFPUState(force); - case e_regSetEXC: return GetEXCState(force); - default: break; - } - return KERN_INVALID_ARGUMENT; +kern_return_t DNBArchImplX86_64::GetRegisterState(int set, bool force) { + switch (set) { + case e_regSetALL: + return GetGPRState(force) | GetFPUState(force) | GetEXCState(force); + case e_regSetGPR: + return GetGPRState(force); + case e_regSetFPU: + return GetFPUState(force); + case e_regSetEXC: + return GetEXCState(force); + default: + break; + } + return KERN_INVALID_ARGUMENT; } -kern_return_t -DNBArchImplX86_64::SetRegisterState(int set) -{ - // Make sure we have a valid context to set. - if (RegisterSetStateIsValid(set)) - { - switch (set) - { - case e_regSetALL: return SetGPRState() | SetFPUState() | SetEXCState(); - case e_regSetGPR: return SetGPRState(); - case e_regSetFPU: return SetFPUState(); - case e_regSetEXC: return SetEXCState(); - default: break; - } +kern_return_t DNBArchImplX86_64::SetRegisterState(int set) { + // Make sure we have a valid context to set. + if (RegisterSetStateIsValid(set)) { + switch (set) { + case e_regSetALL: + return SetGPRState() | SetFPUState() | SetEXCState(); + case e_regSetGPR: + return SetGPRState(); + case e_regSetFPU: + return SetFPUState(); + case e_regSetEXC: + return SetEXCState(); + default: + break; } - return KERN_INVALID_ARGUMENT; + } + return KERN_INVALID_ARGUMENT; } -bool -DNBArchImplX86_64::RegisterSetStateIsValid (int set) const -{ - return m_state.RegsAreValid(set); +bool DNBArchImplX86_64::RegisterSetStateIsValid(int set) const { + return m_state.RegsAreValid(set); } - - -#endif // #if defined (__i386__) || defined (__x86_64__) +#endif // #if defined (__i386__) || defined (__x86_64__) diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h index 20844951261..1b8a3c7da4b 100644 --- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h +++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h @@ -14,7 +14,7 @@ #ifndef __DNBArchImplX86_64_h__ #define __DNBArchImplX86_64_h__ -#if defined (__i386__) || defined (__x86_64__) +#if defined(__i386__) || defined(__x86_64__) #include "DNBArch.h" #include "MachRegisterStatesX86_64.h" @@ -22,239 +22,213 @@ class MachThread; -class DNBArchImplX86_64 : public DNBArchProtocol -{ +class DNBArchImplX86_64 : public DNBArchProtocol { public: - DNBArchImplX86_64(MachThread *thread) : - DNBArchProtocol(), - m_thread(thread), - m_state(), - m_2pc_dbg_checkpoint(), - m_2pc_trans_state(Trans_Done), - m_saved_register_states() - { + DNBArchImplX86_64(MachThread *thread) + : DNBArchProtocol(), m_thread(thread), m_state(), m_2pc_dbg_checkpoint(), + m_2pc_trans_state(Trans_Done), m_saved_register_states() {} + virtual ~DNBArchImplX86_64() {} + + static void Initialize(); + + virtual bool GetRegisterValue(uint32_t set, uint32_t reg, + DNBRegisterValue *value); + virtual bool SetRegisterValue(uint32_t set, uint32_t reg, + const DNBRegisterValue *value); + virtual nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len); + virtual nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len); + virtual uint32_t SaveRegisterState(); + virtual bool RestoreRegisterState(uint32_t save_id); + + virtual kern_return_t GetRegisterState(int set, bool force); + virtual kern_return_t SetRegisterState(int set); + virtual bool RegisterSetStateIsValid(int set) const; + + virtual uint64_t GetPC(uint64_t failValue); // Get program counter + virtual kern_return_t SetPC(uint64_t value); + virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer + virtual void ThreadWillResume(); + virtual bool ThreadDidStop(); + virtual bool NotifyException(MachException::Data &exc); + + virtual uint32_t NumSupportedHardwareWatchpoints(); + virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, + bool read, bool write, + bool also_set_on_task); + virtual bool DisableHardwareWatchpoint(uint32_t hw_break_index, + bool also_set_on_task); + virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); + +protected: + kern_return_t EnableHardwareSingleStep(bool enable); + + typedef __x86_64_thread_state_t GPR; + typedef __x86_64_float_state_t FPU; + typedef __x86_64_exception_state_t EXC; + typedef __x86_64_avx_state_t AVX; + typedef __x86_64_debug_state_t DBG; + + static const DNBRegisterInfo g_gpr_registers[]; + static const DNBRegisterInfo g_fpu_registers_no_avx[]; + static const DNBRegisterInfo g_fpu_registers_avx[]; + static const DNBRegisterInfo g_exc_registers[]; + static const DNBRegisterSetInfo g_reg_sets_no_avx[]; + static const DNBRegisterSetInfo g_reg_sets_avx[]; + static const size_t k_num_gpr_registers; + static const size_t k_num_fpu_registers_no_avx; + static const size_t k_num_fpu_registers_avx; + static const size_t k_num_exc_registers; + static const size_t k_num_all_registers_no_avx; + static const size_t k_num_all_registers_avx; + static const size_t k_num_register_sets; + + typedef enum RegisterSetTag { + e_regSetALL = REGISTER_SET_ALL, + e_regSetGPR, + e_regSetFPU, + e_regSetEXC, + e_regSetDBG, + kNumRegisterSets + } RegisterSet; + + typedef enum RegisterSetWordSizeTag { + e_regSetWordSizeGPR = sizeof(GPR) / sizeof(int), + e_regSetWordSizeFPU = sizeof(FPU) / sizeof(int), + e_regSetWordSizeEXC = sizeof(EXC) / sizeof(int), + e_regSetWordSizeAVX = sizeof(AVX) / sizeof(int), + e_regSetWordSizeDBG = sizeof(DBG) / sizeof(int) + } RegisterSetWordSize; + + enum { Read = 0, Write = 1, kNumErrors = 2 }; + + struct Context { + GPR gpr; + union { + FPU no_avx; + AVX avx; + } fpu; + EXC exc; + DBG dbg; + }; + + struct State { + Context context; + kern_return_t gpr_errs[2]; // Read/Write errors + kern_return_t fpu_errs[2]; // Read/Write errors + kern_return_t exc_errs[2]; // Read/Write errors + kern_return_t dbg_errs[2]; // Read/Write errors + + State() { + uint32_t i; + for (i = 0; i < kNumErrors; i++) { + gpr_errs[i] = -1; + fpu_errs[i] = -1; + exc_errs[i] = -1; + dbg_errs[i] = -1; + } } - virtual ~DNBArchImplX86_64() - { + + void InvalidateAllRegisterStates() { SetError(e_regSetALL, Read, -1); } + + kern_return_t GetError(int flavor, uint32_t err_idx) const { + if (err_idx < kNumErrors) { + switch (flavor) { + // When getting all errors, just OR all values together to see if + // we got any kind of error. + case e_regSetALL: + return gpr_errs[err_idx] | fpu_errs[err_idx] | exc_errs[err_idx]; + case e_regSetGPR: + return gpr_errs[err_idx]; + case e_regSetFPU: + return fpu_errs[err_idx]; + case e_regSetEXC: + return exc_errs[err_idx]; + case e_regSetDBG: + return dbg_errs[err_idx]; + default: + break; + } + } + return -1; } - static void Initialize(); - - virtual bool GetRegisterValue(uint32_t set, uint32_t reg, DNBRegisterValue *value); - virtual bool SetRegisterValue(uint32_t set, uint32_t reg, const DNBRegisterValue *value); - virtual nub_size_t GetRegisterContext (void *buf, nub_size_t buf_len); - virtual nub_size_t SetRegisterContext (const void *buf, nub_size_t buf_len); - virtual uint32_t SaveRegisterState (); - virtual bool RestoreRegisterState (uint32_t save_id); - - virtual kern_return_t GetRegisterState (int set, bool force); - virtual kern_return_t SetRegisterState (int set); - virtual bool RegisterSetStateIsValid (int set) const; - - virtual uint64_t GetPC(uint64_t failValue); // Get program counter - virtual kern_return_t SetPC(uint64_t value); - virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer - virtual void ThreadWillResume(); - virtual bool ThreadDidStop(); - virtual bool NotifyException(MachException::Data& exc); - - virtual uint32_t NumSupportedHardwareWatchpoints(); - virtual uint32_t EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task); - virtual bool DisableHardwareWatchpoint (uint32_t hw_break_index, bool also_set_on_task); - virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); + bool SetError(int flavor, uint32_t err_idx, kern_return_t err) { + if (err_idx < kNumErrors) { + switch (flavor) { + case e_regSetALL: + gpr_errs[err_idx] = fpu_errs[err_idx] = exc_errs[err_idx] = + dbg_errs[err_idx] = err; + return true; -protected: - kern_return_t EnableHardwareSingleStep (bool enable); - - typedef __x86_64_thread_state_t GPR; - typedef __x86_64_float_state_t FPU; - typedef __x86_64_exception_state_t EXC; - typedef __x86_64_avx_state_t AVX; - typedef __x86_64_debug_state_t DBG; - - static const DNBRegisterInfo g_gpr_registers[]; - static const DNBRegisterInfo g_fpu_registers_no_avx[]; - static const DNBRegisterInfo g_fpu_registers_avx[]; - static const DNBRegisterInfo g_exc_registers[]; - static const DNBRegisterSetInfo g_reg_sets_no_avx[]; - static const DNBRegisterSetInfo g_reg_sets_avx[]; - static const size_t k_num_gpr_registers; - static const size_t k_num_fpu_registers_no_avx; - static const size_t k_num_fpu_registers_avx; - static const size_t k_num_exc_registers; - static const size_t k_num_all_registers_no_avx; - static const size_t k_num_all_registers_avx; - static const size_t k_num_register_sets; - - typedef enum RegisterSetTag - { - e_regSetALL = REGISTER_SET_ALL, - e_regSetGPR, - e_regSetFPU, - e_regSetEXC, - e_regSetDBG, - kNumRegisterSets - } RegisterSet; - - typedef enum RegisterSetWordSizeTag - { - e_regSetWordSizeGPR = sizeof(GPR) / sizeof(int), - e_regSetWordSizeFPU = sizeof(FPU) / sizeof(int), - e_regSetWordSizeEXC = sizeof(EXC) / sizeof(int), - e_regSetWordSizeAVX = sizeof(AVX) / sizeof(int), - e_regSetWordSizeDBG = sizeof(DBG) / sizeof(int) - } RegisterSetWordSize; - - enum - { - Read = 0, - Write = 1, - kNumErrors = 2 - }; - - struct Context - { - GPR gpr; - union { - FPU no_avx; - AVX avx; - } fpu; - EXC exc; - DBG dbg; - }; - - struct State - { - Context context; - kern_return_t gpr_errs[2]; // Read/Write errors - kern_return_t fpu_errs[2]; // Read/Write errors - kern_return_t exc_errs[2]; // Read/Write errors - kern_return_t dbg_errs[2]; // Read/Write errors - - State() - { - uint32_t i; - for (i=0; i<kNumErrors; i++) - { - gpr_errs[i] = -1; - fpu_errs[i] = -1; - exc_errs[i] = -1; - dbg_errs[i] = -1; - } - } - - void - InvalidateAllRegisterStates() - { - SetError (e_regSetALL, Read, -1); - } + case e_regSetGPR: + gpr_errs[err_idx] = err; + return true; - kern_return_t - GetError (int flavor, uint32_t err_idx) const - { - if (err_idx < kNumErrors) - { - switch (flavor) - { - // When getting all errors, just OR all values together to see if - // we got any kind of error. - case e_regSetALL: return gpr_errs[err_idx] | - fpu_errs[err_idx] | - exc_errs[err_idx]; - case e_regSetGPR: return gpr_errs[err_idx]; - case e_regSetFPU: return fpu_errs[err_idx]; - case e_regSetEXC: return exc_errs[err_idx]; - case e_regSetDBG: return dbg_errs[err_idx]; - default: break; - } - } - return -1; - } + case e_regSetFPU: + fpu_errs[err_idx] = err; + return true; - bool - SetError (int flavor, uint32_t err_idx, kern_return_t err) - { - if (err_idx < kNumErrors) - { - switch (flavor) - { - case e_regSetALL: - gpr_errs[err_idx] = - fpu_errs[err_idx] = - exc_errs[err_idx] = - dbg_errs[err_idx] = err; - return true; - - case e_regSetGPR: - gpr_errs[err_idx] = err; - return true; - - case e_regSetFPU: - fpu_errs[err_idx] = err; - return true; - - case e_regSetEXC: - exc_errs[err_idx] = err; - return true; - - case e_regSetDBG: - dbg_errs[err_idx] = err; - return true; - - default: break; - } - } - return false; - } + case e_regSetEXC: + exc_errs[err_idx] = err; + return true; + + case e_regSetDBG: + dbg_errs[err_idx] = err; + return true; - bool - RegsAreValid (int flavor) const - { - return GetError(flavor, Read) == KERN_SUCCESS; + default: + break; } - }; - - kern_return_t GetGPRState (bool force); - kern_return_t GetFPUState (bool force); - kern_return_t GetEXCState (bool force); - kern_return_t GetDBGState (bool force); - - kern_return_t SetGPRState (); - kern_return_t SetFPUState (); - kern_return_t SetEXCState (); - kern_return_t SetDBGState (bool also_set_on_task); - - static DNBArchProtocol * - Create (MachThread *thread); - - static const uint8_t * - SoftwareBreakpointOpcode (nub_size_t byte_size); - - static const DNBRegisterSetInfo * - GetRegisterSetInfo(nub_size_t *num_reg_sets); - - static uint32_t GetRegisterContextSize(); - - // Helper functions for watchpoint manipulations. - static void SetWatchpoint(DBG &debug_state, uint32_t hw_index, nub_addr_t addr, nub_size_t size, bool read, bool write); - static void ClearWatchpoint(DBG &debug_state, uint32_t hw_index); - static bool IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index); - static void ClearWatchpointHits(DBG &debug_state); - static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index); - static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); - - virtual bool StartTransForHWP(); - virtual bool RollbackTransForHWP(); - virtual bool FinishTransForHWP(); - DBG GetDBGCheckpoint(); - - MachThread *m_thread; - State m_state; - DBG m_2pc_dbg_checkpoint; - uint32_t m_2pc_trans_state; // Is transaction of DBG state change: Pedning (0), Done (1), or Rolled Back (2)? - typedef std::map<uint32_t, Context> SaveRegisterStates; - SaveRegisterStates m_saved_register_states; + } + return false; + } + + bool RegsAreValid(int flavor) const { + return GetError(flavor, Read) == KERN_SUCCESS; + } + }; + + kern_return_t GetGPRState(bool force); + kern_return_t GetFPUState(bool force); + kern_return_t GetEXCState(bool force); + kern_return_t GetDBGState(bool force); + + kern_return_t SetGPRState(); + kern_return_t SetFPUState(); + kern_return_t SetEXCState(); + kern_return_t SetDBGState(bool also_set_on_task); + + static DNBArchProtocol *Create(MachThread *thread); + + static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size); + + static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets); + + static uint32_t GetRegisterContextSize(); + + // Helper functions for watchpoint manipulations. + static void SetWatchpoint(DBG &debug_state, uint32_t hw_index, + nub_addr_t addr, nub_size_t size, bool read, + bool write); + static void ClearWatchpoint(DBG &debug_state, uint32_t hw_index); + static bool IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index); + static void ClearWatchpointHits(DBG &debug_state); + static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index); + static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); + + virtual bool StartTransForHWP(); + virtual bool RollbackTransForHWP(); + virtual bool FinishTransForHWP(); + DBG GetDBGCheckpoint(); + + MachThread *m_thread; + State m_state; + DBG m_2pc_dbg_checkpoint; + uint32_t m_2pc_trans_state; // Is transaction of DBG state change: Pedning + // (0), Done (1), or Rolled Back (2)? + typedef std::map<uint32_t, Context> SaveRegisterStates; + SaveRegisterStates m_saved_register_states; }; -#endif // #if defined (__i386__) || defined (__x86_64__) -#endif // #ifndef __DNBArchImplX86_64_h__ +#endif // #if defined (__i386__) || defined (__x86_64__) +#endif // #ifndef __DNBArchImplX86_64_h__ diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/MachRegisterStatesX86_64.h b/lldb/tools/debugserver/source/MacOSX/x86_64/MachRegisterStatesX86_64.h index 4e48e9645dd..5ed67611e6e 100644 --- a/lldb/tools/debugserver/source/MacOSX/x86_64/MachRegisterStatesX86_64.h +++ b/lldb/tools/debugserver/source/MacOSX/x86_64/MachRegisterStatesX86_64.h @@ -1,4 +1,5 @@ -//===-- MachRegisterStatesX86_64.h --------------------------------*- C++ -*-===// +//===-- MachRegisterStatesX86_64.h --------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -16,195 +17,192 @@ #include <inttypes.h> -#define __x86_64_THREAD_STATE 4 -#define __x86_64_FLOAT_STATE 5 -#define __x86_64_EXCEPTION_STATE 6 -#define __x86_64_DEBUG_STATE 11 -#define __x86_64_AVX_STATE 17 +#define __x86_64_THREAD_STATE 4 +#define __x86_64_FLOAT_STATE 5 +#define __x86_64_EXCEPTION_STATE 6 +#define __x86_64_DEBUG_STATE 11 +#define __x86_64_AVX_STATE 17 typedef struct { - uint64_t __rax; - uint64_t __rbx; - uint64_t __rcx; - uint64_t __rdx; - uint64_t __rdi; - uint64_t __rsi; - uint64_t __rbp; - uint64_t __rsp; - uint64_t __r8; - uint64_t __r9; - uint64_t __r10; - uint64_t __r11; - uint64_t __r12; - uint64_t __r13; - uint64_t __r14; - uint64_t __r15; - uint64_t __rip; - uint64_t __rflags; - uint64_t __cs; - uint64_t __fs; - uint64_t __gs; + uint64_t __rax; + uint64_t __rbx; + uint64_t __rcx; + uint64_t __rdx; + uint64_t __rdi; + uint64_t __rsi; + uint64_t __rbp; + uint64_t __rsp; + uint64_t __r8; + uint64_t __r9; + uint64_t __r10; + uint64_t __r11; + uint64_t __r12; + uint64_t __r13; + uint64_t __r14; + uint64_t __r15; + uint64_t __rip; + uint64_t __rflags; + uint64_t __cs; + uint64_t __fs; + uint64_t __gs; } __x86_64_thread_state_t; typedef struct { - uint16_t __invalid : 1; - uint16_t __denorm : 1; - uint16_t __zdiv : 1; - uint16_t __ovrfl : 1; - uint16_t __undfl : 1; - uint16_t __precis : 1; - uint16_t __PAD1 : 2; - uint16_t __pc : 2; - uint16_t __rc : 2; - uint16_t __PAD2 : 1; - uint16_t __PAD3 : 3; + uint16_t __invalid : 1; + uint16_t __denorm : 1; + uint16_t __zdiv : 1; + uint16_t __ovrfl : 1; + uint16_t __undfl : 1; + uint16_t __precis : 1; + uint16_t __PAD1 : 2; + uint16_t __pc : 2; + uint16_t __rc : 2; + uint16_t __PAD2 : 1; + uint16_t __PAD3 : 3; } __x86_64_fp_control_t; typedef struct { - uint16_t __invalid : 1; - uint16_t __denorm : 1; - uint16_t __zdiv : 1; - uint16_t __ovrfl : 1; - uint16_t __undfl : 1; - uint16_t __precis : 1; - uint16_t __stkflt : 1; - uint16_t __errsumm : 1; - uint16_t __c0 : 1; - uint16_t __c1 : 1; - uint16_t __c2 : 1; - uint16_t __tos : 3; - uint16_t __c3 : 1; - uint16_t __busy : 1; + uint16_t __invalid : 1; + uint16_t __denorm : 1; + uint16_t __zdiv : 1; + uint16_t __ovrfl : 1; + uint16_t __undfl : 1; + uint16_t __precis : 1; + uint16_t __stkflt : 1; + uint16_t __errsumm : 1; + uint16_t __c0 : 1; + uint16_t __c1 : 1; + uint16_t __c2 : 1; + uint16_t __tos : 3; + uint16_t __c3 : 1; + uint16_t __busy : 1; } __x86_64_fp_status_t; typedef struct { - uint8_t __mmst_reg[10]; - uint8_t __mmst_rsrv[6]; + uint8_t __mmst_reg[10]; + uint8_t __mmst_rsrv[6]; } __x86_64_mmst_reg; -typedef struct { - uint8_t __xmm_reg[16]; -} __x86_64_xmm_reg; +typedef struct { uint8_t __xmm_reg[16]; } __x86_64_xmm_reg; typedef struct { - int32_t __fpu_reserved[2]; - __x86_64_fp_control_t __fpu_fcw; - __x86_64_fp_status_t __fpu_fsw; - uint8_t __fpu_ftw; - uint8_t __fpu_rsrv1; - uint16_t __fpu_fop; - uint32_t __fpu_ip; - uint16_t __fpu_cs; - uint16_t __fpu_rsrv2; - uint32_t __fpu_dp; - uint16_t __fpu_ds; - uint16_t __fpu_rsrv3; - uint32_t __fpu_mxcsr; - uint32_t __fpu_mxcsrmask; - __x86_64_mmst_reg __fpu_stmm0; - __x86_64_mmst_reg __fpu_stmm1; - __x86_64_mmst_reg __fpu_stmm2; - __x86_64_mmst_reg __fpu_stmm3; - __x86_64_mmst_reg __fpu_stmm4; - __x86_64_mmst_reg __fpu_stmm5; - __x86_64_mmst_reg __fpu_stmm6; - __x86_64_mmst_reg __fpu_stmm7; - __x86_64_xmm_reg __fpu_xmm0; - __x86_64_xmm_reg __fpu_xmm1; - __x86_64_xmm_reg __fpu_xmm2; - __x86_64_xmm_reg __fpu_xmm3; - __x86_64_xmm_reg __fpu_xmm4; - __x86_64_xmm_reg __fpu_xmm5; - __x86_64_xmm_reg __fpu_xmm6; - __x86_64_xmm_reg __fpu_xmm7; - __x86_64_xmm_reg __fpu_xmm8; - __x86_64_xmm_reg __fpu_xmm9; - __x86_64_xmm_reg __fpu_xmm10; - __x86_64_xmm_reg __fpu_xmm11; - __x86_64_xmm_reg __fpu_xmm12; - __x86_64_xmm_reg __fpu_xmm13; - __x86_64_xmm_reg __fpu_xmm14; - __x86_64_xmm_reg __fpu_xmm15; - uint8_t __fpu_rsrv4[6*16]; - int32_t __fpu_reserved1; + int32_t __fpu_reserved[2]; + __x86_64_fp_control_t __fpu_fcw; + __x86_64_fp_status_t __fpu_fsw; + uint8_t __fpu_ftw; + uint8_t __fpu_rsrv1; + uint16_t __fpu_fop; + uint32_t __fpu_ip; + uint16_t __fpu_cs; + uint16_t __fpu_rsrv2; + uint32_t __fpu_dp; + uint16_t __fpu_ds; + uint16_t __fpu_rsrv3; + uint32_t __fpu_mxcsr; + uint32_t __fpu_mxcsrmask; + __x86_64_mmst_reg __fpu_stmm0; + __x86_64_mmst_reg __fpu_stmm1; + __x86_64_mmst_reg __fpu_stmm2; + __x86_64_mmst_reg __fpu_stmm3; + __x86_64_mmst_reg __fpu_stmm4; + __x86_64_mmst_reg __fpu_stmm5; + __x86_64_mmst_reg __fpu_stmm6; + __x86_64_mmst_reg __fpu_stmm7; + __x86_64_xmm_reg __fpu_xmm0; + __x86_64_xmm_reg __fpu_xmm1; + __x86_64_xmm_reg __fpu_xmm2; + __x86_64_xmm_reg __fpu_xmm3; + __x86_64_xmm_reg __fpu_xmm4; + __x86_64_xmm_reg __fpu_xmm5; + __x86_64_xmm_reg __fpu_xmm6; + __x86_64_xmm_reg __fpu_xmm7; + __x86_64_xmm_reg __fpu_xmm8; + __x86_64_xmm_reg __fpu_xmm9; + __x86_64_xmm_reg __fpu_xmm10; + __x86_64_xmm_reg __fpu_xmm11; + __x86_64_xmm_reg __fpu_xmm12; + __x86_64_xmm_reg __fpu_xmm13; + __x86_64_xmm_reg __fpu_xmm14; + __x86_64_xmm_reg __fpu_xmm15; + uint8_t __fpu_rsrv4[6 * 16]; + int32_t __fpu_reserved1; } __x86_64_float_state_t; typedef struct { - uint32_t __fpu_reserved[2]; - __x86_64_fp_control_t __fpu_fcw; - __x86_64_fp_status_t __fpu_fsw; - uint8_t __fpu_ftw; - uint8_t __fpu_rsrv1; - uint16_t __fpu_fop; - uint32_t __fpu_ip; - uint16_t __fpu_cs; - uint16_t __fpu_rsrv2; - uint32_t __fpu_dp; - uint16_t __fpu_ds; - uint16_t __fpu_rsrv3; - uint32_t __fpu_mxcsr; - uint32_t __fpu_mxcsrmask; - __x86_64_mmst_reg __fpu_stmm0; - __x86_64_mmst_reg __fpu_stmm1; - __x86_64_mmst_reg __fpu_stmm2; - __x86_64_mmst_reg __fpu_stmm3; - __x86_64_mmst_reg __fpu_stmm4; - __x86_64_mmst_reg __fpu_stmm5; - __x86_64_mmst_reg __fpu_stmm6; - __x86_64_mmst_reg __fpu_stmm7; - __x86_64_xmm_reg __fpu_xmm0; - __x86_64_xmm_reg __fpu_xmm1; - __x86_64_xmm_reg __fpu_xmm2; - __x86_64_xmm_reg __fpu_xmm3; - __x86_64_xmm_reg __fpu_xmm4; - __x86_64_xmm_reg __fpu_xmm5; - __x86_64_xmm_reg __fpu_xmm6; - __x86_64_xmm_reg __fpu_xmm7; - __x86_64_xmm_reg __fpu_xmm8; - __x86_64_xmm_reg __fpu_xmm9; - __x86_64_xmm_reg __fpu_xmm10; - __x86_64_xmm_reg __fpu_xmm11; - __x86_64_xmm_reg __fpu_xmm12; - __x86_64_xmm_reg __fpu_xmm13; - __x86_64_xmm_reg __fpu_xmm14; - __x86_64_xmm_reg __fpu_xmm15; - uint8_t __fpu_rsrv4[6*16]; - uint32_t __fpu_reserved1; - uint8_t __avx_reserved1[64]; - __x86_64_xmm_reg __fpu_ymmh0; - __x86_64_xmm_reg __fpu_ymmh1; - __x86_64_xmm_reg __fpu_ymmh2; - __x86_64_xmm_reg __fpu_ymmh3; - __x86_64_xmm_reg __fpu_ymmh4; - __x86_64_xmm_reg __fpu_ymmh5; - __x86_64_xmm_reg __fpu_ymmh6; - __x86_64_xmm_reg __fpu_ymmh7; - __x86_64_xmm_reg __fpu_ymmh8; - __x86_64_xmm_reg __fpu_ymmh9; - __x86_64_xmm_reg __fpu_ymmh10; - __x86_64_xmm_reg __fpu_ymmh11; - __x86_64_xmm_reg __fpu_ymmh12; - __x86_64_xmm_reg __fpu_ymmh13; - __x86_64_xmm_reg __fpu_ymmh14; - __x86_64_xmm_reg __fpu_ymmh15; + uint32_t __fpu_reserved[2]; + __x86_64_fp_control_t __fpu_fcw; + __x86_64_fp_status_t __fpu_fsw; + uint8_t __fpu_ftw; + uint8_t __fpu_rsrv1; + uint16_t __fpu_fop; + uint32_t __fpu_ip; + uint16_t __fpu_cs; + uint16_t __fpu_rsrv2; + uint32_t __fpu_dp; + uint16_t __fpu_ds; + uint16_t __fpu_rsrv3; + uint32_t __fpu_mxcsr; + uint32_t __fpu_mxcsrmask; + __x86_64_mmst_reg __fpu_stmm0; + __x86_64_mmst_reg __fpu_stmm1; + __x86_64_mmst_reg __fpu_stmm2; + __x86_64_mmst_reg __fpu_stmm3; + __x86_64_mmst_reg __fpu_stmm4; + __x86_64_mmst_reg __fpu_stmm5; + __x86_64_mmst_reg __fpu_stmm6; + __x86_64_mmst_reg __fpu_stmm7; + __x86_64_xmm_reg __fpu_xmm0; + __x86_64_xmm_reg __fpu_xmm1; + __x86_64_xmm_reg __fpu_xmm2; + __x86_64_xmm_reg __fpu_xmm3; + __x86_64_xmm_reg __fpu_xmm4; + __x86_64_xmm_reg __fpu_xmm5; + __x86_64_xmm_reg __fpu_xmm6; + __x86_64_xmm_reg __fpu_xmm7; + __x86_64_xmm_reg __fpu_xmm8; + __x86_64_xmm_reg __fpu_xmm9; + __x86_64_xmm_reg __fpu_xmm10; + __x86_64_xmm_reg __fpu_xmm11; + __x86_64_xmm_reg __fpu_xmm12; + __x86_64_xmm_reg __fpu_xmm13; + __x86_64_xmm_reg __fpu_xmm14; + __x86_64_xmm_reg __fpu_xmm15; + uint8_t __fpu_rsrv4[6 * 16]; + uint32_t __fpu_reserved1; + uint8_t __avx_reserved1[64]; + __x86_64_xmm_reg __fpu_ymmh0; + __x86_64_xmm_reg __fpu_ymmh1; + __x86_64_xmm_reg __fpu_ymmh2; + __x86_64_xmm_reg __fpu_ymmh3; + __x86_64_xmm_reg __fpu_ymmh4; + __x86_64_xmm_reg __fpu_ymmh5; + __x86_64_xmm_reg __fpu_ymmh6; + __x86_64_xmm_reg __fpu_ymmh7; + __x86_64_xmm_reg __fpu_ymmh8; + __x86_64_xmm_reg __fpu_ymmh9; + __x86_64_xmm_reg __fpu_ymmh10; + __x86_64_xmm_reg __fpu_ymmh11; + __x86_64_xmm_reg __fpu_ymmh12; + __x86_64_xmm_reg __fpu_ymmh13; + __x86_64_xmm_reg __fpu_ymmh14; + __x86_64_xmm_reg __fpu_ymmh15; } __x86_64_avx_state_t; typedef struct { - uint32_t __trapno; - uint32_t __err; - uint64_t __faultvaddr; + uint32_t __trapno; + uint32_t __err; + uint64_t __faultvaddr; } __x86_64_exception_state_t; - typedef struct { - uint64_t __dr0; - uint64_t __dr1; - uint64_t __dr2; - uint64_t __dr3; - uint64_t __dr4; - uint64_t __dr5; - uint64_t __dr6; - uint64_t __dr7; + uint64_t __dr0; + uint64_t __dr1; + uint64_t __dr2; + uint64_t __dr3; + uint64_t __dr4; + uint64_t __dr5; + uint64_t __dr6; + uint64_t __dr7; } __x86_64_debug_state_t; #endif diff --git a/lldb/tools/debugserver/source/PThreadCondition.h b/lldb/tools/debugserver/source/PThreadCondition.h index 787cc7941d5..9cd64bf2472 100644 --- a/lldb/tools/debugserver/source/PThreadCondition.h +++ b/lldb/tools/debugserver/source/PThreadCondition.h @@ -16,38 +16,20 @@ #include <pthread.h> -class PThreadCondition -{ +class PThreadCondition { public: + PThreadCondition() { ::pthread_cond_init(&m_condition, NULL); } - PThreadCondition() - { - ::pthread_cond_init (&m_condition, NULL); - } + ~PThreadCondition() { ::pthread_cond_destroy(&m_condition); } - ~PThreadCondition() - { - ::pthread_cond_destroy (&m_condition); - } + pthread_cond_t *Condition() { return &m_condition; } - pthread_cond_t *Condition() - { - return &m_condition; - } + int Broadcast() { return ::pthread_cond_broadcast(&m_condition); } - int Broadcast() - { - return ::pthread_cond_broadcast (&m_condition); - } - - int Signal() - { - return ::pthread_cond_signal (&m_condition); - } + int Signal() { return ::pthread_cond_signal(&m_condition); } protected: - pthread_cond_t m_condition; + pthread_cond_t m_condition; }; #endif - diff --git a/lldb/tools/debugserver/source/PThreadEvent.cpp b/lldb/tools/debugserver/source/PThreadEvent.cpp index 47e72756a96..1b0900ca710 100644 --- a/lldb/tools/debugserver/source/PThreadEvent.cpp +++ b/lldb/tools/debugserver/source/PThreadEvent.cpp @@ -12,117 +12,98 @@ //===----------------------------------------------------------------------===// #include "PThreadEvent.h" -#include "errno.h" #include "DNBLog.h" +#include "errno.h" -PThreadEvent::PThreadEvent(uint32_t bits, uint32_t validBits) : - m_mutex(), - m_set_condition(), - m_reset_condition(), - m_bits(bits), - m_validBits(validBits), - m_reset_ack_mask(0) -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, 0x%8.8x)", this, __FUNCTION__, bits, validBits); +PThreadEvent::PThreadEvent(uint32_t bits, uint32_t validBits) + : m_mutex(), m_set_condition(), m_reset_condition(), m_bits(bits), + m_validBits(validBits), m_reset_ack_mask(0) { + // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, 0x%8.8x)", + // this, __FUNCTION__, bits, validBits); } -PThreadEvent::~PThreadEvent() -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION); +PThreadEvent::~PThreadEvent() { + // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION); } - -uint32_t -PThreadEvent::NewEventBit() -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION); - PTHREAD_MUTEX_LOCKER (locker, m_mutex); - uint32_t mask = 1; - while (mask & m_validBits) - mask <<= 1; - m_validBits |= mask; - return mask; +uint32_t PThreadEvent::NewEventBit() { + // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION); + PTHREAD_MUTEX_LOCKER(locker, m_mutex); + uint32_t mask = 1; + while (mask & m_validBits) + mask <<= 1; + m_validBits |= mask; + return mask; } -void -PThreadEvent::FreeEventBits(const uint32_t mask) -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, __FUNCTION__, mask); - if (mask) - { - PTHREAD_MUTEX_LOCKER (locker, m_mutex); - m_bits &= ~mask; - m_validBits &= ~mask; - } +void PThreadEvent::FreeEventBits(const uint32_t mask) { + // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, + // __FUNCTION__, mask); + if (mask) { + PTHREAD_MUTEX_LOCKER(locker, m_mutex); + m_bits &= ~mask; + m_validBits &= ~mask; + } } - -uint32_t -PThreadEvent::GetEventBits() const -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION); - PTHREAD_MUTEX_LOCKER (locker, m_mutex); - uint32_t bits = m_bits; - return bits; +uint32_t PThreadEvent::GetEventBits() const { + // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION); + PTHREAD_MUTEX_LOCKER(locker, m_mutex); + uint32_t bits = m_bits; + return bits; } // Replace the event bits with a new bitmask value -void -PThreadEvent::ReplaceEventBits(const uint32_t bits) -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, __FUNCTION__, bits); - PTHREAD_MUTEX_LOCKER (locker, m_mutex); - // Make sure we have some bits and that they aren't already set... - if (m_bits != bits) - { - // Figure out which bits are changing - uint32_t changed_bits = m_bits ^ bits; - // Set the new bit values - m_bits = bits; - // If any new bits are set, then broadcast - if (changed_bits & m_bits) - m_set_condition.Broadcast(); - } +void PThreadEvent::ReplaceEventBits(const uint32_t bits) { + // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, + // __FUNCTION__, bits); + PTHREAD_MUTEX_LOCKER(locker, m_mutex); + // Make sure we have some bits and that they aren't already set... + if (m_bits != bits) { + // Figure out which bits are changing + uint32_t changed_bits = m_bits ^ bits; + // Set the new bit values + m_bits = bits; + // If any new bits are set, then broadcast + if (changed_bits & m_bits) + m_set_condition.Broadcast(); + } } // Set one or more event bits and broadcast if any new event bits get set // that weren't already set. -void -PThreadEvent::SetEvents(const uint32_t mask) -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, __FUNCTION__, mask); - // Make sure we have some bits to set - if (mask) - { - PTHREAD_MUTEX_LOCKER (locker, m_mutex); - // Save the old event bit state so we can tell if things change - uint32_t old = m_bits; - // Set the all event bits that are set in 'mask' - m_bits |= mask; - // Broadcast only if any extra bits got set. - if (old != m_bits) - m_set_condition.Broadcast(); - } +void PThreadEvent::SetEvents(const uint32_t mask) { + // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, + // __FUNCTION__, mask); + // Make sure we have some bits to set + if (mask) { + PTHREAD_MUTEX_LOCKER(locker, m_mutex); + // Save the old event bit state so we can tell if things change + uint32_t old = m_bits; + // Set the all event bits that are set in 'mask' + m_bits |= mask; + // Broadcast only if any extra bits got set. + if (old != m_bits) + m_set_condition.Broadcast(); + } } // Reset one or more event bits -void -PThreadEvent::ResetEvents(const uint32_t mask) -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, __FUNCTION__, mask); - if (mask) - { - PTHREAD_MUTEX_LOCKER (locker, m_mutex); - - // Save the old event bit state so we can tell if things change - uint32_t old = m_bits; - // Clear the all event bits that are set in 'mask' - m_bits &= ~mask; - // Broadcast only if any extra bits got reset. - if (old != m_bits) - m_reset_condition.Broadcast(); - } +void PThreadEvent::ResetEvents(const uint32_t mask) { + // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, + // __FUNCTION__, mask); + if (mask) { + PTHREAD_MUTEX_LOCKER(locker, m_mutex); + + // Save the old event bit state so we can tell if things change + uint32_t old = m_bits; + // Clear the all event bits that are set in 'mask' + m_bits &= ~mask; + // Broadcast only if any extra bits got reset. + if (old != m_bits) + m_reset_condition.Broadcast(); + } } //---------------------------------------------------------------------- @@ -130,98 +111,90 @@ PThreadEvent::ResetEvents(const uint32_t mask) // 'mask'. If 'timeout_abstime' is NULL, then wait forever. //---------------------------------------------------------------------- uint32_t -PThreadEvent::WaitForSetEvents(const uint32_t mask, const struct timespec *timeout_abstime) const -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, __FUNCTION__, mask, timeout_abstime); - int err = 0; - // pthread_cond_timedwait() or pthread_cond_wait() will atomically - // unlock the mutex and wait for the condition to be set. When either - // function returns, they will re-lock the mutex. We use an auto lock/unlock - // class (PThreadMutex::Locker) to allow us to return at any point in this - // function and not have to worry about unlocking the mutex. - PTHREAD_MUTEX_LOCKER (locker, m_mutex); - do - { - // Check our predicate (event bits) in case any are already set - if (mask & m_bits) - { - uint32_t bits_set = mask & m_bits; - // Our PThreadMutex::Locker will automatically unlock our mutex - return bits_set; - } - if (timeout_abstime) - { - // Wait for condition to get broadcast, or for a timeout. If we get - // a timeout we will drop out of the do loop and return false which - // is what we want. - err = ::pthread_cond_timedwait (m_set_condition.Condition(), m_mutex.Mutex(), timeout_abstime); - // Retest our predicate in case of a race condition right at the end - // of the timeout. - if (err == ETIMEDOUT) - { - uint32_t bits_set = mask & m_bits; - return bits_set; - } - } - else - { - // Wait for condition to get broadcast. The only error this function - // should return is if - err = ::pthread_cond_wait (m_set_condition.Condition(), m_mutex.Mutex()); - } - } while (err == 0); - return 0; +PThreadEvent::WaitForSetEvents(const uint32_t mask, + const struct timespec *timeout_abstime) const { + // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, + // __FUNCTION__, mask, timeout_abstime); + int err = 0; + // pthread_cond_timedwait() or pthread_cond_wait() will atomically + // unlock the mutex and wait for the condition to be set. When either + // function returns, they will re-lock the mutex. We use an auto lock/unlock + // class (PThreadMutex::Locker) to allow us to return at any point in this + // function and not have to worry about unlocking the mutex. + PTHREAD_MUTEX_LOCKER(locker, m_mutex); + do { + // Check our predicate (event bits) in case any are already set + if (mask & m_bits) { + uint32_t bits_set = mask & m_bits; + // Our PThreadMutex::Locker will automatically unlock our mutex + return bits_set; + } + if (timeout_abstime) { + // Wait for condition to get broadcast, or for a timeout. If we get + // a timeout we will drop out of the do loop and return false which + // is what we want. + err = ::pthread_cond_timedwait(m_set_condition.Condition(), + m_mutex.Mutex(), timeout_abstime); + // Retest our predicate in case of a race condition right at the end + // of the timeout. + if (err == ETIMEDOUT) { + uint32_t bits_set = mask & m_bits; + return bits_set; + } + } else { + // Wait for condition to get broadcast. The only error this function + // should return is if + err = ::pthread_cond_wait(m_set_condition.Condition(), m_mutex.Mutex()); + } + } while (err == 0); + return 0; } //---------------------------------------------------------------------- // Wait until 'timeout_abstime' for any events in 'mask' to reset. // If 'timeout_abstime' is NULL, then wait forever. //---------------------------------------------------------------------- -uint32_t -PThreadEvent::WaitForEventsToReset(const uint32_t mask, const struct timespec *timeout_abstime) const -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, __FUNCTION__, mask, timeout_abstime); - int err = 0; - // pthread_cond_timedwait() or pthread_cond_wait() will atomically - // unlock the mutex and wait for the condition to be set. When either - // function returns, they will re-lock the mutex. We use an auto lock/unlock - // class (PThreadMutex::Locker) to allow us to return at any point in this - // function and not have to worry about unlocking the mutex. - PTHREAD_MUTEX_LOCKER (locker, m_mutex); - do - { - // Check our predicate (event bits) each time through this do loop - if ((mask & m_bits) == 0) - { - // All the bits requested have been reset, return zero indicating - // which bits from the mask were still set (none of them) - return 0; - } - if (timeout_abstime) - { - // Wait for condition to get broadcast, or for a timeout. If we get - // a timeout we will drop out of the do loop and return false which - // is what we want. - err = ::pthread_cond_timedwait (m_reset_condition.Condition(), m_mutex.Mutex(), timeout_abstime); - } - else - { - // Wait for condition to get broadcast. The only error this function - // should return is if - err = ::pthread_cond_wait (m_reset_condition.Condition(), m_mutex.Mutex()); - } - } while (err == 0); - // Return a mask indicating which bits (if any) were still set - return mask & m_bits; +uint32_t PThreadEvent::WaitForEventsToReset( + const uint32_t mask, const struct timespec *timeout_abstime) const { + // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, + // __FUNCTION__, mask, timeout_abstime); + int err = 0; + // pthread_cond_timedwait() or pthread_cond_wait() will atomically + // unlock the mutex and wait for the condition to be set. When either + // function returns, they will re-lock the mutex. We use an auto lock/unlock + // class (PThreadMutex::Locker) to allow us to return at any point in this + // function and not have to worry about unlocking the mutex. + PTHREAD_MUTEX_LOCKER(locker, m_mutex); + do { + // Check our predicate (event bits) each time through this do loop + if ((mask & m_bits) == 0) { + // All the bits requested have been reset, return zero indicating + // which bits from the mask were still set (none of them) + return 0; + } + if (timeout_abstime) { + // Wait for condition to get broadcast, or for a timeout. If we get + // a timeout we will drop out of the do loop and return false which + // is what we want. + err = ::pthread_cond_timedwait(m_reset_condition.Condition(), + m_mutex.Mutex(), timeout_abstime); + } else { + // Wait for condition to get broadcast. The only error this function + // should return is if + err = ::pthread_cond_wait(m_reset_condition.Condition(), m_mutex.Mutex()); + } + } while (err == 0); + // Return a mask indicating which bits (if any) were still set + return mask & m_bits; } uint32_t -PThreadEvent::WaitForResetAck (const uint32_t mask, const struct timespec *timeout_abstime) const -{ - if (mask & m_reset_ack_mask) - { - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, __FUNCTION__, mask, timeout_abstime); - return WaitForEventsToReset (mask & m_reset_ack_mask, timeout_abstime); - } - return 0; +PThreadEvent::WaitForResetAck(const uint32_t mask, + const struct timespec *timeout_abstime) const { + if (mask & m_reset_ack_mask) { + // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, + // __FUNCTION__, mask, timeout_abstime); + return WaitForEventsToReset(mask & m_reset_ack_mask, timeout_abstime); + } + return 0; } diff --git a/lldb/tools/debugserver/source/PThreadEvent.h b/lldb/tools/debugserver/source/PThreadEvent.h index 46c7cc09b12..fbcd4593352 100644 --- a/lldb/tools/debugserver/source/PThreadEvent.h +++ b/lldb/tools/debugserver/source/PThreadEvent.h @@ -13,47 +13,52 @@ #ifndef __PThreadEvent_h__ #define __PThreadEvent_h__ -#include "PThreadMutex.h" #include "PThreadCondition.h" +#include "PThreadMutex.h" #include <stdint.h> #include <time.h> -class PThreadEvent -{ +class PThreadEvent { public: - PThreadEvent (uint32_t bits = 0, uint32_t validBits = 0); - ~PThreadEvent (); - - uint32_t NewEventBit (); - void FreeEventBits (const uint32_t mask); - - void ReplaceEventBits (const uint32_t bits); - uint32_t GetEventBits () const; - void SetEvents (const uint32_t mask); - void ResetEvents (const uint32_t mask); - // Wait for events to be set or reset. These functions take an optional - // timeout value. If timeout is NULL an infinite timeout will be used. - uint32_t WaitForSetEvents (const uint32_t mask, const struct timespec *timeout_abstime = NULL) const; - uint32_t WaitForEventsToReset(const uint32_t mask, const struct timespec *timeout_abstime = NULL) const; - - uint32_t GetResetAckMask () const { return m_reset_ack_mask; } - uint32_t SetResetAckMask (uint32_t mask) { return m_reset_ack_mask = mask; } - uint32_t WaitForResetAck (const uint32_t mask, const struct timespec *timeout_abstime = NULL) const; + PThreadEvent(uint32_t bits = 0, uint32_t validBits = 0); + ~PThreadEvent(); + + uint32_t NewEventBit(); + void FreeEventBits(const uint32_t mask); + + void ReplaceEventBits(const uint32_t bits); + uint32_t GetEventBits() const; + void SetEvents(const uint32_t mask); + void ResetEvents(const uint32_t mask); + // Wait for events to be set or reset. These functions take an optional + // timeout value. If timeout is NULL an infinite timeout will be used. + uint32_t + WaitForSetEvents(const uint32_t mask, + const struct timespec *timeout_abstime = NULL) const; + uint32_t + WaitForEventsToReset(const uint32_t mask, + const struct timespec *timeout_abstime = NULL) const; + + uint32_t GetResetAckMask() const { return m_reset_ack_mask; } + uint32_t SetResetAckMask(uint32_t mask) { return m_reset_ack_mask = mask; } + uint32_t WaitForResetAck(const uint32_t mask, + const struct timespec *timeout_abstime = NULL) const; + protected: - //---------------------------------------------------------------------- - // pthread condition and mutex variable to control access and allow - // blocking between the main thread and the spotlight index thread. - //---------------------------------------------------------------------- - mutable PThreadMutex m_mutex; - mutable PThreadCondition m_set_condition; - mutable PThreadCondition m_reset_condition; - uint32_t m_bits; - uint32_t m_validBits; - uint32_t m_reset_ack_mask; -private: - PThreadEvent(const PThreadEvent&); // Outlaw copy constructor - PThreadEvent& operator=(const PThreadEvent& rhs); + //---------------------------------------------------------------------- + // pthread condition and mutex variable to control access and allow + // blocking between the main thread and the spotlight index thread. + //---------------------------------------------------------------------- + mutable PThreadMutex m_mutex; + mutable PThreadCondition m_set_condition; + mutable PThreadCondition m_reset_condition; + uint32_t m_bits; + uint32_t m_validBits; + uint32_t m_reset_ack_mask; +private: + PThreadEvent(const PThreadEvent &); // Outlaw copy constructor + PThreadEvent &operator=(const PThreadEvent &rhs); }; #endif // #ifndef __PThreadEvent_h__ diff --git a/lldb/tools/debugserver/source/PThreadMutex.cpp b/lldb/tools/debugserver/source/PThreadMutex.cpp index bd91ed0154b..32db862f6b4 100644 --- a/lldb/tools/debugserver/source/PThreadMutex.cpp +++ b/lldb/tools/debugserver/source/PThreadMutex.cpp @@ -19,66 +19,53 @@ // Project includes #include "DNBTimer.h" -#if defined (DEBUG_PTHREAD_MUTEX_DEADLOCKS) +#if defined(DEBUG_PTHREAD_MUTEX_DEADLOCKS) -PThreadMutex::Locker::Locker(PThreadMutex& m, const char *function, const char *file, const int line) : - m_pMutex(m.Mutex()), - m_function(function), - m_file(file), - m_line(line), - m_lock_time(0) -{ - Lock(); +PThreadMutex::Locker::Locker(PThreadMutex &m, const char *function, + const char *file, const int line) + : m_pMutex(m.Mutex()), m_function(function), m_file(file), m_line(line), + m_lock_time(0) { + Lock(); } -PThreadMutex::Locker::Locker(PThreadMutex* m, const char *function, const char *file, const int line) : - m_pMutex(m ? m->Mutex() : NULL), - m_function(function), - m_file(file), - m_line(line), - m_lock_time(0) -{ - Lock(); +PThreadMutex::Locker::Locker(PThreadMutex *m, const char *function, + const char *file, const int line) + : m_pMutex(m ? m->Mutex() : NULL), m_function(function), m_file(file), + m_line(line), m_lock_time(0) { + Lock(); } -PThreadMutex::Locker::Locker(pthread_mutex_t *mutex, const char *function, const char *file, const int line) : - m_pMutex(mutex), - m_function(function), - m_file(file), - m_line(line), - m_lock_time(0) -{ - Lock(); +PThreadMutex::Locker::Locker(pthread_mutex_t *mutex, const char *function, + const char *file, const int line) + : m_pMutex(mutex), m_function(function), m_file(file), m_line(line), + m_lock_time(0) { + Lock(); } +PThreadMutex::Locker::~Locker() { Unlock(); } -PThreadMutex::Locker::~Locker() -{ - Unlock(); -} - - -void -PThreadMutex::Locker::Lock() -{ - if (m_pMutex) - { - m_lock_time = DNBTimer::GetTimeOfDay(); - if (::pthread_mutex_trylock (m_pMutex) != 0) - { - fprintf(stdout, "::pthread_mutex_trylock (%8.8p) mutex is locked (function %s in %s:%i), waiting...\n", m_pMutex, m_function, m_file, m_line); - ::pthread_mutex_lock (m_pMutex); - fprintf(stdout, "::pthread_mutex_lock (%8.8p) succeeded after %6llu usecs (function %s in %s:%i)\n", m_pMutex, DNBTimer::GetTimeOfDay() - m_lock_time, m_function, m_file, m_line); - } +void PThreadMutex::Locker::Lock() { + if (m_pMutex) { + m_lock_time = DNBTimer::GetTimeOfDay(); + if (::pthread_mutex_trylock(m_pMutex) != 0) { + fprintf(stdout, "::pthread_mutex_trylock (%8.8p) mutex is locked " + "(function %s in %s:%i), waiting...\n", + m_pMutex, m_function, m_file, m_line); + ::pthread_mutex_lock(m_pMutex); + fprintf(stdout, "::pthread_mutex_lock (%8.8p) succeeded after %6llu " + "usecs (function %s in %s:%i)\n", + m_pMutex, DNBTimer::GetTimeOfDay() - m_lock_time, m_function, + m_file, m_line); } + } } - -void -PThreadMutex::Locker::Unlock() -{ - fprintf(stdout, "::pthread_mutex_unlock (%8.8p) had lock for %6llu usecs in %s in %s:%i\n", m_pMutex, DNBTimer::GetTimeOfDay() - m_lock_time, m_function, m_file, m_line); - ::pthread_mutex_unlock (m_pMutex); +void PThreadMutex::Locker::Unlock() { + fprintf(stdout, "::pthread_mutex_unlock (%8.8p) had lock for %6llu usecs in " + "%s in %s:%i\n", + m_pMutex, DNBTimer::GetTimeOfDay() - m_lock_time, m_function, m_file, + m_line); + ::pthread_mutex_unlock(m_pMutex); } #endif diff --git a/lldb/tools/debugserver/source/PThreadMutex.h b/lldb/tools/debugserver/source/PThreadMutex.h index 9a12f6e8e03..c6ec293c5e5 100644 --- a/lldb/tools/debugserver/source/PThreadMutex.h +++ b/lldb/tools/debugserver/source/PThreadMutex.h @@ -14,135 +14,107 @@ #ifndef __PThreadMutex_h__ #define __PThreadMutex_h__ -#include <pthread.h> #include <assert.h> +#include <pthread.h> #include <stdint.h> //#define DEBUG_PTHREAD_MUTEX_DEADLOCKS 1 -#if defined (DEBUG_PTHREAD_MUTEX_DEADLOCKS) -#define PTHREAD_MUTEX_LOCKER(var, mutex) PThreadMutex::Locker var(mutex, __FUNCTION__, __FILE__, __LINE__) +#if defined(DEBUG_PTHREAD_MUTEX_DEADLOCKS) +#define PTHREAD_MUTEX_LOCKER(var, mutex) \ + PThreadMutex::Locker var(mutex, __FUNCTION__, __FILE__, __LINE__) #else #define PTHREAD_MUTEX_LOCKER(var, mutex) PThreadMutex::Locker var(mutex) #endif -class PThreadMutex -{ +class PThreadMutex { public: - - class Locker - { - public: -#if defined (DEBUG_PTHREAD_MUTEX_DEADLOCKS) - - Locker(PThreadMutex& m, const char *function, const char *file, int line); - Locker(PThreadMutex* m, const char *function, const char *file, int line); - Locker(pthread_mutex_t *mutex, const char *function, const char *file, int line); - ~Locker(); - void Lock(); - void Unlock(); + class Locker { + public: +#if defined(DEBUG_PTHREAD_MUTEX_DEADLOCKS) + + Locker(PThreadMutex &m, const char *function, const char *file, int line); + Locker(PThreadMutex *m, const char *function, const char *file, int line); + Locker(pthread_mutex_t *mutex, const char *function, const char *file, + int line); + ~Locker(); + void Lock(); + void Unlock(); #else - Locker(PThreadMutex& m) : - m_pMutex(m.Mutex()) - { - Lock(); - } - - Locker(PThreadMutex* m) : - m_pMutex(m ? m->Mutex() : NULL) - { - Lock(); - } - - Locker(pthread_mutex_t *mutex) : - m_pMutex(mutex) - { - Lock(); - } - - void Lock() - { - if (m_pMutex) - ::pthread_mutex_lock (m_pMutex); - } - - void Unlock() - { - if (m_pMutex) - ::pthread_mutex_unlock (m_pMutex); - } - - ~Locker() - { - Unlock(); - } + Locker(PThreadMutex &m) : m_pMutex(m.Mutex()) { Lock(); } -#endif - - // unlock any the current mutex and lock the new one if it is valid - void Reset(pthread_mutex_t *pMutex = NULL) - { - Unlock(); - m_pMutex = pMutex; - Lock(); - } - pthread_mutex_t *m_pMutex; -#if defined (DEBUG_PTHREAD_MUTEX_DEADLOCKS) - const char *m_function; - const char *m_file; - int m_line; - uint64_t m_lock_time; -#endif - }; + Locker(PThreadMutex *m) : m_pMutex(m ? m->Mutex() : NULL) { Lock(); } + Locker(pthread_mutex_t *mutex) : m_pMutex(mutex) { Lock(); } - PThreadMutex() - { - int err; - err = ::pthread_mutex_init (&m_mutex, NULL); assert(err == 0); + void Lock() { + if (m_pMutex) + ::pthread_mutex_lock(m_pMutex); } - PThreadMutex(int type) - { - int err; - ::pthread_mutexattr_t attr; - err = ::pthread_mutexattr_init (&attr); assert(err == 0); - err = ::pthread_mutexattr_settype (&attr, type); assert(err == 0); - err = ::pthread_mutex_init (&m_mutex, &attr); assert(err == 0); - err = ::pthread_mutexattr_destroy (&attr); assert(err == 0); + void Unlock() { + if (m_pMutex) + ::pthread_mutex_unlock(m_pMutex); } - ~PThreadMutex() - { - int err; - err = ::pthread_mutex_destroy (&m_mutex); - if (err != 0) - { - err = Unlock(); - if (err == 0) - ::pthread_mutex_destroy (&m_mutex); - } - } + ~Locker() { Unlock(); } - pthread_mutex_t *Mutex() - { - return &m_mutex; - } +#endif - int Lock() - { - return ::pthread_mutex_lock (&m_mutex); + // unlock any the current mutex and lock the new one if it is valid + void Reset(pthread_mutex_t *pMutex = NULL) { + Unlock(); + m_pMutex = pMutex; + Lock(); } - - int Unlock() - { - return ::pthread_mutex_unlock (&m_mutex); + pthread_mutex_t *m_pMutex; +#if defined(DEBUG_PTHREAD_MUTEX_DEADLOCKS) + const char *m_function; + const char *m_file; + int m_line; + uint64_t m_lock_time; +#endif + }; + + PThreadMutex() { + int err; + err = ::pthread_mutex_init(&m_mutex, NULL); + assert(err == 0); + } + + PThreadMutex(int type) { + int err; + ::pthread_mutexattr_t attr; + err = ::pthread_mutexattr_init(&attr); + assert(err == 0); + err = ::pthread_mutexattr_settype(&attr, type); + assert(err == 0); + err = ::pthread_mutex_init(&m_mutex, &attr); + assert(err == 0); + err = ::pthread_mutexattr_destroy(&attr); + assert(err == 0); + } + + ~PThreadMutex() { + int err; + err = ::pthread_mutex_destroy(&m_mutex); + if (err != 0) { + err = Unlock(); + if (err == 0) + ::pthread_mutex_destroy(&m_mutex); } + } + + pthread_mutex_t *Mutex() { return &m_mutex; } + + int Lock() { return ::pthread_mutex_lock(&m_mutex); } + + int Unlock() { return ::pthread_mutex_unlock(&m_mutex); } protected: - pthread_mutex_t m_mutex; + pthread_mutex_t m_mutex; }; #endif diff --git a/lldb/tools/debugserver/source/PseudoTerminal.cpp b/lldb/tools/debugserver/source/PseudoTerminal.cpp index f1b505cabd4..616aec989c8 100644 --- a/lldb/tools/debugserver/source/PseudoTerminal.cpp +++ b/lldb/tools/debugserver/source/PseudoTerminal.cpp @@ -19,11 +19,8 @@ //---------------------------------------------------------------------- // PseudoTerminal constructor //---------------------------------------------------------------------- -PseudoTerminal::PseudoTerminal() : - m_master_fd(invalid_fd), - m_slave_fd(invalid_fd) -{ -} +PseudoTerminal::PseudoTerminal() + : m_master_fd(invalid_fd), m_slave_fd(invalid_fd) {} //---------------------------------------------------------------------- // Destructor @@ -32,36 +29,29 @@ PseudoTerminal::PseudoTerminal() : // to release any file descriptors that are needed beyond the lifespan // of this object. //---------------------------------------------------------------------- -PseudoTerminal::~PseudoTerminal() -{ - CloseMaster(); - CloseSlave(); +PseudoTerminal::~PseudoTerminal() { + CloseMaster(); + CloseSlave(); } //---------------------------------------------------------------------- // Close the master file descriptor if it is valid. //---------------------------------------------------------------------- -void -PseudoTerminal::CloseMaster() -{ - if (m_master_fd > 0) - { - ::close (m_master_fd); - m_master_fd = invalid_fd; - } +void PseudoTerminal::CloseMaster() { + if (m_master_fd > 0) { + ::close(m_master_fd); + m_master_fd = invalid_fd; + } } //---------------------------------------------------------------------- // Close the slave file descriptor if it is valid. //---------------------------------------------------------------------- -void -PseudoTerminal::CloseSlave() -{ - if (m_slave_fd > 0) - { - ::close (m_slave_fd); - m_slave_fd = invalid_fd; - } +void PseudoTerminal::CloseSlave() { + if (m_slave_fd > 0) { + ::close(m_slave_fd); + m_slave_fd = invalid_fd; + } } //---------------------------------------------------------------------- @@ -75,31 +65,26 @@ PseudoTerminal::CloseSlave() // RETURNS: // Zero when successful, non-zero indicating an error occurred. //---------------------------------------------------------------------- -PseudoTerminal::Error -PseudoTerminal::OpenFirstAvailableMaster(int oflag) -{ - // Open the master side of a pseudo terminal - m_master_fd = ::posix_openpt (oflag); - if (m_master_fd < 0) - { - return err_posix_openpt_failed; - } +PseudoTerminal::Error PseudoTerminal::OpenFirstAvailableMaster(int oflag) { + // Open the master side of a pseudo terminal + m_master_fd = ::posix_openpt(oflag); + if (m_master_fd < 0) { + return err_posix_openpt_failed; + } - // Grant access to the slave pseudo terminal - if (::grantpt (m_master_fd) < 0) - { - CloseMaster(); - return err_grantpt_failed; - } + // Grant access to the slave pseudo terminal + if (::grantpt(m_master_fd) < 0) { + CloseMaster(); + return err_grantpt_failed; + } - // Clear the lock flag on the slave pseudo terminal - if (::unlockpt (m_master_fd) < 0) - { - CloseMaster(); - return err_unlockpt_failed; - } + // Clear the lock flag on the slave pseudo terminal + if (::unlockpt(m_master_fd) < 0) { + CloseMaster(); + return err_unlockpt_failed; + } - return success; + return success; } //---------------------------------------------------------------------- @@ -112,27 +97,23 @@ PseudoTerminal::OpenFirstAvailableMaster(int oflag) // RETURNS: // Zero when successful, non-zero indicating an error occurred. //---------------------------------------------------------------------- -PseudoTerminal::Error -PseudoTerminal::OpenSlave(int oflag) -{ - CloseSlave(); +PseudoTerminal::Error PseudoTerminal::OpenSlave(int oflag) { + CloseSlave(); - // Open the master side of a pseudo terminal - const char *slave_name = SlaveName(); + // Open the master side of a pseudo terminal + const char *slave_name = SlaveName(); - if (slave_name == NULL) - return err_ptsname_failed; + if (slave_name == NULL) + return err_ptsname_failed; - m_slave_fd = ::open (slave_name, oflag); + m_slave_fd = ::open(slave_name, oflag); - if (m_slave_fd < 0) - return err_open_slave_failed; + if (m_slave_fd < 0) + return err_open_slave_failed; - return success; + return success; } - - //---------------------------------------------------------------------- // Get the name of the slave pseudo terminal. A master pseudo terminal // should already be valid prior to calling this function (see @@ -144,15 +125,12 @@ PseudoTerminal::OpenSlave(int oflag) // that comes from static memory, so a copy of the string should be // made as subsequent calls can change this value. //---------------------------------------------------------------------- -const char* -PseudoTerminal::SlaveName() const -{ - if (m_master_fd < 0) - return NULL; - return ::ptsname (m_master_fd); +const char *PseudoTerminal::SlaveName() const { + if (m_master_fd < 0) + return NULL; + return ::ptsname(m_master_fd); } - //---------------------------------------------------------------------- // Fork a child process that and have its stdio routed to a pseudo // terminal. @@ -175,53 +153,44 @@ PseudoTerminal::SlaveName() const // in the child process: zero //---------------------------------------------------------------------- -pid_t -PseudoTerminal::Fork(PseudoTerminal::Error& error) -{ - pid_t pid = invalid_pid; - error = OpenFirstAvailableMaster (O_RDWR|O_NOCTTY); - - if (error == 0) - { - // Successfully opened our master pseudo terminal - - pid = ::fork (); - if (pid < 0) - { - // Fork failed - error = err_fork_failed; - } - else if (pid == 0) - { - // Child Process - ::setsid(); - - error = OpenSlave (O_RDWR); - if (error == 0) - { - // Successfully opened slave - // We are done with the master in the child process so lets close it - CloseMaster (); - -#if defined (TIOCSCTTY) - // Acquire the controlling terminal - if (::ioctl (m_slave_fd, TIOCSCTTY, (char *)0) < 0) - error = err_failed_to_acquire_controlling_terminal; +pid_t PseudoTerminal::Fork(PseudoTerminal::Error &error) { + pid_t pid = invalid_pid; + error = OpenFirstAvailableMaster(O_RDWR | O_NOCTTY); + + if (error == 0) { + // Successfully opened our master pseudo terminal + + pid = ::fork(); + if (pid < 0) { + // Fork failed + error = err_fork_failed; + } else if (pid == 0) { + // Child Process + ::setsid(); + + error = OpenSlave(O_RDWR); + if (error == 0) { + // Successfully opened slave + // We are done with the master in the child process so lets close it + CloseMaster(); + +#if defined(TIOCSCTTY) + // Acquire the controlling terminal + if (::ioctl(m_slave_fd, TIOCSCTTY, (char *)0) < 0) + error = err_failed_to_acquire_controlling_terminal; #endif - // Duplicate all stdio file descriptors to the slave pseudo terminal - if (::dup2 (m_slave_fd, STDIN_FILENO) != STDIN_FILENO) - error = error ? error : err_dup2_failed_on_stdin; - if (::dup2 (m_slave_fd, STDOUT_FILENO) != STDOUT_FILENO) - error = error ? error : err_dup2_failed_on_stdout; - if (::dup2 (m_slave_fd, STDERR_FILENO) != STDERR_FILENO) - error = error ? error : err_dup2_failed_on_stderr; - } - } - else - { - // Parent Process - // Do nothing and let the pid get returned! - } + // Duplicate all stdio file descriptors to the slave pseudo terminal + if (::dup2(m_slave_fd, STDIN_FILENO) != STDIN_FILENO) + error = error ? error : err_dup2_failed_on_stdin; + if (::dup2(m_slave_fd, STDOUT_FILENO) != STDOUT_FILENO) + error = error ? error : err_dup2_failed_on_stdout; + if (::dup2(m_slave_fd, STDERR_FILENO) != STDERR_FILENO) + error = error ? error : err_dup2_failed_on_stderr; + } + } else { + // Parent Process + // Do nothing and let the pid get returned! } - return pid; + } + return pid; } diff --git a/lldb/tools/debugserver/source/PseudoTerminal.h b/lldb/tools/debugserver/source/PseudoTerminal.h index da6b79307b9..409c78ff5e3 100644 --- a/lldb/tools/debugserver/source/PseudoTerminal.h +++ b/lldb/tools/debugserver/source/PseudoTerminal.h @@ -15,80 +15,73 @@ #define __PseudoTerminal_h__ #include <fcntl.h> -#include <termios.h> #include <string> +#include <termios.h> -class PseudoTerminal -{ +class PseudoTerminal { public: - enum { - invalid_fd = -1, - invalid_pid = -1 - }; + enum { invalid_fd = -1, invalid_pid = -1 }; - enum Error - { - success = 0, - err_posix_openpt_failed = -2, - err_grantpt_failed = -3, - err_unlockpt_failed = -4, - err_ptsname_failed = -5, - err_open_slave_failed = -6, - err_fork_failed = -7, - err_setsid_failed = -8, - err_failed_to_acquire_controlling_terminal = -9, - err_dup2_failed_on_stdin = -10, - err_dup2_failed_on_stdout = -11, - err_dup2_failed_on_stderr = -12 - }; - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - PseudoTerminal (); - ~PseudoTerminal (); + enum Error { + success = 0, + err_posix_openpt_failed = -2, + err_grantpt_failed = -3, + err_unlockpt_failed = -4, + err_ptsname_failed = -5, + err_open_slave_failed = -6, + err_fork_failed = -7, + err_setsid_failed = -8, + err_failed_to_acquire_controlling_terminal = -9, + err_dup2_failed_on_stdin = -10, + err_dup2_failed_on_stdout = -11, + err_dup2_failed_on_stderr = -12 + }; + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + PseudoTerminal(); + ~PseudoTerminal(); - void CloseMaster (); - void CloseSlave (); - Error OpenFirstAvailableMaster (int oflag); - Error OpenSlave (int oflag); - int MasterFD () const { return m_master_fd; } - int SlaveFD () const { return m_slave_fd; } - int ReleaseMasterFD () - { - // Release ownership of the master pseudo terminal file - // descriptor without closing it. (the destructor for this - // class will close it otherwise!) - int fd = m_master_fd; - m_master_fd = invalid_fd; - return fd; - } - int ReleaseSlaveFD () - { - // Release ownership of the slave pseudo terminal file - // descriptor without closing it (the destructor for this - // class will close it otherwise!) - int fd = m_slave_fd; - m_slave_fd = invalid_fd; - return fd; - } + void CloseMaster(); + void CloseSlave(); + Error OpenFirstAvailableMaster(int oflag); + Error OpenSlave(int oflag); + int MasterFD() const { return m_master_fd; } + int SlaveFD() const { return m_slave_fd; } + int ReleaseMasterFD() { + // Release ownership of the master pseudo terminal file + // descriptor without closing it. (the destructor for this + // class will close it otherwise!) + int fd = m_master_fd; + m_master_fd = invalid_fd; + return fd; + } + int ReleaseSlaveFD() { + // Release ownership of the slave pseudo terminal file + // descriptor without closing it (the destructor for this + // class will close it otherwise!) + int fd = m_slave_fd; + m_slave_fd = invalid_fd; + return fd; + } - const char* SlaveName () const; + const char *SlaveName() const; + + pid_t Fork(Error &error); - pid_t Fork(Error& error); protected: - //------------------------------------------------------------------ - // Classes that inherit from PseudoTerminal can see and modify these - //------------------------------------------------------------------ - int m_master_fd; - int m_slave_fd; + //------------------------------------------------------------------ + // Classes that inherit from PseudoTerminal can see and modify these + //------------------------------------------------------------------ + int m_master_fd; + int m_slave_fd; private: - //------------------------------------------------------------------ - // Outlaw copy and assignment constructors - //------------------------------------------------------------------ - PseudoTerminal(const PseudoTerminal& rhs); - PseudoTerminal& operator=(const PseudoTerminal& rhs); - + //------------------------------------------------------------------ + // Outlaw copy and assignment constructors + //------------------------------------------------------------------ + PseudoTerminal(const PseudoTerminal &rhs); + PseudoTerminal &operator=(const PseudoTerminal &rhs); }; #endif // #ifndef __PseudoTerminal_h__ diff --git a/lldb/tools/debugserver/source/RNBContext.cpp b/lldb/tools/debugserver/source/RNBContext.cpp index 0b44fdbd581..483cdf9a486 100644 --- a/lldb/tools/debugserver/source/RNBContext.cpp +++ b/lldb/tools/debugserver/source/RNBContext.cpp @@ -13,269 +13,266 @@ #include "RNBContext.h" -#include <sys/stat.h> #include <sstream> +#include <sys/stat.h> -#if defined (__APPLE__) +#if defined(__APPLE__) #include <pthread.h> #include <sched.h> #endif -#include "RNBRemote.h" +#include "CFString.h" #include "DNB.h" #include "DNBLog.h" -#include "CFString.h" - +#include "RNBRemote.h" //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -RNBContext::~RNBContext() -{ - SetProcessID (INVALID_NUB_PROCESS); -} +RNBContext::~RNBContext() { SetProcessID(INVALID_NUB_PROCESS); } //---------------------------------------------------------------------- // RNBContext constructor //---------------------------------------------------------------------- -const char * -RNBContext::EnvironmentAtIndex (size_t index) -{ - if (index < m_env_vec.size()) - return m_env_vec[index].c_str(); - else - return NULL; +const char *RNBContext::EnvironmentAtIndex(size_t index) { + if (index < m_env_vec.size()) + return m_env_vec[index].c_str(); + else + return NULL; } - -const char * -RNBContext::ArgumentAtIndex (size_t index) -{ - if (index < m_arg_vec.size()) - return m_arg_vec[index].c_str(); - else - return NULL; +const char *RNBContext::ArgumentAtIndex(size_t index) { + if (index < m_arg_vec.size()) + return m_arg_vec[index].c_str(); + else + return NULL; } -bool -RNBContext::SetWorkingDirectory (const char *path) -{ - struct stat working_directory_stat; - if (::stat (path, &working_directory_stat) != 0) - { - m_working_directory.clear(); - return false; - } - m_working_directory.assign(path); - return true; +bool RNBContext::SetWorkingDirectory(const char *path) { + struct stat working_directory_stat; + if (::stat(path, &working_directory_stat) != 0) { + m_working_directory.clear(); + return false; + } + m_working_directory.assign(path); + return true; } - -void -RNBContext::SetProcessID (nub_process_t pid) -{ - // Delete and events we created - if (m_pid != INVALID_NUB_PROCESS) - { - StopProcessStatusThread (); - // Unregister this context as a client of the process's events. - } - // Assign our new process ID - m_pid = pid; - - if (pid != INVALID_NUB_PROCESS) - { - StartProcessStatusThread (); - } +void RNBContext::SetProcessID(nub_process_t pid) { + // Delete and events we created + if (m_pid != INVALID_NUB_PROCESS) { + StopProcessStatusThread(); + // Unregister this context as a client of the process's events. + } + // Assign our new process ID + m_pid = pid; + + if (pid != INVALID_NUB_PROCESS) { + StartProcessStatusThread(); + } } -void -RNBContext::StartProcessStatusThread() -{ - DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s called", __FUNCTION__); - if ((m_events.GetEventBits() & event_proc_thread_running) == 0) - { - int err = ::pthread_create (&m_pid_pthread, NULL, ThreadFunctionProcessStatus, this); - if (err == 0) - { - // Our thread was successfully kicked off, wait for it to - // set the started event so we can safely continue - m_events.WaitForSetEvents (event_proc_thread_running); - DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s thread got started!", __FUNCTION__); - } - else - { - DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s thread failed to start: err = %i", __FUNCTION__, err); - m_events.ResetEvents (event_proc_thread_running); - m_events.SetEvents (event_proc_thread_exiting); - } +void RNBContext::StartProcessStatusThread() { + DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s called", __FUNCTION__); + if ((m_events.GetEventBits() & event_proc_thread_running) == 0) { + int err = ::pthread_create(&m_pid_pthread, NULL, + ThreadFunctionProcessStatus, this); + if (err == 0) { + // Our thread was successfully kicked off, wait for it to + // set the started event so we can safely continue + m_events.WaitForSetEvents(event_proc_thread_running); + DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s thread got started!", + __FUNCTION__); + } else { + DNBLogThreadedIf(LOG_RNB_PROC, + "RNBContext::%s thread failed to start: err = %i", + __FUNCTION__, err); + m_events.ResetEvents(event_proc_thread_running); + m_events.SetEvents(event_proc_thread_exiting); } + } } -void -RNBContext::StopProcessStatusThread() -{ - DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s called", __FUNCTION__); - if ((m_events.GetEventBits() & event_proc_thread_running) == event_proc_thread_running) - { - struct timespec timeout_abstime; - DNBTimer::OffsetTimeOfDay(&timeout_abstime, 2, 0); - // Wait for 2 seconds for the rx thread to exit - if (m_events.WaitForSetEvents(RNBContext::event_proc_thread_exiting, &timeout_abstime) == RNBContext::event_proc_thread_exiting) - { - DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s thread stopped as requeseted", __FUNCTION__); - } - else - { - DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s thread did not stop in 2 seconds...", __FUNCTION__); - // Kill the RX thread??? - } +void RNBContext::StopProcessStatusThread() { + DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s called", __FUNCTION__); + if ((m_events.GetEventBits() & event_proc_thread_running) == + event_proc_thread_running) { + struct timespec timeout_abstime; + DNBTimer::OffsetTimeOfDay(&timeout_abstime, 2, 0); + // Wait for 2 seconds for the rx thread to exit + if (m_events.WaitForSetEvents(RNBContext::event_proc_thread_exiting, + &timeout_abstime) == + RNBContext::event_proc_thread_exiting) { + DNBLogThreadedIf(LOG_RNB_PROC, + "RNBContext::%s thread stopped as requeseted", + __FUNCTION__); + } else { + DNBLogThreadedIf(LOG_RNB_PROC, + "RNBContext::%s thread did not stop in 2 seconds...", + __FUNCTION__); + // Kill the RX thread??? } + } } //---------------------------------------------------------------------- // This thread's sole purpose is to watch for any status changes in the // child process. //---------------------------------------------------------------------- -void* -RNBContext::ThreadFunctionProcessStatus(void *arg) -{ - RNBRemoteSP remoteSP(g_remoteSP); - RNBRemote* remote = remoteSP.get(); - if (remote == NULL) - return NULL; - RNBContext& ctx = remote->Context(); - - nub_process_t pid = ctx.ProcessID(); - DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (arg=%p, pid=%4.4x): thread starting...", __FUNCTION__, arg, pid); - ctx.Events().SetEvents (RNBContext::event_proc_thread_running); - -#if defined (__APPLE__) - pthread_setname_np ("child process status watcher 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 *RNBContext::ThreadFunctionProcessStatus(void *arg) { + RNBRemoteSP remoteSP(g_remoteSP); + RNBRemote *remote = remoteSP.get(); + if (remote == NULL) + return NULL; + RNBContext &ctx = remote->Context(); + + nub_process_t pid = ctx.ProcessID(); + DNBLogThreadedIf(LOG_RNB_PROC, + "RNBContext::%s (arg=%p, pid=%4.4x): thread starting...", + __FUNCTION__, arg, pid); + ctx.Events().SetEvents(RNBContext::event_proc_thread_running); + +#if defined(__APPLE__) + pthread_setname_np("child process status watcher 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 - bool done = false; - while (!done) - { - DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s calling DNBProcessWaitForEvent(pid, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged | eEventStdioAvailable | eEventProfileDataAvailable, true)...", __FUNCTION__); - nub_event_t pid_status_event = DNBProcessWaitForEvents (pid, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged | eEventStdioAvailable | eEventProfileDataAvailable, true, NULL); - DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s calling DNBProcessWaitForEvent(pid, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged | eEventStdioAvailable | eEventProfileDataAvailable, true) => 0x%8.8x", __FUNCTION__, pid_status_event); - - if (pid_status_event == 0) - { - DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got ZERO back from DNBProcessWaitForEvent....", __FUNCTION__, pid); - // done = true; + bool done = false; + while (!done) { + DNBLogThreadedIf(LOG_RNB_PROC, + "RNBContext::%s calling DNBProcessWaitForEvent(pid, " + "eEventProcessRunningStateChanged | " + "eEventProcessStoppedStateChanged | eEventStdioAvailable " + "| eEventProfileDataAvailable, true)...", + __FUNCTION__); + nub_event_t pid_status_event = DNBProcessWaitForEvents( + pid, + eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged | + eEventStdioAvailable | eEventProfileDataAvailable, + true, NULL); + DNBLogThreadedIf(LOG_RNB_PROC, + "RNBContext::%s calling DNBProcessWaitForEvent(pid, " + "eEventProcessRunningStateChanged | " + "eEventProcessStoppedStateChanged | eEventStdioAvailable " + "| eEventProfileDataAvailable, true) => 0x%8.8x", + __FUNCTION__, pid_status_event); + + if (pid_status_event == 0) { + DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got ZERO back " + "from DNBProcessWaitForEvent....", + __FUNCTION__, pid); + // done = true; + } else { + if (pid_status_event & eEventStdioAvailable) { + DNBLogThreadedIf( + LOG_RNB_PROC, + "RNBContext::%s (pid=%4.4x) got stdio available event....", + __FUNCTION__, pid); + ctx.Events().SetEvents(RNBContext::event_proc_stdio_available); + // Wait for the main thread to consume this notification if it requested + // we wait for it + ctx.Events().WaitForResetAck(RNBContext::event_proc_stdio_available); + } + + if (pid_status_event & eEventProfileDataAvailable) { + DNBLogThreadedIf( + LOG_RNB_PROC, + "RNBContext::%s (pid=%4.4x) got profile data event....", + __FUNCTION__, pid); + ctx.Events().SetEvents(RNBContext::event_proc_profile_data); + // Wait for the main thread to consume this notification if it requested + // we wait for it + ctx.Events().WaitForResetAck(RNBContext::event_proc_profile_data); + } + + if (pid_status_event & (eEventProcessRunningStateChanged | + eEventProcessStoppedStateChanged)) { + nub_state_t pid_state = DNBProcessGetState(pid); + DNBLogThreadedIf( + LOG_RNB_PROC, + "RNBContext::%s (pid=%4.4x) got process state change: %s", + __FUNCTION__, pid, DNBStateAsString(pid_state)); + + // Let the main thread know there is a process state change to see + ctx.Events().SetEvents(RNBContext::event_proc_state_changed); + // Wait for the main thread to consume this notification if it requested + // we wait for it + ctx.Events().WaitForResetAck(RNBContext::event_proc_state_changed); + + switch (pid_state) { + case eStateStopped: + break; + + case eStateInvalid: + case eStateExited: + case eStateDetached: + done = true; + break; + default: + break; } - else - { - if (pid_status_event & eEventStdioAvailable) - { - DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got stdio available event....", __FUNCTION__, pid); - ctx.Events().SetEvents (RNBContext::event_proc_stdio_available); - // Wait for the main thread to consume this notification if it requested we wait for it - ctx.Events().WaitForResetAck(RNBContext::event_proc_stdio_available); - } - - if (pid_status_event & eEventProfileDataAvailable) - { - DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got profile data event....", __FUNCTION__, pid); - ctx.Events().SetEvents (RNBContext::event_proc_profile_data); - // Wait for the main thread to consume this notification if it requested we wait for it - ctx.Events().WaitForResetAck(RNBContext::event_proc_profile_data); - } - - if (pid_status_event & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged)) - { - nub_state_t pid_state = DNBProcessGetState(pid); - DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (pid=%4.4x) got process state change: %s", __FUNCTION__, pid, DNBStateAsString(pid_state)); + } - // Let the main thread know there is a process state change to see - ctx.Events().SetEvents (RNBContext::event_proc_state_changed); - // Wait for the main thread to consume this notification if it requested we wait for it - ctx.Events().WaitForResetAck(RNBContext::event_proc_state_changed); - - switch (pid_state) - { - case eStateStopped: - break; - - case eStateInvalid: - case eStateExited: - case eStateDetached: - done = true; - break; - default: - break; - } - } - - // Reset any events that we consumed. - DNBProcessResetEvents(pid, pid_status_event); - - } + // Reset any events that we consumed. + DNBProcessResetEvents(pid, pid_status_event); } - DNBLogThreadedIf(LOG_RNB_PROC, "RNBContext::%s (arg=%p, pid=%4.4x): thread exiting...", __FUNCTION__, arg, pid); - ctx.Events().ResetEvents(event_proc_thread_running); - ctx.Events().SetEvents(event_proc_thread_exiting); - return NULL; + } + DNBLogThreadedIf(LOG_RNB_PROC, + "RNBContext::%s (arg=%p, pid=%4.4x): thread exiting...", + __FUNCTION__, arg, pid); + ctx.Events().ResetEvents(event_proc_thread_running); + ctx.Events().SetEvents(event_proc_thread_exiting); + return NULL; } - -const char* -RNBContext::EventsAsString (nub_event_t events, std::string& s) -{ - s.clear(); - if (events & event_proc_state_changed) - s += "proc_state_changed "; - if (events & event_proc_thread_running) - s += "proc_thread_running "; - if (events & event_proc_thread_exiting) - s += "proc_thread_exiting "; - if (events & event_proc_stdio_available) - s += "proc_stdio_available "; - if (events & event_proc_profile_data) - s += "proc_profile_data "; - if (events & event_darwin_log_data_available) - s += "darwin_log_data_available "; - if (events & event_read_packet_available) - s += "read_packet_available "; - if (events & event_read_thread_running) - s += "read_thread_running "; - if (events & event_read_thread_running) - s += "read_thread_running "; - return s.c_str(); +const char *RNBContext::EventsAsString(nub_event_t events, std::string &s) { + s.clear(); + if (events & event_proc_state_changed) + s += "proc_state_changed "; + if (events & event_proc_thread_running) + s += "proc_thread_running "; + if (events & event_proc_thread_exiting) + s += "proc_thread_exiting "; + if (events & event_proc_stdio_available) + s += "proc_stdio_available "; + if (events & event_proc_profile_data) + s += "proc_profile_data "; + if (events & event_darwin_log_data_available) + s += "darwin_log_data_available "; + if (events & event_read_packet_available) + s += "read_packet_available "; + if (events & event_read_thread_running) + s += "read_thread_running "; + if (events & event_read_thread_running) + s += "read_thread_running "; + return s.c_str(); } -const char * -RNBContext::LaunchStatusAsString (std::string& s) -{ - s.clear(); - - const char *err_str = m_launch_status.AsString(); - if (err_str) - s = err_str; - else - { - char error_num_str[64]; - snprintf(error_num_str, sizeof(error_num_str), "%u", m_launch_status.Error()); - s = error_num_str; - } - return s.c_str(); +const char *RNBContext::LaunchStatusAsString(std::string &s) { + s.clear(); + + const char *err_str = m_launch_status.AsString(); + if (err_str) + s = err_str; + else { + char error_num_str[64]; + snprintf(error_num_str, sizeof(error_num_str), "%u", + m_launch_status.Error()); + s = error_num_str; + } + return s.c_str(); } -bool -RNBContext::ProcessStateRunning() const -{ - nub_state_t pid_state = DNBProcessGetState(m_pid); - return pid_state == eStateRunning || pid_state == eStateStepping; +bool RNBContext::ProcessStateRunning() const { + nub_state_t pid_state = DNBProcessGetState(m_pid); + return pid_state == eStateRunning || pid_state == eStateStepping; } diff --git a/lldb/tools/debugserver/source/RNBContext.h b/lldb/tools/debugserver/source/RNBContext.h index 83237ebccd9..6fe7a299573 100644 --- a/lldb/tools/debugserver/source/RNBContext.h +++ b/lldb/tools/debugserver/source/RNBContext.h @@ -14,148 +14,150 @@ #ifndef __RNBContext_h__ #define __RNBContext_h__ -#include "RNBDefs.h" #include "DNBError.h" #include "PThreadEvent.h" -#include <vector> +#include "RNBDefs.h" #include <string> +#include <vector> -class RNBContext -{ +class RNBContext { public: - enum - { - event_proc_state_changed = 0x001, - event_proc_thread_running = 0x002, // Sticky - event_proc_thread_exiting = 0x004, - event_proc_stdio_available = 0x008, - event_proc_profile_data = 0x010, - event_read_packet_available = 0x020, - event_read_thread_running = 0x040, // Sticky - event_read_thread_exiting = 0x080, - event_darwin_log_data_available = 0x100, - - normal_event_bits = event_proc_state_changed | - event_proc_thread_exiting | - event_proc_stdio_available | - event_proc_profile_data | - event_read_packet_available | - event_read_thread_exiting | - event_darwin_log_data_available, - - sticky_event_bits = event_proc_thread_running | - event_read_thread_running, - - - all_event_bits = sticky_event_bits | normal_event_bits - } event_t; - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - RNBContext () : - m_pid(INVALID_NUB_PROCESS), - m_pid_stop_count(0), - m_events(0, all_event_bits), - m_pid_pthread(), - m_launch_status(), - m_arg_vec (), - m_env_vec (), - m_detach_on_error(false) - { - } - - virtual ~RNBContext(); - - - nub_process_t ProcessID() const { return m_pid; } - bool HasValidProcessID() const { return m_pid != INVALID_NUB_PROCESS; } - void SetProcessID (nub_process_t pid); - nub_size_t GetProcessStopCount () const { return m_pid_stop_count; } - bool SetProcessStopCount (nub_size_t count) - { - // Returns true if this class' notion of the PID state changed - if (m_pid_stop_count == count) - return false; // Didn't change - m_pid_stop_count = count; - return true; // The stop count has changed. - } - - bool ProcessStateRunning() const; - PThreadEvent& Events( ) { return m_events; } - nub_event_t AllEventBits() const { return all_event_bits; } - nub_event_t NormalEventBits() const { return normal_event_bits; } - nub_event_t StickyEventBits() const { return sticky_event_bits; } - const char* EventsAsString (nub_event_t events, std::string& s); - - size_t ArgumentCount () const { return m_arg_vec.size(); } - const char * ArgumentAtIndex (size_t index); - void PushArgument (const char *arg) { if (arg) m_arg_vec.push_back (arg); } - void ClearArgv () { m_arg_vec.erase (m_arg_vec.begin(), m_arg_vec.end()); } - - size_t EnvironmentCount () const { return m_env_vec.size(); } - const char * EnvironmentAtIndex (size_t index); - void PushEnvironment (const char *arg) { if (arg) m_env_vec.push_back (arg); } - void ClearEnvironment () { m_env_vec.erase (m_env_vec.begin(), m_env_vec.end()); } - DNBError& LaunchStatus () { return m_launch_status; } - const char * LaunchStatusAsString (std::string& s); - nub_launch_flavor_t LaunchFlavor () const { return m_launch_flavor; } - void SetLaunchFlavor (nub_launch_flavor_t flavor) { m_launch_flavor = flavor; } - - const char * GetWorkingDirectory () const - { - if (!m_working_directory.empty()) - return m_working_directory.c_str(); - return NULL; - } - - bool SetWorkingDirectory (const char *path); - - std::string& GetSTDIN () { return m_stdin; } - std::string& GetSTDOUT () { return m_stdout; } - std::string& GetSTDERR () { return m_stderr; } - std::string& GetWorkingDir () { return m_working_dir; } - - const char * GetSTDINPath() { return m_stdin.empty() ? NULL : m_stdin.c_str(); } - const char * GetSTDOUTPath() { return m_stdout.empty() ? NULL : m_stdout.c_str(); } - const char * GetSTDERRPath() { return m_stderr.empty() ? NULL : m_stderr.c_str(); } - const char * GetWorkingDirPath() { return m_working_dir.empty() ? NULL : m_working_dir.c_str(); } - - void PushProcessEvent (const char *p) { m_process_event.assign(p); } - const char * GetProcessEvent () { return m_process_event.c_str(); } - - void SetDetachOnError(bool detach) { m_detach_on_error = detach; } - bool GetDetachOnError () { return m_detach_on_error; } - + enum { + event_proc_state_changed = 0x001, + event_proc_thread_running = 0x002, // Sticky + event_proc_thread_exiting = 0x004, + event_proc_stdio_available = 0x008, + event_proc_profile_data = 0x010, + event_read_packet_available = 0x020, + event_read_thread_running = 0x040, // Sticky + event_read_thread_exiting = 0x080, + event_darwin_log_data_available = 0x100, + + normal_event_bits = event_proc_state_changed | event_proc_thread_exiting | + event_proc_stdio_available | event_proc_profile_data | + event_read_packet_available | + event_read_thread_exiting | + event_darwin_log_data_available, + + sticky_event_bits = event_proc_thread_running | event_read_thread_running, + + all_event_bits = sticky_event_bits | normal_event_bits + } event_t; + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + RNBContext() + : m_pid(INVALID_NUB_PROCESS), m_pid_stop_count(0), + m_events(0, all_event_bits), m_pid_pthread(), m_launch_status(), + m_arg_vec(), m_env_vec(), m_detach_on_error(false) {} + + virtual ~RNBContext(); + + nub_process_t ProcessID() const { return m_pid; } + bool HasValidProcessID() const { return m_pid != INVALID_NUB_PROCESS; } + void SetProcessID(nub_process_t pid); + nub_size_t GetProcessStopCount() const { return m_pid_stop_count; } + bool SetProcessStopCount(nub_size_t count) { + // Returns true if this class' notion of the PID state changed + if (m_pid_stop_count == count) + return false; // Didn't change + m_pid_stop_count = count; + return true; // The stop count has changed. + } + + bool ProcessStateRunning() const; + PThreadEvent &Events() { return m_events; } + nub_event_t AllEventBits() const { return all_event_bits; } + nub_event_t NormalEventBits() const { return normal_event_bits; } + nub_event_t StickyEventBits() const { return sticky_event_bits; } + const char *EventsAsString(nub_event_t events, std::string &s); + + size_t ArgumentCount() const { return m_arg_vec.size(); } + const char *ArgumentAtIndex(size_t index); + void PushArgument(const char *arg) { + if (arg) + m_arg_vec.push_back(arg); + } + void ClearArgv() { m_arg_vec.erase(m_arg_vec.begin(), m_arg_vec.end()); } + + size_t EnvironmentCount() const { return m_env_vec.size(); } + const char *EnvironmentAtIndex(size_t index); + void PushEnvironment(const char *arg) { + if (arg) + m_env_vec.push_back(arg); + } + void ClearEnvironment() { + m_env_vec.erase(m_env_vec.begin(), m_env_vec.end()); + } + DNBError &LaunchStatus() { return m_launch_status; } + const char *LaunchStatusAsString(std::string &s); + nub_launch_flavor_t LaunchFlavor() const { return m_launch_flavor; } + void SetLaunchFlavor(nub_launch_flavor_t flavor) { m_launch_flavor = flavor; } + + const char *GetWorkingDirectory() const { + if (!m_working_directory.empty()) + return m_working_directory.c_str(); + return NULL; + } + + bool SetWorkingDirectory(const char *path); + + std::string &GetSTDIN() { return m_stdin; } + std::string &GetSTDOUT() { return m_stdout; } + std::string &GetSTDERR() { return m_stderr; } + std::string &GetWorkingDir() { return m_working_dir; } + + const char *GetSTDINPath() { + return m_stdin.empty() ? NULL : m_stdin.c_str(); + } + const char *GetSTDOUTPath() { + return m_stdout.empty() ? NULL : m_stdout.c_str(); + } + const char *GetSTDERRPath() { + return m_stderr.empty() ? NULL : m_stderr.c_str(); + } + const char *GetWorkingDirPath() { + return m_working_dir.empty() ? NULL : m_working_dir.c_str(); + } + + void PushProcessEvent(const char *p) { m_process_event.assign(p); } + const char *GetProcessEvent() { return m_process_event.c_str(); } + + void SetDetachOnError(bool detach) { m_detach_on_error = detach; } + bool GetDetachOnError() { return m_detach_on_error; } + protected: - //------------------------------------------------------------------ - // Classes that inherit from RNBContext can see and modify these - //------------------------------------------------------------------ - nub_process_t m_pid; - std::string m_stdin; - std::string m_stdout; - std::string m_stderr; - std::string m_working_dir; - nub_size_t m_pid_stop_count; - PThreadEvent m_events; // Threaded events that we can wait for - pthread_t m_pid_pthread; - nub_launch_flavor_t m_launch_flavor; // How to launch our inferior process - DNBError m_launch_status; // This holds the status from the last launch attempt. - std::vector<std::string> m_arg_vec; - std::vector<std::string> m_env_vec; // This will be unparsed - entries FOO=value - std::string m_working_directory; - std::string m_process_event; - bool m_detach_on_error; - - void StartProcessStatusThread(); - void StopProcessStatusThread(); - static void* ThreadFunctionProcessStatus(void *arg); + //------------------------------------------------------------------ + // Classes that inherit from RNBContext can see and modify these + //------------------------------------------------------------------ + nub_process_t m_pid; + std::string m_stdin; + std::string m_stdout; + std::string m_stderr; + std::string m_working_dir; + nub_size_t m_pid_stop_count; + PThreadEvent m_events; // Threaded events that we can wait for + pthread_t m_pid_pthread; + nub_launch_flavor_t m_launch_flavor; // How to launch our inferior process + DNBError + m_launch_status; // This holds the status from the last launch attempt. + std::vector<std::string> m_arg_vec; + std::vector<std::string> + m_env_vec; // This will be unparsed - entries FOO=value + std::string m_working_directory; + std::string m_process_event; + bool m_detach_on_error; + + void StartProcessStatusThread(); + void StopProcessStatusThread(); + static void *ThreadFunctionProcessStatus(void *arg); private: - //------------------------------------------------------------------ - // Outlaw copy and assignment operators - //------------------------------------------------------------------ - RNBContext(const RNBContext& rhs); - RNBContext& operator=(const RNBContext& rhs); + //------------------------------------------------------------------ + // Outlaw copy and assignment operators + //------------------------------------------------------------------ + RNBContext(const RNBContext &rhs); + RNBContext &operator=(const RNBContext &rhs); }; #endif // #ifndef __RNBContext_h__ diff --git a/lldb/tools/debugserver/source/RNBDefs.h b/lldb/tools/debugserver/source/RNBDefs.h index cefa986f8ca..5714099f5fc 100644 --- a/lldb/tools/debugserver/source/RNBDefs.h +++ b/lldb/tools/debugserver/source/RNBDefs.h @@ -17,52 +17,55 @@ #include "DNBDefs.h" #include <memory> -#define CONCAT2(a,b) a ## b -#define CONCAT(a,b) CONCAT2(a,b) +#define CONCAT2(a, b) a##b +#define CONCAT(a, b) CONCAT2(a, b) #define STRINGIZE2(x) #x #define STRINGIZE(x) STRINGIZE2(x) -#if !defined (DEBUGSERVER_PROGRAM_SYMBOL) +#if !defined(DEBUGSERVER_PROGRAM_SYMBOL) #define DEBUGSERVER_PROGRAM_SYMBOL debugserver #endif -#if !defined (DEBUGSERVER_PROGRAM_NAME) +#if !defined(DEBUGSERVER_PROGRAM_NAME) #define DEBUGSERVER_PROGRAM_NAME STRINGIZE(DEBUGSERVER_PROGRAM_SYMBOL) #endif #ifndef DEBUGSERVER_VERSION_NUM -extern "C" const unsigned char CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionString)[]; -#define DEBUGSERVER_VERSION_NUM CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionNumber) +extern "C" const unsigned char CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, + VersionString)[]; +#define DEBUGSERVER_VERSION_NUM \ + CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionNumber) #endif #ifndef DEBUGSERVER_VERSION_STR extern "C" const double CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionNumber); -#define DEBUGSERVER_VERSION_STR CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionString) +#define DEBUGSERVER_VERSION_STR \ + CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionString) #endif -#if defined (__i386__) +#if defined(__i386__) -#define RNB_ARCH "i386" +#define RNB_ARCH "i386" -#elif defined (__x86_64__) +#elif defined(__x86_64__) -#define RNB_ARCH "x86_64" +#define RNB_ARCH "x86_64" -#elif defined (__ppc64__) +#elif defined(__ppc64__) -#define RNB_ARCH "ppc64" +#define RNB_ARCH "ppc64" -#elif defined (__powerpc__) || defined (__ppc__) +#elif defined(__powerpc__) || defined(__ppc__) -#define RNB_ARCH "ppc" +#define RNB_ARCH "ppc" -#elif defined (__arm64__) || defined (__aarch64__) +#elif defined(__arm64__) || defined(__aarch64__) -#define RNB_ARCH "arm64" +#define RNB_ARCH "arm64" -#elif defined (__arm__) +#elif defined(__arm__) -#define RNB_ARCH "armv7" +#define RNB_ARCH "armv7" #else @@ -73,25 +76,23 @@ extern "C" const double CONCAT(DEBUGSERVER_PROGRAM_SYMBOL, VersionNumber); class RNBRemote; typedef std::shared_ptr<RNBRemote> RNBRemoteSP; -typedef enum -{ - rnb_success = 0, - rnb_err = 1, - rnb_not_connected = 2 -} rnb_err_t; +typedef enum { rnb_success = 0, rnb_err = 1, rnb_not_connected = 2 } rnb_err_t; // Log bits // reserve low bits for DNB -#define LOG_RNB_MINIMAL ((LOG_LO_USER) << 0) // Minimal logging (min verbosity) -#define LOG_RNB_MEDIUM ((LOG_LO_USER) << 1) // Medium logging (med verbosity) -#define LOG_RNB_MAX ((LOG_LO_USER) << 2) // Max logging (max verbosity) -#define LOG_RNB_COMM ((LOG_LO_USER) << 3) // Log communications (RNBSocket) -#define LOG_RNB_REMOTE ((LOG_LO_USER) << 4) // Log remote (RNBRemote) -#define LOG_RNB_EVENTS ((LOG_LO_USER) << 5) // Log events (PThreadEvents) -#define LOG_RNB_PROC ((LOG_LO_USER) << 6) // Log process state (Process thread) -#define LOG_RNB_PACKETS ((LOG_LO_USER) << 7) // Log gdb remote packets -#define LOG_RNB_ALL (~((LOG_LO_USER) - 1)) -#define LOG_RNB_DEFAULT (LOG_RNB_ALL) +#define LOG_RNB_MINIMAL \ + ((LOG_LO_USER) << 0) // Minimal logging (min verbosity) +#define LOG_RNB_MEDIUM \ + ((LOG_LO_USER) << 1) // Medium logging (med verbosity) +#define LOG_RNB_MAX ((LOG_LO_USER) << 2) // Max logging (max verbosity) +#define LOG_RNB_COMM ((LOG_LO_USER) << 3) // Log communications (RNBSocket) +#define LOG_RNB_REMOTE ((LOG_LO_USER) << 4) // Log remote (RNBRemote) +#define LOG_RNB_EVENTS \ + ((LOG_LO_USER) << 5) // Log events (PThreadEvents) +#define LOG_RNB_PROC ((LOG_LO_USER) << 6) // Log process state (Process thread) +#define LOG_RNB_PACKETS ((LOG_LO_USER) << 7) // Log gdb remote packets +#define LOG_RNB_ALL (~((LOG_LO_USER)-1)) +#define LOG_RNB_DEFAULT (LOG_RNB_ALL) extern RNBRemoteSP g_remoteSP; diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp index e737913c0d4..6ee84eed27d 100644 --- a/lldb/tools/debugserver/source/RNBRemote.cpp +++ b/lldb/tools/debugserver/source/RNBRemote.cpp @@ -14,46 +14,46 @@ #include "RNBRemote.h" #include <errno.h> -#include <unistd.h> -#include <signal.h> -#include <mach/exception_types.h> #include <mach-o/loader.h> +#include <mach/exception_types.h> +#include <signal.h> #include <sys/stat.h> #include <sys/sysctl.h> +#include <unistd.h> -#if defined (__APPLE__) +#if defined(__APPLE__) #include <pthread.h> #include <sched.h> #endif -#include "DarwinLogCollector.h" -#include "DarwinLogEvent.h" #include "DNB.h" #include "DNBDataRef.h" #include "DNBLog.h" #include "DNBThreadResumeActions.h" +#include "DarwinLogCollector.h" +#include "DarwinLogEvent.h" +#include "JSON.h" +#include "JSONGenerator.h" #include "JSONGenerator.h" +#include "MacOSX/Genealogy.h" #include "OsLogger.h" #include "RNBContext.h" #include "RNBServices.h" #include "RNBSocket.h" -#include "JSON.h" #include "lldb/Utility/StdStringExtractor.h" -#include "MacOSX/Genealogy.h" -#include "JSONGenerator.h" -#if defined (HAVE_LIBCOMPRESSION) +#if defined(HAVE_LIBCOMPRESSION) #include <compression.h> #endif -#if defined (HAVE_LIBZ) +#if defined(HAVE_LIBZ) #include <zlib.h> #endif +#include <TargetConditionals.h> // for endianness predefines #include <iomanip> #include <sstream> #include <unordered_set> -#include <TargetConditionals.h> // for endianness predefines //---------------------------------------------------------------------- // constants @@ -61,1230 +61,1319 @@ static const std::string OS_LOG_EVENTS_KEY_NAME("events"); static const std::string JSON_ASYNC_TYPE_KEY_NAME("type"); -static const DarwinLogEventVector::size_type - DARWIN_LOG_MAX_EVENTS_PER_PACKET = 10; +static const DarwinLogEventVector::size_type DARWIN_LOG_MAX_EVENTS_PER_PACKET = + 10; //---------------------------------------------------------------------- // std::iostream formatting macros //---------------------------------------------------------------------- -#define RAW_HEXBASE std::setfill('0') << std::hex << std::right -#define HEXBASE '0' << 'x' << RAW_HEXBASE -#define RAWHEX8(x) RAW_HEXBASE << std::setw(2) << ((uint32_t)((uint8_t)x)) -#define RAWHEX16 RAW_HEXBASE << std::setw(4) -#define RAWHEX32 RAW_HEXBASE << std::setw(8) -#define RAWHEX64 RAW_HEXBASE << std::setw(16) -#define HEX8(x) HEXBASE << std::setw(2) << ((uint32_t)(x)) -#define HEX16 HEXBASE << std::setw(4) -#define HEX32 HEXBASE << std::setw(8) -#define HEX64 HEXBASE << std::setw(16) -#define RAW_HEX(x) RAW_HEXBASE << std::setw(sizeof(x)*2) << (x) -#define HEX(x) HEXBASE << std::setw(sizeof(x)*2) << (x) -#define RAWHEX_SIZE(x, sz) RAW_HEXBASE << std::setw((sz)) << (x) +#define RAW_HEXBASE std::setfill('0') << std::hex << std::right +#define HEXBASE '0' << 'x' << RAW_HEXBASE +#define RAWHEX8(x) RAW_HEXBASE << std::setw(2) << ((uint32_t)((uint8_t)x)) +#define RAWHEX16 RAW_HEXBASE << std::setw(4) +#define RAWHEX32 RAW_HEXBASE << std::setw(8) +#define RAWHEX64 RAW_HEXBASE << std::setw(16) +#define HEX8(x) HEXBASE << std::setw(2) << ((uint32_t)(x)) +#define HEX16 HEXBASE << std::setw(4) +#define HEX32 HEXBASE << std::setw(8) +#define HEX64 HEXBASE << std::setw(16) +#define RAW_HEX(x) RAW_HEXBASE << std::setw(sizeof(x) * 2) << (x) +#define HEX(x) HEXBASE << std::setw(sizeof(x) * 2) << (x) +#define RAWHEX_SIZE(x, sz) RAW_HEXBASE << std::setw((sz)) << (x) #define HEX_SIZE(x, sz) HEXBASE << std::setw((sz)) << (x) #define STRING_WIDTH(w) std::setfill(' ') << std::setw(w) -#define LEFT_STRING_WIDTH(s, w) std::left << std::setfill(' ') << std::setw(w) << (s) << std::right -#define DECIMAL std::dec << std::setfill(' ') +#define LEFT_STRING_WIDTH(s, w) \ + std::left << std::setfill(' ') << std::setw(w) << (s) << std::right +#define DECIMAL std::dec << std::setfill(' ') #define DECIMAL_WIDTH(w) DECIMAL << std::setw(w) -#define FLOAT(n, d) std::setfill(' ') << std::setw((n)+(d)+1) << std::setprecision(d) << std::showpoint << std::fixed -#define INDENT_WITH_SPACES(iword_idx) std::setfill(' ') << std::setw((iword_idx)) << "" -#define INDENT_WITH_TABS(iword_idx) std::setfill('\t') << std::setw((iword_idx)) << "" +#define FLOAT(n, d) \ + std::setfill(' ') << std::setw((n) + (d) + 1) << std::setprecision(d) \ + << std::showpoint << std::fixed +#define INDENT_WITH_SPACES(iword_idx) \ + std::setfill(' ') << std::setw((iword_idx)) << "" +#define INDENT_WITH_TABS(iword_idx) \ + std::setfill('\t') << std::setw((iword_idx)) << "" // Class to handle communications via gdb remote protocol. //---------------------------------------------------------------------- // Prototypes //---------------------------------------------------------------------- -static std::string -binary_encode_string (const std::string &s); +static std::string binary_encode_string(const std::string &s); //---------------------------------------------------------------------- // Decode a single hex character and return the hex value as a number or // -1 if "ch" is not a hex character. //---------------------------------------------------------------------- -static inline int -xdigit_to_sint (char ch) -{ - if (ch >= 'a' && ch <= 'f') - return 10 + ch - 'a'; - if (ch >= 'A' && ch <= 'F') - return 10 + ch - 'A'; - if (ch >= '0' && ch <= '9') - return ch - '0'; - return -1; +static inline int xdigit_to_sint(char ch) { + if (ch >= 'a' && ch <= 'f') + return 10 + ch - 'a'; + if (ch >= 'A' && ch <= 'F') + return 10 + ch - 'A'; + if (ch >= '0' && ch <= '9') + return ch - '0'; + return -1; } //---------------------------------------------------------------------- // Decode a single hex ASCII byte. Return -1 on failure, a value 0-255 // on success. //---------------------------------------------------------------------- -static inline int -decoded_hex_ascii_char(const char *p) -{ - const int hi_nibble = xdigit_to_sint(p[0]); - if (hi_nibble == -1) - return -1; - const int lo_nibble = xdigit_to_sint(p[1]); - if (lo_nibble == -1) - return -1; - return (uint8_t)((hi_nibble << 4) + lo_nibble); +static inline int decoded_hex_ascii_char(const char *p) { + const int hi_nibble = xdigit_to_sint(p[0]); + if (hi_nibble == -1) + return -1; + const int lo_nibble = xdigit_to_sint(p[1]); + if (lo_nibble == -1) + return -1; + return (uint8_t)((hi_nibble << 4) + lo_nibble); } //---------------------------------------------------------------------- // Decode a hex ASCII string back into a string //---------------------------------------------------------------------- -static std::string -decode_hex_ascii_string(const char *p, uint32_t max_length = UINT32_MAX) -{ - std::string arg; - if (p) - { - for (const char *c = p; ((c - p)/2) < max_length; c += 2) - { - int ch = decoded_hex_ascii_char(c); - if (ch == -1) - break; - else - arg.push_back(ch); - } +static std::string decode_hex_ascii_string(const char *p, + uint32_t max_length = UINT32_MAX) { + std::string arg; + if (p) { + for (const char *c = p; ((c - p) / 2) < max_length; c += 2) { + int ch = decoded_hex_ascii_char(c); + if (ch == -1) + break; + else + arg.push_back(ch); } - return arg; + } + return arg; } -uint64_t -decode_uint64 (const char *p, int base, char **end = nullptr, uint64_t fail_value = 0) -{ - nub_addr_t addr = strtoull (p, end, 16); - if (addr == 0 && errno != 0) - return fail_value; - return addr; +uint64_t decode_uint64(const char *p, int base, char **end = nullptr, + uint64_t fail_value = 0) { + nub_addr_t addr = strtoull(p, end, 16); + if (addr == 0 && errno != 0) + return fail_value; + return addr; } -extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args); +extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, + va_list args); -#if defined (__APPLE__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101000) +#if defined(__APPLE__) && \ + (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101000) // from System.framework/Versions/B/PrivateHeaders/sys/codesign.h extern "C" { -#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); // from rootless.h -bool rootless_allows_task_for_pid (pid_t pid); +bool rootless_allows_task_for_pid(pid_t pid); // from sys/csr.h typedef uint32_t csr_config_t; -#define CSR_ALLOW_TASK_FOR_PID (1 << 2) +#define CSR_ALLOW_TASK_FOR_PID (1 << 2) int csr_check(csr_config_t mask); } #endif -RNBRemote::RNBRemote () : - m_ctx (), - m_comm (), - m_arch (), - m_continue_thread(-1), - m_thread(-1), - m_mutex(), - m_dispatch_queue_offsets (), - m_dispatch_queue_offsets_addr (INVALID_NUB_ADDRESS), - m_qSymbol_index (UINT32_MAX), - m_packets_recvd(0), - m_packets(), - m_rx_packets(), - m_rx_partial_data(), - m_rx_pthread(0), - m_max_payload_size(DEFAULT_GDB_REMOTE_PROTOCOL_BUFSIZE - 4), - m_extended_mode(false), - m_noack_mode(false), - m_thread_suffix_supported (false), - m_list_threads_in_stop_reply (false), - m_compression_minsize (384), - m_enable_compression_next_send_packet (false), - m_compression_mode (compression_types::none) -{ - DNBLogThreadedIf (LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__); - CreatePacketTable (); -} - - -RNBRemote::~RNBRemote() -{ - DNBLogThreadedIf (LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__); - StopReadRemoteDataThread(); -} - -void -RNBRemote::CreatePacketTable () -{ - // Step required to add new packets: - // 1 - Add new enumeration to RNBRemote::PacketEnum - // 2 - Create the RNBRemote::HandlePacket_ function if a new function is needed - // 3 - Register the Packet definition with any needed callbacks in this function - // - If no response is needed for a command, then use NULL for the normal callback - // - If the packet is not supported while the target is running, use NULL for the async callback - // 4 - If the packet is a standard packet (starts with a '$' character - // followed by the payload and then '#' and checksum, then you are done - // else go on to step 5 - // 5 - if the packet is a fixed length packet: - // - modify the switch statement for the first character in the payload - // in RNBRemote::CommDataReceived so it doesn't reject the new packet - // type as invalid - // - modify the switch statement for the first character in the payload - // in RNBRemote::GetPacketPayload and make sure the payload of the packet - // is returned correctly - - std::vector <Packet> &t = m_packets; - t.push_back (Packet (ack, NULL, NULL, "+", "ACK")); - t.push_back (Packet (nack, NULL, NULL, "-", "!ACK")); - t.push_back (Packet (read_memory, &RNBRemote::HandlePacket_m, NULL, "m", "Read memory")); - t.push_back (Packet (read_register, &RNBRemote::HandlePacket_p, NULL, "p", "Read one register")); - t.push_back (Packet (read_general_regs, &RNBRemote::HandlePacket_g, NULL, "g", "Read registers")); - t.push_back (Packet (write_memory, &RNBRemote::HandlePacket_M, NULL, "M", "Write memory")); - t.push_back (Packet (write_register, &RNBRemote::HandlePacket_P, NULL, "P", "Write one register")); - t.push_back (Packet (write_general_regs, &RNBRemote::HandlePacket_G, NULL, "G", "Write registers")); - t.push_back (Packet (insert_mem_bp, &RNBRemote::HandlePacket_z, NULL, "Z0", "Insert memory breakpoint")); - t.push_back (Packet (remove_mem_bp, &RNBRemote::HandlePacket_z, NULL, "z0", "Remove memory breakpoint")); - t.push_back (Packet (single_step, &RNBRemote::HandlePacket_s, NULL, "s", "Single step")); - t.push_back (Packet (cont, &RNBRemote::HandlePacket_c, NULL, "c", "continue")); - t.push_back (Packet (single_step_with_sig, &RNBRemote::HandlePacket_S, NULL, "S", "Single step with signal")); - t.push_back (Packet (set_thread, &RNBRemote::HandlePacket_H, NULL, "H", "Set thread")); - t.push_back (Packet (halt, &RNBRemote::HandlePacket_last_signal, &RNBRemote::HandlePacket_stop_process, "\x03", "^C")); -// t.push_back (Packet (use_extended_mode, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "!", "Use extended mode")); - t.push_back (Packet (why_halted, &RNBRemote::HandlePacket_last_signal, NULL, "?", "Why did target halt")); - t.push_back (Packet (set_argv, &RNBRemote::HandlePacket_A, NULL, "A", "Set argv")); -// t.push_back (Packet (set_bp, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "B", "Set/clear breakpoint")); - t.push_back (Packet (continue_with_sig, &RNBRemote::HandlePacket_C, NULL, "C", "Continue with signal")); - t.push_back (Packet (detach, &RNBRemote::HandlePacket_D, NULL, "D", "Detach gdb from remote system")); -// t.push_back (Packet (step_inferior_one_cycle, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "i", "Step inferior by one clock cycle")); -// t.push_back (Packet (signal_and_step_inf_one_cycle, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "I", "Signal inferior, then step one clock cycle")); - t.push_back (Packet (kill, &RNBRemote::HandlePacket_k, NULL, "k", "Kill")); -// t.push_back (Packet (restart, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "R", "Restart inferior")); -// t.push_back (Packet (search_mem_backwards, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "t", "Search memory backwards")); - t.push_back (Packet (thread_alive_p, &RNBRemote::HandlePacket_T, NULL, "T", "Is thread alive")); - t.push_back (Packet (query_supported_features, &RNBRemote::HandlePacket_qSupported, NULL, "qSupported", "Query about supported features")); - t.push_back (Packet (vattach, &RNBRemote::HandlePacket_v, NULL, "vAttach", "Attach to a new process")); - t.push_back (Packet (vattachwait, &RNBRemote::HandlePacket_v, NULL, "vAttachWait", "Wait for a process to start up then attach to it")); - t.push_back (Packet (vattachorwait, &RNBRemote::HandlePacket_v, NULL, "vAttachOrWait", "Attach to the process or if it doesn't exist, wait for the process to start up then attach to it")); - t.push_back (Packet (vattachname, &RNBRemote::HandlePacket_v, NULL, "vAttachName", "Attach to an existing process by name")); - t.push_back (Packet (vcont_list_actions, &RNBRemote::HandlePacket_v, NULL, "vCont;", "Verbose resume with thread actions")); - t.push_back (Packet (vcont_list_actions, &RNBRemote::HandlePacket_v, NULL, "vCont?", "List valid continue-with-thread-actions actions")); - t.push_back (Packet (read_data_from_memory, &RNBRemote::HandlePacket_x, NULL, "x", "Read data from memory")); - t.push_back (Packet (write_data_to_memory, &RNBRemote::HandlePacket_X, NULL, "X", "Write data to memory")); -// t.push_back (Packet (insert_hardware_bp, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "Z1", "Insert hardware breakpoint")); -// t.push_back (Packet (remove_hardware_bp, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "z1", "Remove hardware breakpoint")); - t.push_back (Packet (insert_write_watch_bp, &RNBRemote::HandlePacket_z, NULL, "Z2", "Insert write watchpoint")); - t.push_back (Packet (remove_write_watch_bp, &RNBRemote::HandlePacket_z, NULL, "z2", "Remove write watchpoint")); - t.push_back (Packet (insert_read_watch_bp, &RNBRemote::HandlePacket_z, NULL, "Z3", "Insert read watchpoint")); - t.push_back (Packet (remove_read_watch_bp, &RNBRemote::HandlePacket_z, NULL, "z3", "Remove read watchpoint")); - t.push_back (Packet (insert_access_watch_bp, &RNBRemote::HandlePacket_z, NULL, "Z4", "Insert access watchpoint")); - t.push_back (Packet (remove_access_watch_bp, &RNBRemote::HandlePacket_z, NULL, "z4", "Remove access watchpoint")); - t.push_back (Packet (query_monitor, &RNBRemote::HandlePacket_qRcmd, NULL, "qRcmd", "Monitor command")); - t.push_back (Packet (query_current_thread_id, &RNBRemote::HandlePacket_qC, NULL, "qC", "Query current thread ID")); - t.push_back (Packet (query_echo, &RNBRemote::HandlePacket_qEcho, NULL, "qEcho:", "Echo the packet back to allow the debugger to sync up with this server")); - t.push_back (Packet (query_get_pid, &RNBRemote::HandlePacket_qGetPid, NULL, "qGetPid", "Query process id")); - t.push_back (Packet (query_thread_ids_first, &RNBRemote::HandlePacket_qThreadInfo, NULL, "qfThreadInfo", "Get list of active threads (first req)")); - t.push_back (Packet (query_thread_ids_subsequent, &RNBRemote::HandlePacket_qThreadInfo, NULL, "qsThreadInfo", "Get list of active threads (subsequent req)")); - // APPLE LOCAL: qThreadStopInfo - // syntax: qThreadStopInfoTTTT - // TTTT is hex thread ID - t.push_back (Packet (query_thread_stop_info, &RNBRemote::HandlePacket_qThreadStopInfo, NULL, "qThreadStopInfo", "Get detailed info on why the specified thread stopped")); - t.push_back (Packet (query_thread_extra_info, &RNBRemote::HandlePacket_qThreadExtraInfo,NULL, "qThreadExtraInfo", "Get printable status of a thread")); -// t.push_back (Packet (query_image_offsets, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "qOffsets", "Report offset of loaded program")); - t.push_back (Packet (query_launch_success, &RNBRemote::HandlePacket_qLaunchSuccess,NULL, "qLaunchSuccess", "Report the success or failure of the launch attempt")); - t.push_back (Packet (query_register_info, &RNBRemote::HandlePacket_qRegisterInfo, NULL, "qRegisterInfo", "Dynamically discover remote register context information.")); - t.push_back (Packet (query_shlib_notify_info_addr, &RNBRemote::HandlePacket_qShlibInfoAddr,NULL, "qShlibInfoAddr", "Returns the address that contains info needed for getting shared library notifications")); - t.push_back (Packet (query_step_packet_supported, &RNBRemote::HandlePacket_qStepPacketSupported,NULL, "qStepPacketSupported", "Replys with OK if the 's' packet is supported.")); - t.push_back (Packet (query_vattachorwait_supported, &RNBRemote::HandlePacket_qVAttachOrWaitSupported,NULL, "qVAttachOrWaitSupported", "Replys with OK if the 'vAttachOrWait' packet is supported.")); - t.push_back (Packet (query_sync_thread_state_supported, &RNBRemote::HandlePacket_qSyncThreadStateSupported,NULL, "qSyncThreadStateSupported", "Replys with OK if the 'QSyncThreadState:' packet is supported.")); - t.push_back (Packet (query_host_info, &RNBRemote::HandlePacket_qHostInfo , NULL, "qHostInfo", "Replies with multiple 'key:value;' tuples appended to each other.")); - t.push_back (Packet (query_gdb_server_version, &RNBRemote::HandlePacket_qGDBServerVersion , NULL, "qGDBServerVersion", "Replies with multiple 'key:value;' tuples appended to each other.")); - t.push_back (Packet (query_process_info, &RNBRemote::HandlePacket_qProcessInfo , NULL, "qProcessInfo", "Replies with multiple 'key:value;' tuples appended to each other.")); - t.push_back (Packet (query_symbol_lookup, &RNBRemote::HandlePacket_qSymbol , NULL, "qSymbol:", "Notify that host debugger is ready to do symbol lookups")); - t.push_back (Packet (json_query_thread_extended_info,&RNBRemote::HandlePacket_jThreadExtendedInfo , NULL, "jThreadExtendedInfo", "Replies with JSON data of thread extended information.")); - t.push_back (Packet (json_query_get_loaded_dynamic_libraries_infos, &RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos, NULL, "jGetLoadedDynamicLibrariesInfos", "Replies with JSON data of all the shared libraries loaded in this process.")); - t.push_back (Packet (json_query_threads_info, &RNBRemote::HandlePacket_jThreadsInfo , NULL, "jThreadsInfo", "Replies with JSON data with information about all threads.")); - t.push_back (Packet (json_query_get_shared_cache_info, &RNBRemote::HandlePacket_jGetSharedCacheInfo, NULL, "jGetSharedCacheInfo", "Replies with JSON data about the location and uuid of the shared cache in the inferior process.")); - t.push_back (Packet (start_noack_mode, &RNBRemote::HandlePacket_QStartNoAckMode , NULL, "QStartNoAckMode", "Request that " DEBUGSERVER_PROGRAM_NAME " stop acking remote protocol packets")); - t.push_back (Packet (prefix_reg_packets_with_tid, &RNBRemote::HandlePacket_QThreadSuffixSupported , NULL, "QThreadSuffixSupported", "Check if thread specific packets (register packets 'g', 'G', 'p', and 'P') support having the thread ID appended to the end of the command")); - t.push_back (Packet (set_logging_mode, &RNBRemote::HandlePacket_QSetLogging , NULL, "QSetLogging:", "Check if register packets ('g', 'G', 'p', and 'P' support having the thread ID prefix")); - t.push_back (Packet (set_max_packet_size, &RNBRemote::HandlePacket_QSetMaxPacketSize , NULL, "QSetMaxPacketSize:", "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized packet gdb can handle")); - t.push_back (Packet (set_max_payload_size, &RNBRemote::HandlePacket_QSetMaxPayloadSize , NULL, "QSetMaxPayloadSize:", "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized payload gdb can handle")); - t.push_back (Packet (set_environment_variable, &RNBRemote::HandlePacket_QEnvironment , NULL, "QEnvironment:", "Add an environment variable to the inferior's environment")); - t.push_back (Packet (set_environment_variable_hex, &RNBRemote::HandlePacket_QEnvironmentHexEncoded , NULL, "QEnvironmentHexEncoded:", "Add an environment variable to the inferior's environment")); - t.push_back (Packet (set_launch_arch, &RNBRemote::HandlePacket_QLaunchArch , NULL, "QLaunchArch:", "Set the architecture to use when launching a process for hosts that can run multiple architecture slices from universal files.")); - t.push_back (Packet (set_disable_aslr, &RNBRemote::HandlePacket_QSetDisableASLR , NULL, "QSetDisableASLR:", "Set whether to disable ASLR when launching the process with the set argv ('A') packet")); - t.push_back (Packet (set_stdin, &RNBRemote::HandlePacket_QSetSTDIO , NULL, "QSetSTDIN:", "Set the standard input for a process to be launched with the 'A' packet")); - t.push_back (Packet (set_stdout, &RNBRemote::HandlePacket_QSetSTDIO , NULL, "QSetSTDOUT:", "Set the standard output for a process to be launched with the 'A' packet")); - t.push_back (Packet (set_stderr, &RNBRemote::HandlePacket_QSetSTDIO , NULL, "QSetSTDERR:", "Set the standard error for a process to be launched with the 'A' packet")); - t.push_back (Packet (set_working_dir, &RNBRemote::HandlePacket_QSetWorkingDir , NULL, "QSetWorkingDir:", "Set the working directory for a process to be launched with the 'A' packet")); - t.push_back (Packet (set_list_threads_in_stop_reply,&RNBRemote::HandlePacket_QListThreadsInStopReply , NULL, "QListThreadsInStopReply", "Set if the 'threads' key should be added to the stop reply packets with a list of all thread IDs.")); - t.push_back (Packet (sync_thread_state, &RNBRemote::HandlePacket_QSyncThreadState , NULL, "QSyncThreadState:", "Do whatever is necessary to make sure 'thread' is in a safe state to call functions on.")); -// t.push_back (Packet (pass_signals_to_inferior, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "QPassSignals:", "Specify which signals are passed to the inferior")); - t.push_back (Packet (allocate_memory, &RNBRemote::HandlePacket_AllocateMemory, NULL, "_M", "Allocate memory in the inferior process.")); - t.push_back (Packet (deallocate_memory, &RNBRemote::HandlePacket_DeallocateMemory, NULL, "_m", "Deallocate memory in the inferior process.")); - t.push_back (Packet (save_register_state, &RNBRemote::HandlePacket_SaveRegisterState, NULL, "QSaveRegisterState", "Save the register state for the current thread and return a decimal save ID.")); - t.push_back (Packet (restore_register_state, &RNBRemote::HandlePacket_RestoreRegisterState, NULL, "QRestoreRegisterState:", "Restore the register state given a save ID previously returned from a call to QSaveRegisterState.")); - t.push_back (Packet (memory_region_info, &RNBRemote::HandlePacket_MemoryRegionInfo, NULL, "qMemoryRegionInfo", "Return size and attributes of a memory region that contains the given address")); - t.push_back (Packet (get_profile_data, &RNBRemote::HandlePacket_GetProfileData, NULL, "qGetProfileData", "Return profiling data of the current target.")); - t.push_back (Packet (set_enable_profiling, &RNBRemote::HandlePacket_SetEnableAsyncProfiling, NULL, "QSetEnableAsyncProfiling", "Enable or disable the profiling of current target.")); - t.push_back (Packet (enable_compression, &RNBRemote::HandlePacket_QEnableCompression, NULL, "QEnableCompression:", "Enable compression for the remainder of the connection")); - t.push_back (Packet (watchpoint_support_info, &RNBRemote::HandlePacket_WatchpointSupportInfo, NULL, "qWatchpointSupportInfo", "Return the number of supported hardware watchpoints")); - t.push_back (Packet (set_process_event, &RNBRemote::HandlePacket_QSetProcessEvent, NULL, "QSetProcessEvent:", "Set a process event, to be passed to the process, can be set before the process is started, or after.")); - t.push_back (Packet (set_detach_on_error, &RNBRemote::HandlePacket_QSetDetachOnError, NULL, "QSetDetachOnError:", "Set whether debugserver will detach (1) or kill (0) from the process it is controlling if it loses connection to lldb.")); - t.push_back (Packet (speed_test, &RNBRemote::HandlePacket_qSpeedTest, NULL, "qSpeedTest:", "Test the maximum speed at which packet can be sent/received.")); - t.push_back (Packet (query_transfer, &RNBRemote::HandlePacket_qXfer, NULL, "qXfer:", "Support the qXfer packet.")); - t.push_back (Packet (query_supported_async_json_packets, &RNBRemote::HandlePacket_qStructuredDataPlugins, NULL, "qStructuredDataPlugins", "Query for the structured data plugins supported by the remote.")); - t.push_back (Packet (configure_darwin_log, &RNBRemote::HandlePacket_QConfigureDarwinLog, NULL, "QConfigureDarwinLog:", "Configure the DarwinLog structured data plugin support.")); -} - -void -RNBRemote::FlushSTDIO () -{ - if (m_ctx.HasValidProcessID()) - { - nub_process_t pid = m_ctx.ProcessID(); - char buf[256]; - nub_size_t count; - do - { - count = DNBProcessGetAvailableSTDOUT(pid, buf, sizeof(buf)); - if (count > 0) - { - SendSTDOUTPacket (buf, count); - } - } while (count > 0); +RNBRemote::RNBRemote() + : m_ctx(), m_comm(), m_arch(), m_continue_thread(-1), m_thread(-1), + m_mutex(), m_dispatch_queue_offsets(), + m_dispatch_queue_offsets_addr(INVALID_NUB_ADDRESS), + m_qSymbol_index(UINT32_MAX), m_packets_recvd(0), m_packets(), + m_rx_packets(), m_rx_partial_data(), m_rx_pthread(0), + m_max_payload_size(DEFAULT_GDB_REMOTE_PROTOCOL_BUFSIZE - 4), + m_extended_mode(false), m_noack_mode(false), + m_thread_suffix_supported(false), m_list_threads_in_stop_reply(false), + m_compression_minsize(384), m_enable_compression_next_send_packet(false), + m_compression_mode(compression_types::none) { + DNBLogThreadedIf(LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__); + CreatePacketTable(); +} + +RNBRemote::~RNBRemote() { + DNBLogThreadedIf(LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__); + StopReadRemoteDataThread(); +} + +void RNBRemote::CreatePacketTable() { + // Step required to add new packets: + // 1 - Add new enumeration to RNBRemote::PacketEnum + // 2 - Create the RNBRemote::HandlePacket_ function if a new function is + // needed + // 3 - Register the Packet definition with any needed callbacks in this + // function + // - If no response is needed for a command, then use NULL for the + // normal callback + // - If the packet is not supported while the target is running, use + // NULL for the async callback + // 4 - If the packet is a standard packet (starts with a '$' character + // followed by the payload and then '#' and checksum, then you are done + // else go on to step 5 + // 5 - if the packet is a fixed length packet: + // - modify the switch statement for the first character in the payload + // in RNBRemote::CommDataReceived so it doesn't reject the new packet + // type as invalid + // - modify the switch statement for the first character in the payload + // in RNBRemote::GetPacketPayload and make sure the payload of the + // packet + // is returned correctly + + std::vector<Packet> &t = m_packets; + t.push_back(Packet(ack, NULL, NULL, "+", "ACK")); + t.push_back(Packet(nack, NULL, NULL, "-", "!ACK")); + t.push_back(Packet(read_memory, &RNBRemote::HandlePacket_m, NULL, "m", + "Read memory")); + t.push_back(Packet(read_register, &RNBRemote::HandlePacket_p, NULL, "p", + "Read one register")); + t.push_back(Packet(read_general_regs, &RNBRemote::HandlePacket_g, NULL, "g", + "Read registers")); + t.push_back(Packet(write_memory, &RNBRemote::HandlePacket_M, NULL, "M", + "Write memory")); + t.push_back(Packet(write_register, &RNBRemote::HandlePacket_P, NULL, "P", + "Write one register")); + t.push_back(Packet(write_general_regs, &RNBRemote::HandlePacket_G, NULL, "G", + "Write registers")); + t.push_back(Packet(insert_mem_bp, &RNBRemote::HandlePacket_z, NULL, "Z0", + "Insert memory breakpoint")); + t.push_back(Packet(remove_mem_bp, &RNBRemote::HandlePacket_z, NULL, "z0", + "Remove memory breakpoint")); + t.push_back(Packet(single_step, &RNBRemote::HandlePacket_s, NULL, "s", + "Single step")); + t.push_back(Packet(cont, &RNBRemote::HandlePacket_c, NULL, "c", "continue")); + t.push_back(Packet(single_step_with_sig, &RNBRemote::HandlePacket_S, NULL, + "S", "Single step with signal")); + t.push_back( + Packet(set_thread, &RNBRemote::HandlePacket_H, NULL, "H", "Set thread")); + t.push_back(Packet(halt, &RNBRemote::HandlePacket_last_signal, + &RNBRemote::HandlePacket_stop_process, "\x03", "^C")); + // t.push_back (Packet (use_extended_mode, + // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "!", "Use extended mode")); + t.push_back(Packet(why_halted, &RNBRemote::HandlePacket_last_signal, NULL, + "?", "Why did target halt")); + t.push_back( + Packet(set_argv, &RNBRemote::HandlePacket_A, NULL, "A", "Set argv")); + // t.push_back (Packet (set_bp, + // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "B", "Set/clear + // breakpoint")); + t.push_back(Packet(continue_with_sig, &RNBRemote::HandlePacket_C, NULL, "C", + "Continue with signal")); + t.push_back(Packet(detach, &RNBRemote::HandlePacket_D, NULL, "D", + "Detach gdb from remote system")); + // t.push_back (Packet (step_inferior_one_cycle, + // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "i", "Step inferior by one + // clock cycle")); + // t.push_back (Packet (signal_and_step_inf_one_cycle, + // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "I", "Signal inferior, then + // step one clock cycle")); + t.push_back(Packet(kill, &RNBRemote::HandlePacket_k, NULL, "k", "Kill")); + // t.push_back (Packet (restart, + // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "R", "Restart inferior")); + // t.push_back (Packet (search_mem_backwards, + // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "t", "Search memory + // backwards")); + t.push_back(Packet(thread_alive_p, &RNBRemote::HandlePacket_T, NULL, "T", + "Is thread alive")); + t.push_back(Packet(query_supported_features, + &RNBRemote::HandlePacket_qSupported, NULL, "qSupported", + "Query about supported features")); + t.push_back(Packet(vattach, &RNBRemote::HandlePacket_v, NULL, "vAttach", + "Attach to a new process")); + t.push_back(Packet(vattachwait, &RNBRemote::HandlePacket_v, NULL, + "vAttachWait", + "Wait for a process to start up then attach to it")); + t.push_back(Packet(vattachorwait, &RNBRemote::HandlePacket_v, NULL, + "vAttachOrWait", "Attach to the process or if it doesn't " + "exist, wait for the process to start up " + "then attach to it")); + t.push_back(Packet(vattachname, &RNBRemote::HandlePacket_v, NULL, + "vAttachName", "Attach to an existing process by name")); + t.push_back(Packet(vcont_list_actions, &RNBRemote::HandlePacket_v, NULL, + "vCont;", "Verbose resume with thread actions")); + t.push_back(Packet(vcont_list_actions, &RNBRemote::HandlePacket_v, NULL, + "vCont?", + "List valid continue-with-thread-actions actions")); + t.push_back(Packet(read_data_from_memory, &RNBRemote::HandlePacket_x, NULL, + "x", "Read data from memory")); + t.push_back(Packet(write_data_to_memory, &RNBRemote::HandlePacket_X, NULL, + "X", "Write data to memory")); + // t.push_back (Packet (insert_hardware_bp, + // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "Z1", "Insert hardware + // breakpoint")); + // t.push_back (Packet (remove_hardware_bp, + // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "z1", "Remove hardware + // breakpoint")); + t.push_back(Packet(insert_write_watch_bp, &RNBRemote::HandlePacket_z, NULL, + "Z2", "Insert write watchpoint")); + t.push_back(Packet(remove_write_watch_bp, &RNBRemote::HandlePacket_z, NULL, + "z2", "Remove write watchpoint")); + t.push_back(Packet(insert_read_watch_bp, &RNBRemote::HandlePacket_z, NULL, + "Z3", "Insert read watchpoint")); + t.push_back(Packet(remove_read_watch_bp, &RNBRemote::HandlePacket_z, NULL, + "z3", "Remove read watchpoint")); + t.push_back(Packet(insert_access_watch_bp, &RNBRemote::HandlePacket_z, NULL, + "Z4", "Insert access watchpoint")); + t.push_back(Packet(remove_access_watch_bp, &RNBRemote::HandlePacket_z, NULL, + "z4", "Remove access watchpoint")); + t.push_back(Packet(query_monitor, &RNBRemote::HandlePacket_qRcmd, NULL, + "qRcmd", "Monitor command")); + t.push_back(Packet(query_current_thread_id, &RNBRemote::HandlePacket_qC, NULL, + "qC", "Query current thread ID")); + t.push_back(Packet(query_echo, &RNBRemote::HandlePacket_qEcho, NULL, "qEcho:", + "Echo the packet back to allow the debugger to sync up " + "with this server")); + t.push_back(Packet(query_get_pid, &RNBRemote::HandlePacket_qGetPid, NULL, + "qGetPid", "Query process id")); + t.push_back(Packet(query_thread_ids_first, + &RNBRemote::HandlePacket_qThreadInfo, NULL, "qfThreadInfo", + "Get list of active threads (first req)")); + t.push_back(Packet(query_thread_ids_subsequent, + &RNBRemote::HandlePacket_qThreadInfo, NULL, "qsThreadInfo", + "Get list of active threads (subsequent req)")); + // APPLE LOCAL: qThreadStopInfo + // syntax: qThreadStopInfoTTTT + // TTTT is hex thread ID + t.push_back(Packet(query_thread_stop_info, + &RNBRemote::HandlePacket_qThreadStopInfo, NULL, + "qThreadStopInfo", + "Get detailed info on why the specified thread stopped")); + t.push_back(Packet(query_thread_extra_info, + &RNBRemote::HandlePacket_qThreadExtraInfo, NULL, + "qThreadExtraInfo", "Get printable status of a thread")); + // t.push_back (Packet (query_image_offsets, + // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "qOffsets", "Report offset + // of loaded program")); + t.push_back(Packet( + query_launch_success, &RNBRemote::HandlePacket_qLaunchSuccess, NULL, + "qLaunchSuccess", "Report the success or failure of the launch attempt")); + t.push_back( + Packet(query_register_info, &RNBRemote::HandlePacket_qRegisterInfo, NULL, + "qRegisterInfo", + "Dynamically discover remote register context information.")); + t.push_back(Packet( + query_shlib_notify_info_addr, &RNBRemote::HandlePacket_qShlibInfoAddr, + NULL, "qShlibInfoAddr", "Returns the address that contains info needed " + "for getting shared library notifications")); + t.push_back(Packet(query_step_packet_supported, + &RNBRemote::HandlePacket_qStepPacketSupported, NULL, + "qStepPacketSupported", + "Replys with OK if the 's' packet is supported.")); + t.push_back( + Packet(query_vattachorwait_supported, + &RNBRemote::HandlePacket_qVAttachOrWaitSupported, NULL, + "qVAttachOrWaitSupported", + "Replys with OK if the 'vAttachOrWait' packet is supported.")); + t.push_back( + Packet(query_sync_thread_state_supported, + &RNBRemote::HandlePacket_qSyncThreadStateSupported, NULL, + "qSyncThreadStateSupported", + "Replys with OK if the 'QSyncThreadState:' packet is supported.")); + t.push_back(Packet( + query_host_info, &RNBRemote::HandlePacket_qHostInfo, NULL, "qHostInfo", + "Replies with multiple 'key:value;' tuples appended to each other.")); + t.push_back(Packet( + query_gdb_server_version, &RNBRemote::HandlePacket_qGDBServerVersion, + NULL, "qGDBServerVersion", + "Replies with multiple 'key:value;' tuples appended to each other.")); + t.push_back(Packet( + query_process_info, &RNBRemote::HandlePacket_qProcessInfo, NULL, + "qProcessInfo", + "Replies with multiple 'key:value;' tuples appended to each other.")); + t.push_back(Packet( + query_symbol_lookup, &RNBRemote::HandlePacket_qSymbol, NULL, "qSymbol:", + "Notify that host debugger is ready to do symbol lookups")); + t.push_back(Packet(json_query_thread_extended_info, + &RNBRemote::HandlePacket_jThreadExtendedInfo, NULL, + "jThreadExtendedInfo", + "Replies with JSON data of thread extended information.")); + t.push_back(Packet(json_query_get_loaded_dynamic_libraries_infos, + &RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos, + NULL, "jGetLoadedDynamicLibrariesInfos", + "Replies with JSON data of all the shared libraries " + "loaded in this process.")); + t.push_back( + Packet(json_query_threads_info, &RNBRemote::HandlePacket_jThreadsInfo, + NULL, "jThreadsInfo", + "Replies with JSON data with information about all threads.")); + t.push_back(Packet(json_query_get_shared_cache_info, + &RNBRemote::HandlePacket_jGetSharedCacheInfo, NULL, + "jGetSharedCacheInfo", "Replies with JSON data about the " + "location and uuid of the shared " + "cache in the inferior process.")); + t.push_back(Packet(start_noack_mode, &RNBRemote::HandlePacket_QStartNoAckMode, + NULL, "QStartNoAckMode", + "Request that " DEBUGSERVER_PROGRAM_NAME + " stop acking remote protocol packets")); + t.push_back(Packet(prefix_reg_packets_with_tid, + &RNBRemote::HandlePacket_QThreadSuffixSupported, NULL, + "QThreadSuffixSupported", + "Check if thread specific packets (register packets 'g', " + "'G', 'p', and 'P') support having the thread ID appended " + "to the end of the command")); + t.push_back(Packet(set_logging_mode, &RNBRemote::HandlePacket_QSetLogging, + NULL, "QSetLogging:", "Check if register packets ('g', " + "'G', 'p', and 'P' support having " + "the thread ID prefix")); + t.push_back(Packet( + set_max_packet_size, &RNBRemote::HandlePacket_QSetMaxPacketSize, NULL, + "QSetMaxPacketSize:", + "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized packet gdb can handle")); + t.push_back(Packet( + set_max_payload_size, &RNBRemote::HandlePacket_QSetMaxPayloadSize, NULL, + "QSetMaxPayloadSize:", "Tell " DEBUGSERVER_PROGRAM_NAME + " the max sized payload gdb can handle")); + t.push_back( + Packet(set_environment_variable, &RNBRemote::HandlePacket_QEnvironment, + NULL, "QEnvironment:", + "Add an environment variable to the inferior's environment")); + t.push_back( + Packet(set_environment_variable_hex, + &RNBRemote::HandlePacket_QEnvironmentHexEncoded, NULL, + "QEnvironmentHexEncoded:", + "Add an environment variable to the inferior's environment")); + t.push_back(Packet(set_launch_arch, &RNBRemote::HandlePacket_QLaunchArch, + NULL, "QLaunchArch:", "Set the architecture to use when " + "launching a process for hosts that " + "can run multiple architecture " + "slices from universal files.")); + t.push_back(Packet(set_disable_aslr, &RNBRemote::HandlePacket_QSetDisableASLR, + NULL, "QSetDisableASLR:", + "Set whether to disable ASLR when launching the process " + "with the set argv ('A') packet")); + t.push_back(Packet(set_stdin, &RNBRemote::HandlePacket_QSetSTDIO, NULL, + "QSetSTDIN:", "Set the standard input for a process to be " + "launched with the 'A' packet")); + t.push_back(Packet(set_stdout, &RNBRemote::HandlePacket_QSetSTDIO, NULL, + "QSetSTDOUT:", "Set the standard output for a process to " + "be launched with the 'A' packet")); + t.push_back(Packet(set_stderr, &RNBRemote::HandlePacket_QSetSTDIO, NULL, + "QSetSTDERR:", "Set the standard error for a process to " + "be launched with the 'A' packet")); + t.push_back(Packet(set_working_dir, &RNBRemote::HandlePacket_QSetWorkingDir, + NULL, "QSetWorkingDir:", "Set the working directory for a " + "process to be launched with the " + "'A' packet")); + t.push_back(Packet(set_list_threads_in_stop_reply, + &RNBRemote::HandlePacket_QListThreadsInStopReply, NULL, + "QListThreadsInStopReply", + "Set if the 'threads' key should be added to the stop " + "reply packets with a list of all thread IDs.")); + t.push_back(Packet( + sync_thread_state, &RNBRemote::HandlePacket_QSyncThreadState, NULL, + "QSyncThreadState:", "Do whatever is necessary to make sure 'thread' is " + "in a safe state to call functions on.")); + // t.push_back (Packet (pass_signals_to_inferior, + // &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "QPassSignals:", "Specify + // which signals are passed to the inferior")); + t.push_back(Packet(allocate_memory, &RNBRemote::HandlePacket_AllocateMemory, + NULL, "_M", "Allocate memory in the inferior process.")); + t.push_back(Packet(deallocate_memory, + &RNBRemote::HandlePacket_DeallocateMemory, NULL, "_m", + "Deallocate memory in the inferior process.")); + t.push_back(Packet( + save_register_state, &RNBRemote::HandlePacket_SaveRegisterState, NULL, + "QSaveRegisterState", "Save the register state for the current thread " + "and return a decimal save ID.")); + t.push_back(Packet(restore_register_state, + &RNBRemote::HandlePacket_RestoreRegisterState, NULL, + "QRestoreRegisterState:", + "Restore the register state given a save ID previously " + "returned from a call to QSaveRegisterState.")); + t.push_back(Packet( + memory_region_info, &RNBRemote::HandlePacket_MemoryRegionInfo, NULL, + "qMemoryRegionInfo", "Return size and attributes of a memory region that " + "contains the given address")); + t.push_back(Packet(get_profile_data, &RNBRemote::HandlePacket_GetProfileData, + NULL, "qGetProfileData", + "Return profiling data of the current target.")); + t.push_back(Packet(set_enable_profiling, + &RNBRemote::HandlePacket_SetEnableAsyncProfiling, NULL, + "QSetEnableAsyncProfiling", + "Enable or disable the profiling of current target.")); + t.push_back(Packet(enable_compression, + &RNBRemote::HandlePacket_QEnableCompression, NULL, + "QEnableCompression:", + "Enable compression for the remainder of the connection")); + t.push_back(Packet(watchpoint_support_info, + &RNBRemote::HandlePacket_WatchpointSupportInfo, NULL, + "qWatchpointSupportInfo", + "Return the number of supported hardware watchpoints")); + t.push_back(Packet(set_process_event, + &RNBRemote::HandlePacket_QSetProcessEvent, NULL, + "QSetProcessEvent:", "Set a process event, to be passed " + "to the process, can be set before " + "the process is started, or after.")); + t.push_back( + Packet(set_detach_on_error, &RNBRemote::HandlePacket_QSetDetachOnError, + NULL, "QSetDetachOnError:", + "Set whether debugserver will detach (1) or kill (0) from the " + "process it is controlling if it loses connection to lldb.")); + t.push_back(Packet( + speed_test, &RNBRemote::HandlePacket_qSpeedTest, NULL, "qSpeedTest:", + "Test the maximum speed at which packet can be sent/received.")); + t.push_back(Packet(query_transfer, &RNBRemote::HandlePacket_qXfer, NULL, + "qXfer:", "Support the qXfer packet.")); + t.push_back( + Packet(query_supported_async_json_packets, + &RNBRemote::HandlePacket_qStructuredDataPlugins, NULL, + "qStructuredDataPlugins", + "Query for the structured data plugins supported by the remote.")); + t.push_back( + Packet(configure_darwin_log, &RNBRemote::HandlePacket_QConfigureDarwinLog, + NULL, "QConfigureDarwinLog:", + "Configure the DarwinLog structured data plugin support.")); +} + +void RNBRemote::FlushSTDIO() { + if (m_ctx.HasValidProcessID()) { + nub_process_t pid = m_ctx.ProcessID(); + char buf[256]; + nub_size_t count; + do { + count = DNBProcessGetAvailableSTDOUT(pid, buf, sizeof(buf)); + if (count > 0) { + SendSTDOUTPacket(buf, count); + } + } while (count > 0); - do - { - count = DNBProcessGetAvailableSTDERR(pid, buf, sizeof(buf)); - if (count > 0) - { - SendSTDERRPacket (buf, count); - } - } while (count > 0); - } + do { + count = DNBProcessGetAvailableSTDERR(pid, buf, sizeof(buf)); + if (count > 0) { + SendSTDERRPacket(buf, count); + } + } while (count > 0); + } } -void -RNBRemote::SendAsyncProfileData () -{ - if (m_ctx.HasValidProcessID()) - { - nub_process_t pid = m_ctx.ProcessID(); - char buf[1024]; - nub_size_t count; - do - { - count = DNBProcessGetAvailableProfileData(pid, buf, sizeof(buf)); - if (count > 0) - { - SendAsyncProfileDataPacket (buf, count); - } - } while (count > 0); - } +void RNBRemote::SendAsyncProfileData() { + if (m_ctx.HasValidProcessID()) { + nub_process_t pid = m_ctx.ProcessID(); + char buf[1024]; + nub_size_t count; + do { + count = DNBProcessGetAvailableProfileData(pid, buf, sizeof(buf)); + if (count > 0) { + SendAsyncProfileDataPacket(buf, count); + } + } while (count > 0); + } } -void -RNBRemote::SendAsyncDarwinLogData () -{ - DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): enter", +void RNBRemote::SendAsyncDarwinLogData() { + DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): enter", __FUNCTION__); + + if (!m_ctx.HasValidProcessID()) { + DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): ignoring due to" + "invalid process id", __FUNCTION__); + return; + } - if (!m_ctx.HasValidProcessID()) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): ignoring due to" - "invalid process id", __FUNCTION__); - return; - } + nub_process_t pid = m_ctx.ProcessID(); + DarwinLogEventVector::size_type entry_count = 0; - nub_process_t pid = m_ctx.ProcessID(); - DarwinLogEventVector::size_type entry_count = 0; + // NOTE: the current looping structure here does nothing + // to guarantee that we can send off async packets faster + // than we generate them. It will keep sending as long + // as there's data to send. + do { + DarwinLogEventVector events = DNBProcessGetAvailableDarwinLogEvents(pid); + entry_count = events.size(); - // NOTE: the current looping structure here does nothing - // to guarantee that we can send off async packets faster - // than we generate them. It will keep sending as long - // as there's data to send. - do - { - DarwinLogEventVector events = - DNBProcessGetAvailableDarwinLogEvents(pid); - entry_count = events.size(); - - DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): outer loop enter", - __FUNCTION__); + DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): outer loop enter", + __FUNCTION__); - for (DarwinLogEventVector::size_type base_entry = 0; - base_entry < entry_count; - base_entry += DARWIN_LOG_MAX_EVENTS_PER_PACKET) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): inner loop enter", - __FUNCTION__); - - // We limit the total number of entries we pack - // into a single JSON async packet just so it - // doesn't get too large. - JSONGenerator::Dictionary async_dictionary; - - // Specify the type of the JSON async data we're sending. - async_dictionary.AddStringItem( - JSON_ASYNC_TYPE_KEY_NAME, "DarwinLog"); - - // Create an array entry in the dictionary to hold all - // the events going in this packet. - JSONGenerator::ArraySP events_array(new JSONGenerator::Array()); - async_dictionary.AddItem(OS_LOG_EVENTS_KEY_NAME, events_array); - - // We bundle up to DARWIN_LOG_MAX_EVENTS_PER_PACKET events in - // a single packet. - const auto inner_loop_bound = - std::min(base_entry + DARWIN_LOG_MAX_EVENTS_PER_PACKET, - entry_count); - for (DarwinLogEventVector::size_type i = base_entry; - i < inner_loop_bound; ++i) - { - DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): adding " - "entry index %lu to the JSON packet", - __FUNCTION__, i); - events_array->AddItem(events[i]); - } + for (DarwinLogEventVector::size_type base_entry = 0; + base_entry < entry_count; + base_entry += DARWIN_LOG_MAX_EVENTS_PER_PACKET) { + DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): inner loop enter", + __FUNCTION__); + + // We limit the total number of entries we pack + // into a single JSON async packet just so it + // doesn't get too large. + JSONGenerator::Dictionary async_dictionary; + + // Specify the type of the JSON async data we're sending. + async_dictionary.AddStringItem(JSON_ASYNC_TYPE_KEY_NAME, "DarwinLog"); + + // Create an array entry in the dictionary to hold all + // the events going in this packet. + JSONGenerator::ArraySP events_array(new JSONGenerator::Array()); + async_dictionary.AddItem(OS_LOG_EVENTS_KEY_NAME, events_array); + + // We bundle up to DARWIN_LOG_MAX_EVENTS_PER_PACKET events in + // a single packet. + const auto inner_loop_bound = + std::min(base_entry + DARWIN_LOG_MAX_EVENTS_PER_PACKET, entry_count); + for (DarwinLogEventVector::size_type i = base_entry; i < inner_loop_bound; + ++i) { + DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): adding " + "entry index %lu to the JSON packet", + __FUNCTION__, i); + events_array->AddItem(events[i]); + } - // Send off the packet. - DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): sending JSON " - "packet, %lu entries remain", __FUNCTION__, - entry_count - inner_loop_bound); - SendAsyncJSONPacket(async_dictionary); - } + // Send off the packet. + DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): sending JSON " + "packet, %lu entries remain", + __FUNCTION__, entry_count - inner_loop_bound); + SendAsyncJSONPacket(async_dictionary); + } - DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): outer loop exit", - __FUNCTION__); + DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): outer loop exit", + __FUNCTION__); - } while (entry_count > 0); + } while (entry_count > 0); - DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): exit", - __PRETTY_FUNCTION__); + DNBLogThreadedIf(LOG_DARWIN_LOG, "RNBRemote::%s(): exit", + __PRETTY_FUNCTION__); } -rnb_err_t -RNBRemote::SendHexEncodedBytePacket (const char *header, const void *buf, size_t buf_len, const char *footer) -{ - std::ostringstream packet_sstrm; - // Append the header cstr if there was one - if (header && header[0]) - packet_sstrm << header; - nub_size_t i; - const uint8_t *ubuf8 = (const uint8_t *)buf; - for (i=0; i<buf_len; i++) - { - packet_sstrm << RAWHEX8(ubuf8[i]); - } - // Append the footer cstr if there was one - if (footer && footer[0]) - packet_sstrm << footer; +rnb_err_t RNBRemote::SendHexEncodedBytePacket(const char *header, + const void *buf, size_t buf_len, + const char *footer) { + std::ostringstream packet_sstrm; + // Append the header cstr if there was one + if (header && header[0]) + packet_sstrm << header; + nub_size_t i; + const uint8_t *ubuf8 = (const uint8_t *)buf; + for (i = 0; i < buf_len; i++) { + packet_sstrm << RAWHEX8(ubuf8[i]); + } + // Append the footer cstr if there was one + if (footer && footer[0]) + packet_sstrm << footer; - return SendPacket(packet_sstrm.str()); + return SendPacket(packet_sstrm.str()); } -rnb_err_t -RNBRemote::SendSTDOUTPacket (char *buf, nub_size_t buf_size) -{ - if (buf_size == 0) - return rnb_success; - return SendHexEncodedBytePacket("O", buf, buf_size, NULL); +rnb_err_t RNBRemote::SendSTDOUTPacket(char *buf, nub_size_t buf_size) { + if (buf_size == 0) + return rnb_success; + return SendHexEncodedBytePacket("O", buf, buf_size, NULL); } -rnb_err_t -RNBRemote::SendSTDERRPacket (char *buf, nub_size_t buf_size) -{ - if (buf_size == 0) - return rnb_success; - return SendHexEncodedBytePacket("O", buf, buf_size, NULL); +rnb_err_t RNBRemote::SendSTDERRPacket(char *buf, nub_size_t buf_size) { + if (buf_size == 0) + return rnb_success; + return SendHexEncodedBytePacket("O", buf, buf_size, NULL); } // This makes use of asynchronous bit 'A' in the gdb remote protocol. -rnb_err_t -RNBRemote::SendAsyncProfileDataPacket (char *buf, nub_size_t buf_size) -{ - if (buf_size == 0) - return rnb_success; - - std::string packet("A"); - packet.append(buf, buf_size); - return SendPacket(packet); +rnb_err_t RNBRemote::SendAsyncProfileDataPacket(char *buf, + nub_size_t buf_size) { + if (buf_size == 0) + return rnb_success; + + std::string packet("A"); + packet.append(buf, buf_size); + return SendPacket(packet); } rnb_err_t -RNBRemote::SendAsyncJSONPacket(const JSONGenerator::Dictionary &dictionary) -{ - std::ostringstream stream; - // We're choosing something that is easy to spot if we somehow get one - // of these coming out at the wrong time (i.e. when the remote side - // is not waiting for a process control completion response). - stream << "JSON-async:"; - dictionary.Dump(stream); - const std::string payload = binary_encode_string(stream.str()); - return SendPacket(payload); +RNBRemote::SendAsyncJSONPacket(const JSONGenerator::Dictionary &dictionary) { + std::ostringstream stream; + // We're choosing something that is easy to spot if we somehow get one + // of these coming out at the wrong time (i.e. when the remote side + // is not waiting for a process control completion response). + stream << "JSON-async:"; + dictionary.Dump(stream); + const std::string payload = binary_encode_string(stream.str()); + return SendPacket(payload); } // Given a std::string packet contents to send, possibly encode/compress it. // If compression is enabled, the returned std::string will be in one of two // forms: -// +// // N<original packet contents uncompressed> -// C<size of original decompressed packet>:<packet compressed with the requested compression scheme> +// C<size of original decompressed packet>:<packet compressed with the +// requested compression scheme> // // If compression is not requested, the original packet contents are returned -std::string -RNBRemote::CompressString (const std::string &orig) -{ - std::string compressed; - compression_types compression_type = GetCompressionType(); - if (compression_type != compression_types::none) - { - bool compress_this_packet = false; +std::string RNBRemote::CompressString(const std::string &orig) { + std::string compressed; + compression_types compression_type = GetCompressionType(); + if (compression_type != compression_types::none) { + bool compress_this_packet = false; - if (orig.size() > m_compression_minsize) - { - compress_this_packet = true; - } + if (orig.size() > m_compression_minsize) { + compress_this_packet = true; + } - if (compress_this_packet) - { - const size_t encoded_data_buf_size = orig.size() + 128; - std::vector<uint8_t> encoded_data (encoded_data_buf_size); - size_t compressed_size = 0; + if (compress_this_packet) { + const size_t encoded_data_buf_size = orig.size() + 128; + std::vector<uint8_t> encoded_data(encoded_data_buf_size); + size_t compressed_size = 0; -#if defined (HAVE_LIBCOMPRESSION) - if (compression_decode_buffer && compression_type == compression_types::lz4) - { - compressed_size = compression_encode_buffer (encoded_data.data(), - encoded_data_buf_size, - (uint8_t*) orig.c_str(), - orig.size(), - nullptr, - COMPRESSION_LZ4_RAW); - } - if (compression_decode_buffer && compression_type == compression_types::zlib_deflate) - { - compressed_size = compression_encode_buffer (encoded_data.data(), - encoded_data_buf_size, - (uint8_t*) orig.c_str(), - orig.size(), - nullptr, - COMPRESSION_ZLIB); - } - if (compression_decode_buffer && compression_type == compression_types::lzma) - { - compressed_size = compression_encode_buffer (encoded_data.data(), - encoded_data_buf_size, - (uint8_t*) orig.c_str(), - orig.size(), - nullptr, - COMPRESSION_LZMA); - } - if (compression_decode_buffer && compression_type == compression_types::lzfse) - { - compressed_size = compression_encode_buffer (encoded_data.data(), - encoded_data_buf_size, - (uint8_t*) orig.c_str(), - orig.size(), - nullptr, - COMPRESSION_LZFSE); - } +#if defined(HAVE_LIBCOMPRESSION) + if (compression_decode_buffer && + compression_type == compression_types::lz4) { + compressed_size = compression_encode_buffer( + encoded_data.data(), encoded_data_buf_size, (uint8_t *)orig.c_str(), + orig.size(), nullptr, COMPRESSION_LZ4_RAW); + } + if (compression_decode_buffer && + compression_type == compression_types::zlib_deflate) { + compressed_size = compression_encode_buffer( + encoded_data.data(), encoded_data_buf_size, (uint8_t *)orig.c_str(), + orig.size(), nullptr, COMPRESSION_ZLIB); + } + if (compression_decode_buffer && + compression_type == compression_types::lzma) { + compressed_size = compression_encode_buffer( + encoded_data.data(), encoded_data_buf_size, (uint8_t *)orig.c_str(), + orig.size(), nullptr, COMPRESSION_LZMA); + } + if (compression_decode_buffer && + compression_type == compression_types::lzfse) { + compressed_size = compression_encode_buffer( + encoded_data.data(), encoded_data_buf_size, (uint8_t *)orig.c_str(), + orig.size(), nullptr, COMPRESSION_LZFSE); + } #endif -#if defined (HAVE_LIBZ) - if (compressed_size == 0 && compression_type == compression_types::zlib_deflate) - { - z_stream stream; - memset (&stream, 0, sizeof (z_stream)); - stream.next_in = (Bytef *) orig.c_str(); - stream.avail_in = (uInt) orig.size(); - stream.next_out = (Bytef *) encoded_data.data(); - stream.avail_out = (uInt) encoded_data_buf_size; - stream.zalloc = Z_NULL; - stream.zfree = Z_NULL; - stream.opaque = Z_NULL; - deflateInit2 (&stream, 5, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); - int compress_status = deflate (&stream, Z_FINISH); - deflateEnd (&stream); - if (compress_status == Z_STREAM_END && stream.total_out > 0) - { - compressed_size = stream.total_out; - } - } +#if defined(HAVE_LIBZ) + if (compressed_size == 0 && + compression_type == compression_types::zlib_deflate) { + z_stream stream; + memset(&stream, 0, sizeof(z_stream)); + stream.next_in = (Bytef *)orig.c_str(); + stream.avail_in = (uInt)orig.size(); + stream.next_out = (Bytef *)encoded_data.data(); + stream.avail_out = (uInt)encoded_data_buf_size; + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.opaque = Z_NULL; + deflateInit2(&stream, 5, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); + int compress_status = deflate(&stream, Z_FINISH); + deflateEnd(&stream); + if (compress_status == Z_STREAM_END && stream.total_out > 0) { + compressed_size = stream.total_out; + } + } #endif - if (compressed_size > 0) - { - compressed.clear (); - compressed.reserve (compressed_size); - compressed = "C"; - char numbuf[16]; - snprintf (numbuf, sizeof (numbuf), "%zu:", orig.size()); - numbuf[sizeof (numbuf) - 1] = '\0'; - compressed.append (numbuf); - - for (size_t i = 0; i < compressed_size; i++) - { - uint8_t byte = encoded_data[i]; - if (byte == '#' || byte == '$' || byte == '}' || byte == '*' || byte == '\0') - { - compressed.push_back (0x7d); - compressed.push_back (byte ^ 0x20); - } - else - { - compressed.push_back (byte); - } - } - } - else - { - compressed = "N" + orig; - } - } - else - { - compressed = "N" + orig; + if (compressed_size > 0) { + compressed.clear(); + compressed.reserve(compressed_size); + compressed = "C"; + char numbuf[16]; + snprintf(numbuf, sizeof(numbuf), "%zu:", orig.size()); + numbuf[sizeof(numbuf) - 1] = '\0'; + compressed.append(numbuf); + + for (size_t i = 0; i < compressed_size; i++) { + uint8_t byte = encoded_data[i]; + if (byte == '#' || byte == '$' || byte == '}' || byte == '*' || + byte == '\0') { + compressed.push_back(0x7d); + compressed.push_back(byte ^ 0x20); + } else { + compressed.push_back(byte); + } } + } else { + compressed = "N" + orig; + } + } else { + compressed = "N" + orig; } - else - { - compressed = orig; - } + } else { + compressed = orig; + } - return compressed; + return compressed; } -rnb_err_t -RNBRemote::SendPacket (const std::string &s) -{ - DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s (%s) called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, s.c_str()); +rnb_err_t RNBRemote::SendPacket(const std::string &s) { + DNBLogThreadedIf(LOG_RNB_MAX, "%8d RNBRemote::%s (%s) called", + (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), + __FUNCTION__, s.c_str()); - std::string s_compressed = CompressString (s); + std::string s_compressed = CompressString(s); - std::string sendpacket = "$" + s_compressed + "#"; - int cksum = 0; - char hexbuf[5]; + std::string sendpacket = "$" + s_compressed + "#"; + int cksum = 0; + char hexbuf[5]; - if (m_noack_mode) - { - sendpacket += "00"; - } - else - { - for (size_t i = 0; i != s_compressed.size(); ++i) - cksum += s_compressed[i]; - snprintf (hexbuf, sizeof hexbuf, "%02x", cksum & 0xff); - sendpacket += hexbuf; - } + if (m_noack_mode) { + sendpacket += "00"; + } else { + for (size_t i = 0; i != s_compressed.size(); ++i) + cksum += s_compressed[i]; + snprintf(hexbuf, sizeof hexbuf, "%02x", cksum & 0xff); + sendpacket += hexbuf; + } - rnb_err_t err = m_comm.Write (sendpacket.c_str(), sendpacket.size()); - if (err != rnb_success) - return err; + rnb_err_t err = m_comm.Write(sendpacket.c_str(), sendpacket.size()); + if (err != rnb_success) + return err; - if (m_noack_mode) - return rnb_success; + if (m_noack_mode) + return rnb_success; - std::string reply; - RNBRemote::Packet packet; - err = GetPacket (reply, packet, true); + std::string reply; + RNBRemote::Packet packet; + err = GetPacket(reply, packet, true); - if (err != rnb_success) - { - DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s (%s) got error trying to get reply...", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, sendpacket.c_str()); - return err; - } + if (err != rnb_success) { + DNBLogThreadedIf(LOG_RNB_REMOTE, + "%8d RNBRemote::%s (%s) got error trying to get reply...", + (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), + __FUNCTION__, sendpacket.c_str()); + return err; + } - DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s (%s) got reply: '%s'", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, sendpacket.c_str(), reply.c_str()); + DNBLogThreadedIf(LOG_RNB_MAX, "%8d RNBRemote::%s (%s) got reply: '%s'", + (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), + __FUNCTION__, sendpacket.c_str(), reply.c_str()); - if (packet.type == ack) - return rnb_success; + if (packet.type == ack) + return rnb_success; - // Should we try to resend the packet at this layer? - // if (packet.command == nack) - return rnb_err; + // Should we try to resend the packet at this layer? + // if (packet.command == nack) + return rnb_err; } /* Get a packet via gdb remote protocol. Strip off the prefix/suffix, verify the checksum to make sure a valid packet was received, send an ACK if they match. */ -rnb_err_t -RNBRemote::GetPacketPayload (std::string &return_packet) -{ - //DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__); - - PThreadMutex::Locker locker(m_mutex); - if (m_rx_packets.empty()) - { - // Only reset the remote command available event if we have no more packets - m_ctx.Events().ResetEvents ( RNBContext::event_read_packet_available ); - //DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s error: no packets available...", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__); - return rnb_err; - } - - //DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s has %u queued packets", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, m_rx_packets.size()); - return_packet.swap(m_rx_packets.front()); - m_rx_packets.pop_front(); - locker.Reset(); // Release our lock on the mutex - - if (m_rx_packets.empty()) - { - // Reset the remote command available event if we have no more packets - m_ctx.Events().ResetEvents ( RNBContext::event_read_packet_available ); - } - - //DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s: '%s'", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, return_packet.c_str()); - - switch (return_packet[0]) - { - case '+': - case '-': - case '\x03': - break; - - case '$': - { - long packet_checksum = 0; - if (!m_noack_mode) - { - for (size_t i = return_packet.size() - 2; i < return_packet.size(); ++i) - { - char checksum_char = tolower (return_packet[i]); - if (!isxdigit (checksum_char)) - { - m_comm.Write ("-", 1); - DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s error: packet with invalid checksum characters: %s", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, return_packet.c_str()); - return rnb_err; - } - } - packet_checksum = strtol (&return_packet[return_packet.size() - 2], NULL, 16); - } - - return_packet.erase(0,1); // Strip the leading '$' - return_packet.erase(return_packet.size() - 3);// Strip the #XX checksum - - if (!m_noack_mode) - { - // Compute the checksum - int computed_checksum = 0; - for (std::string::iterator it = return_packet.begin (); - it != return_packet.end (); - ++it) - { - computed_checksum += *it; - } - - if (packet_checksum == (computed_checksum & 0xff)) - { - //DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s sending ACK for '%s'", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, return_packet.c_str()); - m_comm.Write ("+", 1); - } - else - { - DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s sending ACK for '%s' (error: packet checksum mismatch (0x%2.2lx != 0x%2.2x))", - (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), - __FUNCTION__, - return_packet.c_str(), - packet_checksum, - computed_checksum); - m_comm.Write ("-", 1); - return rnb_err; - } - } +rnb_err_t RNBRemote::GetPacketPayload(std::string &return_packet) { + // DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s called", + // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__); + + PThreadMutex::Locker locker(m_mutex); + if (m_rx_packets.empty()) { + // Only reset the remote command available event if we have no more packets + m_ctx.Events().ResetEvents(RNBContext::event_read_packet_available); + // DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s error: no packets + // available...", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), + // __FUNCTION__); + return rnb_err; + } + + // DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s has %u queued packets", + // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, + // m_rx_packets.size()); + return_packet.swap(m_rx_packets.front()); + m_rx_packets.pop_front(); + locker.Reset(); // Release our lock on the mutex + + if (m_rx_packets.empty()) { + // Reset the remote command available event if we have no more packets + m_ctx.Events().ResetEvents(RNBContext::event_read_packet_available); + } + + // DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s: '%s'", + // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, + // return_packet.c_str()); + + switch (return_packet[0]) { + case '+': + case '-': + case '\x03': + break; + + case '$': { + long packet_checksum = 0; + if (!m_noack_mode) { + for (size_t i = return_packet.size() - 2; i < return_packet.size(); ++i) { + char checksum_char = tolower(return_packet[i]); + if (!isxdigit(checksum_char)) { + m_comm.Write("-", 1); + DNBLogThreadedIf(LOG_RNB_REMOTE, "%8u RNBRemote::%s error: packet " + "with invalid checksum characters: " + "%s", + (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), + __FUNCTION__, return_packet.c_str()); + return rnb_err; } - break; - - default: - DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s tossing unexpected packet???? %s", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, return_packet.c_str()); - if (!m_noack_mode) - m_comm.Write ("-", 1); - return rnb_err; + } + packet_checksum = + strtol(&return_packet[return_packet.size() - 2], NULL, 16); } - return rnb_success; -} - -rnb_err_t -RNBRemote::HandlePacket_UNIMPLEMENTED (const char* p) -{ - DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s(\"%s\")", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p ? p : "NULL"); - return SendPacket (""); -} + return_packet.erase(0, 1); // Strip the leading '$' + return_packet.erase(return_packet.size() - 3); // Strip the #XX checksum -rnb_err_t -RNBRemote::HandlePacket_ILLFORMED (const char *file, int line, const char *p, const char *description) -{ - DNBLogThreadedIf (LOG_RNB_PACKETS, "%8u %s:%i ILLFORMED: '%s' (%s)", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), file, line, __FUNCTION__, p); - return SendPacket ("E03"); -} - -rnb_err_t -RNBRemote::GetPacket (std::string &packet_payload, RNBRemote::Packet& packet_info, bool wait) -{ - std::string payload; - rnb_err_t err = GetPacketPayload (payload); - if (err != rnb_success) - { - PThreadEvent& events = m_ctx.Events(); - nub_event_t set_events = events.GetEventBits(); - // TODO: add timeout version of GetPacket?? We would then need to pass - // that timeout value along to DNBProcessTimedWaitForEvent. - if (!wait || ((set_events & RNBContext::event_read_thread_running) == 0)) - return err; - - const nub_event_t events_to_wait_for = RNBContext::event_read_packet_available | RNBContext::event_read_thread_exiting; - - while ((set_events = events.WaitForSetEvents(events_to_wait_for)) != 0) - { - if (set_events & RNBContext::event_read_packet_available) - { - // Try the queue again now that we got an event - err = GetPacketPayload (payload); - if (err == rnb_success) - break; - } - - if (set_events & RNBContext::event_read_thread_exiting) - err = rnb_not_connected; - - if (err == rnb_not_connected) - return err; - - } while (err == rnb_err); + if (!m_noack_mode) { + // Compute the checksum + int computed_checksum = 0; + for (std::string::iterator it = return_packet.begin(); + it != return_packet.end(); ++it) { + computed_checksum += *it; + } - if (set_events == 0) - err = rnb_not_connected; + if (packet_checksum == (computed_checksum & 0xff)) { + // DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s sending ACK for + // '%s'", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), + // __FUNCTION__, return_packet.c_str()); + m_comm.Write("+", 1); + } else { + DNBLogThreadedIf( + LOG_RNB_MEDIUM, "%8u RNBRemote::%s sending ACK for '%s' (error: " + "packet checksum mismatch (0x%2.2lx != 0x%2.2x))", + (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, + return_packet.c_str(), packet_checksum, computed_checksum); + m_comm.Write("-", 1); + return rnb_err; + } } + } break; - if (err == rnb_success) - { - Packet::iterator it; - for (it = m_packets.begin (); it != m_packets.end (); ++it) - { - if (payload.compare (0, it->abbrev.size(), it->abbrev) == 0) - break; - } - - // A packet we don't have an entry for. This can happen when we - // get a packet that we don't know about or support. We just reply - // accordingly and go on. - if (it == m_packets.end ()) - { - DNBLogThreadedIf (LOG_RNB_PACKETS, "unimplemented packet: '%s'", payload.c_str()); - HandlePacket_UNIMPLEMENTED(payload.c_str()); - return rnb_err; - } - else - { - packet_info = *it; - packet_payload = payload; - } - } - return err; -} + default: + DNBLogThreadedIf(LOG_RNB_REMOTE, + "%8u RNBRemote::%s tossing unexpected packet???? %s", + (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), + __FUNCTION__, return_packet.c_str()); + if (!m_noack_mode) + m_comm.Write("-", 1); + return rnb_err; + } + + return rnb_success; +} + +rnb_err_t RNBRemote::HandlePacket_UNIMPLEMENTED(const char *p) { + DNBLogThreadedIf(LOG_RNB_MAX, "%8u RNBRemote::%s(\"%s\")", + (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), + __FUNCTION__, p ? p : "NULL"); + return SendPacket(""); +} + +rnb_err_t RNBRemote::HandlePacket_ILLFORMED(const char *file, int line, + const char *p, + const char *description) { + DNBLogThreadedIf(LOG_RNB_PACKETS, "%8u %s:%i ILLFORMED: '%s' (%s)", + (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), file, + line, __FUNCTION__, p); + return SendPacket("E03"); +} + +rnb_err_t RNBRemote::GetPacket(std::string &packet_payload, + RNBRemote::Packet &packet_info, bool wait) { + std::string payload; + rnb_err_t err = GetPacketPayload(payload); + if (err != rnb_success) { + PThreadEvent &events = m_ctx.Events(); + nub_event_t set_events = events.GetEventBits(); + // TODO: add timeout version of GetPacket?? We would then need to pass + // that timeout value along to DNBProcessTimedWaitForEvent. + if (!wait || ((set_events & RNBContext::event_read_thread_running) == 0)) + return err; + + const nub_event_t events_to_wait_for = + RNBContext::event_read_packet_available | + RNBContext::event_read_thread_exiting; + + while ((set_events = events.WaitForSetEvents(events_to_wait_for)) != 0) { + if (set_events & RNBContext::event_read_packet_available) { + // Try the queue again now that we got an event + err = GetPacketPayload(payload); + if (err == rnb_success) + break; + } -rnb_err_t -RNBRemote::HandleAsyncPacket(PacketEnum *type) -{ - DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__); - static DNBTimer g_packetTimer(true); - rnb_err_t err = rnb_err; - std::string packet_data; - RNBRemote::Packet packet_info; - err = GetPacket (packet_data, packet_info, false); - - if (err == rnb_success) - { - if (!packet_data.empty() && isprint(packet_data[0])) - DNBLogThreadedIf (LOG_RNB_REMOTE | LOG_RNB_PACKETS, "HandleAsyncPacket (\"%s\");", packet_data.c_str()); - else - DNBLogThreadedIf (LOG_RNB_REMOTE | LOG_RNB_PACKETS, "HandleAsyncPacket (%s);", packet_info.printable_name.c_str()); + if (set_events & RNBContext::event_read_thread_exiting) + err = rnb_not_connected; - HandlePacketCallback packet_callback = packet_info.async; - if (packet_callback != NULL) - { - if (type != NULL) - *type = packet_info.type; - return (this->*packet_callback)(packet_data.c_str()); - } + if (err == rnb_not_connected) + return err; } + while (err == rnb_err) + ; - return err; -} + if (set_events == 0) + err = rnb_not_connected; + } -rnb_err_t -RNBRemote::HandleReceivedPacket(PacketEnum *type) -{ - static DNBTimer g_packetTimer(true); - - // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__); - rnb_err_t err = rnb_err; - std::string packet_data; - RNBRemote::Packet packet_info; - err = GetPacket (packet_data, packet_info, false); - - if (err == rnb_success) - { - DNBLogThreadedIf (LOG_RNB_REMOTE, "HandleReceivedPacket (\"%s\");", packet_data.c_str()); - HandlePacketCallback packet_callback = packet_info.normal; - if (packet_callback != NULL) - { - if (type != NULL) - *type = packet_info.type; - return (this->*packet_callback)(packet_data.c_str()); - } - else - { - // Do not fall through to end of this function, if we have valid - // packet_info and it has a NULL callback, then we need to respect - // that it may not want any response or anything to be done. - return err; - } + if (err == rnb_success) { + Packet::iterator it; + for (it = m_packets.begin(); it != m_packets.end(); ++it) { + if (payload.compare(0, it->abbrev.size(), it->abbrev) == 0) + break; } - return rnb_err; -} -void -RNBRemote::CommDataReceived(const std::string& new_data) -{ - // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__); - { - // Put the packet data into the buffer in a thread safe fashion - PThreadMutex::Locker locker(m_mutex); - - std::string data; - // See if we have any left over data from a previous call to this - // function? - if (!m_rx_partial_data.empty()) - { - // We do, so lets start with that data - data.swap(m_rx_partial_data); - } - // Append the new incoming data - data += new_data; - - // Parse up the packets into gdb remote packets - size_t idx = 0; - const size_t data_size = data.size(); - - while (idx < data_size) - { - // end_idx must be one past the last valid packet byte. Start - // it off with an invalid value that is the same as the current - // index. - size_t end_idx = idx; + // A packet we don't have an entry for. This can happen when we + // get a packet that we don't know about or support. We just reply + // accordingly and go on. + if (it == m_packets.end()) { + DNBLogThreadedIf(LOG_RNB_PACKETS, "unimplemented packet: '%s'", + payload.c_str()); + HandlePacket_UNIMPLEMENTED(payload.c_str()); + return rnb_err; + } else { + packet_info = *it; + packet_payload = payload; + } + } + return err; +} + +rnb_err_t RNBRemote::HandleAsyncPacket(PacketEnum *type) { + DNBLogThreadedIf(LOG_RNB_REMOTE, "%8u RNBRemote::%s", + (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), + __FUNCTION__); + static DNBTimer g_packetTimer(true); + rnb_err_t err = rnb_err; + std::string packet_data; + RNBRemote::Packet packet_info; + err = GetPacket(packet_data, packet_info, false); + + if (err == rnb_success) { + if (!packet_data.empty() && isprint(packet_data[0])) + DNBLogThreadedIf(LOG_RNB_REMOTE | LOG_RNB_PACKETS, + "HandleAsyncPacket (\"%s\");", packet_data.c_str()); + else + DNBLogThreadedIf(LOG_RNB_REMOTE | LOG_RNB_PACKETS, + "HandleAsyncPacket (%s);", + packet_info.printable_name.c_str()); + + HandlePacketCallback packet_callback = packet_info.async; + if (packet_callback != NULL) { + if (type != NULL) + *type = packet_info.type; + return (this->*packet_callback)(packet_data.c_str()); + } + } + + return err; +} + +rnb_err_t RNBRemote::HandleReceivedPacket(PacketEnum *type) { + static DNBTimer g_packetTimer(true); + + // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s", + // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__); + rnb_err_t err = rnb_err; + std::string packet_data; + RNBRemote::Packet packet_info; + err = GetPacket(packet_data, packet_info, false); + + if (err == rnb_success) { + DNBLogThreadedIf(LOG_RNB_REMOTE, "HandleReceivedPacket (\"%s\");", + packet_data.c_str()); + HandlePacketCallback packet_callback = packet_info.normal; + if (packet_callback != NULL) { + if (type != NULL) + *type = packet_info.type; + return (this->*packet_callback)(packet_data.c_str()); + } else { + // Do not fall through to end of this function, if we have valid + // packet_info and it has a NULL callback, then we need to respect + // that it may not want any response or anything to be done. + return err; + } + } + return rnb_err; +} + +void RNBRemote::CommDataReceived(const std::string &new_data) { + // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s called", + // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__); + { + // Put the packet data into the buffer in a thread safe fashion + PThreadMutex::Locker locker(m_mutex); - switch (data[idx]) - { - case '+': // Look for ack - case '-': // Look for cancel - case '\x03': // ^C to halt target - end_idx = idx + 1; // The command is one byte long... - break; - - case '$': - // Look for a standard gdb packet? - end_idx = data.find('#', idx + 1); - if (end_idx == std::string::npos || end_idx + 3 > data_size) - { - end_idx = std::string::npos; - } - else - { - // Add two for the checksum bytes and 1 to point to the - // byte just past the end of this packet - end_idx += 3; - } - break; - - default: - break; - } + std::string data; + // See if we have any left over data from a previous call to this + // function? + if (!m_rx_partial_data.empty()) { + // We do, so lets start with that data + data.swap(m_rx_partial_data); + } + // Append the new incoming data + data += new_data; + + // Parse up the packets into gdb remote packets + size_t idx = 0; + const size_t data_size = data.size(); + + while (idx < data_size) { + // end_idx must be one past the last valid packet byte. Start + // it off with an invalid value that is the same as the current + // index. + size_t end_idx = idx; + + switch (data[idx]) { + case '+': // Look for ack + case '-': // Look for cancel + case '\x03': // ^C to halt target + end_idx = idx + 1; // The command is one byte long... + break; - if (end_idx == std::string::npos) - { - // Not all data may be here for the packet yet, save it for - // next time through this function. - m_rx_partial_data += data.substr(idx); - //DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s saving data for later[%u, npos): '%s'",(uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, idx, m_rx_partial_data.c_str()); - idx = end_idx; - } - else - if (idx < end_idx) - { - m_packets_recvd++; - // Hack to get rid of initial '+' ACK??? - if (m_packets_recvd == 1 && (end_idx == idx + 1) && data[idx] == '+') - { - //DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s throwing first ACK away....[%u, npos): '+'",(uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, idx); - } - else - { - // We have a valid packet... - m_rx_packets.push_back(data.substr(idx, end_idx - idx)); - DNBLogThreadedIf (LOG_RNB_PACKETS, "getpkt: %s", m_rx_packets.back().c_str()); - } - idx = end_idx; - } - else - { - DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s tossing junk byte at %c",(uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, data[idx]); - idx = idx + 1; - } + case '$': + // Look for a standard gdb packet? + end_idx = data.find('#', idx + 1); + if (end_idx == std::string::npos || end_idx + 3 > data_size) { + end_idx = std::string::npos; + } else { + // Add two for the checksum bytes and 1 to point to the + // byte just past the end of this packet + end_idx += 3; } - } - - if (!m_rx_packets.empty()) - { - // Let the main thread know we have received a packet - - //DNBLogThreadedIf (LOG_RNB_EVENTS, "%8d RNBRemote::%s called events.SetEvent(RNBContext::event_read_packet_available)", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__); - PThreadEvent& events = m_ctx.Events(); - events.SetEvents (RNBContext::event_read_packet_available); - } -} + break; -rnb_err_t -RNBRemote::GetCommData () -{ - // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__); - std::string comm_data; - rnb_err_t err = m_comm.Read (comm_data); - if (err == rnb_success) - { - if (!comm_data.empty()) - CommDataReceived (comm_data); - } - return err; -} + default: + break; + } -void -RNBRemote::StartReadRemoteDataThread() -{ - DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__); - PThreadEvent& events = m_ctx.Events(); - if ((events.GetEventBits() & RNBContext::event_read_thread_running) == 0) - { - events.ResetEvents (RNBContext::event_read_thread_exiting); - int err = ::pthread_create (&m_rx_pthread, NULL, ThreadFunctionReadRemoteData, this); - if (err == 0) - { - // Our thread was successfully kicked off, wait for it to - // set the started event so we can safely continue - events.WaitForSetEvents (RNBContext::event_read_thread_running); - } - else - { - events.ResetEvents (RNBContext::event_read_thread_running); - events.SetEvents (RNBContext::event_read_thread_exiting); + if (end_idx == std::string::npos) { + // Not all data may be here for the packet yet, save it for + // next time through this function. + m_rx_partial_data += data.substr(idx); + // DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s saving data for + // later[%u, npos): + // '%s'",(uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), + // __FUNCTION__, idx, m_rx_partial_data.c_str()); + idx = end_idx; + } else if (idx < end_idx) { + m_packets_recvd++; + // Hack to get rid of initial '+' ACK??? + if (m_packets_recvd == 1 && (end_idx == idx + 1) && data[idx] == '+') { + // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s throwing first + // ACK away....[%u, npos): + // '+'",(uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), + // __FUNCTION__, idx); + } else { + // We have a valid packet... + m_rx_packets.push_back(data.substr(idx, end_idx - idx)); + DNBLogThreadedIf(LOG_RNB_PACKETS, "getpkt: %s", + m_rx_packets.back().c_str()); } + idx = end_idx; + } else { + DNBLogThreadedIf(LOG_RNB_MAX, + "%8d RNBRemote::%s tossing junk byte at %c", + (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), + __FUNCTION__, data[idx]); + idx = idx + 1; + } } -} - -void -RNBRemote::StopReadRemoteDataThread() -{ - DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__); - PThreadEvent& events = m_ctx.Events(); - if ((events.GetEventBits() & RNBContext::event_read_thread_running) == RNBContext::event_read_thread_running) - { - m_comm.Disconnect(true); - struct timespec timeout_abstime; - DNBTimer::OffsetTimeOfDay(&timeout_abstime, 2, 0); - - // Wait for 2 seconds for the remote data thread to exit - if (events.WaitForSetEvents(RNBContext::event_read_thread_exiting, &timeout_abstime) == 0) - { - // Kill the remote data thread??? - } + } + + if (!m_rx_packets.empty()) { + // Let the main thread know we have received a packet + + // DNBLogThreadedIf (LOG_RNB_EVENTS, "%8d RNBRemote::%s called + // events.SetEvent(RNBContext::event_read_packet_available)", + // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__); + PThreadEvent &events = m_ctx.Events(); + events.SetEvents(RNBContext::event_read_packet_available); + } +} + +rnb_err_t RNBRemote::GetCommData() { + // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s called", + // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__); + std::string comm_data; + rnb_err_t err = m_comm.Read(comm_data); + if (err == rnb_success) { + if (!comm_data.empty()) + CommDataReceived(comm_data); + } + return err; +} + +void RNBRemote::StartReadRemoteDataThread() { + DNBLogThreadedIf(LOG_RNB_REMOTE, "%8u RNBRemote::%s called", + (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), + __FUNCTION__); + PThreadEvent &events = m_ctx.Events(); + if ((events.GetEventBits() & RNBContext::event_read_thread_running) == 0) { + events.ResetEvents(RNBContext::event_read_thread_exiting); + int err = ::pthread_create(&m_rx_pthread, NULL, + ThreadFunctionReadRemoteData, this); + if (err == 0) { + // Our thread was successfully kicked off, wait for it to + // set the started event so we can safely continue + events.WaitForSetEvents(RNBContext::event_read_thread_running); + } else { + events.ResetEvents(RNBContext::event_read_thread_running); + events.SetEvents(RNBContext::event_read_thread_exiting); + } + } +} + +void RNBRemote::StopReadRemoteDataThread() { + DNBLogThreadedIf(LOG_RNB_REMOTE, "%8u RNBRemote::%s called", + (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), + __FUNCTION__); + PThreadEvent &events = m_ctx.Events(); + if ((events.GetEventBits() & RNBContext::event_read_thread_running) == + RNBContext::event_read_thread_running) { + m_comm.Disconnect(true); + struct timespec timeout_abstime; + DNBTimer::OffsetTimeOfDay(&timeout_abstime, 2, 0); + + // Wait for 2 seconds for the remote data thread to exit + if (events.WaitForSetEvents(RNBContext::event_read_thread_exiting, + &timeout_abstime) == 0) { + // Kill the remote data thread??? + } + } +} + +void *RNBRemote::ThreadFunctionReadRemoteData(void *arg) { + // Keep a shared pointer reference so this doesn't go away on us before the + // thread is killed. + DNBLogThreadedIf(LOG_RNB_REMOTE, "RNBRemote::%s (%p): thread starting...", + __FUNCTION__, arg); + RNBRemoteSP remoteSP(g_remoteSP); + if (remoteSP.get() != NULL) { + +#if defined(__APPLE__) + pthread_setname_np("read gdb-remote packets 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* -RNBRemote::ThreadFunctionReadRemoteData(void *arg) -{ - // Keep a shared pointer reference so this doesn't go away on us before the thread is killed. - DNBLogThreadedIf(LOG_RNB_REMOTE, "RNBRemote::%s (%p): thread starting...", __FUNCTION__, arg); - RNBRemoteSP remoteSP(g_remoteSP); - if (remoteSP.get() != NULL) - { - -#if defined (__APPLE__) - pthread_setname_np ("read gdb-remote packets 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 - RNBRemote* remote = remoteSP.get(); - PThreadEvent& events = remote->Context().Events(); - events.SetEvents (RNBContext::event_read_thread_running); - // START: main receive remote command thread loop - bool done = false; - while (!done) - { - rnb_err_t err = remote->GetCommData(); + RNBRemote *remote = remoteSP.get(); + PThreadEvent &events = remote->Context().Events(); + events.SetEvents(RNBContext::event_read_thread_running); + // START: main receive remote command thread loop + bool done = false; + while (!done) { + rnb_err_t err = remote->GetCommData(); - switch (err) - { - case rnb_success: - break; - - case rnb_err: - DNBLogThreadedIf (LOG_RNB_REMOTE, "RNBSocket::GetCommData returned error %u", err); - done = true; - break; - - case rnb_not_connected: - DNBLogThreadedIf (LOG_RNB_REMOTE, "RNBSocket::GetCommData returned not connected..."); - done = true; - break; - } - } - // START: main receive remote command thread loop - events.ResetEvents (RNBContext::event_read_thread_running); - events.SetEvents (RNBContext::event_read_thread_exiting); + switch (err) { + case rnb_success: + break; + + case rnb_err: + DNBLogThreadedIf(LOG_RNB_REMOTE, + "RNBSocket::GetCommData returned error %u", err); + done = true; + break; + + case rnb_not_connected: + DNBLogThreadedIf(LOG_RNB_REMOTE, + "RNBSocket::GetCommData returned not connected..."); + done = true; + break; + } } - DNBLogThreadedIf(LOG_RNB_REMOTE, "RNBRemote::%s (%p): thread exiting...", __FUNCTION__, arg); - return NULL; + // START: main receive remote command thread loop + events.ResetEvents(RNBContext::event_read_thread_running); + events.SetEvents(RNBContext::event_read_thread_exiting); + } + DNBLogThreadedIf(LOG_RNB_REMOTE, "RNBRemote::%s (%p): thread exiting...", + __FUNCTION__, arg); + return NULL; } - // If we fail to get back a valid CPU type for the remote process, // make a best guess for the CPU type based on the currently running // debugserver binary -- the debugger may not handle the case of an // un-specified process CPU type correctly. -static cpu_type_t -best_guess_cpu_type () -{ -#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) - if (sizeof (char *) == 8) - { - return CPU_TYPE_ARM64; - } - else - { - return CPU_TYPE_ARM; - } -#elif defined (__i386__) || defined (__x86_64__) - if (sizeof (char*) == 8) - { - return CPU_TYPE_X86_64; - } - else - { - return CPU_TYPE_I386; - } +static cpu_type_t best_guess_cpu_type() { +#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) + if (sizeof(char *) == 8) { + return CPU_TYPE_ARM64; + } else { + return CPU_TYPE_ARM; + } +#elif defined(__i386__) || defined(__x86_64__) + if (sizeof(char *) == 8) { + return CPU_TYPE_X86_64; + } else { + return CPU_TYPE_I386; + } #endif - return 0; + return 0; } - /* Read the bytes in STR which are GDB Remote Protocol binary encoded bytes (8-bit bytes). - This encoding uses 0x7d ('}') as an escape character for + This encoding uses 0x7d ('}') as an escape character for 0x7d ('}'), 0x23 ('#'), 0x24 ('$'), 0x2a ('*'). LEN is the number of bytes to be processed. If a character is escaped, it is 2 characters for LEN. A LEN of -1 means decode-until-nul-byte (end of string). */ -std::vector<uint8_t> -decode_binary_data (const char *str, size_t len) -{ - std::vector<uint8_t> bytes; - if (len == 0) - { - return bytes; - } - if (len == (size_t)-1) - len = strlen (str); +std::vector<uint8_t> decode_binary_data(const char *str, size_t len) { + std::vector<uint8_t> bytes; + if (len == 0) { + return bytes; + } + if (len == (size_t)-1) + len = strlen(str); - while (len--) - { - unsigned char c = *str++; - if (c == 0x7d && len > 0) - { - len--; - c = *str++ ^ 0x20; - } - bytes.push_back (c); + while (len--) { + unsigned char c = *str++; + if (c == 0x7d && len > 0) { + len--; + c = *str++ ^ 0x20; } - return bytes; + bytes.push_back(c); + } + return bytes; } // Quote any meta characters in a std::string as per the binary // packet convention in the gdb-remote protocol. -static std::string -binary_encode_string (const std::string &s) -{ - std::string output; - const size_t s_size = s.size(); - const char *s_chars = s.c_str(); +static std::string binary_encode_string(const std::string &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 == '#' || ch == '$' || ch == '}' || ch == '*') - { - output.push_back ('}'); // 0x7d - output.push_back (ch ^ 0x20); - } - else - { - output.push_back (ch); - } + for (size_t i = 0; i < s_size; i++) { + unsigned char ch = *(s_chars + i); + if (ch == '#' || ch == '$' || ch == '}' || ch == '*') { + output.push_back('}'); // 0x7d + output.push_back(ch ^ 0x20); + } else { + output.push_back(ch); } - return output; + } + return output; } // If the value side of a key-value pair in JSON is a string, // and that string has a " character in it, the " character must // be escaped. -std::string -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; -} - -typedef struct register_map_entry -{ - uint32_t debugserver_regnum; // debugserver register number - uint32_t offset; // Offset in bytes into the register context data with no padding between register values - DNBRegisterInfo nub_info; // debugnub register info - std::vector<uint32_t> value_regnums; - std::vector<uint32_t> invalidate_regnums; +std::string 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; +} + +typedef struct register_map_entry { + uint32_t debugserver_regnum; // debugserver register number + uint32_t offset; // Offset in bytes into the register context data with no + // padding between register values + DNBRegisterInfo nub_info; // debugnub register info + std::vector<uint32_t> value_regnums; + std::vector<uint32_t> invalidate_regnums; } register_map_entry_t; - - // If the notion of registers differs from what is handed out by the // architecture, then flavors can be defined here. @@ -1292,148 +1381,130 @@ static std::vector<register_map_entry_t> g_dynamic_register_map; static register_map_entry_t *g_reg_entries = NULL; static size_t g_num_reg_entries = 0; -void -RNBRemote::Initialize() -{ - DNBInitialize(); -} - - -bool -RNBRemote::InitializeRegisters (bool force) -{ - pid_t pid = m_ctx.ProcessID(); - if (pid == INVALID_NUB_PROCESS) - return false; +void RNBRemote::Initialize() { DNBInitialize(); } - DNBLogThreadedIf (LOG_RNB_PROC, "RNBRemote::%s() getting native registers from DNB interface", __FUNCTION__); - // Discover the registers by querying the DNB interface and letting it - // state the registers that it would like to export. This allows the - // registers to be discovered using multiple qRegisterInfo calls to get - // all register information after the architecture for the process is - // determined. - if (force) - { - g_dynamic_register_map.clear(); - g_reg_entries = NULL; - g_num_reg_entries = 0; - } - - if (g_dynamic_register_map.empty()) - { - nub_size_t num_reg_sets = 0; - const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo (&num_reg_sets); - - assert (num_reg_sets > 0 && reg_sets != NULL); +bool RNBRemote::InitializeRegisters(bool force) { + pid_t pid = m_ctx.ProcessID(); + if (pid == INVALID_NUB_PROCESS) + return false; - uint32_t regnum = 0; - uint32_t reg_data_offset = 0; - typedef std::map<std::string, uint32_t> NameToRegNum; - NameToRegNum name_to_regnum; - for (nub_size_t set = 0; set < num_reg_sets; ++set) - { - if (reg_sets[set].registers == NULL) - continue; + DNBLogThreadedIf( + LOG_RNB_PROC, + "RNBRemote::%s() getting native registers from DNB interface", + __FUNCTION__); + // Discover the registers by querying the DNB interface and letting it + // state the registers that it would like to export. This allows the + // registers to be discovered using multiple qRegisterInfo calls to get + // all register information after the architecture for the process is + // determined. + if (force) { + g_dynamic_register_map.clear(); + g_reg_entries = NULL; + g_num_reg_entries = 0; + } + + if (g_dynamic_register_map.empty()) { + nub_size_t num_reg_sets = 0; + const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo(&num_reg_sets); + + assert(num_reg_sets > 0 && reg_sets != NULL); + + uint32_t regnum = 0; + uint32_t reg_data_offset = 0; + typedef std::map<std::string, uint32_t> NameToRegNum; + NameToRegNum name_to_regnum; + for (nub_size_t set = 0; set < num_reg_sets; ++set) { + if (reg_sets[set].registers == NULL) + continue; + + for (uint32_t reg = 0; reg < reg_sets[set].num_registers; ++reg) { + register_map_entry_t reg_entry = { + regnum++, // register number starts at zero and goes up with no gaps + reg_data_offset, // Offset into register context data, no gaps + // between registers + reg_sets[set].registers[reg], // DNBRegisterInfo + {}, + {}, + }; - for (uint32_t reg=0; reg < reg_sets[set].num_registers; ++reg) - { - register_map_entry_t reg_entry = { - regnum++, // register number starts at zero and goes up with no gaps - reg_data_offset, // Offset into register context data, no gaps between registers - reg_sets[set].registers[reg], // DNBRegisterInfo - {}, - {}, - }; + name_to_regnum[reg_entry.nub_info.name] = reg_entry.debugserver_regnum; - name_to_regnum[reg_entry.nub_info.name] = reg_entry.debugserver_regnum; + if (reg_entry.nub_info.value_regs == NULL) { + reg_data_offset += reg_entry.nub_info.size; + } - if (reg_entry.nub_info.value_regs == NULL) - { - reg_data_offset += reg_entry.nub_info.size; - } + g_dynamic_register_map.push_back(reg_entry); + } + } - g_dynamic_register_map.push_back (reg_entry); + // Now we must find any registers whose values are in other registers and + // fix up + // the offsets since we removed all gaps... + for (auto ®_entry : g_dynamic_register_map) { + if (reg_entry.nub_info.value_regs) { + uint32_t new_offset = UINT32_MAX; + for (size_t i = 0; reg_entry.nub_info.value_regs[i] != NULL; ++i) { + const char *name = reg_entry.nub_info.value_regs[i]; + auto pos = name_to_regnum.find(name); + if (pos != name_to_regnum.end()) { + regnum = pos->second; + reg_entry.value_regnums.push_back(regnum); + if (regnum < g_dynamic_register_map.size()) { + // The offset for value_regs registers is the offset within the + // register with the lowest offset + const uint32_t reg_offset = + g_dynamic_register_map[regnum].offset + + reg_entry.nub_info.offset; + if (new_offset > reg_offset) + new_offset = reg_offset; } + } } - - // Now we must find any registers whose values are in other registers and fix up - // the offsets since we removed all gaps... - for (auto ®_entry: g_dynamic_register_map) - { - if (reg_entry.nub_info.value_regs) - { - uint32_t new_offset = UINT32_MAX; - for (size_t i=0; reg_entry.nub_info.value_regs[i] != NULL; ++i) - { - const char *name = reg_entry.nub_info.value_regs[i]; - auto pos = name_to_regnum.find(name); - if (pos != name_to_regnum.end()) - { - regnum = pos->second; - reg_entry.value_regnums.push_back(regnum); - if (regnum < g_dynamic_register_map.size()) - { - // The offset for value_regs registers is the offset within the register with the lowest offset - const uint32_t reg_offset = g_dynamic_register_map[regnum].offset + reg_entry.nub_info.offset; - if (new_offset > reg_offset) - new_offset = reg_offset; - } - } - } - - if (new_offset != UINT32_MAX) - { - reg_entry.offset = new_offset; - } - else - { - DNBLogThreaded("no offset was calculated entry for register %s", reg_entry.nub_info.name); - reg_entry.offset = UINT32_MAX; - } - } - if (reg_entry.nub_info.update_regs) - { - for (size_t i=0; reg_entry.nub_info.update_regs[i] != NULL; ++i) - { - const char *name = reg_entry.nub_info.update_regs[i]; - auto pos = name_to_regnum.find(name); - if (pos != name_to_regnum.end()) - { - regnum = pos->second; - reg_entry.invalidate_regnums.push_back(regnum); - } - } - } + if (new_offset != UINT32_MAX) { + reg_entry.offset = new_offset; + } else { + DNBLogThreaded("no offset was calculated entry for register %s", + reg_entry.nub_info.name); + reg_entry.offset = UINT32_MAX; } - - -// for (auto ®_entry: g_dynamic_register_map) -// { -// DNBLogThreaded("%4i: size = %3u, pseudo = %i, name = %s", -// reg_entry.offset, -// reg_entry.nub_info.size, -// reg_entry.nub_info.value_regs != NULL, -// reg_entry.nub_info.name); -// } - - g_reg_entries = g_dynamic_register_map.data(); - g_num_reg_entries = g_dynamic_register_map.size(); + } + + if (reg_entry.nub_info.update_regs) { + for (size_t i = 0; reg_entry.nub_info.update_regs[i] != NULL; ++i) { + const char *name = reg_entry.nub_info.update_regs[i]; + auto pos = name_to_regnum.find(name); + if (pos != name_to_regnum.end()) { + regnum = pos->second; + reg_entry.invalidate_regnums.push_back(regnum); + } + } + } } - return true; + + // for (auto ®_entry: g_dynamic_register_map) + // { + // DNBLogThreaded("%4i: size = %3u, pseudo = %i, name = %s", + // reg_entry.offset, + // reg_entry.nub_info.size, + // reg_entry.nub_info.value_regs != NULL, + // reg_entry.nub_info.name); + // } + + g_reg_entries = g_dynamic_register_map.data(); + g_num_reg_entries = g_dynamic_register_map.size(); + } + return true; } /* The inferior has stopped executing; send a packet to gdb to let it know. */ -void -RNBRemote::NotifyThatProcessStopped (void) -{ - RNBRemote::HandlePacket_last_signal (NULL); - return; +void RNBRemote::NotifyThatProcessStopped(void) { + RNBRemote::HandlePacket_last_signal(NULL); + return; } - /* 'A arglen,argnum,arg,...' Update the inferior context CTX with the program name and arg list. @@ -1450,534 +1521,524 @@ RNBRemote::NotifyThatProcessStopped (void) Note that "argnum" and "arglen" are numbers in base 10. Again, that's not documented either way but I'm assuming it's so. */ -rnb_err_t -RNBRemote::HandlePacket_A (const char *p) -{ - if (p == NULL || *p == '\0') - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Null packet for 'A' pkt"); +rnb_err_t RNBRemote::HandlePacket_A(const char *p) { + if (p == NULL || *p == '\0') { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Null packet for 'A' pkt"); + } + p++; + if (*p == '\0' || !isdigit(*p)) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "arglen not specified on 'A' pkt"); + } + + /* I promise I don't modify it anywhere in this function. strtoul()'s + 2nd arg has to be non-const which makes it problematic to step + through the string easily. */ + char *buf = const_cast<char *>(p); + + RNBContext &ctx = Context(); + + while (*buf != '\0') { + unsigned long arglen, argnum; + std::string arg; + char *c; + + errno = 0; + arglen = strtoul(buf, &c, 10); + if (errno != 0 && arglen == 0) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "arglen not a number on 'A' pkt"); } - p++; - if (*p == '\0' || !isdigit (*p)) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not specified on 'A' pkt"); + if (*c != ',') { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "arglen not followed by comma on 'A' pkt"); } + buf = c + 1; - /* I promise I don't modify it anywhere in this function. strtoul()'s - 2nd arg has to be non-const which makes it problematic to step - through the string easily. */ - char *buf = const_cast<char *>(p); - - RNBContext& ctx = Context(); - - while (*buf != '\0') - { - unsigned long arglen, argnum; - std::string arg; - char *c; - - errno = 0; - arglen = strtoul (buf, &c, 10); - if (errno != 0 && arglen == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not a number on 'A' pkt"); - } - if (*c != ',') - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not followed by comma on 'A' pkt"); - } - buf = c + 1; - - errno = 0; - argnum = strtoul (buf, &c, 10); - if (errno != 0 && argnum == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "argnum not a number on 'A' pkt"); - } - if (*c != ',') - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not followed by comma on 'A' pkt"); - } - buf = c + 1; - - c = buf; - buf = buf + arglen; - while (c < buf && *c != '\0' && c + 1 < buf && *(c + 1) != '\0') - { - char smallbuf[3]; - smallbuf[0] = *c; - smallbuf[1] = *(c + 1); - smallbuf[2] = '\0'; - - errno = 0; - int ch = static_cast<int>(strtoul (smallbuf, NULL, 16)); - if (errno != 0 && ch == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'A' pkt"); - } - - arg.push_back(ch); - c += 2; - } + errno = 0; + argnum = strtoul(buf, &c, 10); + if (errno != 0 && argnum == 0) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "argnum not a number on 'A' pkt"); + } + if (*c != ',') { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "arglen not followed by comma on 'A' pkt"); + } + buf = c + 1; + + c = buf; + buf = buf + arglen; + while (c < buf && *c != '\0' && c + 1 < buf && *(c + 1) != '\0') { + char smallbuf[3]; + smallbuf[0] = *c; + smallbuf[1] = *(c + 1); + smallbuf[2] = '\0'; + + errno = 0; + int ch = static_cast<int>(strtoul(smallbuf, NULL, 16)); + if (errno != 0 && ch == 0) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "non-hex char in arg on 'A' pkt"); + } - ctx.PushArgument (arg.c_str()); - if (*buf == ',') - buf++; + arg.push_back(ch); + c += 2; } - SendPacket ("OK"); - return rnb_success; + ctx.PushArgument(arg.c_str()); + if (*buf == ',') + buf++; + } + SendPacket("OK"); + + return rnb_success; } /* 'H c t' Set the thread for subsequent actions; 'c' for step/continue ops, 'g' for other ops. -1 means all threads, 0 means any thread. */ -rnb_err_t -RNBRemote::HandlePacket_H (const char *p) -{ - p++; // skip 'H' - if (*p != 'c' && *p != 'g') - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Missing 'c' or 'g' type in H packet"); - } +rnb_err_t RNBRemote::HandlePacket_H(const char *p) { + p++; // skip 'H' + if (*p != 'c' && *p != 'g') { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Missing 'c' or 'g' type in H packet"); + } - if (!m_ctx.HasValidProcessID()) - { - // We allow gdb to connect to a server that hasn't started running - // the target yet. gdb still wants to ask questions about it and - // freaks out if it gets an error. So just return OK here. - } + if (!m_ctx.HasValidProcessID()) { + // We allow gdb to connect to a server that hasn't started running + // the target yet. gdb still wants to ask questions about it and + // freaks out if it gets an error. So just return OK here. + } - errno = 0; - nub_thread_t tid = strtoul (p + 1, NULL, 16); - if (errno != 0 && tid == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid thread number in H packet"); - } - if (*p == 'c') - SetContinueThread (tid); - if (*p == 'g') - SetCurrentThread (tid); + errno = 0; + nub_thread_t tid = strtoul(p + 1, NULL, 16); + if (errno != 0 && tid == 0) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Invalid thread number in H packet"); + } + if (*p == 'c') + SetContinueThread(tid); + if (*p == 'g') + SetCurrentThread(tid); - return SendPacket ("OK"); + return SendPacket("OK"); } +rnb_err_t RNBRemote::HandlePacket_qLaunchSuccess(const char *p) { + if (m_ctx.HasValidProcessID() || m_ctx.LaunchStatus().Error() == 0) + return SendPacket("OK"); + std::ostringstream ret_str; + std::string status_str; + ret_str << "E" << m_ctx.LaunchStatusAsString(status_str); -rnb_err_t -RNBRemote::HandlePacket_qLaunchSuccess (const char *p) -{ - if (m_ctx.HasValidProcessID() || m_ctx.LaunchStatus().Error() == 0) - return SendPacket("OK"); - std::ostringstream ret_str; - std::string status_str; - ret_str << "E" << m_ctx.LaunchStatusAsString(status_str); - - return SendPacket (ret_str.str()); + return SendPacket(ret_str.str()); } -rnb_err_t -RNBRemote::HandlePacket_qShlibInfoAddr (const char *p) -{ - if (m_ctx.HasValidProcessID()) - { - nub_addr_t shlib_info_addr = DNBProcessGetSharedLibraryInfoAddress(m_ctx.ProcessID()); - if (shlib_info_addr != INVALID_NUB_ADDRESS) - { - std::ostringstream ostrm; - ostrm << RAW_HEXBASE << shlib_info_addr; - return SendPacket (ostrm.str ()); - } +rnb_err_t RNBRemote::HandlePacket_qShlibInfoAddr(const char *p) { + if (m_ctx.HasValidProcessID()) { + nub_addr_t shlib_info_addr = + DNBProcessGetSharedLibraryInfoAddress(m_ctx.ProcessID()); + if (shlib_info_addr != INVALID_NUB_ADDRESS) { + std::ostringstream ostrm; + ostrm << RAW_HEXBASE << shlib_info_addr; + return SendPacket(ostrm.str()); } - return SendPacket ("E44"); + } + return SendPacket("E44"); } -rnb_err_t -RNBRemote::HandlePacket_qStepPacketSupported (const char *p) -{ - // Normally the "s" packet is mandatory, yet in gdb when using ARM, they - // get around the need for this packet by implementing software single - // stepping from gdb. Current versions of debugserver do support the "s" - // packet, yet some older versions do not. We need a way to tell if this - // packet is supported so we can disable software single stepping in gdb - // for remote targets (so the "s" packet will get used). - return SendPacket("OK"); +rnb_err_t RNBRemote::HandlePacket_qStepPacketSupported(const char *p) { + // Normally the "s" packet is mandatory, yet in gdb when using ARM, they + // get around the need for this packet by implementing software single + // stepping from gdb. Current versions of debugserver do support the "s" + // packet, yet some older versions do not. We need a way to tell if this + // packet is supported so we can disable software single stepping in gdb + // for remote targets (so the "s" packet will get used). + return SendPacket("OK"); } -rnb_err_t -RNBRemote::HandlePacket_qSyncThreadStateSupported (const char *p) -{ - // We support attachOrWait meaning attach if the process exists, otherwise wait to attach. - return SendPacket("OK"); +rnb_err_t RNBRemote::HandlePacket_qSyncThreadStateSupported(const char *p) { + // We support attachOrWait meaning attach if the process exists, otherwise + // wait to attach. + return SendPacket("OK"); } -rnb_err_t -RNBRemote::HandlePacket_qVAttachOrWaitSupported (const char *p) -{ - // We support attachOrWait meaning attach if the process exists, otherwise wait to attach. - return SendPacket("OK"); +rnb_err_t RNBRemote::HandlePacket_qVAttachOrWaitSupported(const char *p) { + // We support attachOrWait meaning attach if the process exists, otherwise + // wait to attach. + return SendPacket("OK"); } -rnb_err_t -RNBRemote::HandlePacket_qThreadStopInfo (const char *p) -{ - p += strlen ("qThreadStopInfo"); - nub_thread_t tid = strtoul(p, 0, 16); - return SendStopReplyPacketForThread (tid); +rnb_err_t RNBRemote::HandlePacket_qThreadStopInfo(const char *p) { + p += strlen("qThreadStopInfo"); + nub_thread_t tid = strtoul(p, 0, 16); + return SendStopReplyPacketForThread(tid); } -rnb_err_t -RNBRemote::HandlePacket_qThreadInfo (const char *p) -{ - // We allow gdb to connect to a server that hasn't started running - // the target yet. gdb still wants to ask questions about it and - // freaks out if it gets an error. So just return OK here. - nub_process_t pid = m_ctx.ProcessID(); - if (pid == INVALID_NUB_PROCESS) - return SendPacket ("OK"); - - // Only "qfThreadInfo" and "qsThreadInfo" get into this function so - // we only need to check the second byte to tell which is which - if (p[1] == 'f') - { - nub_size_t numthreads = DNBProcessGetNumThreads (pid); - std::ostringstream ostrm; - ostrm << "m"; - bool first = true; - for (nub_size_t i = 0; i < numthreads; ++i) - { - if (first) - first = false; - else - ostrm << ","; - nub_thread_t th = DNBProcessGetThreadAtIndex (pid, i); - ostrm << std::hex << th; - } - return SendPacket (ostrm.str ()); - } - else - { - return SendPacket ("l"); - } -} - -rnb_err_t -RNBRemote::HandlePacket_qThreadExtraInfo (const char *p) -{ - // We allow gdb to connect to a server that hasn't started running - // the target yet. gdb still wants to ask questions about it and - // freaks out if it gets an error. So just return OK here. - nub_process_t pid = m_ctx.ProcessID(); - if (pid == INVALID_NUB_PROCESS) - return SendPacket ("OK"); - - /* This is supposed to return a string like 'Runnable' or - 'Blocked on Mutex'. - The returned string is formatted like the "A" packet - a - sequence of letters encoded in as 2-hex-chars-per-letter. */ - p += strlen ("qThreadExtraInfo"); - if (*p++ != ',') - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Illformed qThreadExtraInfo packet"); - errno = 0; - nub_thread_t tid = strtoul (p, NULL, 16); - if (errno != 0 && tid == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid thread number in qThreadExtraInfo packet"); - } +rnb_err_t RNBRemote::HandlePacket_qThreadInfo(const char *p) { + // We allow gdb to connect to a server that hasn't started running + // the target yet. gdb still wants to ask questions about it and + // freaks out if it gets an error. So just return OK here. + nub_process_t pid = m_ctx.ProcessID(); + if (pid == INVALID_NUB_PROCESS) + return SendPacket("OK"); - const char * threadInfo = DNBThreadGetInfo(pid, tid); - if (threadInfo != NULL && threadInfo[0]) - { - return SendHexEncodedBytePacket(NULL, threadInfo, strlen(threadInfo), NULL); - } - else - { - // "OK" == 4f6b - // Return "OK" as a ASCII hex byte stream if things go wrong - return SendPacket ("4f6b"); - } + // Only "qfThreadInfo" and "qsThreadInfo" get into this function so + // we only need to check the second byte to tell which is which + if (p[1] == 'f') { + nub_size_t numthreads = DNBProcessGetNumThreads(pid); + std::ostringstream ostrm; + ostrm << "m"; + bool first = true; + for (nub_size_t i = 0; i < numthreads; ++i) { + if (first) + first = false; + else + ostrm << ","; + nub_thread_t th = DNBProcessGetThreadAtIndex(pid, i); + ostrm << std::hex << th; + } + return SendPacket(ostrm.str()); + } else { + return SendPacket("l"); + } +} + +rnb_err_t RNBRemote::HandlePacket_qThreadExtraInfo(const char *p) { + // We allow gdb to connect to a server that hasn't started running + // the target yet. gdb still wants to ask questions about it and + // freaks out if it gets an error. So just return OK here. + nub_process_t pid = m_ctx.ProcessID(); + if (pid == INVALID_NUB_PROCESS) + return SendPacket("OK"); - return SendPacket (""); + /* This is supposed to return a string like 'Runnable' or + 'Blocked on Mutex'. + The returned string is formatted like the "A" packet - a + sequence of letters encoded in as 2-hex-chars-per-letter. */ + p += strlen("qThreadExtraInfo"); + if (*p++ != ',') + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Illformed qThreadExtraInfo packet"); + errno = 0; + nub_thread_t tid = strtoul(p, NULL, 16); + if (errno != 0 && tid == 0) { + return HandlePacket_ILLFORMED( + __FILE__, __LINE__, p, + "Invalid thread number in qThreadExtraInfo packet"); + } + + const char *threadInfo = DNBThreadGetInfo(pid, tid); + if (threadInfo != NULL && threadInfo[0]) { + return SendHexEncodedBytePacket(NULL, threadInfo, strlen(threadInfo), NULL); + } else { + // "OK" == 4f6b + // Return "OK" as a ASCII hex byte stream if things go wrong + return SendPacket("4f6b"); + } + + return SendPacket(""); } - const char *k_space_delimiters = " \t"; -static void -skip_spaces (std::string &line) -{ - if (!line.empty()) - { - size_t space_pos = line.find_first_not_of (k_space_delimiters); - if (space_pos > 0) - line.erase(0, space_pos); - } -} - -static std::string -get_identifier (std::string &line) -{ - std::string word; - skip_spaces (line); - const size_t line_size = line.size(); - size_t end_pos; - for (end_pos = 0; end_pos < line_size; ++end_pos) - { - if (end_pos == 0) - { - if (isalpha(line[end_pos]) || line[end_pos] == '_') - continue; +static void skip_spaces(std::string &line) { + if (!line.empty()) { + size_t space_pos = line.find_first_not_of(k_space_delimiters); + if (space_pos > 0) + line.erase(0, space_pos); + } +} + +static std::string get_identifier(std::string &line) { + std::string word; + skip_spaces(line); + const size_t line_size = line.size(); + size_t end_pos; + for (end_pos = 0; end_pos < line_size; ++end_pos) { + if (end_pos == 0) { + if (isalpha(line[end_pos]) || line[end_pos] == '_') + continue; + } else if (isalnum(line[end_pos]) || line[end_pos] == '_') + continue; + break; + } + word.assign(line, 0, end_pos); + line.erase(0, end_pos); + return word; +} + +static std::string get_operator(std::string &line) { + std::string op; + skip_spaces(line); + if (!line.empty()) { + if (line[0] == '=') { + op = '='; + line.erase(0, 1); + } + } + return op; +} + +static std::string get_value(std::string &line) { + std::string value; + skip_spaces(line); + if (!line.empty()) { + value.swap(line); + } + return value; +} + +extern void FileLogCallback(void *baton, uint32_t flags, const char *format, + va_list args); +extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, + va_list args); + +rnb_err_t RNBRemote::HandlePacket_qRcmd(const char *p) { + const char *c = p + strlen("qRcmd,"); + std::string line; + while (c[0] && c[1]) { + char smallbuf[3] = {c[0], c[1], '\0'}; + errno = 0; + int ch = static_cast<int>(strtoul(smallbuf, NULL, 16)); + if (errno != 0 && ch == 0) + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "non-hex char in payload of qRcmd packet"); + line.push_back(ch); + c += 2; + } + if (*c == '\0') { + std::string command = get_identifier(line); + if (command.compare("set") == 0) { + std::string variable = get_identifier(line); + std::string op = get_operator(line); + std::string value = get_value(line); + if (variable.compare("logfile") == 0) { + FILE *log_file = fopen(value.c_str(), "w"); + if (log_file) { + DNBLogSetLogCallback(FileLogCallback, log_file); + return SendPacket("OK"); } - else if (isalnum(line[end_pos]) || line[end_pos] == '_') - continue; - break; - } - word.assign (line, 0, end_pos); - line.erase(0, end_pos); - return word; -} - -static std::string -get_operator (std::string &line) -{ - std::string op; - skip_spaces (line); - if (!line.empty()) - { - if (line[0] == '=') - { - op = '='; - line.erase(0,1); + return SendPacket("E71"); + } else if (variable.compare("logmask") == 0) { + char *end; + errno = 0; + uint32_t logmask = + static_cast<uint32_t>(strtoul(value.c_str(), &end, 0)); + if (errno == 0 && end && *end == '\0') { + DNBLogSetLogMask(logmask); + if (!DNBLogGetLogCallback()) + DNBLogSetLogCallback(ASLLogCallback, NULL); + return SendPacket("OK"); } - } - return op; -} - -static std::string -get_value (std::string &line) -{ - std::string value; - skip_spaces (line); - if (!line.empty()) - { - value.swap(line); - } - return value; -} - -extern void FileLogCallback(void *baton, uint32_t flags, const char *format, va_list args); -extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args); - -rnb_err_t -RNBRemote::HandlePacket_qRcmd (const char *p) -{ - const char *c = p + strlen("qRcmd,"); - std::string line; - while (c[0] && c[1]) - { - char smallbuf[3] = { c[0], c[1], '\0' }; errno = 0; - int ch = static_cast<int>(strtoul (smallbuf, NULL, 16)); - if (errno != 0 && ch == 0) - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in payload of qRcmd packet"); - line.push_back(ch); - c += 2; - } - if (*c == '\0') - { - std::string command = get_identifier(line); - if (command.compare("set") == 0) - { - std::string variable = get_identifier (line); - std::string op = get_operator (line); - std::string value = get_value (line); - if (variable.compare("logfile") == 0) - { - FILE *log_file = fopen(value.c_str(), "w"); - if (log_file) - { - DNBLogSetLogCallback(FileLogCallback, log_file); - return SendPacket ("OK"); - } - return SendPacket ("E71"); - } - else if (variable.compare("logmask") == 0) - { - char *end; - errno = 0; - uint32_t logmask = static_cast<uint32_t>(strtoul (value.c_str(), &end, 0)); - if (errno == 0 && end && *end == '\0') - { - DNBLogSetLogMask (logmask); - if (!DNBLogGetLogCallback()) - DNBLogSetLogCallback(ASLLogCallback, NULL); - return SendPacket ("OK"); - } - errno = 0; - logmask = static_cast<uint32_t>(strtoul (value.c_str(), &end, 16)); - if (errno == 0 && end && *end == '\0') - { - DNBLogSetLogMask (logmask); - return SendPacket ("OK"); - } - return SendPacket ("E72"); - } - return SendPacket ("E70"); + logmask = static_cast<uint32_t>(strtoul(value.c_str(), &end, 16)); + if (errno == 0 && end && *end == '\0') { + DNBLogSetLogMask(logmask); + return SendPacket("OK"); } - return SendPacket ("E69"); - } - return SendPacket ("E73"); -} - -rnb_err_t -RNBRemote::HandlePacket_qC (const char *p) -{ - nub_thread_t tid; - std::ostringstream rep; - // If we haven't run the process yet, we tell the debugger the - // pid is 0. That way it can know to tell use to run later on. - if (!m_ctx.HasValidProcessID()) - tid = 0; - else - { - // Grab the current thread. - tid = DNBProcessGetCurrentThread (m_ctx.ProcessID()); - // Make sure we set the current thread so g and p packets return - // the data the gdb will expect. - SetCurrentThread (tid); - } - rep << "QC" << std::hex << tid; - return SendPacket (rep.str()); -} - -rnb_err_t -RNBRemote::HandlePacket_qEcho (const char *p) -{ - // Just send the exact same packet back that we received to - // synchronize the response packets after a previous packet - // timed out. This allows the debugger to get back on track - // with responses after a packet timeout. - return SendPacket (p); -} - -rnb_err_t -RNBRemote::HandlePacket_qGetPid (const char *p) -{ - nub_process_t pid; - std::ostringstream rep; - // If we haven't run the process yet, we tell the debugger the - // pid is 0. That way it can know to tell use to run later on. - if (m_ctx.HasValidProcessID()) - pid = m_ctx.ProcessID(); - else - pid = 0; - rep << std::hex << pid; - return SendPacket (rep.str()); + return SendPacket("E72"); + } + return SendPacket("E70"); + } + return SendPacket("E69"); + } + return SendPacket("E73"); +} + +rnb_err_t RNBRemote::HandlePacket_qC(const char *p) { + nub_thread_t tid; + std::ostringstream rep; + // If we haven't run the process yet, we tell the debugger the + // pid is 0. That way it can know to tell use to run later on. + if (!m_ctx.HasValidProcessID()) + tid = 0; + else { + // Grab the current thread. + tid = DNBProcessGetCurrentThread(m_ctx.ProcessID()); + // Make sure we set the current thread so g and p packets return + // the data the gdb will expect. + SetCurrentThread(tid); + } + rep << "QC" << std::hex << tid; + return SendPacket(rep.str()); +} + +rnb_err_t RNBRemote::HandlePacket_qEcho(const char *p) { + // Just send the exact same packet back that we received to + // synchronize the response packets after a previous packet + // timed out. This allows the debugger to get back on track + // with responses after a packet timeout. + return SendPacket(p); +} + +rnb_err_t RNBRemote::HandlePacket_qGetPid(const char *p) { + nub_process_t pid; + std::ostringstream rep; + // If we haven't run the process yet, we tell the debugger the + // pid is 0. That way it can know to tell use to run later on. + if (m_ctx.HasValidProcessID()) + pid = m_ctx.ProcessID(); + else + pid = 0; + rep << std::hex << pid; + return SendPacket(rep.str()); } -rnb_err_t -RNBRemote::HandlePacket_qRegisterInfo (const char *p) -{ - if (g_num_reg_entries == 0) - InitializeRegisters (); - - p += strlen ("qRegisterInfo"); - - nub_size_t num_reg_sets = 0; - const DNBRegisterSetInfo *reg_set_info = DNBGetRegisterSetInfo (&num_reg_sets); - uint32_t reg_num = static_cast<uint32_t>(strtoul(p, 0, 16)); - - if (reg_num < g_num_reg_entries) - { - const register_map_entry_t *reg_entry = &g_reg_entries[reg_num]; - std::ostringstream ostrm; - if (reg_entry->nub_info.name) - ostrm << "name:" << reg_entry->nub_info.name << ';'; - if (reg_entry->nub_info.alt) - ostrm << "alt-name:" << reg_entry->nub_info.alt << ';'; +rnb_err_t RNBRemote::HandlePacket_qRegisterInfo(const char *p) { + if (g_num_reg_entries == 0) + InitializeRegisters(); - ostrm << "bitsize:" << std::dec << reg_entry->nub_info.size * 8 << ';'; - ostrm << "offset:" << std::dec << reg_entry->offset << ';'; + p += strlen("qRegisterInfo"); - switch (reg_entry->nub_info.type) - { - case Uint: ostrm << "encoding:uint;"; break; - case Sint: ostrm << "encoding:sint;"; break; - case IEEE754: ostrm << "encoding:ieee754;"; break; - case Vector: ostrm << "encoding:vector;"; break; - } + nub_size_t num_reg_sets = 0; + const DNBRegisterSetInfo *reg_set_info = DNBGetRegisterSetInfo(&num_reg_sets); + uint32_t reg_num = static_cast<uint32_t>(strtoul(p, 0, 16)); - switch (reg_entry->nub_info.format) - { - case Binary: ostrm << "format:binary;"; break; - case Decimal: ostrm << "format:decimal;"; break; - case Hex: ostrm << "format:hex;"; break; - case Float: ostrm << "format:float;"; break; - case VectorOfSInt8: ostrm << "format:vector-sint8;"; break; - case VectorOfUInt8: ostrm << "format:vector-uint8;"; break; - case VectorOfSInt16: ostrm << "format:vector-sint16;"; break; - case VectorOfUInt16: ostrm << "format:vector-uint16;"; break; - case VectorOfSInt32: ostrm << "format:vector-sint32;"; break; - case VectorOfUInt32: ostrm << "format:vector-uint32;"; break; - case VectorOfFloat32: ostrm << "format:vector-float32;"; break; - case VectorOfUInt128: ostrm << "format:vector-uint128;"; break; - }; - - if (reg_set_info && reg_entry->nub_info.set < num_reg_sets) - ostrm << "set:" << reg_set_info[reg_entry->nub_info.set].name << ';'; - - if (reg_entry->nub_info.reg_ehframe != INVALID_NUB_REGNUM) - ostrm << "ehframe:" << std::dec << reg_entry->nub_info.reg_ehframe << ';'; - - if (reg_entry->nub_info.reg_dwarf != INVALID_NUB_REGNUM) - ostrm << "dwarf:" << std::dec << reg_entry->nub_info.reg_dwarf << ';'; + if (reg_num < g_num_reg_entries) { + const register_map_entry_t *reg_entry = &g_reg_entries[reg_num]; + std::ostringstream ostrm; + if (reg_entry->nub_info.name) + ostrm << "name:" << reg_entry->nub_info.name << ';'; + if (reg_entry->nub_info.alt) + ostrm << "alt-name:" << reg_entry->nub_info.alt << ';'; + + ostrm << "bitsize:" << std::dec << reg_entry->nub_info.size * 8 << ';'; + ostrm << "offset:" << std::dec << reg_entry->offset << ';'; + + switch (reg_entry->nub_info.type) { + case Uint: + ostrm << "encoding:uint;"; + break; + case Sint: + ostrm << "encoding:sint;"; + break; + case IEEE754: + ostrm << "encoding:ieee754;"; + break; + case Vector: + ostrm << "encoding:vector;"; + break; + } + + switch (reg_entry->nub_info.format) { + case Binary: + ostrm << "format:binary;"; + break; + case Decimal: + ostrm << "format:decimal;"; + break; + case Hex: + ostrm << "format:hex;"; + break; + case Float: + ostrm << "format:float;"; + break; + case VectorOfSInt8: + ostrm << "format:vector-sint8;"; + break; + case VectorOfUInt8: + ostrm << "format:vector-uint8;"; + break; + case VectorOfSInt16: + ostrm << "format:vector-sint16;"; + break; + case VectorOfUInt16: + ostrm << "format:vector-uint16;"; + break; + case VectorOfSInt32: + ostrm << "format:vector-sint32;"; + break; + case VectorOfUInt32: + ostrm << "format:vector-uint32;"; + break; + case VectorOfFloat32: + ostrm << "format:vector-float32;"; + break; + case VectorOfUInt128: + ostrm << "format:vector-uint128;"; + break; + }; - switch (reg_entry->nub_info.reg_generic) - { - case GENERIC_REGNUM_FP: ostrm << "generic:fp;"; break; - case GENERIC_REGNUM_PC: ostrm << "generic:pc;"; break; - case GENERIC_REGNUM_SP: ostrm << "generic:sp;"; break; - case GENERIC_REGNUM_RA: ostrm << "generic:ra;"; break; - case GENERIC_REGNUM_FLAGS: ostrm << "generic:flags;"; break; - case GENERIC_REGNUM_ARG1: ostrm << "generic:arg1;"; break; - case GENERIC_REGNUM_ARG2: ostrm << "generic:arg2;"; break; - case GENERIC_REGNUM_ARG3: ostrm << "generic:arg3;"; break; - case GENERIC_REGNUM_ARG4: ostrm << "generic:arg4;"; break; - case GENERIC_REGNUM_ARG5: ostrm << "generic:arg5;"; break; - case GENERIC_REGNUM_ARG6: ostrm << "generic:arg6;"; break; - case GENERIC_REGNUM_ARG7: ostrm << "generic:arg7;"; break; - case GENERIC_REGNUM_ARG8: ostrm << "generic:arg8;"; break; - default: break; - } - - if (!reg_entry->value_regnums.empty()) - { - ostrm << "container-regs:"; - for (size_t i=0, n=reg_entry->value_regnums.size(); i < n; ++i) - { - if (i > 0) - ostrm << ','; - ostrm << RAW_HEXBASE << reg_entry->value_regnums[i]; - } - ostrm << ';'; - } + if (reg_set_info && reg_entry->nub_info.set < num_reg_sets) + ostrm << "set:" << reg_set_info[reg_entry->nub_info.set].name << ';'; + + if (reg_entry->nub_info.reg_ehframe != INVALID_NUB_REGNUM) + ostrm << "ehframe:" << std::dec << reg_entry->nub_info.reg_ehframe << ';'; + + if (reg_entry->nub_info.reg_dwarf != INVALID_NUB_REGNUM) + ostrm << "dwarf:" << std::dec << reg_entry->nub_info.reg_dwarf << ';'; + + switch (reg_entry->nub_info.reg_generic) { + case GENERIC_REGNUM_FP: + ostrm << "generic:fp;"; + break; + case GENERIC_REGNUM_PC: + ostrm << "generic:pc;"; + break; + case GENERIC_REGNUM_SP: + ostrm << "generic:sp;"; + break; + case GENERIC_REGNUM_RA: + ostrm << "generic:ra;"; + break; + case GENERIC_REGNUM_FLAGS: + ostrm << "generic:flags;"; + break; + case GENERIC_REGNUM_ARG1: + ostrm << "generic:arg1;"; + break; + case GENERIC_REGNUM_ARG2: + ostrm << "generic:arg2;"; + break; + case GENERIC_REGNUM_ARG3: + ostrm << "generic:arg3;"; + break; + case GENERIC_REGNUM_ARG4: + ostrm << "generic:arg4;"; + break; + case GENERIC_REGNUM_ARG5: + ostrm << "generic:arg5;"; + break; + case GENERIC_REGNUM_ARG6: + ostrm << "generic:arg6;"; + break; + case GENERIC_REGNUM_ARG7: + ostrm << "generic:arg7;"; + break; + case GENERIC_REGNUM_ARG8: + ostrm << "generic:arg8;"; + break; + default: + break; + } - if (!reg_entry->invalidate_regnums.empty()) - { - ostrm << "invalidate-regs:"; - for (size_t i=0, n=reg_entry->invalidate_regnums.size(); i < n; ++i) - { - if (i > 0) - ostrm << ','; - ostrm << RAW_HEXBASE << reg_entry->invalidate_regnums[i]; - } - ostrm << ';'; - } + if (!reg_entry->value_regnums.empty()) { + ostrm << "container-regs:"; + for (size_t i = 0, n = reg_entry->value_regnums.size(); i < n; ++i) { + if (i > 0) + ostrm << ','; + ostrm << RAW_HEXBASE << reg_entry->value_regnums[i]; + } + ostrm << ';'; + } - return SendPacket (ostrm.str ()); + if (!reg_entry->invalidate_regnums.empty()) { + ostrm << "invalidate-regs:"; + for (size_t i = 0, n = reg_entry->invalidate_regnums.size(); i < n; ++i) { + if (i > 0) + ostrm << ','; + ostrm << RAW_HEXBASE << reg_entry->invalidate_regnums[i]; + } + ostrm << ';'; } - return SendPacket ("E45"); -} + return SendPacket(ostrm.str()); + } + return SendPacket("E45"); +} /* This expects a packet formatted like @@ -1989,222 +2050,169 @@ RNBRemote::HandlePacket_qRegisterInfo (const char *p) QSetLogging:bitmask=LOG_ALL;mode=asl; */ -rnb_err_t -set_logging (const char *p) -{ - int bitmask = 0; - while (p && *p != '\0') - { - if (strncmp (p, "bitmask=", sizeof ("bitmask=") - 1) == 0) - { - p += sizeof ("bitmask=") - 1; - while (p && *p != '\0' && *p != ';') - { - if (*p == '|') - p++; - -// to regenerate the LOG_ entries (not including the LOG_RNB entries) -// $ for logname in `grep '^#define LOG_' DNBDefs.h | egrep -v 'LOG_HI|LOG_LO' | awk '{print $2}'` -// do -// echo " else if (strncmp (p, \"$logname\", sizeof (\"$logname\") - 1) == 0)" -// echo " {" -// echo " p += sizeof (\"$logname\") - 1;" -// echo " bitmask |= $logname;" -// echo " }" -// done - if (strncmp (p, "LOG_VERBOSE", sizeof ("LOG_VERBOSE") - 1) == 0) - { - p += sizeof ("LOG_VERBOSE") - 1; - bitmask |= LOG_VERBOSE; - } - else if (strncmp (p, "LOG_PROCESS", sizeof ("LOG_PROCESS") - 1) == 0) - { - p += sizeof ("LOG_PROCESS") - 1; - bitmask |= LOG_PROCESS; - } - else if (strncmp (p, "LOG_THREAD", sizeof ("LOG_THREAD") - 1) == 0) - { - p += sizeof ("LOG_THREAD") - 1; - bitmask |= LOG_THREAD; - } - else if (strncmp (p, "LOG_EXCEPTIONS", sizeof ("LOG_EXCEPTIONS") - 1) == 0) - { - p += sizeof ("LOG_EXCEPTIONS") - 1; - bitmask |= LOG_EXCEPTIONS; - } - else if (strncmp (p, "LOG_SHLIB", sizeof ("LOG_SHLIB") - 1) == 0) - { - p += sizeof ("LOG_SHLIB") - 1; - bitmask |= LOG_SHLIB; - } - else if (strncmp (p, "LOG_MEMORY", sizeof ("LOG_MEMORY") - 1) == 0) - { - p += sizeof ("LOG_MEMORY") - 1; - bitmask |= LOG_MEMORY; - } - else if (strncmp (p, "LOG_MEMORY_DATA_SHORT", sizeof ("LOG_MEMORY_DATA_SHORT") - 1) == 0) - { - p += sizeof ("LOG_MEMORY_DATA_SHORT") - 1; - bitmask |= LOG_MEMORY_DATA_SHORT; - } - else if (strncmp (p, "LOG_MEMORY_DATA_LONG", sizeof ("LOG_MEMORY_DATA_LONG") - 1) == 0) - { - p += sizeof ("LOG_MEMORY_DATA_LONG") - 1; - bitmask |= LOG_MEMORY_DATA_LONG; - } - else if (strncmp (p, "LOG_MEMORY_PROTECTIONS", sizeof ("LOG_MEMORY_PROTECTIONS") - 1) == 0) - { - p += sizeof ("LOG_MEMORY_PROTECTIONS") - 1; - bitmask |= LOG_MEMORY_PROTECTIONS; - } - else if (strncmp (p, "LOG_BREAKPOINTS", sizeof ("LOG_BREAKPOINTS") - 1) == 0) - { - p += sizeof ("LOG_BREAKPOINTS") - 1; - bitmask |= LOG_BREAKPOINTS; - } - else if (strncmp (p, "LOG_EVENTS", sizeof ("LOG_EVENTS") - 1) == 0) - { - p += sizeof ("LOG_EVENTS") - 1; - bitmask |= LOG_EVENTS; - } - else if (strncmp (p, "LOG_WATCHPOINTS", sizeof ("LOG_WATCHPOINTS") - 1) == 0) - { - p += sizeof ("LOG_WATCHPOINTS") - 1; - bitmask |= LOG_WATCHPOINTS; - } - else if (strncmp (p, "LOG_STEP", sizeof ("LOG_STEP") - 1) == 0) - { - p += sizeof ("LOG_STEP") - 1; - bitmask |= LOG_STEP; - } - else if (strncmp (p, "LOG_TASK", sizeof ("LOG_TASK") - 1) == 0) - { - p += sizeof ("LOG_TASK") - 1; - bitmask |= LOG_TASK; - } - else if (strncmp (p, "LOG_ALL", sizeof ("LOG_ALL") - 1) == 0) - { - p += sizeof ("LOG_ALL") - 1; - bitmask |= LOG_ALL; - } - else if (strncmp (p, "LOG_DEFAULT", sizeof ("LOG_DEFAULT") - 1) == 0) - { - p += sizeof ("LOG_DEFAULT") - 1; - bitmask |= LOG_DEFAULT; - } -// end of auto-generated entries - - else if (strncmp (p, "LOG_NONE", sizeof ("LOG_NONE") - 1) == 0) - { - p += sizeof ("LOG_NONE") - 1; - bitmask = 0; - } - else if (strncmp (p, "LOG_RNB_MINIMAL", sizeof ("LOG_RNB_MINIMAL") - 1) == 0) - { - p += sizeof ("LOG_RNB_MINIMAL") - 1; - bitmask |= LOG_RNB_MINIMAL; - } - else if (strncmp (p, "LOG_RNB_MEDIUM", sizeof ("LOG_RNB_MEDIUM") - 1) == 0) - { - p += sizeof ("LOG_RNB_MEDIUM") - 1; - bitmask |= LOG_RNB_MEDIUM; - } - else if (strncmp (p, "LOG_RNB_MAX", sizeof ("LOG_RNB_MAX") - 1) == 0) - { - p += sizeof ("LOG_RNB_MAX") - 1; - bitmask |= LOG_RNB_MAX; - } - else if (strncmp (p, "LOG_RNB_COMM", sizeof ("LOG_RNB_COMM") - 1) == 0) - { - p += sizeof ("LOG_RNB_COMM") - 1; - bitmask |= LOG_RNB_COMM; - } - else if (strncmp (p, "LOG_RNB_REMOTE", sizeof ("LOG_RNB_REMOTE") - 1) == 0) - { - p += sizeof ("LOG_RNB_REMOTE") - 1; - bitmask |= LOG_RNB_REMOTE; - } - else if (strncmp (p, "LOG_RNB_EVENTS", sizeof ("LOG_RNB_EVENTS") - 1) == 0) - { - p += sizeof ("LOG_RNB_EVENTS") - 1; - bitmask |= LOG_RNB_EVENTS; - } - else if (strncmp (p, "LOG_RNB_PROC", sizeof ("LOG_RNB_PROC") - 1) == 0) - { - p += sizeof ("LOG_RNB_PROC") - 1; - bitmask |= LOG_RNB_PROC; - } - else if (strncmp (p, "LOG_RNB_PACKETS", sizeof ("LOG_RNB_PACKETS") - 1) == 0) - { - p += sizeof ("LOG_RNB_PACKETS") - 1; - bitmask |= LOG_RNB_PACKETS; - } - else if (strncmp (p, "LOG_RNB_ALL", sizeof ("LOG_RNB_ALL") - 1) == 0) - { - p += sizeof ("LOG_RNB_ALL") - 1; - bitmask |= LOG_RNB_ALL; - } - else if (strncmp (p, "LOG_RNB_DEFAULT", sizeof ("LOG_RNB_DEFAULT") - 1) == 0) - { - p += sizeof ("LOG_RNB_DEFAULT") - 1; - bitmask |= LOG_RNB_DEFAULT; - } - else if (strncmp (p, "LOG_DARWIN_LOG", sizeof ("LOG_DARWIN_LOG") - 1) == 0) - { - p += sizeof ("LOG_DARWIN_LOG") - 1; - bitmask |= LOG_DARWIN_LOG; - } - else if (strncmp (p, "LOG_RNB_NONE", sizeof ("LOG_RNB_NONE") - 1) == 0) - { - p += sizeof ("LOG_RNB_NONE") - 1; - bitmask = 0; - } - else - { - /* Unrecognized logging bit; ignore it. */ - const char *c = strchr (p, '|'); - if (c) - { - p = c; - } - else - { - c = strchr (p, ';'); - if (c) - { - p = c; - } - else - { - // Improperly terminated word; just go to end of str - p = strchr (p, '\0'); - } - } - } - } - // Did we get a properly formatted logging bitmask? - if (p && *p == ';') - { - // Enable DNB logging. - // Use the existing log callback if one was already configured. - if (!DNBLogGetLogCallback()) - { - // Use the os_log()-based logger if available; otherwise, - // fallback to ASL. - auto log_callback = OsLogger::GetLogFunction(); - if (log_callback) - DNBLogSetLogCallback(log_callback, nullptr); - else - DNBLogSetLogCallback(ASLLogCallback, nullptr); - } - - // Update logging to use the configured log channel bitmask. - DNBLogSetLogMask (bitmask); - p++; +rnb_err_t set_logging(const char *p) { + int bitmask = 0; + while (p && *p != '\0') { + if (strncmp(p, "bitmask=", sizeof("bitmask=") - 1) == 0) { + p += sizeof("bitmask=") - 1; + while (p && *p != '\0' && *p != ';') { + if (*p == '|') + p++; + + // to regenerate the LOG_ entries (not including the LOG_RNB entries) + // $ for logname in `grep '^#define LOG_' DNBDefs.h | egrep -v + // 'LOG_HI|LOG_LO' | awk '{print $2}'` + // do + // echo " else if (strncmp (p, \"$logname\", sizeof + // (\"$logname\") - 1) == 0)" + // echo " {" + // echo " p += sizeof (\"$logname\") - 1;" + // echo " bitmask |= $logname;" + // echo " }" + // done + if (strncmp(p, "LOG_VERBOSE", sizeof("LOG_VERBOSE") - 1) == 0) { + p += sizeof("LOG_VERBOSE") - 1; + bitmask |= LOG_VERBOSE; + } else if (strncmp(p, "LOG_PROCESS", sizeof("LOG_PROCESS") - 1) == 0) { + p += sizeof("LOG_PROCESS") - 1; + bitmask |= LOG_PROCESS; + } else if (strncmp(p, "LOG_THREAD", sizeof("LOG_THREAD") - 1) == 0) { + p += sizeof("LOG_THREAD") - 1; + bitmask |= LOG_THREAD; + } else if (strncmp(p, "LOG_EXCEPTIONS", sizeof("LOG_EXCEPTIONS") - 1) == + 0) { + p += sizeof("LOG_EXCEPTIONS") - 1; + bitmask |= LOG_EXCEPTIONS; + } else if (strncmp(p, "LOG_SHLIB", sizeof("LOG_SHLIB") - 1) == 0) { + p += sizeof("LOG_SHLIB") - 1; + bitmask |= LOG_SHLIB; + } else if (strncmp(p, "LOG_MEMORY", sizeof("LOG_MEMORY") - 1) == 0) { + p += sizeof("LOG_MEMORY") - 1; + bitmask |= LOG_MEMORY; + } else if (strncmp(p, "LOG_MEMORY_DATA_SHORT", + sizeof("LOG_MEMORY_DATA_SHORT") - 1) == 0) { + p += sizeof("LOG_MEMORY_DATA_SHORT") - 1; + bitmask |= LOG_MEMORY_DATA_SHORT; + } else if (strncmp(p, "LOG_MEMORY_DATA_LONG", + sizeof("LOG_MEMORY_DATA_LONG") - 1) == 0) { + p += sizeof("LOG_MEMORY_DATA_LONG") - 1; + bitmask |= LOG_MEMORY_DATA_LONG; + } else if (strncmp(p, "LOG_MEMORY_PROTECTIONS", + sizeof("LOG_MEMORY_PROTECTIONS") - 1) == 0) { + p += sizeof("LOG_MEMORY_PROTECTIONS") - 1; + bitmask |= LOG_MEMORY_PROTECTIONS; + } else if (strncmp(p, "LOG_BREAKPOINTS", + sizeof("LOG_BREAKPOINTS") - 1) == 0) { + p += sizeof("LOG_BREAKPOINTS") - 1; + bitmask |= LOG_BREAKPOINTS; + } else if (strncmp(p, "LOG_EVENTS", sizeof("LOG_EVENTS") - 1) == 0) { + p += sizeof("LOG_EVENTS") - 1; + bitmask |= LOG_EVENTS; + } else if (strncmp(p, "LOG_WATCHPOINTS", + sizeof("LOG_WATCHPOINTS") - 1) == 0) { + p += sizeof("LOG_WATCHPOINTS") - 1; + bitmask |= LOG_WATCHPOINTS; + } else if (strncmp(p, "LOG_STEP", sizeof("LOG_STEP") - 1) == 0) { + p += sizeof("LOG_STEP") - 1; + bitmask |= LOG_STEP; + } else if (strncmp(p, "LOG_TASK", sizeof("LOG_TASK") - 1) == 0) { + p += sizeof("LOG_TASK") - 1; + bitmask |= LOG_TASK; + } else if (strncmp(p, "LOG_ALL", sizeof("LOG_ALL") - 1) == 0) { + p += sizeof("LOG_ALL") - 1; + bitmask |= LOG_ALL; + } else if (strncmp(p, "LOG_DEFAULT", sizeof("LOG_DEFAULT") - 1) == 0) { + p += sizeof("LOG_DEFAULT") - 1; + bitmask |= LOG_DEFAULT; + } + // end of auto-generated entries + + else if (strncmp(p, "LOG_NONE", sizeof("LOG_NONE") - 1) == 0) { + p += sizeof("LOG_NONE") - 1; + bitmask = 0; + } else if (strncmp(p, "LOG_RNB_MINIMAL", + sizeof("LOG_RNB_MINIMAL") - 1) == 0) { + p += sizeof("LOG_RNB_MINIMAL") - 1; + bitmask |= LOG_RNB_MINIMAL; + } else if (strncmp(p, "LOG_RNB_MEDIUM", sizeof("LOG_RNB_MEDIUM") - 1) == + 0) { + p += sizeof("LOG_RNB_MEDIUM") - 1; + bitmask |= LOG_RNB_MEDIUM; + } else if (strncmp(p, "LOG_RNB_MAX", sizeof("LOG_RNB_MAX") - 1) == 0) { + p += sizeof("LOG_RNB_MAX") - 1; + bitmask |= LOG_RNB_MAX; + } else if (strncmp(p, "LOG_RNB_COMM", sizeof("LOG_RNB_COMM") - 1) == + 0) { + p += sizeof("LOG_RNB_COMM") - 1; + bitmask |= LOG_RNB_COMM; + } else if (strncmp(p, "LOG_RNB_REMOTE", sizeof("LOG_RNB_REMOTE") - 1) == + 0) { + p += sizeof("LOG_RNB_REMOTE") - 1; + bitmask |= LOG_RNB_REMOTE; + } else if (strncmp(p, "LOG_RNB_EVENTS", sizeof("LOG_RNB_EVENTS") - 1) == + 0) { + p += sizeof("LOG_RNB_EVENTS") - 1; + bitmask |= LOG_RNB_EVENTS; + } else if (strncmp(p, "LOG_RNB_PROC", sizeof("LOG_RNB_PROC") - 1) == + 0) { + p += sizeof("LOG_RNB_PROC") - 1; + bitmask |= LOG_RNB_PROC; + } else if (strncmp(p, "LOG_RNB_PACKETS", + sizeof("LOG_RNB_PACKETS") - 1) == 0) { + p += sizeof("LOG_RNB_PACKETS") - 1; + bitmask |= LOG_RNB_PACKETS; + } else if (strncmp(p, "LOG_RNB_ALL", sizeof("LOG_RNB_ALL") - 1) == 0) { + p += sizeof("LOG_RNB_ALL") - 1; + bitmask |= LOG_RNB_ALL; + } else if (strncmp(p, "LOG_RNB_DEFAULT", + sizeof("LOG_RNB_DEFAULT") - 1) == 0) { + p += sizeof("LOG_RNB_DEFAULT") - 1; + bitmask |= LOG_RNB_DEFAULT; + } else if (strncmp(p, "LOG_DARWIN_LOG", sizeof("LOG_DARWIN_LOG") - 1) == + 0) { + p += sizeof("LOG_DARWIN_LOG") - 1; + bitmask |= LOG_DARWIN_LOG; + } else if (strncmp(p, "LOG_RNB_NONE", sizeof("LOG_RNB_NONE") - 1) == + 0) { + p += sizeof("LOG_RNB_NONE") - 1; + bitmask = 0; + } else { + /* Unrecognized logging bit; ignore it. */ + const char *c = strchr(p, '|'); + if (c) { + p = c; + } else { + c = strchr(p, ';'); + if (c) { + p = c; + } else { + // Improperly terminated word; just go to end of str + p = strchr(p, '\0'); } + } + } + } + // Did we get a properly formatted logging bitmask? + if (p && *p == ';') { + // Enable DNB logging. + // Use the existing log callback if one was already configured. + if (!DNBLogGetLogCallback()) { + // Use the os_log()-based logger if available; otherwise, + // fallback to ASL. + auto log_callback = OsLogger::GetLogFunction(); + if (log_callback) + DNBLogSetLogCallback(log_callback, nullptr); + else + DNBLogSetLogCallback(ASLLogCallback, nullptr); } - // We're not going to support logging to a file for now. All logging - // goes through ASL or the previously arranged log callback. + + // Update logging to use the configured log channel bitmask. + DNBLogSetLogMask(bitmask); + p++; + } + } +// We're not going to support logging to a file for now. All logging +// goes through ASL or the previously arranged log callback. #if 0 else if (strncmp (p, "mode=", sizeof ("mode=") - 1) == 0) { @@ -2261,1022 +2269,930 @@ set_logging (const char *p) p = c + 1; } #endif /* #if 0 to enforce ASL logging only. */ - else - { - // Ignore unknown argument - const char *c = strchr (p, ';'); - if (c) - p = c + 1; - else - p = strchr (p, '\0'); - } + else { + // Ignore unknown argument + const char *c = strchr(p, ';'); + if (c) + p = c + 1; + else + p = strchr(p, '\0'); } + } - return rnb_success; + return rnb_success; } -rnb_err_t -RNBRemote::HandlePacket_QThreadSuffixSupported (const char *p) -{ - m_thread_suffix_supported = true; - return SendPacket ("OK"); +rnb_err_t RNBRemote::HandlePacket_QThreadSuffixSupported(const char *p) { + m_thread_suffix_supported = true; + return SendPacket("OK"); } -rnb_err_t -RNBRemote::HandlePacket_QStartNoAckMode (const char *p) -{ - // Send the OK packet first so the correct checksum is appended... - rnb_err_t result = SendPacket ("OK"); - m_noack_mode = true; - return result; +rnb_err_t RNBRemote::HandlePacket_QStartNoAckMode(const char *p) { + // Send the OK packet first so the correct checksum is appended... + rnb_err_t result = SendPacket("OK"); + m_noack_mode = true; + return result; } +rnb_err_t RNBRemote::HandlePacket_QSetLogging(const char *p) { + p += sizeof("QSetLogging:") - 1; + rnb_err_t result = set_logging(p); + if (result == rnb_success) + return SendPacket("OK"); + else + return SendPacket("E35"); +} + +rnb_err_t RNBRemote::HandlePacket_QSetDisableASLR(const char *p) { + extern int g_disable_aslr; + p += sizeof("QSetDisableASLR:") - 1; + switch (*p) { + case '0': + g_disable_aslr = 0; + break; + case '1': + g_disable_aslr = 1; + break; + default: + return SendPacket("E56"); + } + return SendPacket("OK"); +} + +rnb_err_t RNBRemote::HandlePacket_QSetSTDIO(const char *p) { + // Only set stdin/out/err if we don't already have a process + if (!m_ctx.HasValidProcessID()) { + bool success = false; + // Check the seventh character since the packet will be one of: + // QSetSTDIN + // QSetSTDOUT + // QSetSTDERR + StdStringExtractor packet(p); + packet.SetFilePos(7); + char ch = packet.GetChar(); + while (packet.GetChar() != ':') + /* Do nothing. */; + + switch (ch) { + case 'I': // STDIN + packet.GetHexByteString(m_ctx.GetSTDIN()); + success = !m_ctx.GetSTDIN().empty(); + break; + + case 'O': // STDOUT + packet.GetHexByteString(m_ctx.GetSTDOUT()); + success = !m_ctx.GetSTDOUT().empty(); + break; + + case 'E': // STDERR + packet.GetHexByteString(m_ctx.GetSTDERR()); + success = !m_ctx.GetSTDERR().empty(); + break; -rnb_err_t -RNBRemote::HandlePacket_QSetLogging (const char *p) -{ - p += sizeof ("QSetLogging:") - 1; - rnb_err_t result = set_logging (p); - if (result == rnb_success) - return SendPacket ("OK"); - else - return SendPacket ("E35"); -} - -rnb_err_t -RNBRemote::HandlePacket_QSetDisableASLR (const char *p) -{ - extern int g_disable_aslr; - p += sizeof ("QSetDisableASLR:") - 1; - switch (*p) - { - case '0': g_disable_aslr = 0; break; - case '1': g_disable_aslr = 1; break; default: - return SendPacket ("E56"); - } - return SendPacket ("OK"); -} - -rnb_err_t -RNBRemote::HandlePacket_QSetSTDIO (const char *p) -{ - // Only set stdin/out/err if we don't already have a process - if (!m_ctx.HasValidProcessID()) - { - bool success = false; - // Check the seventh character since the packet will be one of: - // QSetSTDIN - // QSetSTDOUT - // QSetSTDERR - StdStringExtractor packet(p); - packet.SetFilePos (7); - char ch = packet.GetChar(); - while (packet.GetChar() != ':') - /* Do nothing. */; - - switch (ch) - { - case 'I': // STDIN - packet.GetHexByteString (m_ctx.GetSTDIN()); - success = !m_ctx.GetSTDIN().empty(); - break; - - case 'O': // STDOUT - packet.GetHexByteString (m_ctx.GetSTDOUT()); - success = !m_ctx.GetSTDOUT().empty(); - break; - - case 'E': // STDERR - packet.GetHexByteString (m_ctx.GetSTDERR()); - success = !m_ctx.GetSTDERR().empty(); - break; - - default: - break; - } - if (success) - return SendPacket ("OK"); - return SendPacket ("E57"); - } - return SendPacket ("E58"); -} - -rnb_err_t -RNBRemote::HandlePacket_QSetWorkingDir (const char *p) -{ - // Only set the working directory if we don't already have a process - if (!m_ctx.HasValidProcessID()) - { - StdStringExtractor packet(p += sizeof ("QSetWorkingDir:") - 1); - if (packet.GetHexByteString (m_ctx.GetWorkingDir())) - { - struct stat working_dir_stat; - if (::stat(m_ctx.GetWorkingDirPath(), &working_dir_stat) == -1) - { - m_ctx.GetWorkingDir().clear(); - return SendPacket ("E61"); // Working directory doesn't exist... - } - else if ((working_dir_stat.st_mode & S_IFMT) == S_IFDIR) - { - return SendPacket ("OK"); - } - else - { - m_ctx.GetWorkingDir().clear(); - return SendPacket ("E62"); // Working directory isn't a directory... - } - } - return SendPacket ("E59"); // Invalid path - } - return SendPacket ("E60"); // Already had a process, too late to set working dir -} - -rnb_err_t -RNBRemote::HandlePacket_QSyncThreadState (const char *p) -{ - if (!m_ctx.HasValidProcessID()) - { - // We allow gdb to connect to a server that hasn't started running - // the target yet. gdb still wants to ask questions about it and - // freaks out if it gets an error. So just return OK here. - return SendPacket ("OK"); - } - - errno = 0; - p += strlen("QSyncThreadState:"); - nub_thread_t tid = strtoul (p, NULL, 16); - if (errno != 0 && tid == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid thread number in QSyncThreadState packet"); - } - if (DNBProcessSyncThreadState(m_ctx.ProcessID(), tid)) + break; + } + if (success) + return SendPacket("OK"); + return SendPacket("E57"); + } + return SendPacket("E58"); +} + +rnb_err_t RNBRemote::HandlePacket_QSetWorkingDir(const char *p) { + // Only set the working directory if we don't already have a process + if (!m_ctx.HasValidProcessID()) { + StdStringExtractor packet(p += sizeof("QSetWorkingDir:") - 1); + if (packet.GetHexByteString(m_ctx.GetWorkingDir())) { + struct stat working_dir_stat; + if (::stat(m_ctx.GetWorkingDirPath(), &working_dir_stat) == -1) { + m_ctx.GetWorkingDir().clear(); + return SendPacket("E61"); // Working directory doesn't exist... + } else if ((working_dir_stat.st_mode & S_IFMT) == S_IFDIR) { return SendPacket("OK"); - else - return SendPacket ("E61"); -} - -rnb_err_t -RNBRemote::HandlePacket_QSetDetachOnError (const char *p) -{ - p += sizeof ("QSetDetachOnError:") - 1; - bool should_detach = true; - switch (*p) - { - case '0': should_detach = false; break; - case '1': should_detach = true; break; - default: - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid value for QSetDetachOnError - should be 0 or 1"); - break; + } else { + m_ctx.GetWorkingDir().clear(); + return SendPacket("E62"); // Working directory isn't a directory... + } } - - m_ctx.SetDetachOnError(should_detach); - return SendPacket ("OK"); + return SendPacket("E59"); // Invalid path + } + return SendPacket( + "E60"); // Already had a process, too late to set working dir } -rnb_err_t -RNBRemote::HandlePacket_qStructuredDataPlugins(const char *p) -{ - // We'll return a JSON array of supported packet types. - // The type is significant. For each of the supported - // packet types that have been enabled, there will be a - // 'J' async packet sent to the client with payload data. - // This payload data will be a JSON dictionary, and the - // top level dictionary will contain a string field with - // its value set to the relevant packet type from this list. - JSONGenerator::Array supported_json_packets; - - // Check for DarwinLog (libtrace os_log/activity support). - if (DarwinLogCollector::IsSupported()) - supported_json_packets.AddItem(JSONGenerator::StringSP( - new JSONGenerator::String("DarwinLog"))); - - // Send back the array. - std::ostringstream stream; - supported_json_packets.Dump(stream); - return SendPacket(stream.str()); -} - -rnb_err_t -RNBRemote::HandlePacket_QConfigureDarwinLog(const char *p) -{ - if (!DarwinLogCollector::IsSupported()) - { - // We should never have been given this request. - return SendPacket ("E89"); - } - - // Ensure we have a process. We expect a separate configure request for - // each process launched/attached. - const nub_process_t pid = m_ctx.ProcessID(); - if (pid == INVALID_NUB_PROCESS) - return SendPacket ("E94"); - - // Get the configuration dictionary. - p += strlen("QConfigureDarwinLog:"); - - // The configuration dictionary is binary encoded. - std::vector<uint8_t> unescaped_config_data = decode_binary_data(p, -1); - std::string unescaped_config_string((const char*)&unescaped_config_data[0], - unescaped_config_data.size()); - DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLog: received config data: \"%s\"", - unescaped_config_string.c_str()); - auto configuration_sp = - JSONParser(unescaped_config_string.c_str()).ParseJSONValue(); - if (!configuration_sp) - { - // Malformed request - we require configuration data - // indicating whether we're enabling or disabling. - return SendPacket("E90"); - } - - if (!JSONObject::classof(configuration_sp.get())) - { - // Configuration data is not of the right type. - return SendPacket("E91"); - } - JSONObject &config_dict = *static_cast<JSONObject*>(configuration_sp.get()); - - // Check if we're enabling or disabling. - auto enabled_sp = config_dict.GetObject("enabled"); - if (!enabled_sp) - { - // Missing required "enabled" field. - return SendPacket("E92"); - } - if (!JSONTrue::classof(enabled_sp.get()) && - !JSONFalse::classof(enabled_sp.get())) - { - // Should be a boolean type, but wasn't. - return SendPacket("E93"); - } - const bool enabling = JSONTrue::classof(enabled_sp.get()); - - // TODO - handle other configuration parameters here. - - // Shut down any active activity stream for the process. - DarwinLogCollector::CancelStreamForProcess(pid); - - if (enabling) - { - // Look up the procecess. - if (!DarwinLogCollector::StartCollectingForProcess(pid, config_dict)) - return SendPacket("E95"); - } - +rnb_err_t RNBRemote::HandlePacket_QSyncThreadState(const char *p) { + if (!m_ctx.HasValidProcessID()) { + // We allow gdb to connect to a server that hasn't started running + // the target yet. gdb still wants to ask questions about it and + // freaks out if it gets an error. So just return OK here. return SendPacket("OK"); -} - -rnb_err_t -RNBRemote::HandlePacket_QListThreadsInStopReply (const char *p) -{ - // If this packet is received, it allows us to send an extra key/value - // pair in the stop reply packets where we will list all of the thread IDs - // separated by commas: - // - // "threads:10a,10b,10c;" - // - // This will get included in the stop reply packet as something like: - // - // "T11thread:10a;00:00000000;01:00010203:threads:10a,10b,10c;" - // - // This can save two packets on each stop: qfThreadInfo/qsThreadInfo and - // speed things up a bit. - // - // Send the OK packet first so the correct checksum is appended... - rnb_err_t result = SendPacket ("OK"); - m_list_threads_in_stop_reply = true; - - return result; -} - - -rnb_err_t -RNBRemote::HandlePacket_QSetMaxPayloadSize (const char *p) -{ - /* The number of characters in a packet payload that gdb is - prepared to accept. The packet-start char, packet-end char, - 2 checksum chars and terminating null character are not included - in this size. */ - p += sizeof ("QSetMaxPayloadSize:") - 1; - errno = 0; - uint32_t size = static_cast<uint32_t>(strtoul (p, NULL, 16)); - if (errno != 0 && size == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in QSetMaxPayloadSize packet"); - } - m_max_payload_size = size; - return SendPacket ("OK"); -} - -rnb_err_t -RNBRemote::HandlePacket_QSetMaxPacketSize (const char *p) -{ - /* This tells us the largest packet that gdb can handle. - i.e. the size of gdb's packet-reading buffer. - QSetMaxPayloadSize is preferred because it is less ambiguous. */ - p += sizeof ("QSetMaxPacketSize:") - 1; + } + + errno = 0; + p += strlen("QSyncThreadState:"); + nub_thread_t tid = strtoul(p, NULL, 16); + if (errno != 0 && tid == 0) { + return HandlePacket_ILLFORMED( + __FILE__, __LINE__, p, + "Invalid thread number in QSyncThreadState packet"); + } + if (DNBProcessSyncThreadState(m_ctx.ProcessID(), tid)) + return SendPacket("OK"); + else + return SendPacket("E61"); +} + +rnb_err_t RNBRemote::HandlePacket_QSetDetachOnError(const char *p) { + p += sizeof("QSetDetachOnError:") - 1; + bool should_detach = true; + switch (*p) { + case '0': + should_detach = false; + break; + case '1': + should_detach = true; + break; + default: + return HandlePacket_ILLFORMED( + __FILE__, __LINE__, p, + "Invalid value for QSetDetachOnError - should be 0 or 1"); + break; + } + + m_ctx.SetDetachOnError(should_detach); + return SendPacket("OK"); +} + +rnb_err_t RNBRemote::HandlePacket_qStructuredDataPlugins(const char *p) { + // We'll return a JSON array of supported packet types. + // The type is significant. For each of the supported + // packet types that have been enabled, there will be a + // 'J' async packet sent to the client with payload data. + // This payload data will be a JSON dictionary, and the + // top level dictionary will contain a string field with + // its value set to the relevant packet type from this list. + JSONGenerator::Array supported_json_packets; + + // Check for DarwinLog (libtrace os_log/activity support). + if (DarwinLogCollector::IsSupported()) + supported_json_packets.AddItem( + JSONGenerator::StringSP(new JSONGenerator::String("DarwinLog"))); + + // Send back the array. + std::ostringstream stream; + supported_json_packets.Dump(stream); + return SendPacket(stream.str()); +} + +rnb_err_t RNBRemote::HandlePacket_QConfigureDarwinLog(const char *p) { + if (!DarwinLogCollector::IsSupported()) { + // We should never have been given this request. + return SendPacket("E89"); + } + + // Ensure we have a process. We expect a separate configure request for + // each process launched/attached. + const nub_process_t pid = m_ctx.ProcessID(); + if (pid == INVALID_NUB_PROCESS) + return SendPacket("E94"); + + // Get the configuration dictionary. + p += strlen("QConfigureDarwinLog:"); + + // The configuration dictionary is binary encoded. + std::vector<uint8_t> unescaped_config_data = decode_binary_data(p, -1); + std::string unescaped_config_string((const char *)&unescaped_config_data[0], + unescaped_config_data.size()); + DNBLogThreadedIf(LOG_DARWIN_LOG, "DarwinLog: received config data: \"%s\"", + unescaped_config_string.c_str()); + auto configuration_sp = + JSONParser(unescaped_config_string.c_str()).ParseJSONValue(); + if (!configuration_sp) { + // Malformed request - we require configuration data + // indicating whether we're enabling or disabling. + return SendPacket("E90"); + } + + if (!JSONObject::classof(configuration_sp.get())) { + // Configuration data is not of the right type. + return SendPacket("E91"); + } + JSONObject &config_dict = *static_cast<JSONObject *>(configuration_sp.get()); + + // Check if we're enabling or disabling. + auto enabled_sp = config_dict.GetObject("enabled"); + if (!enabled_sp) { + // Missing required "enabled" field. + return SendPacket("E92"); + } + if (!JSONTrue::classof(enabled_sp.get()) && + !JSONFalse::classof(enabled_sp.get())) { + // Should be a boolean type, but wasn't. + return SendPacket("E93"); + } + const bool enabling = JSONTrue::classof(enabled_sp.get()); + + // TODO - handle other configuration parameters here. + + // Shut down any active activity stream for the process. + DarwinLogCollector::CancelStreamForProcess(pid); + + if (enabling) { + // Look up the procecess. + if (!DarwinLogCollector::StartCollectingForProcess(pid, config_dict)) + return SendPacket("E95"); + } + + return SendPacket("OK"); +} + +rnb_err_t RNBRemote::HandlePacket_QListThreadsInStopReply(const char *p) { + // If this packet is received, it allows us to send an extra key/value + // pair in the stop reply packets where we will list all of the thread IDs + // separated by commas: + // + // "threads:10a,10b,10c;" + // + // This will get included in the stop reply packet as something like: + // + // "T11thread:10a;00:00000000;01:00010203:threads:10a,10b,10c;" + // + // This can save two packets on each stop: qfThreadInfo/qsThreadInfo and + // speed things up a bit. + // + // Send the OK packet first so the correct checksum is appended... + rnb_err_t result = SendPacket("OK"); + m_list_threads_in_stop_reply = true; + + return result; +} + +rnb_err_t RNBRemote::HandlePacket_QSetMaxPayloadSize(const char *p) { + /* The number of characters in a packet payload that gdb is + prepared to accept. The packet-start char, packet-end char, + 2 checksum chars and terminating null character are not included + in this size. */ + p += sizeof("QSetMaxPayloadSize:") - 1; + errno = 0; + uint32_t size = static_cast<uint32_t>(strtoul(p, NULL, 16)); + if (errno != 0 && size == 0) { + return HandlePacket_ILLFORMED( + __FILE__, __LINE__, p, "Invalid length in QSetMaxPayloadSize packet"); + } + m_max_payload_size = size; + return SendPacket("OK"); +} + +rnb_err_t RNBRemote::HandlePacket_QSetMaxPacketSize(const char *p) { + /* This tells us the largest packet that gdb can handle. + i.e. the size of gdb's packet-reading buffer. + QSetMaxPayloadSize is preferred because it is less ambiguous. */ + p += sizeof("QSetMaxPacketSize:") - 1; + errno = 0; + uint32_t size = static_cast<uint32_t>(strtoul(p, NULL, 16)); + if (errno != 0 && size == 0) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Invalid length in QSetMaxPacketSize packet"); + } + m_max_payload_size = size - 5; + return SendPacket("OK"); +} + +rnb_err_t RNBRemote::HandlePacket_QEnvironment(const char *p) { + /* This sets the environment for the target program. The packet is of the + form: + + QEnvironment:VARIABLE=VALUE + + */ + + DNBLogThreadedIf( + LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironment: \"%s\"", + (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p); + + p += sizeof("QEnvironment:") - 1; + RNBContext &ctx = Context(); + + ctx.PushEnvironment(p); + return SendPacket("OK"); +} + +rnb_err_t RNBRemote::HandlePacket_QEnvironmentHexEncoded(const char *p) { + /* This sets the environment for the target program. The packet is of the + form: + + QEnvironmentHexEncoded:VARIABLE=VALUE + + The VARIABLE=VALUE part is sent hex-encoded so characters like '#' with + special + meaning in the remote protocol won't break it. + */ + + DNBLogThreadedIf(LOG_RNB_REMOTE, + "%8u RNBRemote::%s Handling QEnvironmentHexEncoded: \"%s\"", + (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), + __FUNCTION__, p); + + p += sizeof("QEnvironmentHexEncoded:") - 1; + + std::string arg; + const char *c; + c = p; + while (*c != '\0') { + if (*(c + 1) == '\0') { + return HandlePacket_ILLFORMED( + __FILE__, __LINE__, p, + "non-hex char in arg on 'QEnvironmentHexEncoded' pkt"); + } + char smallbuf[3]; + smallbuf[0] = *c; + smallbuf[1] = *(c + 1); + smallbuf[2] = '\0'; errno = 0; - uint32_t size = static_cast<uint32_t>(strtoul (p, NULL, 16)); - if (errno != 0 && size == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in QSetMaxPacketSize packet"); + int ch = static_cast<int>(strtoul(smallbuf, NULL, 16)); + if (errno != 0 && ch == 0) { + return HandlePacket_ILLFORMED( + __FILE__, __LINE__, p, + "non-hex char in arg on 'QEnvironmentHexEncoded' pkt"); } - m_max_payload_size = size - 5; - return SendPacket ("OK"); -} - - - - -rnb_err_t -RNBRemote::HandlePacket_QEnvironment (const char *p) -{ - /* This sets the environment for the target program. The packet is of the form: - - QEnvironment:VARIABLE=VALUE - - */ - - DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironment: \"%s\"", - (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p); - - p += sizeof ("QEnvironment:") - 1; - RNBContext& ctx = Context(); - - ctx.PushEnvironment (p); - return SendPacket ("OK"); -} - -rnb_err_t -RNBRemote::HandlePacket_QEnvironmentHexEncoded (const char *p) -{ - /* This sets the environment for the target program. The packet is of the form: - - QEnvironmentHexEncoded:VARIABLE=VALUE - - The VARIABLE=VALUE part is sent hex-encoded so characters like '#' with special - meaning in the remote protocol won't break it. - */ - - DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironmentHexEncoded: \"%s\"", - (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p); - - p += sizeof ("QEnvironmentHexEncoded:") - 1; - - std::string arg; - const char *c; - c = p; - while (*c != '\0') - { - if (*(c + 1) == '\0') - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'QEnvironmentHexEncoded' pkt"); - } - char smallbuf[3]; - smallbuf[0] = *c; - smallbuf[1] = *(c + 1); - smallbuf[2] = '\0'; - errno = 0; - int ch = static_cast<int>(strtoul (smallbuf, NULL, 16)); - if (errno != 0 && ch == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'QEnvironmentHexEncoded' pkt"); - } - arg.push_back(ch); - c += 2; - } - - RNBContext& ctx = Context(); - if (arg.length() > 0) - ctx.PushEnvironment (arg.c_str()); - - return SendPacket ("OK"); -} + arg.push_back(ch); + c += 2; + } + RNBContext &ctx = Context(); + if (arg.length() > 0) + ctx.PushEnvironment(arg.c_str()); -rnb_err_t -RNBRemote::HandlePacket_QLaunchArch (const char *p) -{ - p += sizeof ("QLaunchArch:") - 1; - if (DNBSetArchitecture(p)) - return SendPacket ("OK"); - return SendPacket ("E63"); + return SendPacket("OK"); } -rnb_err_t -RNBRemote::HandlePacket_QSetProcessEvent (const char *p) -{ - p += sizeof ("QSetProcessEvent:") - 1; - // If the process is running, then send the event to the process, otherwise - // store it in the context. - if (Context().HasValidProcessID()) - { - if (DNBProcessSendEvent (Context().ProcessID(), p)) - return SendPacket("OK"); - else - return SendPacket ("E80"); - } - else - { - Context().PushProcessEvent(p); - } - return SendPacket ("OK"); +rnb_err_t RNBRemote::HandlePacket_QLaunchArch(const char *p) { + p += sizeof("QLaunchArch:") - 1; + if (DNBSetArchitecture(p)) + return SendPacket("OK"); + return SendPacket("E63"); } -void -append_hex_value (std::ostream& ostrm, const void *buf, size_t buf_size, bool swap) -{ - int i; - const uint8_t *p = (const uint8_t *)buf; - if (swap) - { - for (i = static_cast<int>(buf_size)-1; i >= 0; i--) - ostrm << RAWHEX8(p[i]); - } +rnb_err_t RNBRemote::HandlePacket_QSetProcessEvent(const char *p) { + p += sizeof("QSetProcessEvent:") - 1; + // If the process is running, then send the event to the process, otherwise + // store it in the context. + if (Context().HasValidProcessID()) { + if (DNBProcessSendEvent(Context().ProcessID(), p)) + return SendPacket("OK"); else - { - for (size_t i = 0; i < buf_size; i++) - ostrm << RAWHEX8(p[i]); - } -} - -void -append_hexified_string (std::ostream& ostrm, const std::string &string) -{ - size_t string_size = string.size(); - const char *string_buf = string.c_str(); - for (size_t i = 0; i < string_size; i++) - { - ostrm << RAWHEX8(*(string_buf + i)); - } -} - - - -void -register_value_in_hex_fixed_width (std::ostream& ostrm, - nub_process_t pid, - nub_thread_t tid, - const register_map_entry_t* reg, - const DNBRegisterValue *reg_value_ptr) -{ - if (reg != NULL) - { - DNBRegisterValue reg_value; - if (reg_value_ptr == NULL) - { - if (DNBThreadGetRegisterValueByID (pid, tid, reg->nub_info.set, reg->nub_info.reg, ®_value)) - reg_value_ptr = ®_value; - } - - if (reg_value_ptr) - { - append_hex_value (ostrm, reg_value_ptr->value.v_uint8, reg->nub_info.size, false); - } - else - { - // If we fail to read a register value, check if it has a default - // fail value. If it does, return this instead in case some of - // the registers are not available on the current system. - if (reg->nub_info.size > 0) - { - std::basic_string<uint8_t> zeros(reg->nub_info.size, '\0'); - append_hex_value (ostrm, zeros.data(), zeros.size(), false); - } - } - } -} - - -void -debugserver_regnum_with_fixed_width_hex_register_value (std::ostream& ostrm, - nub_process_t pid, - nub_thread_t tid, - const register_map_entry_t* reg, - const DNBRegisterValue *reg_value_ptr) -{ - // Output the register number as 'NN:VVVVVVVV;' where NN is a 2 bytes HEX - // gdb register number, and VVVVVVVV is the correct number of hex bytes - // as ASCII for the register value. - if (reg != NULL) - { - ostrm << RAWHEX8(reg->debugserver_regnum) << ':'; - register_value_in_hex_fixed_width (ostrm, pid, tid, reg, reg_value_ptr); - ostrm << ';'; + return SendPacket("E80"); + } else { + Context().PushProcessEvent(p); + } + return SendPacket("OK"); +} + +void append_hex_value(std::ostream &ostrm, const void *buf, size_t buf_size, + bool swap) { + int i; + const uint8_t *p = (const uint8_t *)buf; + if (swap) { + for (i = static_cast<int>(buf_size) - 1; i >= 0; i--) + ostrm << RAWHEX8(p[i]); + } else { + for (size_t i = 0; i < buf_size; i++) + ostrm << RAWHEX8(p[i]); + } +} + +void append_hexified_string(std::ostream &ostrm, const std::string &string) { + size_t string_size = string.size(); + const char *string_buf = string.c_str(); + for (size_t i = 0; i < string_size; i++) { + ostrm << RAWHEX8(*(string_buf + i)); + } +} + +void register_value_in_hex_fixed_width(std::ostream &ostrm, nub_process_t pid, + nub_thread_t tid, + const register_map_entry_t *reg, + const DNBRegisterValue *reg_value_ptr) { + if (reg != NULL) { + DNBRegisterValue reg_value; + if (reg_value_ptr == NULL) { + if (DNBThreadGetRegisterValueByID(pid, tid, reg->nub_info.set, + reg->nub_info.reg, ®_value)) + reg_value_ptr = ®_value; + } + + if (reg_value_ptr) { + append_hex_value(ostrm, reg_value_ptr->value.v_uint8, reg->nub_info.size, + false); + } else { + // If we fail to read a register value, check if it has a default + // fail value. If it does, return this instead in case some of + // the registers are not available on the current system. + if (reg->nub_info.size > 0) { + std::basic_string<uint8_t> zeros(reg->nub_info.size, '\0'); + append_hex_value(ostrm, zeros.data(), zeros.size(), false); + } } -} - - -void -RNBRemote::DispatchQueueOffsets::GetThreadQueueInfo (nub_process_t pid, - nub_addr_t dispatch_qaddr, - nub_addr_t &dispatch_queue_t, - std::string &queue_name, - uint64_t &queue_width, - uint64_t &queue_serialnum) const -{ - queue_name.clear(); - queue_width = 0; - queue_serialnum = 0; - - if (IsValid() && dispatch_qaddr != INVALID_NUB_ADDRESS && dispatch_qaddr != 0) - { - dispatch_queue_t = DNBProcessMemoryReadPointer (pid, dispatch_qaddr); - if (dispatch_queue_t) - { - queue_width = DNBProcessMemoryReadInteger (pid, dispatch_queue_t + dqo_width, dqo_width_size, 0); - queue_serialnum = DNBProcessMemoryReadInteger (pid, dispatch_queue_t + dqo_serialnum, dqo_serialnum_size, 0); - - if (dqo_version >= 4) - { - // libdispatch versions 4+, pointer to dispatch name is in the - // queue structure. - nub_addr_t pointer_to_label_address = dispatch_queue_t + dqo_label; - nub_addr_t label_addr = DNBProcessMemoryReadPointer (pid, pointer_to_label_address); - if (label_addr) - queue_name = DNBProcessMemoryReadCString(pid, label_addr); - } - else - { - // libdispatch versions 1-3, dispatch name is a fixed width char array - // in the queue structure. - queue_name = DNBProcessMemoryReadCStringFixed(pid, dispatch_queue_t + dqo_label, dqo_label_size); - } - } + } +} + +void debugserver_regnum_with_fixed_width_hex_register_value( + std::ostream &ostrm, nub_process_t pid, nub_thread_t tid, + const register_map_entry_t *reg, const DNBRegisterValue *reg_value_ptr) { + // Output the register number as 'NN:VVVVVVVV;' where NN is a 2 bytes HEX + // gdb register number, and VVVVVVVV is the correct number of hex bytes + // as ASCII for the register value. + if (reg != NULL) { + ostrm << RAWHEX8(reg->debugserver_regnum) << ':'; + register_value_in_hex_fixed_width(ostrm, pid, tid, reg, reg_value_ptr); + ostrm << ';'; + } +} + +void RNBRemote::DispatchQueueOffsets::GetThreadQueueInfo( + nub_process_t pid, nub_addr_t dispatch_qaddr, nub_addr_t &dispatch_queue_t, + std::string &queue_name, uint64_t &queue_width, + uint64_t &queue_serialnum) const { + queue_name.clear(); + queue_width = 0; + queue_serialnum = 0; + + if (IsValid() && dispatch_qaddr != INVALID_NUB_ADDRESS && + dispatch_qaddr != 0) { + dispatch_queue_t = DNBProcessMemoryReadPointer(pid, dispatch_qaddr); + if (dispatch_queue_t) { + queue_width = DNBProcessMemoryReadInteger( + pid, dispatch_queue_t + dqo_width, dqo_width_size, 0); + queue_serialnum = DNBProcessMemoryReadInteger( + pid, dispatch_queue_t + dqo_serialnum, dqo_serialnum_size, 0); + + if (dqo_version >= 4) { + // libdispatch versions 4+, pointer to dispatch name is in the + // queue structure. + nub_addr_t pointer_to_label_address = dispatch_queue_t + dqo_label; + nub_addr_t label_addr = + DNBProcessMemoryReadPointer(pid, pointer_to_label_address); + if (label_addr) + queue_name = DNBProcessMemoryReadCString(pid, label_addr); + } else { + // libdispatch versions 1-3, dispatch name is a fixed width char array + // in the queue structure. + queue_name = DNBProcessMemoryReadCStringFixed( + pid, dispatch_queue_t + dqo_label, dqo_label_size); + } } + } } -struct StackMemory -{ - uint8_t bytes[2*sizeof(nub_addr_t)]; - nub_size_t length; +struct StackMemory { + uint8_t bytes[2 * sizeof(nub_addr_t)]; + nub_size_t length; }; typedef std::map<nub_addr_t, StackMemory> StackMemoryMap; +static void ReadStackMemory(nub_process_t pid, nub_thread_t tid, + StackMemoryMap &stack_mmap, + uint32_t backtrace_limit = 256) { + DNBRegisterValue reg_value; + if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC, + GENERIC_REGNUM_FP, ®_value)) { + uint32_t frame_count = 0; + uint64_t fp = 0; + if (reg_value.info.size == 4) + fp = reg_value.value.uint32; + else + fp = reg_value.value.uint64; + while (fp != 0) { + // Make sure we never recurse more than 256 times so we don't recurse too + // far or + // store up too much memory in the expedited cache + if (++frame_count > backtrace_limit) + break; -static void -ReadStackMemory (nub_process_t pid, nub_thread_t tid, StackMemoryMap &stack_mmap, uint32_t backtrace_limit = 256) -{ - DNBRegisterValue reg_value; - if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC, GENERIC_REGNUM_FP, ®_value)) - { - uint32_t frame_count = 0; - uint64_t fp = 0; - if (reg_value.info.size == 4) - fp = reg_value.value.uint32; - else - fp = reg_value.value.uint64; - while (fp != 0) - { - // Make sure we never recurse more than 256 times so we don't recurse too far or - // store up too much memory in the expedited cache - if (++frame_count > backtrace_limit) - break; - - const nub_size_t read_size = reg_value.info.size*2; - StackMemory stack_memory; - stack_memory.length = read_size; - if (DNBProcessMemoryRead(pid, fp, read_size, stack_memory.bytes) != read_size) - break; - // Make sure we don't try to put the same stack memory in more than once - if (stack_mmap.find(fp) != stack_mmap.end()) - break; - // Put the entry into the cache - stack_mmap[fp] = stack_memory; - // Dereference the frame pointer to get to the previous frame pointer - if (reg_value.info.size == 4) - fp = ((uint32_t *)stack_memory.bytes)[0]; - else - fp = ((uint64_t *)stack_memory.bytes)[0]; - } + const nub_size_t read_size = reg_value.info.size * 2; + StackMemory stack_memory; + stack_memory.length = read_size; + if (DNBProcessMemoryRead(pid, fp, read_size, stack_memory.bytes) != + read_size) + break; + // Make sure we don't try to put the same stack memory in more than once + if (stack_mmap.find(fp) != stack_mmap.end()) + break; + // Put the entry into the cache + stack_mmap[fp] = stack_memory; + // Dereference the frame pointer to get to the previous frame pointer + if (reg_value.info.size == 4) + fp = ((uint32_t *)stack_memory.bytes)[0]; + else + fp = ((uint64_t *)stack_memory.bytes)[0]; } + } } -rnb_err_t -RNBRemote::SendStopReplyPacketForThread (nub_thread_t tid) -{ - const nub_process_t pid = m_ctx.ProcessID(); - if (pid == INVALID_NUB_PROCESS) - return SendPacket("E50"); - - struct DNBThreadStopInfo tid_stop_info; - - /* Fill the remaining space in this packet with as many registers - as we can stuff in there. */ - - if (DNBThreadGetStopReason (pid, tid, &tid_stop_info)) - { - const bool did_exec = tid_stop_info.reason == eStopTypeExec; - if (did_exec) - { - RNBRemote::InitializeRegisters(true); - - // Reset any symbols that need resetting when we exec - m_dispatch_queue_offsets_addr = INVALID_NUB_ADDRESS; - m_dispatch_queue_offsets.Clear(); - } +rnb_err_t RNBRemote::SendStopReplyPacketForThread(nub_thread_t tid) { + const nub_process_t pid = m_ctx.ProcessID(); + if (pid == INVALID_NUB_PROCESS) + return SendPacket("E50"); - std::ostringstream ostrm; - // Output the T packet with the thread - ostrm << 'T'; - int signum = tid_stop_info.details.signal.signo; - DNBLogThreadedIf (LOG_RNB_PROC, "%8d %s got signal signo = %u, exc_type = %u", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, signum, tid_stop_info.details.exception.type); + struct DNBThreadStopInfo tid_stop_info; - // Translate any mach exceptions to gdb versions, unless they are - // common exceptions like a breakpoint or a soft signal. - switch (tid_stop_info.details.exception.type) - { - default: signum = 0; break; - case EXC_BREAKPOINT: signum = SIGTRAP; break; - case EXC_BAD_ACCESS: signum = TARGET_EXC_BAD_ACCESS; break; - case EXC_BAD_INSTRUCTION: signum = TARGET_EXC_BAD_INSTRUCTION; break; - case EXC_ARITHMETIC: signum = TARGET_EXC_ARITHMETIC; break; - case EXC_EMULATION: signum = TARGET_EXC_EMULATION; break; - case EXC_SOFTWARE: - if (tid_stop_info.details.exception.data_count == 2 && - tid_stop_info.details.exception.data[0] == EXC_SOFT_SIGNAL) - signum = static_cast<int>(tid_stop_info.details.exception.data[1]); - else - signum = TARGET_EXC_SOFTWARE; - break; - } + /* Fill the remaining space in this packet with as many registers + as we can stuff in there. */ - ostrm << RAWHEX8(signum & 0xff); + if (DNBThreadGetStopReason(pid, tid, &tid_stop_info)) { + const bool did_exec = tid_stop_info.reason == eStopTypeExec; + if (did_exec) { + RNBRemote::InitializeRegisters(true); - ostrm << std::hex << "thread:" << tid << ';'; + // Reset any symbols that need resetting when we exec + m_dispatch_queue_offsets_addr = INVALID_NUB_ADDRESS; + m_dispatch_queue_offsets.Clear(); + } - const char *thread_name = DNBThreadGetName (pid, tid); - if (thread_name && thread_name[0]) - { - size_t thread_name_len = strlen(thread_name); - + std::ostringstream ostrm; + // Output the T packet with the thread + ostrm << 'T'; + int signum = tid_stop_info.details.signal.signo; + DNBLogThreadedIf( + LOG_RNB_PROC, "%8d %s got signal signo = %u, exc_type = %u", + (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, + signum, tid_stop_info.details.exception.type); + + // Translate any mach exceptions to gdb versions, unless they are + // common exceptions like a breakpoint or a soft signal. + switch (tid_stop_info.details.exception.type) { + default: + signum = 0; + break; + case EXC_BREAKPOINT: + signum = SIGTRAP; + break; + case EXC_BAD_ACCESS: + signum = TARGET_EXC_BAD_ACCESS; + break; + case EXC_BAD_INSTRUCTION: + signum = TARGET_EXC_BAD_INSTRUCTION; + break; + case EXC_ARITHMETIC: + signum = TARGET_EXC_ARITHMETIC; + break; + case EXC_EMULATION: + signum = TARGET_EXC_EMULATION; + break; + case EXC_SOFTWARE: + if (tid_stop_info.details.exception.data_count == 2 && + tid_stop_info.details.exception.data[0] == EXC_SOFT_SIGNAL) + signum = static_cast<int>(tid_stop_info.details.exception.data[1]); + else + signum = TARGET_EXC_SOFTWARE; + break; + } + + ostrm << RAWHEX8(signum & 0xff); + + ostrm << std::hex << "thread:" << tid << ';'; + + const char *thread_name = DNBThreadGetName(pid, tid); + if (thread_name && thread_name[0]) { + size_t thread_name_len = strlen(thread_name); + + if (::strcspn(thread_name, "$#+-;:") == thread_name_len) + ostrm << std::hex << "name:" << thread_name << ';'; + else { + // the thread name contains special chars, send as hex bytes + ostrm << std::hex << "hexname:"; + uint8_t *u_thread_name = (uint8_t *)thread_name; + for (size_t i = 0; i < thread_name_len; i++) + ostrm << RAWHEX8(u_thread_name[i]); + ostrm << ';'; + } + } - if (::strcspn (thread_name, "$#+-;:") == thread_name_len) - ostrm << std::hex << "name:" << thread_name << ';'; - else - { - // the thread name contains special chars, send as hex bytes - ostrm << std::hex << "hexname:"; - uint8_t *u_thread_name = (uint8_t *)thread_name; - for (size_t i = 0; i < thread_name_len; i++) - ostrm << RAWHEX8(u_thread_name[i]); - ostrm << ';'; + // If a 'QListThreadsInStopReply' was sent to enable this feature, we + // will send all thread IDs back in the "threads" key whose value is + // a list of hex thread IDs separated by commas: + // "threads:10a,10b,10c;" + // This will save the debugger from having to send a pair of qfThreadInfo + // and qsThreadInfo packets, but it also might take a lot of room in the + // stop reply packet, so it must be enabled only on systems where there + // are no limits on packet lengths. + if (m_list_threads_in_stop_reply) { + const nub_size_t numthreads = DNBProcessGetNumThreads(pid); + if (numthreads > 0) { + std::vector<uint64_t> pc_values; + ostrm << std::hex << "threads:"; + for (nub_size_t i = 0; i < numthreads; ++i) { + nub_thread_t th = DNBProcessGetThreadAtIndex(pid, i); + if (i > 0) + ostrm << ','; + ostrm << std::hex << th; + DNBRegisterValue pc_regval; + if (DNBThreadGetRegisterValueByID(pid, th, REGISTER_SET_GENERIC, + GENERIC_REGNUM_PC, &pc_regval)) { + uint64_t pc = INVALID_NUB_ADDRESS; + if (pc_regval.value.uint64 != INVALID_NUB_ADDRESS) { + if (pc_regval.info.size == 4) { + pc = pc_regval.value.uint32; + } else if (pc_regval.info.size == 8) { + pc = pc_regval.value.uint64; + } + if (pc != INVALID_NUB_ADDRESS) { + pc_values.push_back(pc); + } } + } } + ostrm << ';'; - // If a 'QListThreadsInStopReply' was sent to enable this feature, we - // will send all thread IDs back in the "threads" key whose value is - // a list of hex thread IDs separated by commas: - // "threads:10a,10b,10c;" - // This will save the debugger from having to send a pair of qfThreadInfo - // and qsThreadInfo packets, but it also might take a lot of room in the - // stop reply packet, so it must be enabled only on systems where there - // are no limits on packet lengths. - if (m_list_threads_in_stop_reply) - { - const nub_size_t numthreads = DNBProcessGetNumThreads (pid); - if (numthreads > 0) - { - std::vector<uint64_t> pc_values; - ostrm << std::hex << "threads:"; - for (nub_size_t i = 0; i < numthreads; ++i) - { - nub_thread_t th = DNBProcessGetThreadAtIndex (pid, i); - if (i > 0) - ostrm << ','; - ostrm << std::hex << th; - DNBRegisterValue pc_regval; - if (DNBThreadGetRegisterValueByID (pid, th, REGISTER_SET_GENERIC, GENERIC_REGNUM_PC, &pc_regval)) - { - uint64_t pc = INVALID_NUB_ADDRESS; - if (pc_regval.value.uint64 != INVALID_NUB_ADDRESS) - { - if (pc_regval.info.size == 4) - { - pc = pc_regval.value.uint32; - } - else if (pc_regval.info.size == 8) - { - pc = pc_regval.value.uint64; - } - if (pc != INVALID_NUB_ADDRESS) - { - pc_values.push_back (pc); - } - } - } - } - ostrm << ';'; - - // If we failed to get any of the thread pc values, the size of our vector will not - // be the same as the # of threads. Don't provide any expedited thread pc values in - // that case. This should not happen. - if (pc_values.size() == numthreads) - { - ostrm << std::hex << "thread-pcs:"; - for (nub_size_t i = 0; i < numthreads; ++i) - { - if (i > 0) - ostrm << ','; - ostrm << std::hex << pc_values[i]; - } - ostrm << ';'; - } - } - - // Include JSON info that describes the stop reason for any threads - // that actually have stop reasons. We use the new "jstopinfo" key - // whose values is hex ascii JSON that contains the thread IDs - // thread stop info only for threads that have stop reasons. Only send - // this if we have more than one thread otherwise this packet has all - // the info it needs. - if (numthreads > 1) - { - const bool threads_with_valid_stop_info_only = true; - JSONGenerator::ObjectSP threads_info_sp = GetJSONThreadsInfo(threads_with_valid_stop_info_only); - if (threads_info_sp) - { - ostrm << std::hex << "jstopinfo:"; - std::ostringstream json_strm; - threads_info_sp->Dump (json_strm); - append_hexified_string (ostrm, json_strm.str()); - ostrm << ';'; - } - } + // If we failed to get any of the thread pc values, the size of our + // vector will not + // be the same as the # of threads. Don't provide any expedited thread + // pc values in + // that case. This should not happen. + if (pc_values.size() == numthreads) { + ostrm << std::hex << "thread-pcs:"; + for (nub_size_t i = 0; i < numthreads; ++i) { + if (i > 0) + ostrm << ','; + ostrm << std::hex << pc_values[i]; + } + ostrm << ';'; } + } - if (g_num_reg_entries == 0) - InitializeRegisters (); - - if (g_reg_entries != NULL) - { - DNBRegisterValue reg_value; - for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) - { - // Expedite all registers in the first register set that aren't - // contained in other registers - if (g_reg_entries[reg].nub_info.set == 1 && - g_reg_entries[reg].nub_info.value_regs == NULL) - { - if (!DNBThreadGetRegisterValueByID (pid, tid, g_reg_entries[reg].nub_info.set, g_reg_entries[reg].nub_info.reg, ®_value)) - continue; - - debugserver_regnum_with_fixed_width_hex_register_value (ostrm, pid, tid, &g_reg_entries[reg], ®_value); - } - } - } - - if (did_exec) - { - ostrm << "reason:exec;"; - } - else if (tid_stop_info.details.exception.type) - { - ostrm << "metype:" << std::hex << tid_stop_info.details.exception.type << ';'; - ostrm << "mecount:" << std::hex << tid_stop_info.details.exception.data_count << ';'; - for (nub_size_t i = 0; i < tid_stop_info.details.exception.data_count; ++i) - ostrm << "medata:" << std::hex << tid_stop_info.details.exception.data[i] << ';'; + // Include JSON info that describes the stop reason for any threads + // that actually have stop reasons. We use the new "jstopinfo" key + // whose values is hex ascii JSON that contains the thread IDs + // thread stop info only for threads that have stop reasons. Only send + // this if we have more than one thread otherwise this packet has all + // the info it needs. + if (numthreads > 1) { + const bool threads_with_valid_stop_info_only = true; + JSONGenerator::ObjectSP threads_info_sp = + GetJSONThreadsInfo(threads_with_valid_stop_info_only); + if (threads_info_sp) { + ostrm << std::hex << "jstopinfo:"; + std::ostringstream json_strm; + threads_info_sp->Dump(json_strm); + append_hexified_string(ostrm, json_strm.str()); + ostrm << ';'; } + } + } - // Add expedited stack memory so stack backtracing doesn't need to read anything from the - // frame pointer chain. - StackMemoryMap stack_mmap; - ReadStackMemory (pid, tid, stack_mmap, 2); - if (!stack_mmap.empty()) - { - for (const auto &stack_memory : stack_mmap) - { - ostrm << "memory:" << HEXBASE << stack_memory.first << '='; - append_hex_value (ostrm, stack_memory.second.bytes, stack_memory.second.length, false); - ostrm << ';'; - } + if (g_num_reg_entries == 0) + InitializeRegisters(); + + if (g_reg_entries != NULL) { + DNBRegisterValue reg_value; + for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) { + // Expedite all registers in the first register set that aren't + // contained in other registers + if (g_reg_entries[reg].nub_info.set == 1 && + g_reg_entries[reg].nub_info.value_regs == NULL) { + if (!DNBThreadGetRegisterValueByID( + pid, tid, g_reg_entries[reg].nub_info.set, + g_reg_entries[reg].nub_info.reg, ®_value)) + continue; + + debugserver_regnum_with_fixed_width_hex_register_value( + ostrm, pid, tid, &g_reg_entries[reg], ®_value); } + } + } - return SendPacket (ostrm.str ()); + if (did_exec) { + ostrm << "reason:exec;"; + } else if (tid_stop_info.details.exception.type) { + ostrm << "metype:" << std::hex << tid_stop_info.details.exception.type + << ';'; + ostrm << "mecount:" << std::hex + << tid_stop_info.details.exception.data_count << ';'; + for (nub_size_t i = 0; i < tid_stop_info.details.exception.data_count; + ++i) + ostrm << "medata:" << std::hex + << tid_stop_info.details.exception.data[i] << ';'; + } + + // Add expedited stack memory so stack backtracing doesn't need to read + // anything from the + // frame pointer chain. + StackMemoryMap stack_mmap; + ReadStackMemory(pid, tid, stack_mmap, 2); + if (!stack_mmap.empty()) { + for (const auto &stack_memory : stack_mmap) { + ostrm << "memory:" << HEXBASE << stack_memory.first << '='; + append_hex_value(ostrm, stack_memory.second.bytes, + stack_memory.second.length, false); + ostrm << ';'; + } } - return SendPacket("E51"); + + return SendPacket(ostrm.str()); + } + return SendPacket("E51"); } /* '?' The stop reply packet - tell gdb what the status of the inferior is. Often called the questionmark_packet. */ -rnb_err_t -RNBRemote::HandlePacket_last_signal (const char *unused) -{ - if (!m_ctx.HasValidProcessID()) - { - // Inferior is not yet specified/running - return SendPacket ("E02"); - } - - nub_process_t pid = m_ctx.ProcessID(); - nub_state_t pid_state = DNBProcessGetState (pid); - - switch (pid_state) - { - case eStateAttaching: - case eStateLaunching: - case eStateRunning: - case eStateStepping: - case eStateDetached: - return rnb_success; // Ignore - - case eStateSuspended: - case eStateStopped: - case eStateCrashed: - { - nub_thread_t tid = DNBProcessGetCurrentThread (pid); - // Make sure we set the current thread so g and p packets return - // the data the gdb will expect. - SetCurrentThread (tid); - - SendStopReplyPacketForThread (tid); - } - break; - - case eStateInvalid: - case eStateUnloaded: - case eStateExited: - { - char pid_exited_packet[16] = ""; - int pid_status = 0; - // Process exited with exit status - if (!DNBProcessGetExitStatus(pid, &pid_status)) - pid_status = 0; - - if (pid_status) - { - if (WIFEXITED (pid_status)) - snprintf (pid_exited_packet, sizeof(pid_exited_packet), "W%02x", WEXITSTATUS (pid_status)); - else if (WIFSIGNALED (pid_status)) - snprintf (pid_exited_packet, sizeof(pid_exited_packet), "X%02x", WEXITSTATUS (pid_status)); - else if (WIFSTOPPED (pid_status)) - snprintf (pid_exited_packet, sizeof(pid_exited_packet), "S%02x", WSTOPSIG (pid_status)); - } - - // If we have an empty exit packet, lets fill one in to be safe. - if (!pid_exited_packet[0]) - { - strncpy (pid_exited_packet, "W00", sizeof(pid_exited_packet)-1); - pid_exited_packet[sizeof(pid_exited_packet)-1] = '\0'; - } - - const char *exit_info = DNBProcessGetExitInfo (pid); - if (exit_info != NULL && *exit_info != '\0') - { - std::ostringstream exit_packet; - exit_packet << pid_exited_packet; - exit_packet << ';'; - exit_packet << RAW_HEXBASE << "description"; - exit_packet << ':'; - for (size_t i = 0; exit_info[i] != '\0'; i++) - exit_packet << RAWHEX8(exit_info[i]); - exit_packet << ';'; - return SendPacket (exit_packet.str()); - } - else - return SendPacket (pid_exited_packet); - } - break; - } - return rnb_success; -} - -rnb_err_t -RNBRemote::HandlePacket_M (const char *p) -{ - if (p == NULL || p[0] == '\0' || strlen (p) < 3) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short M packet"); - } - - char *c; - p++; - errno = 0; - nub_addr_t addr = strtoull (p, &c, 16); - if (errno != 0 && addr == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in M packet"); - } - if (*c != ',') - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in M packet"); - } +rnb_err_t RNBRemote::HandlePacket_last_signal(const char *unused) { + if (!m_ctx.HasValidProcessID()) { + // Inferior is not yet specified/running + return SendPacket("E02"); + } + + nub_process_t pid = m_ctx.ProcessID(); + nub_state_t pid_state = DNBProcessGetState(pid); + + switch (pid_state) { + case eStateAttaching: + case eStateLaunching: + case eStateRunning: + case eStateStepping: + case eStateDetached: + return rnb_success; // Ignore + + case eStateSuspended: + case eStateStopped: + case eStateCrashed: { + nub_thread_t tid = DNBProcessGetCurrentThread(pid); + // Make sure we set the current thread so g and p packets return + // the data the gdb will expect. + SetCurrentThread(tid); + + SendStopReplyPacketForThread(tid); + } break; + + case eStateInvalid: + case eStateUnloaded: + case eStateExited: { + char pid_exited_packet[16] = ""; + int pid_status = 0; + // Process exited with exit status + if (!DNBProcessGetExitStatus(pid, &pid_status)) + pid_status = 0; + + if (pid_status) { + if (WIFEXITED(pid_status)) + snprintf(pid_exited_packet, sizeof(pid_exited_packet), "W%02x", + WEXITSTATUS(pid_status)); + else if (WIFSIGNALED(pid_status)) + snprintf(pid_exited_packet, sizeof(pid_exited_packet), "X%02x", + WEXITSTATUS(pid_status)); + else if (WIFSTOPPED(pid_status)) + snprintf(pid_exited_packet, sizeof(pid_exited_packet), "S%02x", + WSTOPSIG(pid_status)); + } + + // If we have an empty exit packet, lets fill one in to be safe. + if (!pid_exited_packet[0]) { + strncpy(pid_exited_packet, "W00", sizeof(pid_exited_packet) - 1); + pid_exited_packet[sizeof(pid_exited_packet) - 1] = '\0'; + } + + const char *exit_info = DNBProcessGetExitInfo(pid); + if (exit_info != NULL && *exit_info != '\0') { + std::ostringstream exit_packet; + exit_packet << pid_exited_packet; + exit_packet << ';'; + exit_packet << RAW_HEXBASE << "description"; + exit_packet << ':'; + for (size_t i = 0; exit_info[i] != '\0'; i++) + exit_packet << RAWHEX8(exit_info[i]); + exit_packet << ';'; + return SendPacket(exit_packet.str()); + } else + return SendPacket(pid_exited_packet); + } break; + } + return rnb_success; +} + +rnb_err_t RNBRemote::HandlePacket_M(const char *p) { + if (p == NULL || p[0] == '\0' || strlen(p) < 3) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short M packet"); + } + + char *c; + p++; + errno = 0; + nub_addr_t addr = strtoull(p, &c, 16); + if (errno != 0 && addr == 0) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Invalid address in M packet"); + } + if (*c != ',') { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Comma sep missing in M packet"); + } + + /* Advance 'p' to the length part of the packet. */ + p += (c - p) + 1; + + errno = 0; + unsigned long length = strtoul(p, &c, 16); + if (errno != 0 && length == 0) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Invalid length in M packet"); + } + if (length == 0) { + return SendPacket("OK"); + } + + if (*c != ':') { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Missing colon in M packet"); + } + /* Advance 'p' to the data part of the packet. */ + p += (c - p) + 1; + + size_t datalen = strlen(p); + if (datalen & 0x1) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Uneven # of hex chars for data in M packet"); + } + if (datalen == 0) { + return SendPacket("OK"); + } - /* Advance 'p' to the length part of the packet. */ - p += (c - p) + 1; + uint8_t *buf = (uint8_t *)alloca(datalen / 2); + uint8_t *i = buf; + while (*p != '\0' && *(p + 1) != '\0') { + char hexbuf[3]; + hexbuf[0] = *p; + hexbuf[1] = *(p + 1); + hexbuf[2] = '\0'; errno = 0; - unsigned long length = strtoul (p, &c, 16); - if (errno != 0 && length == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in M packet"); - } - if (length == 0) - { - return SendPacket ("OK"); - } - - if (*c != ':') - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Missing colon in M packet"); - } - /* Advance 'p' to the data part of the packet. */ - p += (c - p) + 1; - - size_t datalen = strlen (p); - if (datalen & 0x1) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Uneven # of hex chars for data in M packet"); - } - if (datalen == 0) - { - return SendPacket ("OK"); - } - - uint8_t *buf = (uint8_t *) alloca (datalen / 2); - uint8_t *i = buf; - - while (*p != '\0' && *(p + 1) != '\0') - { - char hexbuf[3]; - hexbuf[0] = *p; - hexbuf[1] = *(p + 1); - hexbuf[2] = '\0'; - errno = 0; - uint8_t byte = strtoul (hexbuf, NULL, 16); - if (errno != 0 && byte == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid hex byte in M packet"); - } - *i++ = byte; - p += 2; - } - - nub_size_t wrote = DNBProcessMemoryWrite (m_ctx.ProcessID(), addr, length, buf); - if (wrote != length) - return SendPacket ("E09"); - else - return SendPacket ("OK"); + uint8_t byte = strtoul(hexbuf, NULL, 16); + if (errno != 0 && byte == 0) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Invalid hex byte in M packet"); + } + *i++ = byte; + p += 2; + } + + nub_size_t wrote = + DNBProcessMemoryWrite(m_ctx.ProcessID(), addr, length, buf); + if (wrote != length) + return SendPacket("E09"); + else + return SendPacket("OK"); } - -rnb_err_t -RNBRemote::HandlePacket_m (const char *p) -{ - if (p == NULL || p[0] == '\0' || strlen (p) < 3) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short m packet"); - } - - char *c; - p++; - errno = 0; - nub_addr_t addr = strtoull (p, &c, 16); - if (errno != 0 && addr == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in m packet"); - } - if (*c != ',') - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in m packet"); - } - - /* Advance 'p' to the length part of the packet. */ - p += (c - p) + 1; - - errno = 0; - auto length = strtoul (p, NULL, 16); - if (errno != 0 && length == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in m packet"); - } - if (length == 0) - { - return SendPacket (""); - } - - std::string buf(length, '\0'); - if (buf.empty()) - { - return SendPacket ("E78"); - } - nub_size_t bytes_read = DNBProcessMemoryRead (m_ctx.ProcessID(), addr, buf.size(), &buf[0]); - if (bytes_read == 0) - { - return SendPacket ("E08"); - } - - // "The reply may contain fewer bytes than requested if the server was able - // to read only part of the region of memory." - length = bytes_read; - - std::ostringstream ostrm; - for (unsigned long i = 0; i < length; i++) - ostrm << RAWHEX8(buf[i]); - return SendPacket (ostrm.str ()); +rnb_err_t RNBRemote::HandlePacket_m(const char *p) { + if (p == NULL || p[0] == '\0' || strlen(p) < 3) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short m packet"); + } + + char *c; + p++; + errno = 0; + nub_addr_t addr = strtoull(p, &c, 16); + if (errno != 0 && addr == 0) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Invalid address in m packet"); + } + if (*c != ',') { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Comma sep missing in m packet"); + } + + /* Advance 'p' to the length part of the packet. */ + p += (c - p) + 1; + + errno = 0; + auto length = strtoul(p, NULL, 16); + if (errno != 0 && length == 0) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Invalid length in m packet"); + } + if (length == 0) { + return SendPacket(""); + } + + std::string buf(length, '\0'); + if (buf.empty()) { + return SendPacket("E78"); + } + nub_size_t bytes_read = + DNBProcessMemoryRead(m_ctx.ProcessID(), addr, buf.size(), &buf[0]); + if (bytes_read == 0) { + return SendPacket("E08"); + } + + // "The reply may contain fewer bytes than requested if the server was able + // to read only part of the region of memory." + length = bytes_read; + + std::ostringstream ostrm; + for (unsigned long i = 0; i < length; i++) + ostrm << RAWHEX8(buf[i]); + return SendPacket(ostrm.str()); } // Read memory, sent it up as binary data. @@ -3284,137 +3200,127 @@ RNBRemote::HandlePacket_m (const char *p) // ADDR and LEN are both base 16. // Responds with 'OK' for zero-length request -// or +// or // // DATA // // where DATA is the binary data payload. -rnb_err_t -RNBRemote::HandlePacket_x (const char *p) -{ - if (p == NULL || p[0] == '\0' || strlen (p) < 3) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short X packet"); - } - - char *c; - p++; - errno = 0; - nub_addr_t addr = strtoull (p, &c, 16); - if (errno != 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in X packet"); - } - if (*c != ',') - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in X packet"); - } - - /* Advance 'p' to the number of bytes to be read. */ - p += (c - p) + 1; - - errno = 0; - auto length = strtoul (p, NULL, 16); - if (errno != 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in x packet"); - } - - // zero length read means this is a test of whether that packet is implemented or not. - if (length == 0) - { - return SendPacket ("OK"); - } - - std::vector<uint8_t> buf (length); - - if (buf.capacity() != length) - { - return SendPacket ("E79"); - } - nub_size_t bytes_read = DNBProcessMemoryRead (m_ctx.ProcessID(), addr, buf.size(), &buf[0]); - if (bytes_read == 0) - { - return SendPacket ("E80"); - } - - std::vector<uint8_t> buf_quoted; - buf_quoted.reserve (bytes_read + 30); - for (nub_size_t i = 0; i < bytes_read; i++) - { - if (buf[i] == '#' || buf[i] == '$' || buf[i] == '}' || buf[i] == '*') - { - buf_quoted.push_back(0x7d); - buf_quoted.push_back(buf[i] ^ 0x20); - } - else - { - buf_quoted.push_back(buf[i]); - } - } - length = buf_quoted.size(); - - std::ostringstream ostrm; - for (unsigned long i = 0; i < length; i++) - ostrm << buf_quoted[i]; - - return SendPacket (ostrm.str ()); -} - -rnb_err_t -RNBRemote::HandlePacket_X (const char *p) -{ - if (p == NULL || p[0] == '\0' || strlen (p) < 3) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short X packet"); - } - - char *c; - p++; - errno = 0; - nub_addr_t addr = strtoull (p, &c, 16); - if (errno != 0 && addr == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in X packet"); - } - if (*c != ',') - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in X packet"); - } - - /* Advance 'p' to the length part of the packet. NB this is the length of the packet - including any escaped chars. The data payload may be a little bit smaller after - decoding. */ - p += (c - p) + 1; - - errno = 0; - auto length = strtoul (p, NULL, 16); - if (errno != 0 && length == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in X packet"); - } - - // I think gdb sends a zero length write request to test whether this - // packet is accepted. - if (length == 0) - { - return SendPacket ("OK"); - } +rnb_err_t RNBRemote::HandlePacket_x(const char *p) { + if (p == NULL || p[0] == '\0' || strlen(p) < 3) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short X packet"); + } + + char *c; + p++; + errno = 0; + nub_addr_t addr = strtoull(p, &c, 16); + if (errno != 0) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Invalid address in X packet"); + } + if (*c != ',') { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Comma sep missing in X packet"); + } + + /* Advance 'p' to the number of bytes to be read. */ + p += (c - p) + 1; + + errno = 0; + auto length = strtoul(p, NULL, 16); + if (errno != 0) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Invalid length in x packet"); + } + + // zero length read means this is a test of whether that packet is implemented + // or not. + if (length == 0) { + return SendPacket("OK"); + } + + std::vector<uint8_t> buf(length); + + if (buf.capacity() != length) { + return SendPacket("E79"); + } + nub_size_t bytes_read = + DNBProcessMemoryRead(m_ctx.ProcessID(), addr, buf.size(), &buf[0]); + if (bytes_read == 0) { + return SendPacket("E80"); + } + + std::vector<uint8_t> buf_quoted; + buf_quoted.reserve(bytes_read + 30); + for (nub_size_t i = 0; i < bytes_read; i++) { + if (buf[i] == '#' || buf[i] == '$' || buf[i] == '}' || buf[i] == '*') { + buf_quoted.push_back(0x7d); + buf_quoted.push_back(buf[i] ^ 0x20); + } else { + buf_quoted.push_back(buf[i]); + } + } + length = buf_quoted.size(); + + std::ostringstream ostrm; + for (unsigned long i = 0; i < length; i++) + ostrm << buf_quoted[i]; + + return SendPacket(ostrm.str()); +} + +rnb_err_t RNBRemote::HandlePacket_X(const char *p) { + if (p == NULL || p[0] == '\0' || strlen(p) < 3) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Too short X packet"); + } + + char *c; + p++; + errno = 0; + nub_addr_t addr = strtoull(p, &c, 16); + if (errno != 0 && addr == 0) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Invalid address in X packet"); + } + if (*c != ',') { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Comma sep missing in X packet"); + } + + /* Advance 'p' to the length part of the packet. NB this is the length of the + packet + including any escaped chars. The data payload may be a little bit smaller + after + decoding. */ + p += (c - p) + 1; + + errno = 0; + auto length = strtoul(p, NULL, 16); + if (errno != 0 && length == 0) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Invalid length in X packet"); + } + + // I think gdb sends a zero length write request to test whether this + // packet is accepted. + if (length == 0) { + return SendPacket("OK"); + } - std::vector<uint8_t> data = decode_binary_data (c, -1); - std::vector<uint8_t>::const_iterator it; - uint8_t *buf = (uint8_t *) alloca (data.size ()); - uint8_t *i = buf; - for (it = data.begin (); it != data.end (); ++it) - { - *i++ = *it; - } + std::vector<uint8_t> data = decode_binary_data(c, -1); + std::vector<uint8_t>::const_iterator it; + uint8_t *buf = (uint8_t *)alloca(data.size()); + uint8_t *i = buf; + for (it = data.begin(); it != data.end(); ++it) { + *i++ = *it; + } - nub_size_t wrote = DNBProcessMemoryWrite (m_ctx.ProcessID(), addr, data.size(), buf); - if (wrote != data.size ()) - return SendPacket ("E08"); - return SendPacket ("OK"); + nub_size_t wrote = + DNBProcessMemoryWrite(m_ctx.ProcessID(), addr, data.size(), buf); + if (wrote != data.size()) + return SendPacket("E08"); + return SendPacket("OK"); } /* 'g' -- read registers @@ -3423,108 +3329,99 @@ RNBRemote::HandlePacket_X (const char *p) Should the setting of the Hg packet determine which thread's registers are returned? */ -rnb_err_t -RNBRemote::HandlePacket_g (const char *p) -{ - std::ostringstream ostrm; - if (!m_ctx.HasValidProcessID()) - { - return SendPacket ("E11"); - } - - if (g_num_reg_entries == 0) - InitializeRegisters (); - - nub_process_t pid = m_ctx.ProcessID (); - nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p + 1); - if (tid == INVALID_NUB_THREAD) - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet"); - - // Get the register context size first by calling with NULL buffer - nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0); - if (reg_ctx_size) - { - // Now allocate enough space for the entire register context - std::vector<uint8_t> reg_ctx; - reg_ctx.resize(reg_ctx_size); - // Now read the register context - reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, ®_ctx[0], reg_ctx.size()); - if (reg_ctx_size) - { - append_hex_value (ostrm, reg_ctx.data(), reg_ctx.size(), false); - return SendPacket (ostrm.str ()); - } - } - return SendPacket ("E74"); +rnb_err_t RNBRemote::HandlePacket_g(const char *p) { + std::ostringstream ostrm; + if (!m_ctx.HasValidProcessID()) { + return SendPacket("E11"); + } + + if (g_num_reg_entries == 0) + InitializeRegisters(); + + nub_process_t pid = m_ctx.ProcessID(); + nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p + 1); + if (tid == INVALID_NUB_THREAD) + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "No thread specified in p packet"); + + // Get the register context size first by calling with NULL buffer + nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0); + if (reg_ctx_size) { + // Now allocate enough space for the entire register context + std::vector<uint8_t> reg_ctx; + reg_ctx.resize(reg_ctx_size); + // Now read the register context + reg_ctx_size = + DNBThreadGetRegisterContext(pid, tid, ®_ctx[0], reg_ctx.size()); + if (reg_ctx_size) { + append_hex_value(ostrm, reg_ctx.data(), reg_ctx.size(), false); + return SendPacket(ostrm.str()); + } + } + return SendPacket("E74"); } /* 'G XXX...' -- write registers How is the thread for these specified, beyond "the current thread"? Does gdb actually use the Hg packet to set this? */ -rnb_err_t -RNBRemote::HandlePacket_G (const char *p) -{ - if (!m_ctx.HasValidProcessID()) - { - return SendPacket ("E11"); - } - - if (g_num_reg_entries == 0) - InitializeRegisters (); - - StdStringExtractor packet(p); - packet.SetFilePos(1); // Skip the 'G' - - nub_process_t pid = m_ctx.ProcessID(); - nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p); - if (tid == INVALID_NUB_THREAD) - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet"); - - // Get the register context size first by calling with NULL buffer - nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0); - if (reg_ctx_size) - { - // Now allocate enough space for the entire register context - std::vector<uint8_t> reg_ctx; - reg_ctx.resize(reg_ctx_size); - - const nub_size_t bytes_extracted = packet.GetHexBytes (®_ctx[0], reg_ctx.size(), 0xcc); - if (bytes_extracted == reg_ctx.size()) - { - // Now write the register context - reg_ctx_size = DNBThreadSetRegisterContext(pid, tid, reg_ctx.data(), reg_ctx.size()); - if (reg_ctx_size == reg_ctx.size()) - return SendPacket ("OK"); - else - return SendPacket ("E55"); - } - else - { - DNBLogError("RNBRemote::HandlePacket_G(%s): extracted %llu of %llu bytes, size mismatch\n", p, (uint64_t)bytes_extracted, (uint64_t)reg_ctx_size); - return SendPacket ("E64"); - } - } - return SendPacket ("E65"); -} - -static bool -RNBRemoteShouldCancelCallback (void *not_used) -{ - RNBRemoteSP remoteSP(g_remoteSP); - if (remoteSP.get() != NULL) - { - RNBRemote* remote = remoteSP.get(); - if (remote->Comm().IsConnected()) - return false; - else - return true; - } - return true; +rnb_err_t RNBRemote::HandlePacket_G(const char *p) { + if (!m_ctx.HasValidProcessID()) { + return SendPacket("E11"); + } + + if (g_num_reg_entries == 0) + InitializeRegisters(); + + StdStringExtractor packet(p); + packet.SetFilePos(1); // Skip the 'G' + + nub_process_t pid = m_ctx.ProcessID(); + nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p); + if (tid == INVALID_NUB_THREAD) + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "No thread specified in p packet"); + + // Get the register context size first by calling with NULL buffer + nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0); + if (reg_ctx_size) { + // Now allocate enough space for the entire register context + std::vector<uint8_t> reg_ctx; + reg_ctx.resize(reg_ctx_size); + + const nub_size_t bytes_extracted = + packet.GetHexBytes(®_ctx[0], reg_ctx.size(), 0xcc); + if (bytes_extracted == reg_ctx.size()) { + // Now write the register context + reg_ctx_size = + DNBThreadSetRegisterContext(pid, tid, reg_ctx.data(), reg_ctx.size()); + if (reg_ctx_size == reg_ctx.size()) + return SendPacket("OK"); + else + return SendPacket("E55"); + } else { + DNBLogError("RNBRemote::HandlePacket_G(%s): extracted %llu of %llu " + "bytes, size mismatch\n", + p, (uint64_t)bytes_extracted, (uint64_t)reg_ctx_size); + return SendPacket("E64"); + } + } + return SendPacket("E65"); +} + +static bool RNBRemoteShouldCancelCallback(void *not_used) { + RNBRemoteSP remoteSP(g_remoteSP); + if (remoteSP.get() != NULL) { + RNBRemote *remote = remoteSP.get(); + if (remote->Comm().IsConnected()) + return false; + else + return true; + } + return true; } - -// FORMAT: _MXXXXXX,PPP +// FORMAT: _MXXXXXX,PPP // XXXXXX: big endian hex chars // PPP: permissions can be any combo of r w x chars // @@ -3537,74 +3434,73 @@ RNBRemoteShouldCancelCallback (void *not_used) // _M123000,rwx // _M123000,xw -rnb_err_t -RNBRemote::HandlePacket_AllocateMemory (const char *p) -{ - StdStringExtractor packet (p); - packet.SetFilePos(2); // Skip the "_M" - - nub_addr_t size = packet.GetHexMaxU64 (StdStringExtractor::BigEndian, 0); - if (size != 0) - { - if (packet.GetChar() == ',') - { - uint32_t permissions = 0; - char ch; - bool success = true; - while (success && (ch = packet.GetChar()) != '\0') - { - switch (ch) - { - case 'r': permissions |= eMemoryPermissionsReadable; break; - case 'w': permissions |= eMemoryPermissionsWritable; break; - case 'x': permissions |= eMemoryPermissionsExecutable; break; - default: success = false; break; - } - } - - if (success) - { - nub_addr_t addr = DNBProcessMemoryAllocate (m_ctx.ProcessID(), size, permissions); - if (addr != INVALID_NUB_ADDRESS) - { - std::ostringstream ostrm; - ostrm << RAW_HEXBASE << addr; - return SendPacket (ostrm.str ()); - } - } +rnb_err_t RNBRemote::HandlePacket_AllocateMemory(const char *p) { + StdStringExtractor packet(p); + packet.SetFilePos(2); // Skip the "_M" + + nub_addr_t size = packet.GetHexMaxU64(StdStringExtractor::BigEndian, 0); + if (size != 0) { + if (packet.GetChar() == ',') { + uint32_t permissions = 0; + char ch; + bool success = true; + while (success && (ch = packet.GetChar()) != '\0') { + switch (ch) { + case 'r': + permissions |= eMemoryPermissionsReadable; + break; + case 'w': + permissions |= eMemoryPermissionsWritable; + break; + case 'x': + permissions |= eMemoryPermissionsExecutable; + break; + default: + success = false; + break; + } + } + + if (success) { + nub_addr_t addr = + DNBProcessMemoryAllocate(m_ctx.ProcessID(), size, permissions); + if (addr != INVALID_NUB_ADDRESS) { + std::ostringstream ostrm; + ostrm << RAW_HEXBASE << addr; + return SendPacket(ostrm.str()); } + } } - return SendPacket ("E53"); + } + return SendPacket("E53"); } -// FORMAT: _mXXXXXX +// FORMAT: _mXXXXXX // XXXXXX: address that was previously allocated // // RESPONSE: XXXXXX // OK: address was deallocated // EXX: error code // -// EXAMPLES: +// EXAMPLES: // _m123000 -rnb_err_t -RNBRemote::HandlePacket_DeallocateMemory (const char *p) -{ - StdStringExtractor packet (p); - packet.SetFilePos(2); // Skip the "_m" - nub_addr_t addr = packet.GetHexMaxU64 (StdStringExtractor::BigEndian, INVALID_NUB_ADDRESS); +rnb_err_t RNBRemote::HandlePacket_DeallocateMemory(const char *p) { + StdStringExtractor packet(p); + packet.SetFilePos(2); // Skip the "_m" + nub_addr_t addr = + packet.GetHexMaxU64(StdStringExtractor::BigEndian, INVALID_NUB_ADDRESS); - if (addr != INVALID_NUB_ADDRESS) - { - if (DNBProcessMemoryDeallocate (m_ctx.ProcessID(), addr)) - return SendPacket ("OK"); - } - return SendPacket ("E54"); + if (addr != INVALID_NUB_ADDRESS) { + if (DNBProcessMemoryDeallocate(m_ctx.ProcessID(), addr)) + return SendPacket("OK"); + } + return SendPacket("E54"); } - // FORMAT: QSaveRegisterState;thread:TTTT; (when thread suffix is supported) -// FORMAT: QSaveRegisterState (when thread suffix is NOT supported) +// FORMAT: QSaveRegisterState (when thread suffix is NOT +// supported) // TTTT: thread ID in hex // // RESPONSE: @@ -3614,36 +3510,36 @@ RNBRemote::HandlePacket_DeallocateMemory (const char *p) // // EXAMPLES: // QSaveRegisterState;thread:1E34; (when thread suffix is supported) -// QSaveRegisterState (when thread suffix is NOT supported) +// QSaveRegisterState (when thread suffix is NOT +// supported) -rnb_err_t -RNBRemote::HandlePacket_SaveRegisterState (const char *p) -{ - nub_process_t pid = m_ctx.ProcessID (); - nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p); - if (tid == INVALID_NUB_THREAD) - { - if (m_thread_suffix_supported) - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in QSaveRegisterState packet"); - else - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread was is set with the Hg packet"); - } - - // Get the register context size first by calling with NULL buffer - const uint32_t save_id = DNBThreadSaveRegisterState(pid, tid); - if (save_id != 0) - { - char response[64]; - snprintf (response, sizeof(response), "%u", save_id); - return SendPacket (response); - } +rnb_err_t RNBRemote::HandlePacket_SaveRegisterState(const char *p) { + nub_process_t pid = m_ctx.ProcessID(); + nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p); + if (tid == INVALID_NUB_THREAD) { + if (m_thread_suffix_supported) + return HandlePacket_ILLFORMED( + __FILE__, __LINE__, p, + "No thread specified in QSaveRegisterState packet"); else - { - return SendPacket ("E75"); - } -} -// FORMAT: QRestoreRegisterState:SAVEID;thread:TTTT; (when thread suffix is supported) -// FORMAT: QRestoreRegisterState:SAVEID (when thread suffix is NOT supported) + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "No thread was is set with the Hg packet"); + } + + // Get the register context size first by calling with NULL buffer + const uint32_t save_id = DNBThreadSaveRegisterState(pid, tid); + if (save_id != 0) { + char response[64]; + snprintf(response, sizeof(response), "%u", save_id); + return SendPacket(response); + } else { + return SendPacket("E75"); + } +} +// FORMAT: QRestoreRegisterState:SAVEID;thread:TTTT; (when thread suffix is +// supported) +// FORMAT: QRestoreRegisterState:SAVEID (when thread suffix is NOT +// supported) // TTTT: thread ID in hex // SAVEID: a decimal number that represents the save ID that was // returned from a call to "QSaveRegisterState" @@ -3653,109 +3549,113 @@ RNBRemote::HandlePacket_SaveRegisterState (const char *p) // EXX: error code // // EXAMPLES: -// QRestoreRegisterState:1;thread:1E34; (when thread suffix is supported) -// QRestoreRegisterState:1 (when thread suffix is NOT supported) - -rnb_err_t -RNBRemote::HandlePacket_RestoreRegisterState (const char *p) -{ - nub_process_t pid = m_ctx.ProcessID (); - nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p); - if (tid == INVALID_NUB_THREAD) - { - if (m_thread_suffix_supported) - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in QSaveRegisterState packet"); - else - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread was is set with the Hg packet"); - } - - StdStringExtractor packet (p); - packet.SetFilePos(strlen("QRestoreRegisterState:")); // Skip the "QRestoreRegisterState:" - const uint32_t save_id = packet.GetU32(0); - - if (save_id != 0) - { - // Get the register context size first by calling with NULL buffer - if (DNBThreadRestoreRegisterState(pid, tid, save_id)) - return SendPacket ("OK"); - else - return SendPacket ("E77"); - } - return SendPacket ("E76"); -} +// QRestoreRegisterState:1;thread:1E34; (when thread suffix is +// supported) +// QRestoreRegisterState:1 (when thread suffix is NOT +// supported) + +rnb_err_t RNBRemote::HandlePacket_RestoreRegisterState(const char *p) { + nub_process_t pid = m_ctx.ProcessID(); + nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p); + if (tid == INVALID_NUB_THREAD) { + if (m_thread_suffix_supported) + return HandlePacket_ILLFORMED( + __FILE__, __LINE__, p, + "No thread specified in QSaveRegisterState packet"); + else + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "No thread was is set with the Hg packet"); + } -static bool -GetProcessNameFrom_vAttach (const char *&p, std::string &attach_name) -{ - bool return_val = true; - while (*p != '\0') - { - char smallbuf[3]; - smallbuf[0] = *p; - smallbuf[1] = *(p + 1); - smallbuf[2] = '\0'; + StdStringExtractor packet(p); + packet.SetFilePos( + strlen("QRestoreRegisterState:")); // Skip the "QRestoreRegisterState:" + const uint32_t save_id = packet.GetU32(0); - errno = 0; - int ch = static_cast<int>(strtoul (smallbuf, NULL, 16)); - if (errno != 0 && ch == 0) - { - return_val = false; - break; - } - - attach_name.push_back(ch); - p += 2; - } - return return_val; + if (save_id != 0) { + // Get the register context size first by calling with NULL buffer + if (DNBThreadRestoreRegisterState(pid, tid, save_id)) + return SendPacket("OK"); + else + return SendPacket("E77"); + } + return SendPacket("E76"); } -rnb_err_t -RNBRemote::HandlePacket_qSupported (const char *p) -{ - uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet size--debugger can always use less - char buf[256]; - snprintf (buf, sizeof(buf), "qXfer:features:read+;PacketSize=%x;qEcho+", max_packet_size); - - // By default, don't enable compression. It's only worth doing when we are working - // with a low speed communication channel. - bool enable_compression = false; - (void)enable_compression; +static bool GetProcessNameFrom_vAttach(const char *&p, + std::string &attach_name) { + bool return_val = true; + while (*p != '\0') { + char smallbuf[3]; + smallbuf[0] = *p; + smallbuf[1] = *(p + 1); + smallbuf[2] = '\0'; - // Enable compression when debugserver is running on a watchOS device where communication may be over Bluetooth. -#if defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 - enable_compression = true; + errno = 0; + int ch = static_cast<int>(strtoul(smallbuf, NULL, 16)); + if (errno != 0 && ch == 0) { + return_val = false; + break; + } + + attach_name.push_back(ch); + p += 2; + } + return return_val; +} + +rnb_err_t RNBRemote::HandlePacket_qSupported(const char *p) { + uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet + // size--debugger can always use less + char buf[256]; + snprintf(buf, sizeof(buf), "qXfer:features:read+;PacketSize=%x;qEcho+", + max_packet_size); + + // By default, don't enable compression. It's only worth doing when we are + // working + // with a low speed communication channel. + bool enable_compression = false; + (void)enable_compression; + +// Enable compression when debugserver is running on a watchOS device where +// communication may be over Bluetooth. +#if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 + enable_compression = true; #endif -#if defined (HAVE_LIBCOMPRESSION) - // libcompression is weak linked so test if compression_decode_buffer() is available - if (enable_compression && compression_decode_buffer != NULL) - { - strcat (buf, ";SupportedCompressions=lzfse,zlib-deflate,lz4,lzma;DefaultCompressionMinSize="); - char numbuf[16]; - snprintf (numbuf, sizeof (numbuf), "%zu", m_compression_minsize); - numbuf[sizeof (numbuf) - 1] = '\0'; - strcat (buf, numbuf); - } -#elif defined (HAVE_LIBZ) - if (enable_compression) - { - strcat (buf, ";SupportedCompressions=zlib-deflate;DefaultCompressionMinSize="); - char numbuf[16]; - snprintf (numbuf, sizeof (numbuf), "%zu", m_compression_minsize); - numbuf[sizeof (numbuf) - 1] = '\0'; - strcat (buf, numbuf); - } +#if defined(HAVE_LIBCOMPRESSION) + // libcompression is weak linked so test if compression_decode_buffer() is + // available + if (enable_compression && compression_decode_buffer != NULL) { + strcat(buf, ";SupportedCompressions=lzfse,zlib-deflate,lz4,lzma;" + "DefaultCompressionMinSize="); + char numbuf[16]; + snprintf(numbuf, sizeof(numbuf), "%zu", m_compression_minsize); + numbuf[sizeof(numbuf) - 1] = '\0'; + strcat(buf, numbuf); + } +#elif defined(HAVE_LIBZ) + if (enable_compression) { + strcat(buf, + ";SupportedCompressions=zlib-deflate;DefaultCompressionMinSize="); + char numbuf[16]; + snprintf(numbuf, sizeof(numbuf), "%zu", m_compression_minsize); + numbuf[sizeof(numbuf) - 1] = '\0'; + strcat(buf, numbuf); + } #endif - return SendPacket (buf); + return SendPacket(buf); } /* vAttach;pid - Attach to a new process with the specified process ID. pid is a hexadecimal integer + Attach to a new process with the specified process ID. pid is a hexadecimal + integer identifying the process. If the stub is currently controlling a process, it is - killed. The attached process is stopped.This packet is only available in extended + killed. The attached process is stopped.This packet is only available in + extended mode (see extended mode). Reply: @@ -3763,1351 +3663,1317 @@ RNBRemote::HandlePacket_qSupported (const char *p) "Any Stop Reply Packet" for success */ -rnb_err_t -RNBRemote::HandlePacket_v (const char *p) -{ - if (strcmp (p, "vCont;c") == 0) - { - // Simple continue - return RNBRemote::HandlePacket_c("c"); - } - else if (strcmp (p, "vCont;s") == 0) - { - // Simple step - return RNBRemote::HandlePacket_s("s"); - } - else if (strstr (p, "vCont") == p) - { - DNBThreadResumeActions thread_actions; - char *c = (char *)(p += strlen("vCont")); - char *c_end = c + strlen(c); - if (*c == '?') - return SendPacket ("vCont;c;C;s;S"); +rnb_err_t RNBRemote::HandlePacket_v(const char *p) { + if (strcmp(p, "vCont;c") == 0) { + // Simple continue + return RNBRemote::HandlePacket_c("c"); + } else if (strcmp(p, "vCont;s") == 0) { + // Simple step + return RNBRemote::HandlePacket_s("s"); + } else if (strstr(p, "vCont") == p) { + DNBThreadResumeActions thread_actions; + char *c = (char *)(p += strlen("vCont")); + char *c_end = c + strlen(c); + if (*c == '?') + return SendPacket("vCont;c;C;s;S"); + + while (c < c_end && *c == ';') { + ++c; // Skip the semi-colon + DNBThreadResumeAction thread_action; + thread_action.tid = INVALID_NUB_THREAD; + thread_action.state = eStateInvalid; + thread_action.signal = 0; + thread_action.addr = INVALID_NUB_ADDRESS; + + char action = *c++; + + switch (action) { + case 'C': + errno = 0; + thread_action.signal = static_cast<int>(strtoul(c, &c, 16)); + if (errno != 0) + return HandlePacket_ILLFORMED( + __FILE__, __LINE__, p, "Could not parse signal in vCont packet"); + // Fall through to next case... - while (c < c_end && *c == ';') - { - ++c; // Skip the semi-colon - DNBThreadResumeAction thread_action; - thread_action.tid = INVALID_NUB_THREAD; - thread_action.state = eStateInvalid; - thread_action.signal = 0; - thread_action.addr = INVALID_NUB_ADDRESS; + case 'c': + // Continue + thread_action.state = eStateRunning; + break; - char action = *c++; + case 'S': + errno = 0; + thread_action.signal = static_cast<int>(strtoul(c, &c, 16)); + if (errno != 0) + return HandlePacket_ILLFORMED( + __FILE__, __LINE__, p, "Could not parse signal in vCont packet"); + // Fall through to next case... - switch (action) - { - case 'C': - errno = 0; - thread_action.signal = static_cast<int>(strtoul (c, &c, 16)); - if (errno != 0) - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet"); - // Fall through to next case... - - case 'c': - // Continue - thread_action.state = eStateRunning; - break; - - case 'S': - errno = 0; - thread_action.signal = static_cast<int>(strtoul (c, &c, 16)); - if (errno != 0) - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet"); - // Fall through to next case... - - case 's': - // Step - thread_action.state = eStateStepping; - break; - - default: - HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Unsupported action in vCont packet"); - break; - } - if (*c == ':') - { - errno = 0; - thread_action.tid = strtoul (++c, &c, 16); - if (errno != 0) - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in vCont packet"); - } + case 's': + // Step + thread_action.state = eStateStepping; + break; - thread_actions.Append (thread_action); - } + default: + HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Unsupported action in vCont packet"); + break; + } + if (*c == ':') { + errno = 0; + thread_action.tid = strtoul(++c, &c, 16); + if (errno != 0) + return HandlePacket_ILLFORMED( + __FILE__, __LINE__, p, + "Could not parse thread number in vCont packet"); + } - // If a default action for all other threads wasn't mentioned - // then we should stop the threads - thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0); - DNBProcessResume(m_ctx.ProcessID(), thread_actions.GetFirst (), thread_actions.GetSize()); - return rnb_success; + thread_actions.Append(thread_action); } - else if (strstr (p, "vAttach") == p) - { - nub_process_t attach_pid = INVALID_NUB_PROCESS; // attach_pid will be set to 0 if the attach fails - nub_process_t pid_attaching_to = INVALID_NUB_PROCESS; // pid_attaching_to is the original pid specified - char err_str[1024]={'\0'}; - std::string attach_name; - - if (strstr (p, "vAttachWait;") == p) - { - p += strlen("vAttachWait;"); - if (!GetProcessNameFrom_vAttach(p, attach_name)) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt"); - } - const bool ignore_existing = true; - attach_pid = DNBProcessAttachWait(attach_name.c_str (), m_ctx.LaunchFlavor(), ignore_existing, NULL, 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback); - } - else if (strstr (p, "vAttachOrWait;") == p) - { - p += strlen("vAttachOrWait;"); - if (!GetProcessNameFrom_vAttach(p, attach_name)) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachOrWait' pkt"); - } - const bool ignore_existing = false; - attach_pid = DNBProcessAttachWait(attach_name.c_str (), m_ctx.LaunchFlavor(), ignore_existing, NULL, 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback); - } - else if (strstr (p, "vAttachName;") == p) - { - p += strlen("vAttachName;"); - if (!GetProcessNameFrom_vAttach(p, attach_name)) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachName' pkt"); - } + // If a default action for all other threads wasn't mentioned + // then we should stop the threads + thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); + DNBProcessResume(m_ctx.ProcessID(), thread_actions.GetFirst(), + thread_actions.GetSize()); + return rnb_success; + } else if (strstr(p, "vAttach") == p) { + nub_process_t attach_pid = + INVALID_NUB_PROCESS; // attach_pid will be set to 0 if the attach fails + nub_process_t pid_attaching_to = + INVALID_NUB_PROCESS; // pid_attaching_to is the original pid specified + char err_str[1024] = {'\0'}; + std::string attach_name; + + if (strstr(p, "vAttachWait;") == p) { + p += strlen("vAttachWait;"); + if (!GetProcessNameFrom_vAttach(p, attach_name)) { + return HandlePacket_ILLFORMED( + __FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt"); + } + const bool ignore_existing = true; + attach_pid = DNBProcessAttachWait( + attach_name.c_str(), m_ctx.LaunchFlavor(), ignore_existing, NULL, + 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback); + + } else if (strstr(p, "vAttachOrWait;") == p) { + p += strlen("vAttachOrWait;"); + if (!GetProcessNameFrom_vAttach(p, attach_name)) { + return HandlePacket_ILLFORMED( + __FILE__, __LINE__, p, + "non-hex char in arg on 'vAttachOrWait' pkt"); + } + const bool ignore_existing = false; + attach_pid = DNBProcessAttachWait( + attach_name.c_str(), m_ctx.LaunchFlavor(), ignore_existing, NULL, + 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback); + } else if (strstr(p, "vAttachName;") == p) { + p += strlen("vAttachName;"); + if (!GetProcessNameFrom_vAttach(p, attach_name)) { + return HandlePacket_ILLFORMED( + __FILE__, __LINE__, p, "non-hex char in arg on 'vAttachName' pkt"); + } - attach_pid = DNBProcessAttachByName (attach_name.c_str(), NULL, err_str, sizeof(err_str)); + attach_pid = DNBProcessAttachByName(attach_name.c_str(), NULL, err_str, + sizeof(err_str)); + + } else if (strstr(p, "vAttach;") == p) { + p += strlen("vAttach;"); + char *end = NULL; + pid_attaching_to = static_cast<int>( + strtoul(p, &end, 16)); // PID will be in hex, so use base 16 to decode + if (p != end && *end == '\0') { + // Wait at most 30 second for attach + struct timespec attach_timeout_abstime; + DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0); + attach_pid = DNBProcessAttach(pid_attaching_to, &attach_timeout_abstime, + err_str, sizeof(err_str)); + } + } else { + return HandlePacket_UNIMPLEMENTED(p); + } + + if (attach_pid != INVALID_NUB_PROCESS) { + if (m_ctx.ProcessID() != attach_pid) + m_ctx.SetProcessID(attach_pid); + // Send a stop reply packet to indicate we successfully attached! + NotifyThatProcessStopped(); + return rnb_success; + } else { + m_ctx.LaunchStatus().SetError(-1, DNBError::Generic); + if (err_str[0]) + m_ctx.LaunchStatus().SetErrorString(err_str); + else + m_ctx.LaunchStatus().SetErrorString("attach failed"); + +#if defined(__APPLE__) && \ + (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101000) + if (pid_attaching_to == INVALID_NUB_PROCESS && !attach_name.empty()) { + pid_attaching_to = DNBProcessGetPIDByName(attach_name.c_str()); + } + if (pid_attaching_to != INVALID_NUB_PROCESS && + strcmp(err_str, "No such process") != 0) { + // csr_check(CSR_ALLOW_TASK_FOR_PID) will be nonzero if System Integrity + // Protection is in effect. + if (csr_check(CSR_ALLOW_TASK_FOR_PID) != 0) { + bool attach_failed_due_to_sip = false; + + if (rootless_allows_task_for_pid(pid_attaching_to) == 0) { + attach_failed_due_to_sip = true; + } - } - else if (strstr (p, "vAttach;") == p) - { - p += strlen("vAttach;"); - char *end = NULL; - pid_attaching_to = static_cast<int>(strtoul (p, &end, 16)); // PID will be in hex, so use base 16 to decode - if (p != end && *end == '\0') - { - // Wait at most 30 second for attach - struct timespec attach_timeout_abstime; - DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0); - attach_pid = DNBProcessAttach(pid_attaching_to, &attach_timeout_abstime, err_str, sizeof(err_str)); + if (attach_failed_due_to_sip == false) { + int csops_flags = 0; + int retval = ::csops(pid_attaching_to, CS_OPS_STATUS, &csops_flags, + sizeof(csops_flags)); + if (retval != -1 && (csops_flags & CS_RESTRICT)) { + attach_failed_due_to_sip = true; } + } + if (attach_failed_due_to_sip) { + SendPacket("E87"); // E87 is the magic value which says that we are + // not allowed to attach + DNBLogError("Attach failed because process does not allow " + "attaching: \"%s\".", + err_str); + return rnb_err; + } } - else - { - return HandlePacket_UNIMPLEMENTED(p); - } - - - if (attach_pid != INVALID_NUB_PROCESS) - { - if (m_ctx.ProcessID() != attach_pid) - m_ctx.SetProcessID(attach_pid); - // Send a stop reply packet to indicate we successfully attached! - NotifyThatProcessStopped (); - return rnb_success; - } - else - { - m_ctx.LaunchStatus().SetError(-1, DNBError::Generic); - if (err_str[0]) - m_ctx.LaunchStatus().SetErrorString(err_str); - else - m_ctx.LaunchStatus().SetErrorString("attach failed"); + } -#if defined (__APPLE__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101000) - if (pid_attaching_to == INVALID_NUB_PROCESS && !attach_name.empty()) - { - pid_attaching_to = DNBProcessGetPIDByName (attach_name.c_str()); - } - if (pid_attaching_to != INVALID_NUB_PROCESS && strcmp (err_str, "No such process") != 0) - { - // csr_check(CSR_ALLOW_TASK_FOR_PID) will be nonzero if System Integrity Protection is in effect. - if (csr_check(CSR_ALLOW_TASK_FOR_PID) != 0) - { - bool attach_failed_due_to_sip = false; - - if (rootless_allows_task_for_pid (pid_attaching_to) == 0) - { - attach_failed_due_to_sip = true; - } - - if (attach_failed_due_to_sip == false) - { - int csops_flags = 0; - int retval = ::csops (pid_attaching_to, CS_OPS_STATUS, &csops_flags, sizeof (csops_flags)); - if (retval != -1 && (csops_flags & CS_RESTRICT)) - { - attach_failed_due_to_sip = true; - } - } - if (attach_failed_due_to_sip) - { - SendPacket ("E87"); // E87 is the magic value which says that we are not allowed to attach - DNBLogError ("Attach failed because process does not allow attaching: \"%s\".", err_str); - return rnb_err; - } - } - } - #endif - SendPacket ("E01"); // E01 is our magic error value for attach failed. - DNBLogError ("Attach failed: \"%s\".", err_str); - return rnb_err; - } + SendPacket("E01"); // E01 is our magic error value for attach failed. + DNBLogError("Attach failed: \"%s\".", err_str); + return rnb_err; } + } - // All other failures come through here - return HandlePacket_UNIMPLEMENTED(p); + // All other failures come through here + return HandlePacket_UNIMPLEMENTED(p); } /* 'T XX' -- status of thread Check if the specified thread is alive. The thread number is in hex? */ -rnb_err_t -RNBRemote::HandlePacket_T (const char *p) -{ - p++; - if (p == NULL || *p == '\0') - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in T packet"); - } - if (!m_ctx.HasValidProcessID()) - { - return SendPacket ("E15"); - } - errno = 0; - nub_thread_t tid = strtoul (p, NULL, 16); - if (errno != 0 && tid == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in T packet"); - } - - nub_state_t state = DNBThreadGetState (m_ctx.ProcessID(), tid); - if (state == eStateInvalid || state == eStateExited || state == eStateCrashed) - { - return SendPacket ("E16"); - } - - return SendPacket ("OK"); -} - - -rnb_err_t -RNBRemote::HandlePacket_z (const char *p) -{ - if (p == NULL || *p == '\0') - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in z packet"); - - if (!m_ctx.HasValidProcessID()) - return SendPacket ("E15"); - - char packet_cmd = *p++; - char break_type = *p++; - - if (*p++ != ',') - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet"); - - char *c = NULL; - nub_process_t pid = m_ctx.ProcessID(); - errno = 0; - nub_addr_t addr = strtoull (p, &c, 16); - if (errno != 0 && addr == 0) - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in z packet"); - p = c; - if (*p++ != ',') - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet"); - - errno = 0; - auto byte_size = strtoul (p, &c, 16); - if (errno != 0 && byte_size == 0) - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in z packet"); - - if (packet_cmd == 'Z') - { - // set - switch (break_type) - { - case '0': // set software breakpoint - case '1': // set hardware breakpoint - { - // gdb can send multiple Z packets for the same address and - // these calls must be ref counted. - bool hardware = (break_type == '1'); - - if (DNBBreakpointSet (pid, addr, byte_size, hardware)) - { - // We successfully created a breakpoint, now lets full out - // a ref count structure with the breakID and add it to our - // map. - return SendPacket ("OK"); - } - else - { - // We failed to set the software breakpoint - return SendPacket ("E09"); - } - } - break; - - case '2': // set write watchpoint - case '3': // set read watchpoint - case '4': // set access watchpoint - { - bool hardware = true; - uint32_t watch_flags = 0; - if (break_type == '2') - watch_flags = WATCH_TYPE_WRITE; - else if (break_type == '3') - watch_flags = WATCH_TYPE_READ; - else - watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE; - - if (DNBWatchpointSet (pid, addr, byte_size, watch_flags, hardware)) - { - return SendPacket ("OK"); - } - else - { - // We failed to set the watchpoint - return SendPacket ("E09"); - } - } - break; +rnb_err_t RNBRemote::HandlePacket_T(const char *p) { + p++; + if (p == NULL || *p == '\0') { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "No thread specified in T packet"); + } + if (!m_ctx.HasValidProcessID()) { + return SendPacket("E15"); + } + errno = 0; + nub_thread_t tid = strtoul(p, NULL, 16); + if (errno != 0 && tid == 0) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Could not parse thread number in T packet"); + } + + nub_state_t state = DNBThreadGetState(m_ctx.ProcessID(), tid); + if (state == eStateInvalid || state == eStateExited || + state == eStateCrashed) { + return SendPacket("E16"); + } + + return SendPacket("OK"); +} + +rnb_err_t RNBRemote::HandlePacket_z(const char *p) { + if (p == NULL || *p == '\0') + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "No thread specified in z packet"); + + if (!m_ctx.HasValidProcessID()) + return SendPacket("E15"); + + char packet_cmd = *p++; + char break_type = *p++; + + if (*p++ != ',') + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Comma separator missing in z packet"); + + char *c = NULL; + nub_process_t pid = m_ctx.ProcessID(); + errno = 0; + nub_addr_t addr = strtoull(p, &c, 16); + if (errno != 0 && addr == 0) + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Invalid address in z packet"); + p = c; + if (*p++ != ',') + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Comma separator missing in z packet"); + + errno = 0; + auto byte_size = strtoul(p, &c, 16); + if (errno != 0 && byte_size == 0) + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Invalid length in z packet"); + + if (packet_cmd == 'Z') { + // set + switch (break_type) { + case '0': // set software breakpoint + case '1': // set hardware breakpoint + { + // gdb can send multiple Z packets for the same address and + // these calls must be ref counted. + bool hardware = (break_type == '1'); + + if (DNBBreakpointSet(pid, addr, byte_size, hardware)) { + // We successfully created a breakpoint, now lets full out + // a ref count structure with the breakID and add it to our + // map. + return SendPacket("OK"); + } else { + // We failed to set the software breakpoint + return SendPacket("E09"); + } + } break; + + case '2': // set write watchpoint + case '3': // set read watchpoint + case '4': // set access watchpoint + { + bool hardware = true; + uint32_t watch_flags = 0; + if (break_type == '2') + watch_flags = WATCH_TYPE_WRITE; + else if (break_type == '3') + watch_flags = WATCH_TYPE_READ; + else + watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE; + + if (DNBWatchpointSet(pid, addr, byte_size, watch_flags, hardware)) { + return SendPacket("OK"); + } else { + // We failed to set the watchpoint + return SendPacket("E09"); + } + } break; - default: - break; - } - } - else if (packet_cmd == 'z') - { - // remove - switch (break_type) - { - case '0': // remove software breakpoint - case '1': // remove hardware breakpoint - if (DNBBreakpointClear (pid, addr)) - { - return SendPacket ("OK"); - } - else - { - return SendPacket ("E08"); - } - break; + default: + break; + } + } else if (packet_cmd == 'z') { + // remove + switch (break_type) { + case '0': // remove software breakpoint + case '1': // remove hardware breakpoint + if (DNBBreakpointClear(pid, addr)) { + return SendPacket("OK"); + } else { + return SendPacket("E08"); + } + break; - case '2': // remove write watchpoint - case '3': // remove read watchpoint - case '4': // remove access watchpoint - if (DNBWatchpointClear (pid, addr)) - { - return SendPacket ("OK"); - } - else - { - return SendPacket ("E08"); - } - break; + case '2': // remove write watchpoint + case '3': // remove read watchpoint + case '4': // remove access watchpoint + if (DNBWatchpointClear(pid, addr)) { + return SendPacket("OK"); + } else { + return SendPacket("E08"); + } + break; - default: - break; - } + default: + break; } - return HandlePacket_UNIMPLEMENTED(p); + } + return HandlePacket_UNIMPLEMENTED(p); } // Extract the thread number from the thread suffix that might be appended to -// thread specific packets. This will only be enabled if m_thread_suffix_supported +// thread specific packets. This will only be enabled if +// m_thread_suffix_supported // is true. -nub_thread_t -RNBRemote::ExtractThreadIDFromThreadSuffix (const char *p) -{ - if (m_thread_suffix_supported) - { - nub_thread_t tid = INVALID_NUB_THREAD; - if (p) - { - const char *tid_cstr = strstr (p, "thread:"); - if (tid_cstr) - { - tid_cstr += strlen ("thread:"); - tid = strtoul(tid_cstr, NULL, 16); - } - } - return tid; +nub_thread_t RNBRemote::ExtractThreadIDFromThreadSuffix(const char *p) { + if (m_thread_suffix_supported) { + nub_thread_t tid = INVALID_NUB_THREAD; + if (p) { + const char *tid_cstr = strstr(p, "thread:"); + if (tid_cstr) { + tid_cstr += strlen("thread:"); + tid = strtoul(tid_cstr, NULL, 16); + } } - return GetCurrentThread(); - + return tid; + } + return GetCurrentThread(); } /* 'p XX' print the contents of register X */ -rnb_err_t -RNBRemote::HandlePacket_p (const char *p) -{ - if (g_num_reg_entries == 0) - InitializeRegisters (); - - if (p == NULL || *p == '\0') - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet"); - } - if (!m_ctx.HasValidProcessID()) - { - return SendPacket ("E15"); - } - nub_process_t pid = m_ctx.ProcessID(); - errno = 0; - char *tid_cstr = NULL; - uint32_t reg = static_cast<uint32_t>(strtoul (p + 1, &tid_cstr, 16)); - if (errno != 0 && reg == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse register number in p packet"); - } - - nub_thread_t tid = ExtractThreadIDFromThreadSuffix (tid_cstr); - if (tid == INVALID_NUB_THREAD) - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet"); - - const register_map_entry_t *reg_entry; - - if (reg < g_num_reg_entries) - reg_entry = &g_reg_entries[reg]; - else - reg_entry = NULL; - - std::ostringstream ostrm; - if (reg_entry == NULL) - { - DNBLogError("RNBRemote::HandlePacket_p(%s): unknown register number %u requested\n", p, reg); - ostrm << "00000000"; - } - else if (reg_entry->nub_info.reg == (uint32_t)-1) - { - if (reg_entry->nub_info.size > 0) - { - std::basic_string<uint8_t> zeros(reg_entry->nub_info.size, '\0'); - append_hex_value(ostrm, zeros.data(), zeros.size(), false); - } - } - else - { - register_value_in_hex_fixed_width (ostrm, pid, tid, reg_entry, NULL); - } - return SendPacket (ostrm.str()); +rnb_err_t RNBRemote::HandlePacket_p(const char *p) { + if (g_num_reg_entries == 0) + InitializeRegisters(); + + if (p == NULL || *p == '\0') { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "No thread specified in p packet"); + } + if (!m_ctx.HasValidProcessID()) { + return SendPacket("E15"); + } + nub_process_t pid = m_ctx.ProcessID(); + errno = 0; + char *tid_cstr = NULL; + uint32_t reg = static_cast<uint32_t>(strtoul(p + 1, &tid_cstr, 16)); + if (errno != 0 && reg == 0) { + return HandlePacket_ILLFORMED( + __FILE__, __LINE__, p, "Could not parse register number in p packet"); + } + + nub_thread_t tid = ExtractThreadIDFromThreadSuffix(tid_cstr); + if (tid == INVALID_NUB_THREAD) + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "No thread specified in p packet"); + + const register_map_entry_t *reg_entry; + + if (reg < g_num_reg_entries) + reg_entry = &g_reg_entries[reg]; + else + reg_entry = NULL; + + std::ostringstream ostrm; + if (reg_entry == NULL) { + DNBLogError( + "RNBRemote::HandlePacket_p(%s): unknown register number %u requested\n", + p, reg); + ostrm << "00000000"; + } else if (reg_entry->nub_info.reg == (uint32_t)-1) { + if (reg_entry->nub_info.size > 0) { + std::basic_string<uint8_t> zeros(reg_entry->nub_info.size, '\0'); + append_hex_value(ostrm, zeros.data(), zeros.size(), false); + } + } else { + register_value_in_hex_fixed_width(ostrm, pid, tid, reg_entry, NULL); + } + return SendPacket(ostrm.str()); } /* 'Pnn=rrrrr' Set register number n to value r. n and r are hex strings. */ -rnb_err_t -RNBRemote::HandlePacket_P (const char *p) -{ - if (g_num_reg_entries == 0) - InitializeRegisters (); +rnb_err_t RNBRemote::HandlePacket_P(const char *p) { + if (g_num_reg_entries == 0) + InitializeRegisters(); - if (p == NULL || *p == '\0') - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Empty P packet"); - } - if (!m_ctx.HasValidProcessID()) - { - return SendPacket ("E28"); - } + if (p == NULL || *p == '\0') { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, "Empty P packet"); + } + if (!m_ctx.HasValidProcessID()) { + return SendPacket("E28"); + } - nub_process_t pid = m_ctx.ProcessID(); + nub_process_t pid = m_ctx.ProcessID(); - StdStringExtractor packet (p); + StdStringExtractor packet(p); - const char cmd_char = packet.GetChar(); - // Register ID is always in big endian - const uint32_t reg = packet.GetHexMaxU32 (false, UINT32_MAX); - const char equal_char = packet.GetChar(); + const char cmd_char = packet.GetChar(); + // Register ID is always in big endian + const uint32_t reg = packet.GetHexMaxU32(false, UINT32_MAX); + const char equal_char = packet.GetChar(); - if (cmd_char != 'P') - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Improperly formed P packet"); + if (cmd_char != 'P') + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Improperly formed P packet"); - if (reg == UINT32_MAX) - return SendPacket ("E29"); + if (reg == UINT32_MAX) + return SendPacket("E29"); - if (equal_char != '=') - return SendPacket ("E30"); + if (equal_char != '=') + return SendPacket("E30"); - const register_map_entry_t *reg_entry; + const register_map_entry_t *reg_entry; - if (reg >= g_num_reg_entries) - return SendPacket("E47"); + if (reg >= g_num_reg_entries) + return SendPacket("E47"); - reg_entry = &g_reg_entries[reg]; + reg_entry = &g_reg_entries[reg]; - if (reg_entry->nub_info.set == (uint32_t)-1 && reg_entry->nub_info.reg == (uint32_t)-1) - { - DNBLogError("RNBRemote::HandlePacket_P(%s): unknown register number %u requested\n", p, reg); - return SendPacket("E48"); - } + if (reg_entry->nub_info.set == (uint32_t)-1 && + reg_entry->nub_info.reg == (uint32_t)-1) { + DNBLogError( + "RNBRemote::HandlePacket_P(%s): unknown register number %u requested\n", + p, reg); + return SendPacket("E48"); + } - DNBRegisterValue reg_value; - reg_value.info = reg_entry->nub_info; - packet.GetHexBytes (reg_value.value.v_sint8, reg_entry->nub_info.size, 0xcc); + DNBRegisterValue reg_value; + reg_value.info = reg_entry->nub_info; + packet.GetHexBytes(reg_value.value.v_sint8, reg_entry->nub_info.size, 0xcc); - nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p); - if (tid == INVALID_NUB_THREAD) - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet"); + nub_thread_t tid = ExtractThreadIDFromThreadSuffix(p); + if (tid == INVALID_NUB_THREAD) + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "No thread specified in p packet"); - if (!DNBThreadSetRegisterValueByID (pid, tid, reg_entry->nub_info.set, reg_entry->nub_info.reg, ®_value)) - { - return SendPacket ("E32"); - } - return SendPacket ("OK"); + if (!DNBThreadSetRegisterValueByID(pid, tid, reg_entry->nub_info.set, + reg_entry->nub_info.reg, ®_value)) { + return SendPacket("E32"); + } + return SendPacket("OK"); } /* 'c [addr]' Continue, optionally from a specified address. */ -rnb_err_t -RNBRemote::HandlePacket_c (const char *p) -{ - const nub_process_t pid = m_ctx.ProcessID(); - - if (pid == INVALID_NUB_PROCESS) - return SendPacket ("E23"); +rnb_err_t RNBRemote::HandlePacket_c(const char *p) { + const nub_process_t pid = m_ctx.ProcessID(); - DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS }; + if (pid == INVALID_NUB_PROCESS) + return SendPacket("E23"); - if (*(p + 1) != '\0') - { - action.tid = GetContinueThread(); - errno = 0; - action.addr = strtoull (p + 1, NULL, 16); - if (errno != 0 && action.addr == 0) - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in c packet"); - } + DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateRunning, 0, + INVALID_NUB_ADDRESS}; - DNBThreadResumeActions thread_actions; - thread_actions.Append(action); - thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0); - if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize())) - return SendPacket ("E25"); - // Don't send an "OK" packet; response is the stopped/exited message. - return rnb_success; + if (*(p + 1) != '\0') { + action.tid = GetContinueThread(); + errno = 0; + action.addr = strtoull(p + 1, NULL, 16); + if (errno != 0 && action.addr == 0) + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Could not parse address in c packet"); + } + + DNBThreadResumeActions thread_actions; + thread_actions.Append(action); + thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0); + if (!DNBProcessResume(pid, thread_actions.GetFirst(), + thread_actions.GetSize())) + return SendPacket("E25"); + // Don't send an "OK" packet; response is the stopped/exited message. + return rnb_success; +} + +rnb_err_t RNBRemote::HandlePacket_MemoryRegionInfo(const char *p) { + /* This packet will find memory attributes (e.g. readable, writable, + executable, stack, jitted code) + for the memory region containing a given address and return that + information. + + Users of this packet must be prepared for three results: + + Region information is returned + Region information is unavailable for this address because the address + is in unmapped memory + Region lookup cannot be performed on this platform or process is not + yet launched + This packet isn't implemented + + Examples of use: + qMemoryRegionInfo:3a55140 + start:3a50000,size:100000,permissions:rwx + + qMemoryRegionInfo:0 + error:address in unmapped region + + qMemoryRegionInfo:3a551140 (on a different platform) + error:region lookup cannot be performed + + qMemoryRegionInfo + OK // this packet is implemented by the remote nub + */ + + p += sizeof("qMemoryRegionInfo") - 1; + if (*p == '\0') + return SendPacket("OK"); + if (*p++ != ':') + return SendPacket("E67"); + if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X')) + p += 2; + + errno = 0; + uint64_t address = strtoul(p, NULL, 16); + if (errno != 0 && address == 0) { + return HandlePacket_ILLFORMED( + __FILE__, __LINE__, p, "Invalid address in qMemoryRegionInfo packet"); + } + + DNBRegionInfo region_info = {0, 0, 0}; + DNBProcessMemoryRegionInfo(m_ctx.ProcessID(), address, ®ion_info); + std::ostringstream ostrm; + + // start:3a50000,size:100000,permissions:rwx + ostrm << "start:" << std::hex << region_info.addr << ';'; + + if (region_info.size > 0) + ostrm << "size:" << std::hex << region_info.size << ';'; + + if (region_info.permissions) { + ostrm << "permissions:"; + + if (region_info.permissions & eMemoryPermissionsReadable) + ostrm << 'r'; + if (region_info.permissions & eMemoryPermissionsWritable) + ostrm << 'w'; + if (region_info.permissions & eMemoryPermissionsExecutable) + ostrm << 'x'; + ostrm << ';'; + } + return SendPacket(ostrm.str()); } -rnb_err_t -RNBRemote::HandlePacket_MemoryRegionInfo (const char *p) -{ - /* This packet will find memory attributes (e.g. readable, writable, executable, stack, jitted code) - for the memory region containing a given address and return that information. - - Users of this packet must be prepared for three results: - - Region information is returned - Region information is unavailable for this address because the address is in unmapped memory - Region lookup cannot be performed on this platform or process is not yet launched - This packet isn't implemented - - Examples of use: - qMemoryRegionInfo:3a55140 - start:3a50000,size:100000,permissions:rwx - - qMemoryRegionInfo:0 - error:address in unmapped region - - qMemoryRegionInfo:3a551140 (on a different platform) - error:region lookup cannot be performed - - qMemoryRegionInfo - OK // this packet is implemented by the remote nub - */ - - p += sizeof ("qMemoryRegionInfo") - 1; - if (*p == '\0') - return SendPacket ("OK"); - if (*p++ != ':') - return SendPacket ("E67"); - if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X')) - p += 2; +// qGetProfileData;scan_type:0xYYYYYYY +rnb_err_t RNBRemote::HandlePacket_GetProfileData(const char *p) { + nub_process_t pid = m_ctx.ProcessID(); + if (pid == INVALID_NUB_PROCESS) + return SendPacket("OK"); - errno = 0; - uint64_t address = strtoul (p, NULL, 16); - if (errno != 0 && address == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in qMemoryRegionInfo packet"); + StdStringExtractor packet(p += sizeof("qGetProfileData")); + DNBProfileDataScanType scan_type = eProfileAll; + std::string name; + std::string value; + while (packet.GetNameColonValue(name, value)) { + if (name.compare("scan_type") == 0) { + std::istringstream iss(value); + uint32_t int_value = 0; + if (iss >> std::hex >> int_value) { + scan_type = (DNBProfileDataScanType)int_value; + } } + } - DNBRegionInfo region_info = { 0, 0, 0 }; - DNBProcessMemoryRegionInfo (m_ctx.ProcessID(), address, ®ion_info); - std::ostringstream ostrm; + std::string data = DNBProcessGetProfileData(pid, scan_type); + if (!data.empty()) { + return SendPacket(data.c_str()); + } else { + return SendPacket("OK"); + } +} - // start:3a50000,size:100000,permissions:rwx - ostrm << "start:" << std::hex << region_info.addr << ';'; +// QSetEnableAsyncProfiling;enable:[0|1]:interval_usec:XXXXXX;scan_type:0xYYYYYYY +rnb_err_t RNBRemote::HandlePacket_SetEnableAsyncProfiling(const char *p) { + nub_process_t pid = m_ctx.ProcessID(); + if (pid == INVALID_NUB_PROCESS) + return SendPacket("OK"); - if (region_info.size > 0) - ostrm << "size:" << std::hex << region_info.size << ';'; - - if (region_info.permissions) - { - ostrm << "permissions:"; - - if (region_info.permissions & eMemoryPermissionsReadable) - ostrm << 'r'; - if (region_info.permissions & eMemoryPermissionsWritable) - ostrm << 'w'; - if (region_info.permissions & eMemoryPermissionsExecutable) - ostrm << 'x'; - ostrm << ';'; + StdStringExtractor packet(p += sizeof("QSetEnableAsyncProfiling")); + bool enable = false; + uint64_t interval_usec = 0; + DNBProfileDataScanType scan_type = eProfileAll; + std::string name; + std::string value; + while (packet.GetNameColonValue(name, value)) { + if (name.compare("enable") == 0) { + enable = strtoul(value.c_str(), NULL, 10) > 0; + } else if (name.compare("interval_usec") == 0) { + interval_usec = strtoul(value.c_str(), NULL, 10); + } else if (name.compare("scan_type") == 0) { + std::istringstream iss(value); + uint32_t int_value = 0; + if (iss >> std::hex >> int_value) { + scan_type = (DNBProfileDataScanType)int_value; + } } - return SendPacket (ostrm.str()); -} + } -// qGetProfileData;scan_type:0xYYYYYYY -rnb_err_t -RNBRemote::HandlePacket_GetProfileData (const char *p) -{ - nub_process_t pid = m_ctx.ProcessID(); - if (pid == INVALID_NUB_PROCESS) - return SendPacket ("OK"); - - StdStringExtractor packet(p += sizeof ("qGetProfileData")); - DNBProfileDataScanType scan_type = eProfileAll; - std::string name; - std::string value; - while (packet.GetNameColonValue(name, value)) - { - if (name.compare ("scan_type") == 0) - { - std::istringstream iss(value); - uint32_t int_value = 0; - if (iss >> std::hex >> int_value) - { - scan_type = (DNBProfileDataScanType)int_value; - } - } - } - - std::string data = DNBProcessGetProfileData(pid, scan_type); - if (!data.empty()) - { - return SendPacket (data.c_str()); - } - else - { - return SendPacket ("OK"); - } -} + if (interval_usec == 0) { + enable = 0; + } -// QSetEnableAsyncProfiling;enable:[0|1]:interval_usec:XXXXXX;scan_type:0xYYYYYYY -rnb_err_t -RNBRemote::HandlePacket_SetEnableAsyncProfiling (const char *p) -{ - nub_process_t pid = m_ctx.ProcessID(); - if (pid == INVALID_NUB_PROCESS) - return SendPacket ("OK"); - - StdStringExtractor packet(p += sizeof ("QSetEnableAsyncProfiling")); - bool enable = false; - uint64_t interval_usec = 0; - DNBProfileDataScanType scan_type = eProfileAll; - std::string name; - std::string value; - while (packet.GetNameColonValue(name, value)) - { - if (name.compare ("enable") == 0) - { - enable = strtoul(value.c_str(), NULL, 10) > 0; - } - else if (name.compare ("interval_usec") == 0) - { - interval_usec = strtoul(value.c_str(), NULL, 10); - } - else if (name.compare ("scan_type") == 0) - { - std::istringstream iss(value); - uint32_t int_value = 0; - if (iss >> std::hex >> int_value) - { - scan_type = (DNBProfileDataScanType)int_value; - } - } - } - - if (interval_usec == 0) - { - enable = 0; - } - - DNBProcessSetEnableAsyncProfiling(pid, enable, interval_usec, scan_type); - return SendPacket ("OK"); + DNBProcessSetEnableAsyncProfiling(pid, enable, interval_usec, scan_type); + return SendPacket("OK"); } -// QEnableCompression:type:<COMPRESSION-TYPE>;minsize:<MINIMUM PACKET SIZE TO COMPRESS>; +// QEnableCompression:type:<COMPRESSION-TYPE>;minsize:<MINIMUM PACKET SIZE TO +// COMPRESS>; // -// type: must be a type previously reported by the qXfer:features: SupportedCompressions list +// type: must be a type previously reported by the qXfer:features: +// SupportedCompressions list // -// minsize: is optional; by default the qXfer:features: DefaultCompressionMinSize value is used -// debugserver may have a better idea of what a good minimum packet size to compress is than lldb. - -rnb_err_t -RNBRemote::HandlePacket_QEnableCompression (const char *p) -{ - p += sizeof ("QEnableCompression:") - 1; - - size_t new_compression_minsize = m_compression_minsize; - const char *new_compression_minsize_str = strstr (p, "minsize:"); - if (new_compression_minsize_str) - { - new_compression_minsize_str += strlen ("minsize:"); - errno = 0; - new_compression_minsize = strtoul (new_compression_minsize_str, NULL, 10); - if (errno != 0 || new_compression_minsize == ULONG_MAX) - { - new_compression_minsize = m_compression_minsize; - } - } - -#if defined (HAVE_LIBCOMPRESSION) - if (compression_decode_buffer != NULL) - { - if (strstr (p, "type:zlib-deflate;") != nullptr) - { - EnableCompressionNextSendPacket (compression_types::zlib_deflate); - m_compression_minsize = new_compression_minsize; - return SendPacket ("OK"); - } - else if (strstr (p, "type:lz4;") != nullptr) - { - EnableCompressionNextSendPacket (compression_types::lz4); - m_compression_minsize = new_compression_minsize; - return SendPacket ("OK"); - } - else if (strstr (p, "type:lzma;") != nullptr) - { - EnableCompressionNextSendPacket (compression_types::lzma); - m_compression_minsize = new_compression_minsize; - return SendPacket ("OK"); - } - else if (strstr (p, "type:lzfse;") != nullptr) - { - EnableCompressionNextSendPacket (compression_types::lzfse); - m_compression_minsize = new_compression_minsize; - return SendPacket ("OK"); - } - } +// minsize: is optional; by default the qXfer:features: +// DefaultCompressionMinSize value is used +// debugserver may have a better idea of what a good minimum packet size to +// compress is than lldb. + +rnb_err_t RNBRemote::HandlePacket_QEnableCompression(const char *p) { + p += sizeof("QEnableCompression:") - 1; + + size_t new_compression_minsize = m_compression_minsize; + const char *new_compression_minsize_str = strstr(p, "minsize:"); + if (new_compression_minsize_str) { + new_compression_minsize_str += strlen("minsize:"); + errno = 0; + new_compression_minsize = strtoul(new_compression_minsize_str, NULL, 10); + if (errno != 0 || new_compression_minsize == ULONG_MAX) { + new_compression_minsize = m_compression_minsize; + } + } + +#if defined(HAVE_LIBCOMPRESSION) + if (compression_decode_buffer != NULL) { + if (strstr(p, "type:zlib-deflate;") != nullptr) { + EnableCompressionNextSendPacket(compression_types::zlib_deflate); + m_compression_minsize = new_compression_minsize; + return SendPacket("OK"); + } else if (strstr(p, "type:lz4;") != nullptr) { + EnableCompressionNextSendPacket(compression_types::lz4); + m_compression_minsize = new_compression_minsize; + return SendPacket("OK"); + } else if (strstr(p, "type:lzma;") != nullptr) { + EnableCompressionNextSendPacket(compression_types::lzma); + m_compression_minsize = new_compression_minsize; + return SendPacket("OK"); + } else if (strstr(p, "type:lzfse;") != nullptr) { + EnableCompressionNextSendPacket(compression_types::lzfse); + m_compression_minsize = new_compression_minsize; + return SendPacket("OK"); + } + } #endif -#if defined (HAVE_LIBZ) - if (strstr (p, "type:zlib-deflate;") != nullptr) - { - EnableCompressionNextSendPacket (compression_types::zlib_deflate); - m_compression_minsize = new_compression_minsize; - return SendPacket ("OK"); - } +#if defined(HAVE_LIBZ) + if (strstr(p, "type:zlib-deflate;") != nullptr) { + EnableCompressionNextSendPacket(compression_types::zlib_deflate); + m_compression_minsize = new_compression_minsize; + return SendPacket("OK"); + } #endif - return SendPacket ("E88"); -} - -rnb_err_t -RNBRemote::HandlePacket_qSpeedTest (const char *p) -{ - p += strlen ("qSpeedTest:response_size:"); - char *end = NULL; - errno = 0; - uint64_t response_size = ::strtoul (p, &end, 16); - if (errno != 0) - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Didn't find response_size value at right offset"); - else if (*end == ';') - { - static char g_data[4*1024*1024+16] = "data:"; - memset(g_data + 5, 'a', response_size); - g_data[response_size + 5] = '\0'; - return SendPacket (g_data); - } - else - { - return SendPacket ("E79"); - } -} - -rnb_err_t -RNBRemote::HandlePacket_WatchpointSupportInfo (const char *p) -{ - /* This packet simply returns the number of supported hardware watchpoints. - - Examples of use: - qWatchpointSupportInfo: - num:4 - - qWatchpointSupportInfo - OK // this packet is implemented by the remote nub - */ - - p += sizeof ("qWatchpointSupportInfo") - 1; - if (*p == '\0') - return SendPacket ("OK"); - if (*p++ != ':') - return SendPacket ("E67"); + return SendPacket("E88"); +} + +rnb_err_t RNBRemote::HandlePacket_qSpeedTest(const char *p) { + p += strlen("qSpeedTest:response_size:"); + char *end = NULL; + errno = 0; + uint64_t response_size = ::strtoul(p, &end, 16); + if (errno != 0) + return HandlePacket_ILLFORMED( + __FILE__, __LINE__, p, + "Didn't find response_size value at right offset"); + else if (*end == ';') { + static char g_data[4 * 1024 * 1024 + 16] = "data:"; + memset(g_data + 5, 'a', response_size); + g_data[response_size + 5] = '\0'; + return SendPacket(g_data); + } else { + return SendPacket("E79"); + } +} + +rnb_err_t RNBRemote::HandlePacket_WatchpointSupportInfo(const char *p) { + /* This packet simply returns the number of supported hardware watchpoints. + + Examples of use: + qWatchpointSupportInfo: + num:4 + + qWatchpointSupportInfo + OK // this packet is implemented by the remote nub + */ + + p += sizeof("qWatchpointSupportInfo") - 1; + if (*p == '\0') + return SendPacket("OK"); + if (*p++ != ':') + return SendPacket("E67"); - errno = 0; - uint32_t num = DNBWatchpointGetNumSupportedHWP (m_ctx.ProcessID()); - std::ostringstream ostrm; + errno = 0; + uint32_t num = DNBWatchpointGetNumSupportedHWP(m_ctx.ProcessID()); + std::ostringstream ostrm; - // size:4 - ostrm << "num:" << std::dec << num << ';'; - return SendPacket (ostrm.str()); + // size:4 + ostrm << "num:" << std::dec << num << ';'; + return SendPacket(ostrm.str()); } /* 'C sig [;addr]' Resume with signal sig, optionally at address addr. */ -rnb_err_t -RNBRemote::HandlePacket_C (const char *p) -{ - const nub_process_t pid = m_ctx.ProcessID(); +rnb_err_t RNBRemote::HandlePacket_C(const char *p) { + const nub_process_t pid = m_ctx.ProcessID(); - if (pid == INVALID_NUB_PROCESS) - return SendPacket ("E36"); + if (pid == INVALID_NUB_PROCESS) + return SendPacket("E36"); - DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS }; - int process_signo = -1; - if (*(p + 1) != '\0') - { - action.tid = GetContinueThread(); - char *end = NULL; - errno = 0; - process_signo = static_cast<int>(strtoul (p + 1, &end, 16)); - if (errno != 0) - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in C packet"); - else if (*end == ';') - { - errno = 0; - action.addr = strtoull (end + 1, NULL, 16); - if (errno != 0 && action.addr == 0) - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in C packet"); - } - } - - DNBThreadResumeActions thread_actions; - thread_actions.Append (action); - thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, action.signal); - if (!DNBProcessSignal(pid, process_signo)) - return SendPacket ("E52"); - if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize())) - return SendPacket ("E38"); - /* Don't send an "OK" packet; response is the stopped/exited message. */ - return rnb_success; + DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateRunning, 0, + INVALID_NUB_ADDRESS}; + int process_signo = -1; + if (*(p + 1) != '\0') { + action.tid = GetContinueThread(); + char *end = NULL; + errno = 0; + process_signo = static_cast<int>(strtoul(p + 1, &end, 16)); + if (errno != 0) + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Could not parse signal in C packet"); + else if (*end == ';') { + errno = 0; + action.addr = strtoull(end + 1, NULL, 16); + if (errno != 0 && action.addr == 0) + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Could not parse address in C packet"); + } + } + + DNBThreadResumeActions thread_actions; + thread_actions.Append(action); + thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, action.signal); + if (!DNBProcessSignal(pid, process_signo)) + return SendPacket("E52"); + if (!DNBProcessResume(pid, thread_actions.GetFirst(), + thread_actions.GetSize())) + return SendPacket("E38"); + /* Don't send an "OK" packet; response is the stopped/exited message. */ + return rnb_success; } //---------------------------------------------------------------------- // 'D' packet // Detach from gdb. //---------------------------------------------------------------------- -rnb_err_t -RNBRemote::HandlePacket_D (const char *p) -{ - if (m_ctx.HasValidProcessID()) - { - if (DNBProcessDetach(m_ctx.ProcessID())) - SendPacket ("OK"); - else - SendPacket ("E"); - } +rnb_err_t RNBRemote::HandlePacket_D(const char *p) { + if (m_ctx.HasValidProcessID()) { + if (DNBProcessDetach(m_ctx.ProcessID())) + SendPacket("OK"); else - { - SendPacket ("E"); - } - return rnb_success; + SendPacket("E"); + } else { + SendPacket("E"); + } + return rnb_success; } /* 'k' Kill the inferior process. */ -rnb_err_t -RNBRemote::HandlePacket_k (const char *p) -{ - DNBLog ("Got a 'k' packet, killing the inferior process."); - // No response to should be sent to the kill packet - if (m_ctx.HasValidProcessID()) - DNBProcessKill (m_ctx.ProcessID()); - SendPacket ("X09"); - return rnb_success; +rnb_err_t RNBRemote::HandlePacket_k(const char *p) { + DNBLog("Got a 'k' packet, killing the inferior process."); + // No response to should be sent to the kill packet + if (m_ctx.HasValidProcessID()) + DNBProcessKill(m_ctx.ProcessID()); + SendPacket("X09"); + return rnb_success; } -rnb_err_t -RNBRemote::HandlePacket_stop_process (const char *p) -{ -//#define TEST_EXIT_ON_INTERRUPT // This should only be uncommented to test exiting on interrupt +rnb_err_t RNBRemote::HandlePacket_stop_process(const char *p) { +//#define TEST_EXIT_ON_INTERRUPT // This should only be uncommented to test +//exiting on interrupt #if defined(TEST_EXIT_ON_INTERRUPT) - rnb_err_t err = HandlePacket_k (p); - m_comm.Disconnect(true); - return err; + rnb_err_t err = HandlePacket_k(p); + m_comm.Disconnect(true); + return err; #else - if (!DNBProcessInterrupt(m_ctx.ProcessID())) - { - // If we failed to interrupt the process, then send a stop - // reply packet as the process was probably already stopped - DNBLogThreaded ("RNBRemote::HandlePacket_stop_process() sending extra stop reply because DNBProcessInterrupt returned false"); - HandlePacket_last_signal (NULL); - } - return rnb_success; + if (!DNBProcessInterrupt(m_ctx.ProcessID())) { + // If we failed to interrupt the process, then send a stop + // reply packet as the process was probably already stopped + DNBLogThreaded("RNBRemote::HandlePacket_stop_process() sending extra stop " + "reply because DNBProcessInterrupt returned false"); + HandlePacket_last_signal(NULL); + } + return rnb_success; #endif } /* 's' Step the inferior process. */ -rnb_err_t -RNBRemote::HandlePacket_s (const char *p) -{ - const nub_process_t pid = m_ctx.ProcessID(); - if (pid == INVALID_NUB_PROCESS) - return SendPacket ("E32"); +rnb_err_t RNBRemote::HandlePacket_s(const char *p) { + const nub_process_t pid = m_ctx.ProcessID(); + if (pid == INVALID_NUB_PROCESS) + return SendPacket("E32"); - // Hardware supported stepping not supported on arm - nub_thread_t tid = GetContinueThread (); - if (tid == 0 || tid == (nub_thread_t)-1) - tid = GetCurrentThread(); + // Hardware supported stepping not supported on arm + nub_thread_t tid = GetContinueThread(); + if (tid == 0 || tid == (nub_thread_t)-1) + tid = GetCurrentThread(); - if (tid == INVALID_NUB_THREAD) - return SendPacket ("E33"); + if (tid == INVALID_NUB_THREAD) + return SendPacket("E33"); - DNBThreadResumeActions thread_actions; - thread_actions.AppendAction(tid, eStateStepping); + DNBThreadResumeActions thread_actions; + thread_actions.AppendAction(tid, eStateStepping); - // Make all other threads stop when we are stepping - thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0); - if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize())) - return SendPacket ("E49"); - // Don't send an "OK" packet; response is the stopped/exited message. - return rnb_success; + // Make all other threads stop when we are stepping + thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); + if (!DNBProcessResume(pid, thread_actions.GetFirst(), + thread_actions.GetSize())) + return SendPacket("E49"); + // Don't send an "OK" packet; response is the stopped/exited message. + return rnb_success; } /* 'S sig [;addr]' Step with signal sig, optionally at address addr. */ -rnb_err_t -RNBRemote::HandlePacket_S (const char *p) -{ - const nub_process_t pid = m_ctx.ProcessID(); - if (pid == INVALID_NUB_PROCESS) - return SendPacket ("E36"); - - DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateStepping, 0, INVALID_NUB_ADDRESS }; - - if (*(p + 1) != '\0') - { - char *end = NULL; - errno = 0; - action.signal = static_cast<int>(strtoul (p + 1, &end, 16)); - if (errno != 0) - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in S packet"); - else if (*end == ';') - { - errno = 0; - action.addr = strtoull (end + 1, NULL, 16); - if (errno != 0 && action.addr == 0) - { - return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in S packet"); - } - } - } - - action.tid = GetContinueThread (); - if (action.tid == 0 || action.tid == (nub_thread_t)-1) - return SendPacket ("E40"); - - nub_state_t tstate = DNBThreadGetState (pid, action.tid); - if (tstate == eStateInvalid || tstate == eStateExited) - return SendPacket ("E37"); - - - DNBThreadResumeActions thread_actions; - thread_actions.Append (action); - - // Make all other threads stop when we are stepping - thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); - if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize())) - return SendPacket ("E39"); +rnb_err_t RNBRemote::HandlePacket_S(const char *p) { + const nub_process_t pid = m_ctx.ProcessID(); + if (pid == INVALID_NUB_PROCESS) + return SendPacket("E36"); - // Don't send an "OK" packet; response is the stopped/exited message. - return rnb_success; -} + DNBThreadResumeAction action = {INVALID_NUB_THREAD, eStateStepping, 0, + INVALID_NUB_ADDRESS}; -static const char * -GetArchName (const uint32_t cputype, const uint32_t cpusubtype) -{ - switch (cputype) - { - case CPU_TYPE_ARM: - switch (cpusubtype) - { - case 5: return "armv4"; - case 6: return "armv6"; - case 7: return "armv5t"; - case 8: return "xscale"; - case 9: return "armv7"; - case 10: return "armv7f"; - case 11: return "armv7s"; - case 12: return "armv7k"; - case 14: return "armv6m"; - case 15: return "armv7m"; - case 16: return "armv7em"; - default: return "arm"; - } - break; - case CPU_TYPE_ARM64: return "arm64"; - case CPU_TYPE_I386: return "i386"; - case CPU_TYPE_X86_64: - switch (cpusubtype) - { - default: return "x86_64"; - case 8: return "x86_64h"; - } - break; + if (*(p + 1) != '\0') { + char *end = NULL; + errno = 0; + action.signal = static_cast<int>(strtoul(p + 1, &end, 16)); + if (errno != 0) + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Could not parse signal in S packet"); + else if (*end == ';') { + errno = 0; + action.addr = strtoull(end + 1, NULL, 16); + if (errno != 0 && action.addr == 0) { + return HandlePacket_ILLFORMED(__FILE__, __LINE__, p, + "Could not parse address in S packet"); + } } - return NULL; -} - -static bool -GetHostCPUType (uint32_t &cputype, uint32_t &cpusubtype, uint32_t &is_64_bit_capable, bool &promoted_to_64) -{ - static uint32_t g_host_cputype = 0; - static uint32_t g_host_cpusubtype = 0; - static uint32_t g_is_64_bit_capable = 0; - static bool g_promoted_to_64 = false; - - if (g_host_cputype == 0) - { - g_promoted_to_64 = false; - size_t len = sizeof(uint32_t); - if (::sysctlbyname("hw.cputype", &g_host_cputype, &len, NULL, 0) == 0) - { - len = sizeof (uint32_t); - if (::sysctlbyname("hw.cpu64bit_capable", &g_is_64_bit_capable, &len, NULL, 0) == 0) - { - if (g_is_64_bit_capable && ((g_host_cputype & CPU_ARCH_ABI64) == 0)) - { - g_promoted_to_64 = true; - g_host_cputype |= CPU_ARCH_ABI64; - } - } - } - - len = sizeof(uint32_t); - if (::sysctlbyname("hw.cpusubtype", &g_host_cpusubtype, &len, NULL, 0) == 0) - { - if (g_promoted_to_64 && - g_host_cputype == CPU_TYPE_X86_64 && g_host_cpusubtype == CPU_SUBTYPE_486) - g_host_cpusubtype = CPU_SUBTYPE_X86_64_ALL; + } + + action.tid = GetContinueThread(); + if (action.tid == 0 || action.tid == (nub_thread_t)-1) + return SendPacket("E40"); + + nub_state_t tstate = DNBThreadGetState(pid, action.tid); + if (tstate == eStateInvalid || tstate == eStateExited) + return SendPacket("E37"); + + DNBThreadResumeActions thread_actions; + thread_actions.Append(action); + + // Make all other threads stop when we are stepping + thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); + if (!DNBProcessResume(pid, thread_actions.GetFirst(), + thread_actions.GetSize())) + return SendPacket("E39"); + + // Don't send an "OK" packet; response is the stopped/exited message. + return rnb_success; +} + +static const char *GetArchName(const uint32_t cputype, + const uint32_t cpusubtype) { + switch (cputype) { + case CPU_TYPE_ARM: + switch (cpusubtype) { + case 5: + return "armv4"; + case 6: + return "armv6"; + case 7: + return "armv5t"; + case 8: + return "xscale"; + case 9: + return "armv7"; + case 10: + return "armv7f"; + case 11: + return "armv7s"; + case 12: + return "armv7k"; + case 14: + return "armv6m"; + case 15: + return "armv7m"; + case 16: + return "armv7em"; + default: + return "arm"; + } + break; + case CPU_TYPE_ARM64: + return "arm64"; + case CPU_TYPE_I386: + return "i386"; + case CPU_TYPE_X86_64: + switch (cpusubtype) { + default: + return "x86_64"; + case 8: + return "x86_64h"; + } + break; + } + return NULL; +} + +static bool GetHostCPUType(uint32_t &cputype, uint32_t &cpusubtype, + uint32_t &is_64_bit_capable, bool &promoted_to_64) { + static uint32_t g_host_cputype = 0; + static uint32_t g_host_cpusubtype = 0; + static uint32_t g_is_64_bit_capable = 0; + static bool g_promoted_to_64 = false; + + if (g_host_cputype == 0) { + g_promoted_to_64 = false; + size_t len = sizeof(uint32_t); + if (::sysctlbyname("hw.cputype", &g_host_cputype, &len, NULL, 0) == 0) { + len = sizeof(uint32_t); + if (::sysctlbyname("hw.cpu64bit_capable", &g_is_64_bit_capable, &len, + NULL, 0) == 0) { + if (g_is_64_bit_capable && ((g_host_cputype & CPU_ARCH_ABI64) == 0)) { + g_promoted_to_64 = true; + g_host_cputype |= CPU_ARCH_ABI64; } - } - - cputype = g_host_cputype; - cpusubtype = g_host_cpusubtype; - is_64_bit_capable = g_is_64_bit_capable; - promoted_to_64 = g_promoted_to_64; - return g_host_cputype != 0; -} - -rnb_err_t -RNBRemote::HandlePacket_qHostInfo (const char *p) -{ - std::ostringstream strm; - - uint32_t cputype = 0; - uint32_t cpusubtype = 0; - uint32_t is_64_bit_capable = 0; - bool promoted_to_64 = false; - if (GetHostCPUType (cputype, cpusubtype, is_64_bit_capable, promoted_to_64)) - { - strm << "cputype:" << std::dec << cputype << ';'; - strm << "cpusubtype:" << std::dec << cpusubtype << ';'; + } } - // The OS in the triple should be "ios" or "macosx" which doesn't match our - // "Darwin" which gets returned from "kern.ostype", so we need to hardcode - // this for now. - if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) - { -#if defined (TARGET_OS_TV) && TARGET_OS_TV == 1 - strm << "ostype:tvos;"; -#elif defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 - strm << "ostype:watchos;"; + len = sizeof(uint32_t); + if (::sysctlbyname("hw.cpusubtype", &g_host_cpusubtype, &len, NULL, 0) == + 0) { + if (g_promoted_to_64 && g_host_cputype == CPU_TYPE_X86_64 && + g_host_cpusubtype == CPU_SUBTYPE_486) + g_host_cpusubtype = CPU_SUBTYPE_X86_64_ALL; + } + } + + cputype = g_host_cputype; + cpusubtype = g_host_cpusubtype; + is_64_bit_capable = g_is_64_bit_capable; + promoted_to_64 = g_promoted_to_64; + return g_host_cputype != 0; +} + +rnb_err_t RNBRemote::HandlePacket_qHostInfo(const char *p) { + std::ostringstream strm; + + uint32_t cputype = 0; + uint32_t cpusubtype = 0; + uint32_t is_64_bit_capable = 0; + bool promoted_to_64 = false; + if (GetHostCPUType(cputype, cpusubtype, is_64_bit_capable, promoted_to_64)) { + strm << "cputype:" << std::dec << cputype << ';'; + strm << "cpusubtype:" << std::dec << cpusubtype << ';'; + } + + // The OS in the triple should be "ios" or "macosx" which doesn't match our + // "Darwin" which gets returned from "kern.ostype", so we need to hardcode + // this for now. + if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) { +#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1 + strm << "ostype:tvos;"; +#elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 + strm << "ostype:watchos;"; #else - strm << "ostype:ios;"; + strm << "ostype:ios;"; #endif - // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes. - strm << "watchpoint_exceptions_received:before;"; - } - else - { - strm << "ostype:macosx;"; - strm << "watchpoint_exceptions_received:after;"; - } -// char ostype[64]; -// len = sizeof(ostype); -// if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0) -// { -// len = strlen(ostype); -// std::transform (ostype, ostype + len, ostype, tolower); -// strm << "ostype:" << std::dec << ostype << ';'; -// } - - strm << "vendor:apple;"; - - uint64_t major, minor, patch; - if (DNBGetOSVersionNumbers (&major, &minor, &patch)) - { - strm << "os_version:" << major << "." << minor; - if (patch != UINT64_MAX) - strm << "." << patch; - strm << ";"; - } - -#if defined (__LITTLE_ENDIAN__) - strm << "endian:little;"; -#elif defined (__BIG_ENDIAN__) - strm << "endian:big;"; -#elif defined (__PDP_ENDIAN__) - strm << "endian:pdp;"; + // On armv7 we use "synchronous" watchpoints which means the exception is + // delivered before the instruction executes. + strm << "watchpoint_exceptions_received:before;"; + } else { + strm << "ostype:macosx;"; + strm << "watchpoint_exceptions_received:after;"; + } + // char ostype[64]; + // len = sizeof(ostype); + // if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0) + // { + // len = strlen(ostype); + // std::transform (ostype, ostype + len, ostype, tolower); + // strm << "ostype:" << std::dec << ostype << ';'; + // } + + strm << "vendor:apple;"; + + uint64_t major, minor, patch; + if (DNBGetOSVersionNumbers(&major, &minor, &patch)) { + strm << "os_version:" << major << "." << minor; + if (patch != UINT64_MAX) + strm << "." << patch; + strm << ";"; + } + +#if defined(__LITTLE_ENDIAN__) + strm << "endian:little;"; +#elif defined(__BIG_ENDIAN__) + strm << "endian:big;"; +#elif defined(__PDP_ENDIAN__) + strm << "endian:pdp;"; #endif - if (promoted_to_64) - strm << "ptrsize:8;"; - else - strm << "ptrsize:" << std::dec << sizeof(void *) << ';'; + if (promoted_to_64) + strm << "ptrsize:8;"; + else + strm << "ptrsize:" << std::dec << sizeof(void *) << ';'; -#if defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 - strm << "default_packet_timeout:10;"; +#if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 + strm << "default_packet_timeout:10;"; #endif - return SendPacket (strm.str()); -} - -void -XMLElementStart (std::ostringstream &s, uint32_t indent, const char *name, bool has_attributes) -{ - if (indent) - s << INDENT_WITH_SPACES(indent); - s << '<' << name; - if (!has_attributes) - s << '>' << std::endl; + return SendPacket(strm.str()); } -void -XMLElementStartEndAttributes (std::ostringstream &s, bool empty) -{ - if (empty) - s << '/'; +void XMLElementStart(std::ostringstream &s, uint32_t indent, const char *name, + bool has_attributes) { + if (indent) + s << INDENT_WITH_SPACES(indent); + s << '<' << name; + if (!has_attributes) s << '>' << std::endl; } -void -XMLElementEnd (std::ostringstream &s, uint32_t indent, const char *name) -{ - if (indent) - s << INDENT_WITH_SPACES(indent); - s << '<' << '/' << name << '>' << std::endl; +void XMLElementStartEndAttributes(std::ostringstream &s, bool empty) { + if (empty) + s << '/'; + s << '>' << std::endl; } -void -XMLElementWithStringValue (std::ostringstream &s, uint32_t indent, const char *name, const char *value, bool close = true) -{ - if (value) - { - if (indent) - s << INDENT_WITH_SPACES(indent); - s << '<' << name << '>' << value; - if (close) - XMLElementEnd(s, 0, name); - } +void XMLElementEnd(std::ostringstream &s, uint32_t indent, const char *name) { + if (indent) + s << INDENT_WITH_SPACES(indent); + s << '<' << '/' << name << '>' << std::endl; } -void -XMLElementWithUnsignedValue (std::ostringstream &s, uint32_t indent, const char *name, uint64_t value, bool close = true) -{ +void XMLElementWithStringValue(std::ostringstream &s, uint32_t indent, + const char *name, const char *value, + bool close = true) { + if (value) { if (indent) - s << INDENT_WITH_SPACES(indent); - - s << '<' << name << '>' << DECIMAL << value; + s << INDENT_WITH_SPACES(indent); + s << '<' << name << '>' << value; if (close) - XMLElementEnd(s, 0, name); -} - -void -XMLAttributeString (std::ostringstream &s, const char *name, const char *value, const char *default_value = NULL) -{ - if (value) - { - if (default_value && strcmp(value, default_value) == 0) - return; // No need to emit the attribute because it matches the default value - s <<' ' << name << "=\"" << value << "\""; - } -} - -void -XMLAttributeUnsignedDecimal (std::ostringstream &s, const char *name, uint64_t value) -{ - s <<' ' << name << "=\"" << DECIMAL << value << "\""; -} - -void -GenerateTargetXMLRegister (std::ostringstream &s, - const uint32_t reg_num, - nub_size_t num_reg_sets, - const DNBRegisterSetInfo *reg_set_info, - const register_map_entry_t ®) -{ - const char *default_lldb_encoding = "uint"; - const char *lldb_encoding = default_lldb_encoding; - const char *gdb_group = "general"; - const char *default_gdb_type = "int"; - const char *gdb_type = default_gdb_type; - const char *default_lldb_format = "hex"; - const char *lldb_format = default_lldb_format; - const char *lldb_set = NULL; - - switch (reg.nub_info.type) - { - case Uint: lldb_encoding = "uint"; break; - case Sint: lldb_encoding = "sint"; break; - case IEEE754: lldb_encoding = "ieee754"; if (reg.nub_info.set > 0) gdb_group = "float"; break; - case Vector: lldb_encoding = "vector"; if (reg.nub_info.set > 0) gdb_group = "vector"; break; - } - - switch (reg.nub_info.format) - { - case Binary: lldb_format = "binary"; break; - case Decimal: lldb_format = "decimal"; break; - case Hex: lldb_format = "hex"; break; - case Float: gdb_type = "float"; lldb_format = "float"; break; - case VectorOfSInt8: gdb_type = "float"; lldb_format = "vector-sint8"; break; - case VectorOfUInt8: gdb_type = "float"; lldb_format = "vector-uint8"; break; - case VectorOfSInt16: gdb_type = "float"; lldb_format = "vector-sint16"; break; - case VectorOfUInt16: gdb_type = "float"; lldb_format = "vector-uint16"; break; - case VectorOfSInt32: gdb_type = "float"; lldb_format = "vector-sint32"; break; - case VectorOfUInt32: gdb_type = "float"; lldb_format = "vector-uint32"; break; - case VectorOfFloat32: gdb_type = "float"; lldb_format = "vector-float32"; break; - case VectorOfUInt128: gdb_type = "float"; lldb_format = "vector-uint128"; break; - }; - if (reg_set_info && reg.nub_info.set < num_reg_sets) - lldb_set = reg_set_info[reg.nub_info.set].name; - - uint32_t indent = 2; - - XMLElementStart(s, indent, "reg", true); - XMLAttributeString(s, "name", reg.nub_info.name); - XMLAttributeUnsignedDecimal(s, "regnum", reg_num); - XMLAttributeUnsignedDecimal(s, "offset", reg.offset); - XMLAttributeUnsignedDecimal(s, "bitsize", reg.nub_info.size * 8); - XMLAttributeString(s, "group", gdb_group); - XMLAttributeString(s, "type", gdb_type, default_gdb_type); - XMLAttributeString (s, "altname", reg.nub_info.alt); - XMLAttributeString(s, "encoding", lldb_encoding, default_lldb_encoding); - XMLAttributeString(s, "format", lldb_format, default_lldb_format); - XMLAttributeUnsignedDecimal(s, "group_id", reg.nub_info.set); - if (reg.nub_info.reg_ehframe != INVALID_NUB_REGNUM) - XMLAttributeUnsignedDecimal(s, "ehframe_regnum", reg.nub_info.reg_ehframe); - if (reg.nub_info.reg_dwarf != INVALID_NUB_REGNUM) - XMLAttributeUnsignedDecimal(s, "dwarf_regnum", reg.nub_info.reg_dwarf); - - const char *lldb_generic = NULL; - switch (reg.nub_info.reg_generic) - { - case GENERIC_REGNUM_FP: lldb_generic = "fp"; break; - case GENERIC_REGNUM_PC: lldb_generic = "pc"; break; - case GENERIC_REGNUM_SP: lldb_generic = "sp"; break; - case GENERIC_REGNUM_RA: lldb_generic = "ra"; break; - case GENERIC_REGNUM_FLAGS: lldb_generic = "flags"; break; - case GENERIC_REGNUM_ARG1: lldb_generic = "arg1"; break; - case GENERIC_REGNUM_ARG2: lldb_generic = "arg2"; break; - case GENERIC_REGNUM_ARG3: lldb_generic = "arg3"; break; - case GENERIC_REGNUM_ARG4: lldb_generic = "arg4"; break; - case GENERIC_REGNUM_ARG5: lldb_generic = "arg5"; break; - case GENERIC_REGNUM_ARG6: lldb_generic = "arg6"; break; - case GENERIC_REGNUM_ARG7: lldb_generic = "arg7"; break; - case GENERIC_REGNUM_ARG8: lldb_generic = "arg8"; break; - default: break; - } - XMLAttributeString(s, "generic", lldb_generic); - - - bool empty = reg.value_regnums.empty() && reg.invalidate_regnums.empty(); - if (!empty) - { - if (!reg.value_regnums.empty()) - { - std::ostringstream regnums; - bool first = true; - regnums << DECIMAL; - for (auto regnum : reg.value_regnums) - { - if (!first) - regnums << ','; - regnums << regnum; - first = false; - } - XMLAttributeString(s, "value_regnums", regnums.str().c_str()); - } - - if (!reg.invalidate_regnums.empty()) - { - std::ostringstream regnums; - bool first = true; - regnums << DECIMAL; - for (auto regnum : reg.invalidate_regnums) - { - if (!first) - regnums << ','; - regnums << regnum; - first = false; - } - XMLAttributeString(s, "invalidate_regnums", regnums.str().c_str()); - } - } - XMLElementStartEndAttributes(s, true); -} - -void -GenerateTargetXMLRegisters (std::ostringstream &s) -{ - nub_size_t num_reg_sets = 0; - const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo (&num_reg_sets); - - - uint32_t cputype = DNBGetRegisterCPUType(); - if (cputype) - { - XMLElementStart(s, 0, "feature", true); - std::ostringstream name_strm; - name_strm << "com.apple.debugserver." << GetArchName (cputype, 0); - XMLAttributeString(s, "name", name_strm.str().c_str()); - XMLElementStartEndAttributes(s, false); - for (uint32_t reg_num = 0; reg_num < g_num_reg_entries; ++reg_num) -// for (const auto ®: g_dynamic_register_map) - { - GenerateTargetXMLRegister(s, reg_num, num_reg_sets, reg_sets, g_reg_entries[reg_num]); - } - XMLElementEnd(s, 0, "feature"); - - if (num_reg_sets > 0) - { - XMLElementStart(s, 0, "groups", false); - for (uint32_t set=1; set<num_reg_sets; ++set) - { - XMLElementStart(s, 2, "group", true); - XMLAttributeUnsignedDecimal(s, "id", set); - XMLAttributeString(s, "name", reg_sets[set].name); - XMLElementStartEndAttributes(s, true); - } - XMLElementEnd(s, 0, "groups"); - } + XMLElementEnd(s, 0, name); + } +} + +void XMLElementWithUnsignedValue(std::ostringstream &s, uint32_t indent, + const char *name, uint64_t value, + bool close = true) { + if (indent) + s << INDENT_WITH_SPACES(indent); + + s << '<' << name << '>' << DECIMAL << value; + if (close) + XMLElementEnd(s, 0, name); +} + +void XMLAttributeString(std::ostringstream &s, const char *name, + const char *value, const char *default_value = NULL) { + if (value) { + if (default_value && strcmp(value, default_value) == 0) + return; // No need to emit the attribute because it matches the default + // value + s << ' ' << name << "=\"" << value << "\""; + } +} + +void XMLAttributeUnsignedDecimal(std::ostringstream &s, const char *name, + uint64_t value) { + s << ' ' << name << "=\"" << DECIMAL << value << "\""; +} + +void GenerateTargetXMLRegister(std::ostringstream &s, const uint32_t reg_num, + nub_size_t num_reg_sets, + const DNBRegisterSetInfo *reg_set_info, + const register_map_entry_t ®) { + const char *default_lldb_encoding = "uint"; + const char *lldb_encoding = default_lldb_encoding; + const char *gdb_group = "general"; + const char *default_gdb_type = "int"; + const char *gdb_type = default_gdb_type; + const char *default_lldb_format = "hex"; + const char *lldb_format = default_lldb_format; + const char *lldb_set = NULL; + + switch (reg.nub_info.type) { + case Uint: + lldb_encoding = "uint"; + break; + case Sint: + lldb_encoding = "sint"; + break; + case IEEE754: + lldb_encoding = "ieee754"; + if (reg.nub_info.set > 0) + gdb_group = "float"; + break; + case Vector: + lldb_encoding = "vector"; + if (reg.nub_info.set > 0) + gdb_group = "vector"; + break; + } + + switch (reg.nub_info.format) { + case Binary: + lldb_format = "binary"; + break; + case Decimal: + lldb_format = "decimal"; + break; + case Hex: + lldb_format = "hex"; + break; + case Float: + gdb_type = "float"; + lldb_format = "float"; + break; + case VectorOfSInt8: + gdb_type = "float"; + lldb_format = "vector-sint8"; + break; + case VectorOfUInt8: + gdb_type = "float"; + lldb_format = "vector-uint8"; + break; + case VectorOfSInt16: + gdb_type = "float"; + lldb_format = "vector-sint16"; + break; + case VectorOfUInt16: + gdb_type = "float"; + lldb_format = "vector-uint16"; + break; + case VectorOfSInt32: + gdb_type = "float"; + lldb_format = "vector-sint32"; + break; + case VectorOfUInt32: + gdb_type = "float"; + lldb_format = "vector-uint32"; + break; + case VectorOfFloat32: + gdb_type = "float"; + lldb_format = "vector-float32"; + break; + case VectorOfUInt128: + gdb_type = "float"; + lldb_format = "vector-uint128"; + break; + }; + if (reg_set_info && reg.nub_info.set < num_reg_sets) + lldb_set = reg_set_info[reg.nub_info.set].name; + + uint32_t indent = 2; + + XMLElementStart(s, indent, "reg", true); + XMLAttributeString(s, "name", reg.nub_info.name); + XMLAttributeUnsignedDecimal(s, "regnum", reg_num); + XMLAttributeUnsignedDecimal(s, "offset", reg.offset); + XMLAttributeUnsignedDecimal(s, "bitsize", reg.nub_info.size * 8); + XMLAttributeString(s, "group", gdb_group); + XMLAttributeString(s, "type", gdb_type, default_gdb_type); + XMLAttributeString(s, "altname", reg.nub_info.alt); + XMLAttributeString(s, "encoding", lldb_encoding, default_lldb_encoding); + XMLAttributeString(s, "format", lldb_format, default_lldb_format); + XMLAttributeUnsignedDecimal(s, "group_id", reg.nub_info.set); + if (reg.nub_info.reg_ehframe != INVALID_NUB_REGNUM) + XMLAttributeUnsignedDecimal(s, "ehframe_regnum", reg.nub_info.reg_ehframe); + if (reg.nub_info.reg_dwarf != INVALID_NUB_REGNUM) + XMLAttributeUnsignedDecimal(s, "dwarf_regnum", reg.nub_info.reg_dwarf); + + const char *lldb_generic = NULL; + switch (reg.nub_info.reg_generic) { + case GENERIC_REGNUM_FP: + lldb_generic = "fp"; + break; + case GENERIC_REGNUM_PC: + lldb_generic = "pc"; + break; + case GENERIC_REGNUM_SP: + lldb_generic = "sp"; + break; + case GENERIC_REGNUM_RA: + lldb_generic = "ra"; + break; + case GENERIC_REGNUM_FLAGS: + lldb_generic = "flags"; + break; + case GENERIC_REGNUM_ARG1: + lldb_generic = "arg1"; + break; + case GENERIC_REGNUM_ARG2: + lldb_generic = "arg2"; + break; + case GENERIC_REGNUM_ARG3: + lldb_generic = "arg3"; + break; + case GENERIC_REGNUM_ARG4: + lldb_generic = "arg4"; + break; + case GENERIC_REGNUM_ARG5: + lldb_generic = "arg5"; + break; + case GENERIC_REGNUM_ARG6: + lldb_generic = "arg6"; + break; + case GENERIC_REGNUM_ARG7: + lldb_generic = "arg7"; + break; + case GENERIC_REGNUM_ARG8: + lldb_generic = "arg8"; + break; + default: + break; + } + XMLAttributeString(s, "generic", lldb_generic); + + bool empty = reg.value_regnums.empty() && reg.invalidate_regnums.empty(); + if (!empty) { + if (!reg.value_regnums.empty()) { + std::ostringstream regnums; + bool first = true; + regnums << DECIMAL; + for (auto regnum : reg.value_regnums) { + if (!first) + regnums << ','; + regnums << regnum; + first = false; + } + XMLAttributeString(s, "value_regnums", regnums.str().c_str()); + } + + if (!reg.invalidate_regnums.empty()) { + std::ostringstream regnums; + bool first = true; + regnums << DECIMAL; + for (auto regnum : reg.invalidate_regnums) { + if (!first) + regnums << ','; + regnums << regnum; + first = false; + } + XMLAttributeString(s, "invalidate_regnums", regnums.str().c_str()); + } + } + XMLElementStartEndAttributes(s, true); +} + +void GenerateTargetXMLRegisters(std::ostringstream &s) { + nub_size_t num_reg_sets = 0; + const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo(&num_reg_sets); + + uint32_t cputype = DNBGetRegisterCPUType(); + if (cputype) { + XMLElementStart(s, 0, "feature", true); + std::ostringstream name_strm; + name_strm << "com.apple.debugserver." << GetArchName(cputype, 0); + XMLAttributeString(s, "name", name_strm.str().c_str()); + XMLElementStartEndAttributes(s, false); + for (uint32_t reg_num = 0; reg_num < g_num_reg_entries; ++reg_num) + // for (const auto ®: g_dynamic_register_map) + { + GenerateTargetXMLRegister(s, reg_num, num_reg_sets, reg_sets, + g_reg_entries[reg_num]); + } + XMLElementEnd(s, 0, "feature"); + + if (num_reg_sets > 0) { + XMLElementStart(s, 0, "groups", false); + for (uint32_t set = 1; set < num_reg_sets; ++set) { + XMLElementStart(s, 2, "group", true); + XMLAttributeUnsignedDecimal(s, "id", set); + XMLAttributeString(s, "name", reg_sets[set].name); + XMLElementStartEndAttributes(s, true); + } + XMLElementEnd(s, 0, "groups"); } + } } static const char *g_target_xml_header = R"(<?xml version="1.0"?> @@ -5117,171 +4983,146 @@ static const char *g_target_xml_footer = "</target>"; static std::string g_target_xml; -void -UpdateTargetXML () -{ - std::ostringstream s; - s << g_target_xml_header << std::endl; - - // Set the architecture - //s << "<architecture>" << arch "</architecture>" << std::endl; - - // Set the OSABI - //s << "<osabi>abi-name</osabi>" +void UpdateTargetXML() { + std::ostringstream s; + s << g_target_xml_header << std::endl; + + // Set the architecture + // s << "<architecture>" << arch "</architecture>" << std::endl; - GenerateTargetXMLRegisters(s); - - s << g_target_xml_footer << std::endl; + // Set the OSABI + // s << "<osabi>abi-name</osabi>" - // Save the XML output in case it gets retrieved in chunks - g_target_xml = s.str(); + GenerateTargetXMLRegisters(s); + + s << g_target_xml_footer << std::endl; + + // Save the XML output in case it gets retrieved in chunks + g_target_xml = s.str(); } -rnb_err_t -RNBRemote::HandlePacket_qXfer (const char *command) -{ - const char *p = command; - p += strlen ("qXfer:"); - const char *sep = strchr(p, ':'); - if (sep) - { - std::string object(p, sep - p); // "auxv", "backtrace", "features", etc - p = sep + 1; - sep = strchr(p, ':'); - if (sep) - { - std::string rw(p, sep - p); // "read" or "write" - p = sep + 1; - sep = strchr(p, ':'); - if (sep) - { - std::string annex(p, sep - p); // "read" or "write" +rnb_err_t RNBRemote::HandlePacket_qXfer(const char *command) { + const char *p = command; + p += strlen("qXfer:"); + const char *sep = strchr(p, ':'); + if (sep) { + std::string object(p, sep - p); // "auxv", "backtrace", "features", etc + p = sep + 1; + sep = strchr(p, ':'); + if (sep) { + std::string rw(p, sep - p); // "read" or "write" + p = sep + 1; + sep = strchr(p, ':'); + if (sep) { + std::string annex(p, sep - p); // "read" or "write" - p = sep + 1; - sep = strchr(p, ','); - if (sep) - { - std::string offset_str(p, sep - p); // read the length as a string - p = sep + 1; - std::string length_str(p); // read the offset as a string - char *end = nullptr; - const uint64_t offset = strtoul(offset_str.c_str(), &end, 16); // convert offset_str to a offset - if (*end == '\0') - { - const uint64_t length = strtoul(length_str.c_str(), &end, 16); // convert length_str to a length - if (*end == '\0') - { - if (object == "features" && - rw == "read" && - annex == "target.xml") - { - std::ostringstream xml_out; - - if (offset == 0) - { - InitializeRegisters (true); - - UpdateTargetXML(); - if (g_target_xml.empty()) - return SendPacket("E83"); - - if (length > g_target_xml.size()) - { - xml_out << 'l'; // No more data - xml_out << binary_encode_string(g_target_xml); - } - else - { - xml_out << 'm'; // More data needs to be read with a subsequent call - xml_out << binary_encode_string(std::string(g_target_xml, offset, length)); - } - } - else - { - // Retrieving target XML in chunks - if (offset < g_target_xml.size()) - { - std::string chunk(g_target_xml, offset, length); - if (chunk.size() < length) - xml_out << 'l'; // No more data - else - xml_out << 'm'; // More data needs to be read with a subsequent call - xml_out << binary_encode_string(chunk.data()); - } - } - return SendPacket(xml_out.str()); - } - // Well formed, put not supported - return HandlePacket_UNIMPLEMENTED (command); - } - } + p = sep + 1; + sep = strchr(p, ','); + if (sep) { + std::string offset_str(p, sep - p); // read the length as a string + p = sep + 1; + std::string length_str(p); // read the offset as a string + char *end = nullptr; + const uint64_t offset = strtoul(offset_str.c_str(), &end, + 16); // convert offset_str to a offset + if (*end == '\0') { + const uint64_t length = strtoul( + length_str.c_str(), &end, 16); // convert length_str to a length + if (*end == '\0') { + if (object == "features" && rw == "read" && + annex == "target.xml") { + std::ostringstream xml_out; + + if (offset == 0) { + InitializeRegisters(true); + + UpdateTargetXML(); + if (g_target_xml.empty()) + return SendPacket("E83"); + + if (length > g_target_xml.size()) { + xml_out << 'l'; // No more data + xml_out << binary_encode_string(g_target_xml); + } else { + xml_out << 'm'; // More data needs to be read with a + // subsequent call + xml_out << binary_encode_string( + std::string(g_target_xml, offset, length)); + } + } else { + // Retrieving target XML in chunks + if (offset < g_target_xml.size()) { + std::string chunk(g_target_xml, offset, length); + if (chunk.size() < length) + xml_out << 'l'; // No more data + else + xml_out << 'm'; // More data needs to be read with a + // subsequent call + xml_out << binary_encode_string(chunk.data()); + } } + return SendPacket(xml_out.str()); + } + // Well formed, put not supported + return HandlePacket_UNIMPLEMENTED(command); } - else - { - SendPacket ("E85"); - } - } - else - { - SendPacket ("E86"); + } } + } else { + SendPacket("E85"); + } + } else { + SendPacket("E86"); } - return SendPacket ("E82"); + } + return SendPacket("E82"); } +rnb_err_t RNBRemote::HandlePacket_qGDBServerVersion(const char *p) { + std::ostringstream strm; -rnb_err_t -RNBRemote::HandlePacket_qGDBServerVersion (const char *p) -{ - std::ostringstream strm; - #if defined(DEBUGSERVER_PROGRAM_NAME) - strm << "name:" DEBUGSERVER_PROGRAM_NAME ";"; + strm << "name:" DEBUGSERVER_PROGRAM_NAME ";"; #else - strm << "name:debugserver;"; + strm << "name:debugserver;"; #endif - strm << "version:" << DEBUGSERVER_VERSION_NUM << ";"; + strm << "version:" << DEBUGSERVER_VERSION_NUM << ";"; - return SendPacket (strm.str()); + return SendPacket(strm.str()); } // A helper function that retrieves a single integer value from // a one-level-deep JSON dictionary of key-value pairs. e.g. // jThreadExtendedInfo:{"plo_pthread_tsd_base_address_offset":0,"plo_pthread_tsd_base_offset":224,"plo_pthread_tsd_entry_size":8,"thread":144305}] // -uint64_t -get_integer_value_for_key_name_from_json (const char *key, const char *json_string) -{ - uint64_t retval = INVALID_NUB_ADDRESS; - std::string key_with_quotes = "\""; - key_with_quotes += key; - key_with_quotes += "\""; - const char *c = strstr (json_string, key_with_quotes.c_str()); - if (c) - { - c += key_with_quotes.size(); - - while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) - c++; - - if (*c == ':') - { - c++; - - while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) - c++; - - errno = 0; - retval = strtoul (c, NULL, 10); - if (errno != 0) - { - retval = INVALID_NUB_ADDRESS; - } - } +uint64_t get_integer_value_for_key_name_from_json(const char *key, + const char *json_string) { + uint64_t retval = INVALID_NUB_ADDRESS; + std::string key_with_quotes = "\""; + key_with_quotes += key; + key_with_quotes += "\""; + const char *c = strstr(json_string, key_with_quotes.c_str()); + if (c) { + c += key_with_quotes.size(); + + while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) + c++; + + if (*c == ':') { + c++; + + while (*c != '\0' && + (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) + c++; + + errno = 0; + retval = strtoul(c, NULL, 10); + if (errno != 0) { + retval = INVALID_NUB_ADDRESS; + } } - return retval; - + } + return retval; } // A helper function that retrieves a boolean value from @@ -5291,39 +5132,36 @@ get_integer_value_for_key_name_from_json (const char *key, const char *json_stri // Returns true if it was able to find the key name, and sets the 'value' // argument to the value found. -bool -get_boolean_value_for_key_name_from_json (const char *key, const char *json_string, bool &value) -{ - std::string key_with_quotes = "\""; - key_with_quotes += key; - key_with_quotes += "\""; - const char *c = strstr (json_string, key_with_quotes.c_str()); - if (c) - { - c += key_with_quotes.size(); - - while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) - c++; - - if (*c == ':') - { - c++; - - while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) - c++; - - if (strncmp (c, "true", 4) == 0) - { - value = true; - return true; - } else if (strncmp (c, "false", 5) == 0) - { - value = false; - return true; - } - } +bool get_boolean_value_for_key_name_from_json(const char *key, + const char *json_string, + bool &value) { + std::string key_with_quotes = "\""; + key_with_quotes += key; + key_with_quotes += "\""; + const char *c = strstr(json_string, key_with_quotes.c_str()); + if (c) { + c += key_with_quotes.size(); + + while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) + c++; + + if (*c == ':') { + c++; + + while (*c != '\0' && + (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) + c++; + + if (strncmp(c, "true", 4) == 0) { + value = true; + return true; + } else if (strncmp(c, "false", 5) == 0) { + value = false; + return true; + } } - return false; + } + return false; } // A helper function that reads an array of uint64_t's from @@ -5333,577 +5171,582 @@ get_boolean_value_for_key_name_from_json (const char *key, const char *json_stri // Returns true if it was able to find the key name, false if it did not. // "ints" will have all integers found in the array appended to it. -bool -get_array_of_ints_value_for_key_name_from_json (const char *key, const char *json_string, std::vector<uint64_t> &ints) -{ - std::string key_with_quotes = "\""; - key_with_quotes += key; - key_with_quotes += "\""; - const char *c = strstr (json_string, key_with_quotes.c_str()); - if (c) - { - c += key_with_quotes.size(); +bool get_array_of_ints_value_for_key_name_from_json( + const char *key, const char *json_string, std::vector<uint64_t> &ints) { + std::string key_with_quotes = "\""; + key_with_quotes += key; + key_with_quotes += "\""; + const char *c = strstr(json_string, key_with_quotes.c_str()); + if (c) { + c += key_with_quotes.size(); + + while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) + c++; + + if (*c == ':') { + c++; + + while (*c != '\0' && + (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) + c++; + + if (*c == '[') { + c++; + while (*c != '\0' && + (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) + c++; + while (1) { + if (!isdigit(*c)) { + return true; + } - while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) - c++; + errno = 0; + char *endptr; + uint64_t value = strtoul(c, &endptr, 10); + if (errno == 0) { + ints.push_back(value); + } else { + break; + } + if (endptr == c || endptr == nullptr || *endptr == '\0') { + break; + } + c = endptr; - if (*c == ':') - { + while (*c != '\0' && + (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) c++; - - while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) - c++; - - if (*c == '[') - { - c++; - while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) - c++; - while (1) - { - if (!isdigit (*c)) - { - return true; - } - - errno = 0; - char *endptr; - uint64_t value = strtoul (c, &endptr, 10); - if (errno == 0) - { - ints.push_back (value); - } - else - { - break; - } - if (endptr == c || endptr == nullptr || *endptr == '\0') - { - break; - } - c = endptr; - - while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) - c++; - if (*c == ',') - c++; - while (*c != '\0' && (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) - c++; - if (*c == ']') - { - return true; - } - } - } + if (*c == ',') + c++; + while (*c != '\0' && + (*c == ' ' || *c == '\t' || *c == '\n' || *c == '\r')) + c++; + if (*c == ']') { + return true; + } } + } } - return false; + } + return false; } JSONGenerator::ObjectSP -RNBRemote::GetJSONThreadsInfo(bool threads_with_valid_stop_info_only) -{ - JSONGenerator::ArraySP threads_array_sp; - if (m_ctx.HasValidProcessID()) - { - threads_array_sp.reset(new JSONGenerator::Array()); - - nub_process_t pid = m_ctx.ProcessID(); +RNBRemote::GetJSONThreadsInfo(bool threads_with_valid_stop_info_only) { + JSONGenerator::ArraySP threads_array_sp; + if (m_ctx.HasValidProcessID()) { + threads_array_sp.reset(new JSONGenerator::Array()); - nub_size_t numthreads = DNBProcessGetNumThreads (pid); - for (nub_size_t i = 0; i < numthreads; ++i) - { - nub_thread_t tid = DNBProcessGetThreadAtIndex (pid, i); - - struct DNBThreadStopInfo tid_stop_info; - - const bool stop_info_valid = DNBThreadGetStopReason (pid, tid, &tid_stop_info); + nub_process_t pid = m_ctx.ProcessID(); - // If we are doing stop info only, then we only show threads that have a - // valid stop reason - if (threads_with_valid_stop_info_only) - { - if (!stop_info_valid || tid_stop_info.reason == eStopTypeInvalid) - continue; - } + nub_size_t numthreads = DNBProcessGetNumThreads(pid); + for (nub_size_t i = 0; i < numthreads; ++i) { + nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, i); - JSONGenerator::DictionarySP thread_dict_sp(new JSONGenerator::Dictionary()); - thread_dict_sp->AddIntegerItem("tid", tid); + struct DNBThreadStopInfo tid_stop_info; - std::string reason_value("none"); + const bool stop_info_valid = + DNBThreadGetStopReason(pid, tid, &tid_stop_info); - if (stop_info_valid) - { - switch (tid_stop_info.reason) - { - case eStopTypeInvalid: - break; - - case eStopTypeSignal: - if (tid_stop_info.details.signal.signo != 0) - { - thread_dict_sp->AddIntegerItem("signal", tid_stop_info.details.signal.signo); - reason_value = "signal"; - } - break; - - case eStopTypeException: - if (tid_stop_info.details.exception.type != 0) - { - reason_value = "exception"; - thread_dict_sp->AddIntegerItem("metype", tid_stop_info.details.exception.type); - JSONGenerator::ArraySP medata_array_sp(new JSONGenerator::Array()); - for (nub_size_t i=0; i<tid_stop_info.details.exception.data_count; ++i) - { - medata_array_sp->AddItem(JSONGenerator::IntegerSP(new JSONGenerator::Integer(tid_stop_info.details.exception.data[i]))); - } - thread_dict_sp->AddItem("medata", medata_array_sp); - } - break; - - case eStopTypeExec: - reason_value = "exec"; - break; - } - } + // If we are doing stop info only, then we only show threads that have a + // valid stop reason + if (threads_with_valid_stop_info_only) { + if (!stop_info_valid || tid_stop_info.reason == eStopTypeInvalid) + continue; + } - thread_dict_sp->AddStringItem("reason", reason_value); + JSONGenerator::DictionarySP thread_dict_sp( + new JSONGenerator::Dictionary()); + thread_dict_sp->AddIntegerItem("tid", tid); - if (threads_with_valid_stop_info_only == false) - { - const char *thread_name = DNBThreadGetName (pid, tid); - if (thread_name && thread_name[0]) - thread_dict_sp->AddStringItem("name", thread_name); + std::string reason_value("none"); - thread_identifier_info_data_t thread_ident_info; - if (DNBThreadGetIdentifierInfo (pid, tid, &thread_ident_info)) - { - if (thread_ident_info.dispatch_qaddr != 0) - { - thread_dict_sp->AddIntegerItem("qaddr", thread_ident_info.dispatch_qaddr); - - const DispatchQueueOffsets *dispatch_queue_offsets = GetDispatchQueueOffsets(); - if (dispatch_queue_offsets) - { - std::string queue_name; - uint64_t queue_width = 0; - uint64_t queue_serialnum = 0; - nub_addr_t dispatch_queue_t = INVALID_NUB_ADDRESS; - dispatch_queue_offsets->GetThreadQueueInfo(pid, thread_ident_info.dispatch_qaddr, dispatch_queue_t, queue_name, queue_width, queue_serialnum); - if (dispatch_queue_t == 0 && queue_name.empty() && queue_serialnum == 0) - { - thread_dict_sp->AddBooleanItem ("associated_with_dispatch_queue", false); - } - else - { - thread_dict_sp->AddBooleanItem ("associated_with_dispatch_queue", true); - } - if (dispatch_queue_t != INVALID_NUB_ADDRESS && dispatch_queue_t != 0) - thread_dict_sp->AddIntegerItem("dispatch_queue_t", dispatch_queue_t); - if (!queue_name.empty()) - thread_dict_sp->AddStringItem("qname", queue_name); - if (queue_width == 1) - thread_dict_sp->AddStringItem("qkind", "serial"); - else if (queue_width > 1) - thread_dict_sp->AddStringItem("qkind", "concurrent"); - if (queue_serialnum > 0) - thread_dict_sp->AddIntegerItem("qserialnum", queue_serialnum); - } - } - } - - DNBRegisterValue reg_value; + if (stop_info_valid) { + switch (tid_stop_info.reason) { + case eStopTypeInvalid: + break; - if (g_reg_entries != NULL) - { - JSONGenerator::DictionarySP registers_dict_sp(new JSONGenerator::Dictionary()); - - for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) - { - // Expedite all registers in the first register set that aren't - // contained in other registers - if (g_reg_entries[reg].nub_info.set == 1 && - g_reg_entries[reg].nub_info.value_regs == NULL) - { - if (!DNBThreadGetRegisterValueByID (pid, tid, g_reg_entries[reg].nub_info.set, g_reg_entries[reg].nub_info.reg, ®_value)) - continue; - - std::ostringstream reg_num; - reg_num << std::dec << g_reg_entries[reg].debugserver_regnum; - // Encode native byte ordered bytes as hex ascii - registers_dict_sp->AddBytesAsHexASCIIString(reg_num.str(), reg_value.value.v_uint8, g_reg_entries[reg].nub_info.size); - } - } - thread_dict_sp->AddItem("registers", registers_dict_sp); - } + case eStopTypeSignal: + if (tid_stop_info.details.signal.signo != 0) { + thread_dict_sp->AddIntegerItem("signal", + tid_stop_info.details.signal.signo); + reason_value = "signal"; + } + break; - // Add expedited stack memory so stack backtracing doesn't need to read anything from the - // frame pointer chain. - StackMemoryMap stack_mmap; - ReadStackMemory (pid, tid, stack_mmap); - if (!stack_mmap.empty()) - { - JSONGenerator::ArraySP memory_array_sp(new JSONGenerator::Array()); - - for (const auto &stack_memory : stack_mmap) - { - JSONGenerator::DictionarySP stack_memory_sp(new JSONGenerator::Dictionary()); - stack_memory_sp->AddIntegerItem("address", stack_memory.first); - stack_memory_sp->AddBytesAsHexASCIIString("bytes", stack_memory.second.bytes, stack_memory.second.length); - memory_array_sp->AddItem(stack_memory_sp); - } - thread_dict_sp->AddItem("memory", memory_array_sp); - } + case eStopTypeException: + if (tid_stop_info.details.exception.type != 0) { + reason_value = "exception"; + thread_dict_sp->AddIntegerItem( + "metype", tid_stop_info.details.exception.type); + JSONGenerator::ArraySP medata_array_sp(new JSONGenerator::Array()); + for (nub_size_t i = 0; + i < tid_stop_info.details.exception.data_count; ++i) { + medata_array_sp->AddItem( + JSONGenerator::IntegerSP(new JSONGenerator::Integer( + tid_stop_info.details.exception.data[i]))); } + thread_dict_sp->AddItem("medata", medata_array_sp); + } + break; - threads_array_sp->AddItem(thread_dict_sp); + case eStopTypeExec: + reason_value = "exec"; + break; } - } - return threads_array_sp; -} + } -rnb_err_t -RNBRemote::HandlePacket_jThreadsInfo (const char *p) -{ - JSONGenerator::ObjectSP threads_info_sp; - std::ostringstream json; - std::ostringstream reply_strm; - // If we haven't run the process yet, return an error. - if (m_ctx.HasValidProcessID()) - { - const bool threads_with_valid_stop_info_only = false; - JSONGenerator::ObjectSP threads_info_sp = GetJSONThreadsInfo(threads_with_valid_stop_info_only); + thread_dict_sp->AddStringItem("reason", reason_value); - if (threads_info_sp) - { - std::ostringstream strm; - threads_info_sp->Dump (strm); - std::string binary_packet = binary_encode_string (strm.str()); - if (!binary_packet.empty()) - return SendPacket (binary_packet.c_str()); + if (threads_with_valid_stop_info_only == false) { + const char *thread_name = DNBThreadGetName(pid, tid); + if (thread_name && thread_name[0]) + thread_dict_sp->AddStringItem("name", thread_name); + + thread_identifier_info_data_t thread_ident_info; + if (DNBThreadGetIdentifierInfo(pid, tid, &thread_ident_info)) { + if (thread_ident_info.dispatch_qaddr != 0) { + thread_dict_sp->AddIntegerItem("qaddr", + thread_ident_info.dispatch_qaddr); + + const DispatchQueueOffsets *dispatch_queue_offsets = + GetDispatchQueueOffsets(); + if (dispatch_queue_offsets) { + std::string queue_name; + uint64_t queue_width = 0; + uint64_t queue_serialnum = 0; + nub_addr_t dispatch_queue_t = INVALID_NUB_ADDRESS; + dispatch_queue_offsets->GetThreadQueueInfo( + pid, thread_ident_info.dispatch_qaddr, dispatch_queue_t, + queue_name, queue_width, queue_serialnum); + if (dispatch_queue_t == 0 && queue_name.empty() && + queue_serialnum == 0) { + thread_dict_sp->AddBooleanItem("associated_with_dispatch_queue", + false); + } else { + thread_dict_sp->AddBooleanItem("associated_with_dispatch_queue", + true); + } + if (dispatch_queue_t != INVALID_NUB_ADDRESS && + dispatch_queue_t != 0) + thread_dict_sp->AddIntegerItem("dispatch_queue_t", + dispatch_queue_t); + if (!queue_name.empty()) + thread_dict_sp->AddStringItem("qname", queue_name); + if (queue_width == 1) + thread_dict_sp->AddStringItem("qkind", "serial"); + else if (queue_width > 1) + thread_dict_sp->AddStringItem("qkind", "concurrent"); + if (queue_serialnum > 0) + thread_dict_sp->AddIntegerItem("qserialnum", queue_serialnum); + } + } } - } - return SendPacket ("E85"); -} - -rnb_err_t -RNBRemote::HandlePacket_jThreadExtendedInfo (const char *p) -{ - nub_process_t pid; - std::ostringstream json; - // If we haven't run the process yet, return an error. - if (!m_ctx.HasValidProcessID()) - { - return SendPacket ("E81"); - } - - pid = m_ctx.ProcessID(); + DNBRegisterValue reg_value; - const char thread_extended_info_str[] = { "jThreadExtendedInfo:{" }; - if (strncmp (p, thread_extended_info_str, sizeof (thread_extended_info_str) - 1) == 0) - { - p += strlen (thread_extended_info_str); - - uint64_t tid = get_integer_value_for_key_name_from_json ("thread", p); - uint64_t plo_pthread_tsd_base_address_offset = get_integer_value_for_key_name_from_json ("plo_pthread_tsd_base_address_offset", p); - uint64_t plo_pthread_tsd_base_offset = get_integer_value_for_key_name_from_json ("plo_pthread_tsd_base_offset", p); - uint64_t plo_pthread_tsd_entry_size = get_integer_value_for_key_name_from_json ("plo_pthread_tsd_entry_size", p); - uint64_t dti_qos_class_index = get_integer_value_for_key_name_from_json ("dti_qos_class_index", p); - // Commented out the two variables below as they are not being used -// uint64_t dti_queue_index = get_integer_value_for_key_name_from_json ("dti_queue_index", p); -// uint64_t dti_voucher_index = get_integer_value_for_key_name_from_json ("dti_voucher_index", p); - - if (tid != INVALID_NUB_ADDRESS) - { - nub_addr_t pthread_t_value = DNBGetPThreadT (pid, tid); + if (g_reg_entries != NULL) { + JSONGenerator::DictionarySP registers_dict_sp( + new JSONGenerator::Dictionary()); + + for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) { + // Expedite all registers in the first register set that aren't + // contained in other registers + if (g_reg_entries[reg].nub_info.set == 1 && + g_reg_entries[reg].nub_info.value_regs == NULL) { + if (!DNBThreadGetRegisterValueByID( + pid, tid, g_reg_entries[reg].nub_info.set, + g_reg_entries[reg].nub_info.reg, ®_value)) + continue; - uint64_t tsd_address = INVALID_NUB_ADDRESS; - if (plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS - && plo_pthread_tsd_base_offset != INVALID_NUB_ADDRESS - && plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS) - { - tsd_address = DNBGetTSDAddressForThread (pid, tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size); + std::ostringstream reg_num; + reg_num << std::dec << g_reg_entries[reg].debugserver_regnum; + // Encode native byte ordered bytes as hex ascii + registers_dict_sp->AddBytesAsHexASCIIString( + reg_num.str(), reg_value.value.v_uint8, + g_reg_entries[reg].nub_info.size); } + } + thread_dict_sp->AddItem("registers", registers_dict_sp); + } - bool timed_out = false; - Genealogy::ThreadActivitySP thread_activity_sp; - - // If the pthread_t value is invalid, or if we were able to fetch the thread's TSD base - // and got an invalid value back, then we have a thread in early startup or shutdown and - // it's possible that gathering the genealogy information for this thread go badly. - // Ideally fetching this info for a thread in these odd states shouldn't matter - but - // we've seen some problems with these new SPI and threads in edge-casey states. + // Add expedited stack memory so stack backtracing doesn't need to read + // anything from the + // frame pointer chain. + StackMemoryMap stack_mmap; + ReadStackMemory(pid, tid, stack_mmap); + if (!stack_mmap.empty()) { + JSONGenerator::ArraySP memory_array_sp(new JSONGenerator::Array()); + + for (const auto &stack_memory : stack_mmap) { + JSONGenerator::DictionarySP stack_memory_sp( + new JSONGenerator::Dictionary()); + stack_memory_sp->AddIntegerItem("address", stack_memory.first); + stack_memory_sp->AddBytesAsHexASCIIString( + "bytes", stack_memory.second.bytes, stack_memory.second.length); + memory_array_sp->AddItem(stack_memory_sp); + } + thread_dict_sp->AddItem("memory", memory_array_sp); + } + } - double genealogy_fetch_time = 0; - if (pthread_t_value != INVALID_NUB_ADDRESS && tsd_address != INVALID_NUB_ADDRESS) - { - DNBTimer timer(false); - thread_activity_sp = DNBGetGenealogyInfoForThread (pid, tid, timed_out); - genealogy_fetch_time = timer.ElapsedMicroSeconds(false) / 1000000.0; - } + threads_array_sp->AddItem(thread_dict_sp); + } + } + return threads_array_sp; +} + +rnb_err_t RNBRemote::HandlePacket_jThreadsInfo(const char *p) { + JSONGenerator::ObjectSP threads_info_sp; + std::ostringstream json; + std::ostringstream reply_strm; + // If we haven't run the process yet, return an error. + if (m_ctx.HasValidProcessID()) { + const bool threads_with_valid_stop_info_only = false; + JSONGenerator::ObjectSP threads_info_sp = + GetJSONThreadsInfo(threads_with_valid_stop_info_only); + + if (threads_info_sp) { + std::ostringstream strm; + threads_info_sp->Dump(strm); + std::string binary_packet = binary_encode_string(strm.str()); + if (!binary_packet.empty()) + return SendPacket(binary_packet.c_str()); + } + } + return SendPacket("E85"); +} + +rnb_err_t RNBRemote::HandlePacket_jThreadExtendedInfo(const char *p) { + nub_process_t pid; + std::ostringstream json; + // If we haven't run the process yet, return an error. + if (!m_ctx.HasValidProcessID()) { + return SendPacket("E81"); + } + + pid = m_ctx.ProcessID(); + + const char thread_extended_info_str[] = {"jThreadExtendedInfo:{"}; + if (strncmp(p, thread_extended_info_str, + sizeof(thread_extended_info_str) - 1) == 0) { + p += strlen(thread_extended_info_str); + + uint64_t tid = get_integer_value_for_key_name_from_json("thread", p); + uint64_t plo_pthread_tsd_base_address_offset = + get_integer_value_for_key_name_from_json( + "plo_pthread_tsd_base_address_offset", p); + uint64_t plo_pthread_tsd_base_offset = + get_integer_value_for_key_name_from_json("plo_pthread_tsd_base_offset", + p); + uint64_t plo_pthread_tsd_entry_size = + get_integer_value_for_key_name_from_json("plo_pthread_tsd_entry_size", + p); + uint64_t dti_qos_class_index = + get_integer_value_for_key_name_from_json("dti_qos_class_index", p); + // Commented out the two variables below as they are not being used + // uint64_t dti_queue_index = + // get_integer_value_for_key_name_from_json ("dti_queue_index", p); + // uint64_t dti_voucher_index = + // get_integer_value_for_key_name_from_json ("dti_voucher_index", p); + + if (tid != INVALID_NUB_ADDRESS) { + nub_addr_t pthread_t_value = DNBGetPThreadT(pid, tid); + + uint64_t tsd_address = INVALID_NUB_ADDRESS; + if (plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS && + plo_pthread_tsd_base_offset != INVALID_NUB_ADDRESS && + plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS) { + tsd_address = DNBGetTSDAddressForThread( + pid, tid, plo_pthread_tsd_base_address_offset, + plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size); + } - std::unordered_set<uint32_t> process_info_indexes; // an array of the process info #'s seen + bool timed_out = false; + Genealogy::ThreadActivitySP thread_activity_sp; + + // If the pthread_t value is invalid, or if we were able to fetch the + // thread's TSD base + // and got an invalid value back, then we have a thread in early startup + // or shutdown and + // it's possible that gathering the genealogy information for this thread + // go badly. + // Ideally fetching this info for a thread in these odd states shouldn't + // matter - but + // we've seen some problems with these new SPI and threads in edge-casey + // states. + + double genealogy_fetch_time = 0; + if (pthread_t_value != INVALID_NUB_ADDRESS && + tsd_address != INVALID_NUB_ADDRESS) { + DNBTimer timer(false); + thread_activity_sp = DNBGetGenealogyInfoForThread(pid, tid, timed_out); + genealogy_fetch_time = timer.ElapsedMicroSeconds(false) / 1000000.0; + } + std::unordered_set<uint32_t> + process_info_indexes; // an array of the process info #'s seen + + json << "{"; + + bool need_to_print_comma = false; + + if (thread_activity_sp && timed_out == false) { + const Genealogy::Activity *activity = + &thread_activity_sp->current_activity; + bool need_vouchers_comma_sep = false; + json << "\"activity_query_timed_out\":false,"; + if (genealogy_fetch_time != 0) { + // If we append the floating point value with << we'll get it in + // scientific + // notation. + char floating_point_ascii_buffer[64]; + floating_point_ascii_buffer[0] = '\0'; + snprintf(floating_point_ascii_buffer, + sizeof(floating_point_ascii_buffer), "%f", + genealogy_fetch_time); + if (strlen(floating_point_ascii_buffer) > 0) { + if (need_to_print_comma) + json << ","; + need_to_print_comma = true; + json << "\"activity_query_duration\":" + << floating_point_ascii_buffer; + } + } + if (activity->activity_id != 0) { + if (need_to_print_comma) + json << ","; + need_to_print_comma = true; + need_vouchers_comma_sep = true; + json << "\"activity\":{"; + json << "\"start\":" << activity->activity_start << ","; + json << "\"id\":" << activity->activity_id << ","; + json << "\"parent_id\":" << activity->parent_id << ","; + json << "\"name\":\"" + << json_string_quote_metachars(activity->activity_name) << "\","; + json << "\"reason\":\"" + << json_string_quote_metachars(activity->reason) << "\""; + json << "}"; + } + if (thread_activity_sp->messages.size() > 0) { + need_to_print_comma = true; + if (need_vouchers_comma_sep) + json << ","; + need_vouchers_comma_sep = true; + json << "\"trace_messages\":["; + bool printed_one_message = false; + for (auto iter = thread_activity_sp->messages.begin(); + iter != thread_activity_sp->messages.end(); ++iter) { + if (printed_one_message) + json << ","; + else + printed_one_message = true; json << "{"; - - bool need_to_print_comma = false; - - if (thread_activity_sp && timed_out == false) - { - const Genealogy::Activity *activity = &thread_activity_sp->current_activity; - bool need_vouchers_comma_sep = false; - json << "\"activity_query_timed_out\":false,"; - if (genealogy_fetch_time != 0) - { - // If we append the floating point value with << we'll get it in scientific - // notation. - char floating_point_ascii_buffer[64]; - floating_point_ascii_buffer[0] = '\0'; - snprintf (floating_point_ascii_buffer, sizeof (floating_point_ascii_buffer), "%f", genealogy_fetch_time); - if (strlen (floating_point_ascii_buffer) > 0) - { - if (need_to_print_comma) - json << ","; - need_to_print_comma = true; - json << "\"activity_query_duration\":" << floating_point_ascii_buffer; - } - } - if (activity->activity_id != 0) - { - if (need_to_print_comma) - json << ","; - need_to_print_comma = true; - need_vouchers_comma_sep = true; - json << "\"activity\":{"; - json << "\"start\":" << activity->activity_start << ","; - json << "\"id\":" << activity->activity_id << ","; - json << "\"parent_id\":" << activity->parent_id << ","; - json << "\"name\":\"" << json_string_quote_metachars (activity->activity_name) << "\","; - json << "\"reason\":\"" << json_string_quote_metachars (activity->reason) << "\""; - json << "}"; - } - if (thread_activity_sp->messages.size() > 0) - { - need_to_print_comma = true; - if (need_vouchers_comma_sep) - json << ","; - need_vouchers_comma_sep = true; - json << "\"trace_messages\":["; - bool printed_one_message = false; - for (auto iter = thread_activity_sp->messages.begin() ; iter != thread_activity_sp->messages.end(); ++iter) - { - if (printed_one_message) - json << ","; - else - printed_one_message = true; - json << "{"; - json << "\"timestamp\":" << iter->timestamp << ","; - json << "\"activity_id\":" << iter->activity_id << ","; - json << "\"trace_id\":" << iter->trace_id << ","; - json << "\"thread\":" << iter->thread << ","; - json << "\"type\":" << (int) iter->type << ","; - json << "\"process_info_index\":" << iter->process_info_index << ","; - process_info_indexes.insert (iter->process_info_index); - json << "\"message\":\"" << json_string_quote_metachars (iter->message) << "\""; - json << "}"; - } - json << "]"; - } - if (thread_activity_sp->breadcrumbs.size() == 1) - { - need_to_print_comma = true; - if (need_vouchers_comma_sep) - json << ","; - need_vouchers_comma_sep = true; - json << "\"breadcrumb\":{"; - for (auto iter = thread_activity_sp->breadcrumbs.begin() ; iter != thread_activity_sp->breadcrumbs.end(); ++iter) - { - json << "\"breadcrumb_id\":" << iter->breadcrumb_id << ","; - json << "\"activity_id\":" << iter->activity_id << ","; - json << "\"timestamp\":" << iter->timestamp << ","; - json << "\"name\":\"" << json_string_quote_metachars (iter->name) << "\""; - } - json << "}"; - } - if (process_info_indexes.size() > 0) - { - need_to_print_comma = true; - if (need_vouchers_comma_sep) - json << ","; - need_vouchers_comma_sep = true; - bool printed_one_process_info = false; - for (auto iter = process_info_indexes.begin(); iter != process_info_indexes.end(); ++iter) - { - if (printed_one_process_info) - json << ","; - Genealogy::ProcessExecutableInfoSP image_info_sp; - uint32_t idx = *iter; - image_info_sp = DNBGetGenealogyImageInfo (pid, idx); - if (image_info_sp) - { - if (!printed_one_process_info) - { - json << "\"process_infos\":["; - printed_one_process_info = true; - } - - json << "{"; - char uuid_buf[37]; - uuid_unparse_upper (image_info_sp->image_uuid, uuid_buf); - json << "\"process_info_index\":" << idx << ","; - json << "\"image_path\":\"" << json_string_quote_metachars (image_info_sp->image_path) << "\","; - json << "\"image_uuid\":\"" << uuid_buf <<"\""; - json << "}"; - } - } - if (printed_one_process_info) - json << "]"; - } + json << "\"timestamp\":" << iter->timestamp << ","; + json << "\"activity_id\":" << iter->activity_id << ","; + json << "\"trace_id\":" << iter->trace_id << ","; + json << "\"thread\":" << iter->thread << ","; + json << "\"type\":" << (int)iter->type << ","; + json << "\"process_info_index\":" << iter->process_info_index + << ","; + process_info_indexes.insert(iter->process_info_index); + json << "\"message\":\"" + << json_string_quote_metachars(iter->message) << "\""; + json << "}"; + } + json << "]"; + } + if (thread_activity_sp->breadcrumbs.size() == 1) { + need_to_print_comma = true; + if (need_vouchers_comma_sep) + json << ","; + need_vouchers_comma_sep = true; + json << "\"breadcrumb\":{"; + for (auto iter = thread_activity_sp->breadcrumbs.begin(); + iter != thread_activity_sp->breadcrumbs.end(); ++iter) { + json << "\"breadcrumb_id\":" << iter->breadcrumb_id << ","; + json << "\"activity_id\":" << iter->activity_id << ","; + json << "\"timestamp\":" << iter->timestamp << ","; + json << "\"name\":\"" << json_string_quote_metachars(iter->name) + << "\""; + } + json << "}"; + } + if (process_info_indexes.size() > 0) { + need_to_print_comma = true; + if (need_vouchers_comma_sep) + json << ","; + need_vouchers_comma_sep = true; + bool printed_one_process_info = false; + for (auto iter = process_info_indexes.begin(); + iter != process_info_indexes.end(); ++iter) { + if (printed_one_process_info) + json << ","; + Genealogy::ProcessExecutableInfoSP image_info_sp; + uint32_t idx = *iter; + image_info_sp = DNBGetGenealogyImageInfo(pid, idx); + if (image_info_sp) { + if (!printed_one_process_info) { + json << "\"process_infos\":["; + printed_one_process_info = true; + } + + json << "{"; + char uuid_buf[37]; + uuid_unparse_upper(image_info_sp->image_uuid, uuid_buf); + json << "\"process_info_index\":" << idx << ","; + json << "\"image_path\":\"" + << json_string_quote_metachars(image_info_sp->image_path) + << "\","; + json << "\"image_uuid\":\"" << uuid_buf << "\""; + json << "}"; } - else - { - if (timed_out) - { - if (need_to_print_comma) - json << ","; - need_to_print_comma = true; - json << "\"activity_query_timed_out\":true"; - if (genealogy_fetch_time != 0) - { - // If we append the floating point value with << we'll get it in scientific - // notation. - char floating_point_ascii_buffer[64]; - floating_point_ascii_buffer[0] = '\0'; - snprintf (floating_point_ascii_buffer, sizeof (floating_point_ascii_buffer), "%f", genealogy_fetch_time); - if (strlen (floating_point_ascii_buffer) > 0) - { - json << ","; - json << "\"activity_query_duration\":" << floating_point_ascii_buffer; - } - } - } + } + if (printed_one_process_info) + json << "]"; + } + } else { + if (timed_out) { + if (need_to_print_comma) + json << ","; + need_to_print_comma = true; + json << "\"activity_query_timed_out\":true"; + if (genealogy_fetch_time != 0) { + // If we append the floating point value with << we'll get it in + // scientific + // notation. + char floating_point_ascii_buffer[64]; + floating_point_ascii_buffer[0] = '\0'; + snprintf(floating_point_ascii_buffer, + sizeof(floating_point_ascii_buffer), "%f", + genealogy_fetch_time); + if (strlen(floating_point_ascii_buffer) > 0) { + json << ","; + json << "\"activity_query_duration\":" + << floating_point_ascii_buffer; } + } + } + } - if (tsd_address != INVALID_NUB_ADDRESS) - { - if (need_to_print_comma) - json << ","; - need_to_print_comma = true; - json << "\"tsd_address\":" << tsd_address; - - if (dti_qos_class_index != 0 && dti_qos_class_index != UINT64_MAX) - { - ThreadInfo::QoS requested_qos = DNBGetRequestedQoSForThread (pid, tid, tsd_address, dti_qos_class_index); - if (requested_qos.IsValid()) - { - if (need_to_print_comma) - json << ","; - need_to_print_comma = true; - json << "\"requested_qos\":{"; - json << "\"enum_value\":" << requested_qos.enum_value << ","; - json << "\"constant_name\":\"" << json_string_quote_metachars (requested_qos.constant_name) << "\","; - json << "\"printable_name\":\"" << json_string_quote_metachars (requested_qos.printable_name) << "\""; - json << "}"; - } - } - } + if (tsd_address != INVALID_NUB_ADDRESS) { + if (need_to_print_comma) + json << ","; + need_to_print_comma = true; + json << "\"tsd_address\":" << tsd_address; + + if (dti_qos_class_index != 0 && dti_qos_class_index != UINT64_MAX) { + ThreadInfo::QoS requested_qos = DNBGetRequestedQoSForThread( + pid, tid, tsd_address, dti_qos_class_index); + if (requested_qos.IsValid()) { + if (need_to_print_comma) + json << ","; + need_to_print_comma = true; + json << "\"requested_qos\":{"; + json << "\"enum_value\":" << requested_qos.enum_value << ","; + json << "\"constant_name\":\"" + << json_string_quote_metachars(requested_qos.constant_name) + << "\","; + json << "\"printable_name\":\"" + << json_string_quote_metachars(requested_qos.printable_name) + << "\""; + json << "}"; + } + } + } - if (pthread_t_value != INVALID_NUB_ADDRESS) - { - if (need_to_print_comma) - json << ","; - need_to_print_comma = true; - json << "\"pthread_t\":" << pthread_t_value; - } + if (pthread_t_value != INVALID_NUB_ADDRESS) { + if (need_to_print_comma) + json << ","; + need_to_print_comma = true; + json << "\"pthread_t\":" << pthread_t_value; + } - nub_addr_t dispatch_queue_t_value = DNBGetDispatchQueueT (pid, tid); - if (dispatch_queue_t_value != INVALID_NUB_ADDRESS) - { - if (need_to_print_comma) - json << ","; - need_to_print_comma = true; - json << "\"dispatch_queue_t\":" << dispatch_queue_t_value; - } + nub_addr_t dispatch_queue_t_value = DNBGetDispatchQueueT(pid, tid); + if (dispatch_queue_t_value != INVALID_NUB_ADDRESS) { + if (need_to_print_comma) + json << ","; + need_to_print_comma = true; + json << "\"dispatch_queue_t\":" << dispatch_queue_t_value; + } - json << "}"; - std::string json_quoted = binary_encode_string (json.str()); - return SendPacket (json_quoted); - } + json << "}"; + std::string json_quoted = binary_encode_string(json.str()); + return SendPacket(json_quoted); } - return SendPacket ("OK"); + } + return SendPacket("OK"); } // This packet may be called in one of three ways: // // jGetLoadedDynamicLibrariesInfos:{"image_count":40,"image_list_address":4295244704} -// Look for an array of the old dyld_all_image_infos style of binary infos at the image_list_address. -// This an array of {void* load_addr, void* mod_date, void* pathname} +// Look for an array of the old dyld_all_image_infos style of binary infos +// at the image_list_address. +// This an array of {void* load_addr, void* mod_date, void* pathname} // // jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true} -// Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to get a list of all the +// Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to +// get a list of all the // libraries loaded // // jGetLoadedDynamicLibrariesInfos:{"solib_addresses":[8382824135,3258302053,830202858503]} -// Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to get the information +// Use the new style (macOS 10.12, tvOS 10, iOS 10, watchOS 3) dyld SPI to +// get the information // about the libraries loaded at these addresses. // rnb_err_t -RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos (const char *p) -{ - nub_process_t pid; - // If we haven't run the process yet, return an error. - if (!m_ctx.HasValidProcessID()) - { - return SendPacket ("E83"); +RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos(const char *p) { + nub_process_t pid; + // If we haven't run the process yet, return an error. + if (!m_ctx.HasValidProcessID()) { + return SendPacket("E83"); + } + + pid = m_ctx.ProcessID(); + + const char get_loaded_dynamic_libraries_infos_str[] = { + "jGetLoadedDynamicLibrariesInfos:{"}; + if (strncmp(p, get_loaded_dynamic_libraries_infos_str, + sizeof(get_loaded_dynamic_libraries_infos_str) - 1) == 0) { + p += strlen(get_loaded_dynamic_libraries_infos_str); + + JSONGenerator::ObjectSP json_sp; + + std::vector<uint64_t> macho_addresses; + bool fetch_all_solibs = false; + if (get_boolean_value_for_key_name_from_json("fetch_all_solibs", p, + fetch_all_solibs) && + fetch_all_solibs) { + json_sp = DNBGetAllLoadedLibrariesInfos(pid); + } else if (get_array_of_ints_value_for_key_name_from_json( + "solib_addresses", p, macho_addresses)) { + json_sp = DNBGetLibrariesInfoForAddresses(pid, macho_addresses); + } else { + nub_addr_t image_list_address = + get_integer_value_for_key_name_from_json("image_list_address", p); + nub_addr_t image_count = + get_integer_value_for_key_name_from_json("image_count", p); + + if (image_list_address != INVALID_NUB_ADDRESS && + image_count != INVALID_NUB_ADDRESS) { + json_sp = DNBGetLoadedDynamicLibrariesInfos(pid, image_list_address, + image_count); + } } - pid = m_ctx.ProcessID(); - - const char get_loaded_dynamic_libraries_infos_str[] = { "jGetLoadedDynamicLibrariesInfos:{" }; - if (strncmp (p, get_loaded_dynamic_libraries_infos_str, sizeof (get_loaded_dynamic_libraries_infos_str) - 1) == 0) - { - p += strlen (get_loaded_dynamic_libraries_infos_str); - - JSONGenerator::ObjectSP json_sp; - - std::vector<uint64_t> macho_addresses; - bool fetch_all_solibs = false; - if (get_boolean_value_for_key_name_from_json ("fetch_all_solibs", p, fetch_all_solibs) && fetch_all_solibs) - { - json_sp = DNBGetAllLoadedLibrariesInfos (pid); - } - else if (get_array_of_ints_value_for_key_name_from_json ("solib_addresses", p, macho_addresses)) - { - json_sp = DNBGetLibrariesInfoForAddresses (pid, macho_addresses); - } - else - { - nub_addr_t image_list_address = get_integer_value_for_key_name_from_json ("image_list_address", p); - nub_addr_t image_count = get_integer_value_for_key_name_from_json ("image_count", p); - - if (image_list_address != INVALID_NUB_ADDRESS && image_count != INVALID_NUB_ADDRESS) - { - json_sp = DNBGetLoadedDynamicLibrariesInfos (pid, image_list_address, image_count); - } - } - - if (json_sp.get()) - { - std::ostringstream json_str; - json_sp->Dump (json_str); - if (json_str.str().size() > 0) - { - std::string json_str_quoted = binary_encode_string (json_str.str()); - return SendPacket (json_str_quoted.c_str()); - } - else - { - SendPacket ("E84"); - } - } + if (json_sp.get()) { + std::ostringstream json_str; + json_sp->Dump(json_str); + if (json_str.str().size() > 0) { + std::string json_str_quoted = binary_encode_string(json_str.str()); + return SendPacket(json_str_quoted.c_str()); + } else { + SendPacket("E84"); + } } - return SendPacket ("OK"); + } + return SendPacket("OK"); } // This packet does not currently take any arguments. So the behavior is @@ -5911,556 +5754,539 @@ RNBRemote::HandlePacket_jGetLoadedDynamicLibrariesInfos (const char *p) // send information about the inferior's shared cache // jGetSharedCacheInfo: // send "OK" to indicate that this packet is supported -rnb_err_t -RNBRemote::HandlePacket_jGetSharedCacheInfo (const char *p) -{ - nub_process_t pid; - // If we haven't run the process yet, return an error. - if (!m_ctx.HasValidProcessID()) - { - return SendPacket ("E85"); - } - - pid = m_ctx.ProcessID(); - - const char get_shared_cache_info_str[] = { "jGetSharedCacheInfo:{" }; - if (strncmp (p, get_shared_cache_info_str, sizeof (get_shared_cache_info_str) - 1) == 0) - { - JSONGenerator::ObjectSP json_sp = DNBGetSharedCacheInfo (pid); - - if (json_sp.get()) - { - std::ostringstream json_str; - json_sp->Dump (json_str); - if (json_str.str().size() > 0) - { - std::string json_str_quoted = binary_encode_string (json_str.str()); - return SendPacket (json_str_quoted.c_str()); - } - else - { - SendPacket ("E86"); - } - } +rnb_err_t RNBRemote::HandlePacket_jGetSharedCacheInfo(const char *p) { + nub_process_t pid; + // If we haven't run the process yet, return an error. + if (!m_ctx.HasValidProcessID()) { + return SendPacket("E85"); + } + + pid = m_ctx.ProcessID(); + + const char get_shared_cache_info_str[] = {"jGetSharedCacheInfo:{"}; + if (strncmp(p, get_shared_cache_info_str, + sizeof(get_shared_cache_info_str) - 1) == 0) { + JSONGenerator::ObjectSP json_sp = DNBGetSharedCacheInfo(pid); + + if (json_sp.get()) { + std::ostringstream json_str; + json_sp->Dump(json_str); + if (json_str.str().size() > 0) { + std::string json_str_quoted = binary_encode_string(json_str.str()); + return SendPacket(json_str_quoted.c_str()); + } else { + SendPacket("E86"); + } } - return SendPacket ("OK"); -} - -static bool -MachHeaderIsMainExecutable (nub_process_t pid, uint32_t addr_size, nub_addr_t mach_header_addr, mach_header &mh) -{ - DNBLogThreadedIf (LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, addr_size = %u, mach_header_addr = 0x%16.16llx)", pid, addr_size, mach_header_addr); - const nub_size_t bytes_read = DNBProcessMemoryRead(pid, mach_header_addr, sizeof(mh), &mh); - if (bytes_read == sizeof(mh)) - { - DNBLogThreadedIf (LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, addr_size = %u, mach_header_addr = 0x%16.16llx): mh = {\n magic = 0x%8.8x\n cpu = 0x%8.8x\n sub = 0x%8.8x\n filetype = %u\n ncmds = %u\n sizeofcmds = 0x%8.8x\n flags = 0x%8.8x }", pid, addr_size, mach_header_addr, mh.magic, mh.cputype, mh.cpusubtype, mh.filetype, mh.ncmds, mh.sizeofcmds, mh.flags); - if ((addr_size == 4 && mh.magic == MH_MAGIC) || - (addr_size == 8 && mh.magic == MH_MAGIC_64)) - { - if (mh.filetype == MH_EXECUTE) - { - DNBLogThreadedIf (LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, addr_size = %u, mach_header_addr = 0x%16.16llx) -> this is the executable!!!", pid, addr_size, mach_header_addr); - return true; - } - } + } + return SendPacket("OK"); +} + +static bool MachHeaderIsMainExecutable(nub_process_t pid, uint32_t addr_size, + nub_addr_t mach_header_addr, + mach_header &mh) { + DNBLogThreadedIf(LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, " + "addr_size = %u, mach_header_addr = " + "0x%16.16llx)", + pid, addr_size, mach_header_addr); + const nub_size_t bytes_read = + DNBProcessMemoryRead(pid, mach_header_addr, sizeof(mh), &mh); + if (bytes_read == sizeof(mh)) { + DNBLogThreadedIf( + LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = %u, addr_size = " + "%u, mach_header_addr = 0x%16.16llx): mh = {\n magic = " + "0x%8.8x\n cpu = 0x%8.8x\n sub = 0x%8.8x\n filetype = " + "%u\n ncmds = %u\n sizeofcmds = 0x%8.8x\n flags = " + "0x%8.8x }", + pid, addr_size, mach_header_addr, mh.magic, mh.cputype, mh.cpusubtype, + mh.filetype, mh.ncmds, mh.sizeofcmds, mh.flags); + if ((addr_size == 4 && mh.magic == MH_MAGIC) || + (addr_size == 8 && mh.magic == MH_MAGIC_64)) { + if (mh.filetype == MH_EXECUTE) { + DNBLogThreadedIf(LOG_RNB_PROC, "GetMachHeaderForMainExecutable(pid = " + "%u, addr_size = %u, mach_header_addr = " + "0x%16.16llx) -> this is the " + "executable!!!", + pid, addr_size, mach_header_addr); + return true; + } } - return false; -} - -static nub_addr_t -GetMachHeaderForMainExecutable (const nub_process_t pid, const uint32_t addr_size, mach_header &mh) -{ - struct AllImageInfos - { - uint32_t version; - uint32_t dylib_info_count; - uint64_t dylib_info_addr; - }; - - uint64_t mach_header_addr = 0; - - const nub_addr_t shlib_addr = DNBProcessGetSharedLibraryInfoAddress (pid); - uint8_t bytes[256]; - nub_size_t bytes_read = 0; - DNBDataRef data (bytes, sizeof(bytes), false); - DNBDataRef::offset_t offset = 0; - data.SetPointerSize(addr_size); - - //---------------------------------------------------------------------- - // When we are sitting at __dyld_start, the kernel has placed the - // address of the mach header of the main executable on the stack. If we - // read the SP and dereference a pointer, we might find the mach header - // for the executable. We also just make sure there is only 1 thread - // since if we are at __dyld_start we shouldn't have multiple threads. - //---------------------------------------------------------------------- - if (DNBProcessGetNumThreads(pid) == 1) - { - nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, 0); - if (tid != INVALID_NUB_THREAD) - { - DNBRegisterValue sp_value; - if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC, GENERIC_REGNUM_SP, &sp_value)) - { - uint64_t sp = addr_size == 8 ? sp_value.value.uint64 : sp_value.value.uint32; - bytes_read = DNBProcessMemoryRead(pid, sp, addr_size, bytes); - if (bytes_read == addr_size) - { - offset = 0; - mach_header_addr = data.GetPointer(&offset); - if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh)) - return mach_header_addr; - } - } + } + return false; +} + +static nub_addr_t GetMachHeaderForMainExecutable(const nub_process_t pid, + const uint32_t addr_size, + mach_header &mh) { + struct AllImageInfos { + uint32_t version; + uint32_t dylib_info_count; + uint64_t dylib_info_addr; + }; + + uint64_t mach_header_addr = 0; + + const nub_addr_t shlib_addr = DNBProcessGetSharedLibraryInfoAddress(pid); + uint8_t bytes[256]; + nub_size_t bytes_read = 0; + DNBDataRef data(bytes, sizeof(bytes), false); + DNBDataRef::offset_t offset = 0; + data.SetPointerSize(addr_size); + + //---------------------------------------------------------------------- + // When we are sitting at __dyld_start, the kernel has placed the + // address of the mach header of the main executable on the stack. If we + // read the SP and dereference a pointer, we might find the mach header + // for the executable. We also just make sure there is only 1 thread + // since if we are at __dyld_start we shouldn't have multiple threads. + //---------------------------------------------------------------------- + if (DNBProcessGetNumThreads(pid) == 1) { + nub_thread_t tid = DNBProcessGetThreadAtIndex(pid, 0); + if (tid != INVALID_NUB_THREAD) { + DNBRegisterValue sp_value; + if (DNBThreadGetRegisterValueByID(pid, tid, REGISTER_SET_GENERIC, + GENERIC_REGNUM_SP, &sp_value)) { + uint64_t sp = + addr_size == 8 ? sp_value.value.uint64 : sp_value.value.uint32; + bytes_read = DNBProcessMemoryRead(pid, sp, addr_size, bytes); + if (bytes_read == addr_size) { + offset = 0; + mach_header_addr = data.GetPointer(&offset); + if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh)) + return mach_header_addr; } + } } - - //---------------------------------------------------------------------- - // Check the dyld_all_image_info structure for a list of mach header - // since it is a very easy thing to check - //---------------------------------------------------------------------- - if (shlib_addr != INVALID_NUB_ADDRESS) - { - bytes_read = DNBProcessMemoryRead(pid, shlib_addr, sizeof(AllImageInfos), bytes); - if (bytes_read > 0) - { - AllImageInfos aii; + } + + //---------------------------------------------------------------------- + // Check the dyld_all_image_info structure for a list of mach header + // since it is a very easy thing to check + //---------------------------------------------------------------------- + if (shlib_addr != INVALID_NUB_ADDRESS) { + bytes_read = + DNBProcessMemoryRead(pid, shlib_addr, sizeof(AllImageInfos), bytes); + if (bytes_read > 0) { + AllImageInfos aii; + offset = 0; + aii.version = data.Get32(&offset); + aii.dylib_info_count = data.Get32(&offset); + if (aii.dylib_info_count > 0) { + aii.dylib_info_addr = data.GetPointer(&offset); + if (aii.dylib_info_addr != 0) { + const size_t image_info_byte_size = 3 * addr_size; + for (uint32_t i = 0; i < aii.dylib_info_count; ++i) { + bytes_read = DNBProcessMemoryRead(pid, aii.dylib_info_addr + + i * image_info_byte_size, + image_info_byte_size, bytes); + if (bytes_read != image_info_byte_size) + break; offset = 0; - aii.version = data.Get32(&offset); - aii.dylib_info_count = data.Get32(&offset); - if (aii.dylib_info_count > 0) - { - aii.dylib_info_addr = data.GetPointer(&offset); - if (aii.dylib_info_addr != 0) - { - const size_t image_info_byte_size = 3 * addr_size; - for (uint32_t i=0; i<aii.dylib_info_count; ++i) - { - bytes_read = DNBProcessMemoryRead(pid, aii.dylib_info_addr + i * image_info_byte_size, image_info_byte_size, bytes); - if (bytes_read != image_info_byte_size) - break; - offset = 0; - mach_header_addr = data.GetPointer(&offset); - if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh)) - return mach_header_addr; - } - } - } - } - } - - //---------------------------------------------------------------------- - // We failed to find the executable's mach header from the all image - // infos and by dereferencing the stack pointer. Now we fall back to - // enumerating the memory regions and looking for regions that are - // executable. - //---------------------------------------------------------------------- - DNBRegionInfo region_info; - mach_header_addr = 0; - while (DNBProcessMemoryRegionInfo(pid, mach_header_addr, ®ion_info)) - { - if (region_info.size == 0) - break; - - if (region_info.permissions & eMemoryPermissionsExecutable) - { - DNBLogThreadedIf (LOG_RNB_PROC, "[0x%16.16llx - 0x%16.16llx) permissions = %c%c%c: checking region for executable mach header", region_info.addr, region_info.addr + region_info.size, (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-', (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-', (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-'); - if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh)) - return mach_header_addr; - } - else - { - DNBLogThreadedIf (LOG_RNB_PROC, "[0x%16.16llx - 0x%16.16llx): permissions = %c%c%c: skipping region", region_info.addr, region_info.addr + region_info.size, (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-', (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-', (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-'); - } - // Set the address to the next mapped region - mach_header_addr = region_info.addr + region_info.size; - } - bzero (&mh, sizeof(mh)); - return INVALID_NUB_ADDRESS; -} - -rnb_err_t -RNBRemote::HandlePacket_qSymbol (const char *command) -{ - const char *p = command; - p += strlen ("qSymbol:"); - const char *sep = strchr(p, ':'); - - std::string symbol_name; - std::string symbol_value_str; - // Extract the symbol value if there is one - if (sep > p) - symbol_value_str.assign(p, sep - p); - p = sep + 1; - - if (*p) - { - // We have a symbol name - symbol_name = decode_hex_ascii_string(p); - if (!symbol_value_str.empty()) - { - nub_addr_t symbol_value = decode_uint64(symbol_value_str.c_str(), 16); - if (symbol_name == "dispatch_queue_offsets") - m_dispatch_queue_offsets_addr = symbol_value; + mach_header_addr = data.GetPointer(&offset); + if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, + mh)) + return mach_header_addr; + } } - ++m_qSymbol_index; + } } + } + + //---------------------------------------------------------------------- + // We failed to find the executable's mach header from the all image + // infos and by dereferencing the stack pointer. Now we fall back to + // enumerating the memory regions and looking for regions that are + // executable. + //---------------------------------------------------------------------- + DNBRegionInfo region_info; + mach_header_addr = 0; + while (DNBProcessMemoryRegionInfo(pid, mach_header_addr, ®ion_info)) { + if (region_info.size == 0) + break; + + if (region_info.permissions & eMemoryPermissionsExecutable) { + DNBLogThreadedIf( + LOG_RNB_PROC, "[0x%16.16llx - 0x%16.16llx) permissions = %c%c%c: " + "checking region for executable mach header", + region_info.addr, region_info.addr + region_info.size, + (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-', + (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-', + (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-'); + if (MachHeaderIsMainExecutable(pid, addr_size, mach_header_addr, mh)) + return mach_header_addr; + } else { + DNBLogThreadedIf( + LOG_RNB_PROC, + "[0x%16.16llx - 0x%16.16llx): permissions = %c%c%c: skipping region", + region_info.addr, region_info.addr + region_info.size, + (region_info.permissions & eMemoryPermissionsReadable) ? 'r' : '-', + (region_info.permissions & eMemoryPermissionsWritable) ? 'w' : '-', + (region_info.permissions & eMemoryPermissionsExecutable) ? 'x' : '-'); + } + // Set the address to the next mapped region + mach_header_addr = region_info.addr + region_info.size; + } + bzero(&mh, sizeof(mh)); + return INVALID_NUB_ADDRESS; +} + +rnb_err_t RNBRemote::HandlePacket_qSymbol(const char *command) { + const char *p = command; + p += strlen("qSymbol:"); + const char *sep = strchr(p, ':'); + + std::string symbol_name; + std::string symbol_value_str; + // Extract the symbol value if there is one + if (sep > p) + symbol_value_str.assign(p, sep - p); + p = sep + 1; + + if (*p) { + // We have a symbol name + symbol_name = decode_hex_ascii_string(p); + if (!symbol_value_str.empty()) { + nub_addr_t symbol_value = decode_uint64(symbol_value_str.c_str(), 16); + if (symbol_name == "dispatch_queue_offsets") + m_dispatch_queue_offsets_addr = symbol_value; + } + ++m_qSymbol_index; + } else { + // No symbol name, set our symbol index to zero so we can + // read any symbols that we need + m_qSymbol_index = 0; + } + + symbol_name.clear(); + + if (m_qSymbol_index == 0) { + if (m_dispatch_queue_offsets_addr == INVALID_NUB_ADDRESS) + symbol_name = "dispatch_queue_offsets"; else - { - // No symbol name, set our symbol index to zero so we can - // read any symbols that we need - m_qSymbol_index = 0; - } - - symbol_name.clear(); - - if (m_qSymbol_index == 0) - { - if (m_dispatch_queue_offsets_addr == INVALID_NUB_ADDRESS) - symbol_name = "dispatch_queue_offsets"; - else - ++m_qSymbol_index; - } + ++m_qSymbol_index; + } -// // Lookup next symbol when we have one... -// if (m_qSymbol_index == 1) -// { -// } + // // Lookup next symbol when we have one... + // if (m_qSymbol_index == 1) + // { + // } - - if (symbol_name.empty()) - { - // Done with symbol lookups - return SendPacket ("OK"); - } - else - { - std::ostringstream reply; - reply << "qSymbol:"; - for (size_t i = 0; i < symbol_name.size(); ++i) - reply << RAWHEX8(symbol_name[i]); - return SendPacket (reply.str().c_str()); - } + if (symbol_name.empty()) { + // Done with symbol lookups + return SendPacket("OK"); + } else { + std::ostringstream reply; + reply << "qSymbol:"; + for (size_t i = 0; i < symbol_name.size(); ++i) + reply << RAWHEX8(symbol_name[i]); + return SendPacket(reply.str().c_str()); + } } // Note that all numeric values returned by qProcessInfo are hex encoded, // including the pid and the cpu type. -rnb_err_t -RNBRemote::HandlePacket_qProcessInfo (const char *p) -{ - nub_process_t pid; - std::ostringstream rep; - - // If we haven't run the process yet, return an error. - if (!m_ctx.HasValidProcessID()) - return SendPacket ("E68"); - - pid = m_ctx.ProcessID(); - - rep << "pid:" << std::hex << pid << ';'; - - int procpid_mib[4]; - procpid_mib[0] = CTL_KERN; - procpid_mib[1] = KERN_PROC; - procpid_mib[2] = KERN_PROC_PID; - procpid_mib[3] = pid; - struct kinfo_proc proc_kinfo; - size_t proc_kinfo_size = sizeof(struct kinfo_proc); - - if (::sysctl (procpid_mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) - { - if (proc_kinfo_size > 0) - { - rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ';'; - rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid << ';'; - rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid << ';'; - rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid << ';'; - if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0) - rep << "effective-gid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ';'; - } - } - - cpu_type_t cputype = DNBProcessGetCPUType (pid); - if (cputype == 0) - { - DNBLog ("Unable to get the process cpu_type, making a best guess."); - cputype = best_guess_cpu_type(); - } - - uint32_t addr_size = 0; - if (cputype != 0) - { - rep << "cputype:" << std::hex << cputype << ";"; - if (cputype & CPU_ARCH_ABI64) - addr_size = 8; - else - addr_size = 4; - } - - bool host_cpu_is_64bit = false; - uint32_t is64bit_capable; - size_t is64bit_capable_len = sizeof (is64bit_capable); - if (sysctlbyname("hw.cpu64bit_capable", &is64bit_capable, &is64bit_capable_len, NULL, 0) == 0) - host_cpu_is_64bit = is64bit_capable != 0; - - uint32_t cpusubtype; - size_t cpusubtype_len = sizeof(cpusubtype); - if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &cpusubtype_len, NULL, 0) == 0) - { - // If a process is CPU_TYPE_X86, then ignore the cpusubtype that we detected - // from the host and use CPU_SUBTYPE_I386_ALL because we don't want the - // CPU_SUBTYPE_X86_ARCH1 or CPU_SUBTYPE_X86_64_H to be used as the cpu subtype - // for i386... - if (host_cpu_is_64bit) - { - if (cputype == CPU_TYPE_X86) - { - cpusubtype = 3; // CPU_SUBTYPE_I386_ALL - } - else if (cputype == CPU_TYPE_ARM) - { - // We can query a process' cputype but we cannot query a process' cpusubtype. - // If the process has cputype CPU_TYPE_ARM, then it is an armv7 (32-bit process) and we - // need to override the host cpusubtype (which is in the CPU_SUBTYPE_ARM64 subtype namespace) - // with a reasonable CPU_SUBTYPE_ARMV7 subtype. - cpusubtype = 11; // CPU_SUBTYPE_ARM_V7S - } - } - rep << "cpusubtype:" << std::hex << cpusubtype << ';'; +rnb_err_t RNBRemote::HandlePacket_qProcessInfo(const char *p) { + nub_process_t pid; + std::ostringstream rep; + + // If we haven't run the process yet, return an error. + if (!m_ctx.HasValidProcessID()) + return SendPacket("E68"); + + pid = m_ctx.ProcessID(); + + rep << "pid:" << std::hex << pid << ';'; + + int procpid_mib[4]; + procpid_mib[0] = CTL_KERN; + procpid_mib[1] = KERN_PROC; + procpid_mib[2] = KERN_PROC_PID; + procpid_mib[3] = pid; + struct kinfo_proc proc_kinfo; + size_t proc_kinfo_size = sizeof(struct kinfo_proc); + + if (::sysctl(procpid_mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) { + if (proc_kinfo_size > 0) { + rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ';'; + rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid + << ';'; + rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid + << ';'; + rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid + << ';'; + if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0) + rep << "effective-gid:" << std::hex + << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ';'; + } + } + + cpu_type_t cputype = DNBProcessGetCPUType(pid); + if (cputype == 0) { + DNBLog("Unable to get the process cpu_type, making a best guess."); + cputype = best_guess_cpu_type(); + } + + uint32_t addr_size = 0; + if (cputype != 0) { + rep << "cputype:" << std::hex << cputype << ";"; + if (cputype & CPU_ARCH_ABI64) + addr_size = 8; + else + addr_size = 4; + } + + bool host_cpu_is_64bit = false; + uint32_t is64bit_capable; + size_t is64bit_capable_len = sizeof(is64bit_capable); + if (sysctlbyname("hw.cpu64bit_capable", &is64bit_capable, + &is64bit_capable_len, NULL, 0) == 0) + host_cpu_is_64bit = is64bit_capable != 0; + + uint32_t cpusubtype; + size_t cpusubtype_len = sizeof(cpusubtype); + if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &cpusubtype_len, NULL, 0) == + 0) { + // If a process is CPU_TYPE_X86, then ignore the cpusubtype that we detected + // from the host and use CPU_SUBTYPE_I386_ALL because we don't want the + // CPU_SUBTYPE_X86_ARCH1 or CPU_SUBTYPE_X86_64_H to be used as the cpu + // subtype + // for i386... + if (host_cpu_is_64bit) { + if (cputype == CPU_TYPE_X86) { + cpusubtype = 3; // CPU_SUBTYPE_I386_ALL + } else if (cputype == CPU_TYPE_ARM) { + // We can query a process' cputype but we cannot query a process' + // cpusubtype. + // If the process has cputype CPU_TYPE_ARM, then it is an armv7 (32-bit + // process) and we + // need to override the host cpusubtype (which is in the + // CPU_SUBTYPE_ARM64 subtype namespace) + // with a reasonable CPU_SUBTYPE_ARMV7 subtype. + cpusubtype = 11; // CPU_SUBTYPE_ARM_V7S + } } + rep << "cpusubtype:" << std::hex << cpusubtype << ';'; + } + + bool os_handled = false; + if (addr_size > 0) { + rep << "ptrsize:" << std::dec << addr_size << ';'; + +#if (defined(__x86_64__) || defined(__i386__)) + // Try and get the OS type by looking at the load commands in the main + // executable and looking for a LC_VERSION_MIN load command. This is the + // most reliable way to determine the "ostype" value when on desktop. + + mach_header mh; + nub_addr_t exe_mach_header_addr = + GetMachHeaderForMainExecutable(pid, addr_size, mh); + if (exe_mach_header_addr != INVALID_NUB_ADDRESS) { + uint64_t load_command_addr = + exe_mach_header_addr + + ((addr_size == 8) ? sizeof(mach_header_64) : sizeof(mach_header)); + load_command lc; + for (uint32_t i = 0; i < mh.ncmds && !os_handled; ++i) { + const nub_size_t bytes_read = + DNBProcessMemoryRead(pid, load_command_addr, sizeof(lc), &lc); + uint32_t raw_cmd = lc.cmd & ~LC_REQ_DYLD; + if (bytes_read != sizeof(lc)) + break; + switch (raw_cmd) { + case LC_VERSION_MIN_IPHONEOS: + os_handled = true; + rep << "ostype:ios;"; + DNBLogThreadedIf(LOG_RNB_PROC, + "LC_VERSION_MIN_IPHONEOS -> 'ostype:ios;'"); + break; - bool os_handled = false; - if (addr_size > 0) - { - rep << "ptrsize:" << std::dec << addr_size << ';'; - -#if (defined (__x86_64__) || defined (__i386__)) - // Try and get the OS type by looking at the load commands in the main - // executable and looking for a LC_VERSION_MIN load command. This is the - // most reliable way to determine the "ostype" value when on desktop. + case LC_VERSION_MIN_MACOSX: + os_handled = true; + rep << "ostype:macosx;"; + DNBLogThreadedIf(LOG_RNB_PROC, + "LC_VERSION_MIN_MACOSX -> 'ostype:macosx;'"); + break; - mach_header mh; - nub_addr_t exe_mach_header_addr = GetMachHeaderForMainExecutable (pid, addr_size, mh); - if (exe_mach_header_addr != INVALID_NUB_ADDRESS) - { - uint64_t load_command_addr = exe_mach_header_addr + ((addr_size == 8) ? sizeof(mach_header_64) : sizeof(mach_header)); - load_command lc; - for (uint32_t i=0; i<mh.ncmds && !os_handled; ++i) - { - const nub_size_t bytes_read = DNBProcessMemoryRead (pid, load_command_addr, sizeof(lc), &lc); - uint32_t raw_cmd = lc.cmd & ~LC_REQ_DYLD; - if (bytes_read != sizeof(lc)) - break; - switch (raw_cmd) - { - case LC_VERSION_MIN_IPHONEOS: - os_handled = true; - rep << "ostype:ios;"; - DNBLogThreadedIf (LOG_RNB_PROC, "LC_VERSION_MIN_IPHONEOS -> 'ostype:ios;'"); - break; - - case LC_VERSION_MIN_MACOSX: - os_handled = true; - rep << "ostype:macosx;"; - DNBLogThreadedIf (LOG_RNB_PROC, "LC_VERSION_MIN_MACOSX -> 'ostype:macosx;'"); - break; - -#if defined (LC_VERSION_MIN_TVOS) - case LC_VERSION_MIN_TVOS: - os_handled = true; - rep << "ostype:tvos;"; - DNBLogThreadedIf (LOG_RNB_PROC, "LC_VERSION_MIN_TVOS -> 'ostype:tvos;'"); - break; +#if defined(LC_VERSION_MIN_TVOS) + case LC_VERSION_MIN_TVOS: + os_handled = true; + rep << "ostype:tvos;"; + DNBLogThreadedIf(LOG_RNB_PROC, + "LC_VERSION_MIN_TVOS -> 'ostype:tvos;'"); + break; #endif -#if defined (LC_VERSION_MIN_WATCHOS) - case LC_VERSION_MIN_WATCHOS: - os_handled = true; - rep << "ostype:watchos;"; - DNBLogThreadedIf (LOG_RNB_PROC, "LC_VERSION_MIN_WATCHOS -> 'ostype:watchos;'"); - break; +#if defined(LC_VERSION_MIN_WATCHOS) + case LC_VERSION_MIN_WATCHOS: + os_handled = true; + rep << "ostype:watchos;"; + DNBLogThreadedIf(LOG_RNB_PROC, + "LC_VERSION_MIN_WATCHOS -> 'ostype:watchos;'"); + break; #endif - default: - break; - } - load_command_addr = load_command_addr + lc.cmdsize; - } + default: + break; } -#endif + load_command_addr = load_command_addr + lc.cmdsize; + } } +#endif + } - // If we weren't able to find the OS in a LC_VERSION_MIN load command, try - // to set it correctly by using the cpu type and other tricks - if (!os_handled) - { - // The OS in the triple should be "ios" or "macosx" which doesn't match our - // "Darwin" which gets returned from "kern.ostype", so we need to hardcode - // this for now. - if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) - { -#if defined (TARGET_OS_TV) && TARGET_OS_TV == 1 - rep << "ostype:tvos;"; -#elif defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 - rep << "ostype:watchos;"; + // If we weren't able to find the OS in a LC_VERSION_MIN load command, try + // to set it correctly by using the cpu type and other tricks + if (!os_handled) { + // The OS in the triple should be "ios" or "macosx" which doesn't match our + // "Darwin" which gets returned from "kern.ostype", so we need to hardcode + // this for now. + if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) { +#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1 + rep << "ostype:tvos;"; +#elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 + rep << "ostype:watchos;"; #else - rep << "ostype:ios;"; + rep << "ostype:ios;"; #endif - } - else - { - bool is_ios_simulator = false; - if (cputype == CPU_TYPE_X86 || cputype == CPU_TYPE_X86_64) - { - // Check for iOS simulator binaries by getting the process argument - // and environment and checking for SIMULATOR_UDID in the environment - int proc_args_mib[3] = { CTL_KERN, KERN_PROCARGS2, (int)pid }; - - uint8_t arg_data[8192]; - size_t arg_data_size = sizeof(arg_data); - if (::sysctl (proc_args_mib, 3, arg_data, &arg_data_size , NULL, 0) == 0) - { - DNBDataRef data (arg_data, arg_data_size, false); - DNBDataRef::offset_t offset = 0; - uint32_t argc = data.Get32 (&offset); - const char *cstr; - - cstr = data.GetCStr (&offset); - if (cstr) - { - // Skip NULLs - while (1) - { - const char *p = data.PeekCStr(offset); - if ((p == NULL) || (*p != '\0')) - break; - ++offset; - } - // Now skip all arguments - for (uint32_t i = 0; i < argc; ++i) - { - data.GetCStr(&offset); - } - - // Now iterate across all environment variables - while ((cstr = data.GetCStr(&offset))) - { - if (strncmp(cstr, "SIMULATOR_UDID=", strlen("SIMULATOR_UDID=")) == 0) - { - is_ios_simulator = true; - break; - } - if (cstr[0] == '\0') - break; - - } - } - } + } else { + bool is_ios_simulator = false; + if (cputype == CPU_TYPE_X86 || cputype == CPU_TYPE_X86_64) { + // Check for iOS simulator binaries by getting the process argument + // and environment and checking for SIMULATOR_UDID in the environment + int proc_args_mib[3] = {CTL_KERN, KERN_PROCARGS2, (int)pid}; + + uint8_t arg_data[8192]; + size_t arg_data_size = sizeof(arg_data); + if (::sysctl(proc_args_mib, 3, arg_data, &arg_data_size, NULL, 0) == + 0) { + DNBDataRef data(arg_data, arg_data_size, false); + DNBDataRef::offset_t offset = 0; + uint32_t argc = data.Get32(&offset); + const char *cstr; + + cstr = data.GetCStr(&offset); + if (cstr) { + // Skip NULLs + while (1) { + const char *p = data.PeekCStr(offset); + if ((p == NULL) || (*p != '\0')) + break; + ++offset; } - if (is_ios_simulator) - { -#if defined (TARGET_OS_TV) && TARGET_OS_TV == 1 - rep << "ostype:tvos;"; -#elif defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 - rep << "ostype:watchos;"; -#else - rep << "ostype:ios;"; -#endif + // Now skip all arguments + for (uint32_t i = 0; i < argc; ++i) { + data.GetCStr(&offset); } - else - { - rep << "ostype:macosx;"; + + // Now iterate across all environment variables + while ((cstr = data.GetCStr(&offset))) { + if (strncmp(cstr, "SIMULATOR_UDID=", strlen("SIMULATOR_UDID=")) == + 0) { + is_ios_simulator = true; + break; + } + if (cstr[0] == '\0') + break; } + } } + } + if (is_ios_simulator) { +#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1 + rep << "ostype:tvos;"; +#elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 + rep << "ostype:watchos;"; +#else + rep << "ostype:ios;"; +#endif + } else { + rep << "ostype:macosx;"; + } } + } - rep << "vendor:apple;"; + rep << "vendor:apple;"; -#if defined (__LITTLE_ENDIAN__) - rep << "endian:little;"; -#elif defined (__BIG_ENDIAN__) - rep << "endian:big;"; -#elif defined (__PDP_ENDIAN__) - rep << "endian:pdp;"; +#if defined(__LITTLE_ENDIAN__) + rep << "endian:little;"; +#elif defined(__BIG_ENDIAN__) + rep << "endian:big;"; +#elif defined(__PDP_ENDIAN__) + rep << "endian:pdp;"; #endif - if (addr_size == 0) - { -#if (defined (__x86_64__) || defined (__i386__)) && defined (x86_THREAD_STATE) - nub_thread_t thread = DNBProcessGetCurrentThreadMachPort (pid); - kern_return_t kr; - x86_thread_state_t gp_regs; - mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT; - kr = thread_get_state (static_cast<thread_act_t>(thread), - x86_THREAD_STATE, - (thread_state_t) &gp_regs, - &gp_count); - if (kr == KERN_SUCCESS) - { - if (gp_regs.tsh.flavor == x86_THREAD_STATE64) - rep << "ptrsize:8;"; - else - rep << "ptrsize:4;"; - } -#elif defined (__arm__) + if (addr_size == 0) { +#if (defined(__x86_64__) || defined(__i386__)) && defined(x86_THREAD_STATE) + nub_thread_t thread = DNBProcessGetCurrentThreadMachPort(pid); + kern_return_t kr; + x86_thread_state_t gp_regs; + mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT; + kr = thread_get_state(static_cast<thread_act_t>(thread), x86_THREAD_STATE, + (thread_state_t)&gp_regs, &gp_count); + if (kr == KERN_SUCCESS) { + if (gp_regs.tsh.flavor == x86_THREAD_STATE64) + rep << "ptrsize:8;"; + else rep << "ptrsize:4;"; -#elif (defined (__arm64__) || defined (__aarch64__)) && defined (ARM_UNIFIED_THREAD_STATE) - nub_thread_t thread = DNBProcessGetCurrentThreadMachPort (pid); - kern_return_t kr; - arm_unified_thread_state_t gp_regs; - mach_msg_type_number_t gp_count = ARM_UNIFIED_THREAD_STATE_COUNT; - kr = thread_get_state (thread, ARM_UNIFIED_THREAD_STATE, - (thread_state_t) &gp_regs, &gp_count); - if (kr == KERN_SUCCESS) - { - if (gp_regs.ash.flavor == ARM_THREAD_STATE64) - rep << "ptrsize:8;"; - else - rep << "ptrsize:4;"; - } -#endif } - - return SendPacket (rep.str()); -} - -const RNBRemote::DispatchQueueOffsets * -RNBRemote::GetDispatchQueueOffsets() -{ - if (!m_dispatch_queue_offsets.IsValid() && m_dispatch_queue_offsets_addr != INVALID_NUB_ADDRESS && m_ctx.HasValidProcessID()) - { - nub_process_t pid = m_ctx.ProcessID(); - nub_size_t bytes_read = DNBProcessMemoryRead(pid, m_dispatch_queue_offsets_addr, sizeof(m_dispatch_queue_offsets), &m_dispatch_queue_offsets); - if (bytes_read != sizeof(m_dispatch_queue_offsets)) - m_dispatch_queue_offsets.Clear(); +#elif defined(__arm__) + rep << "ptrsize:4;"; +#elif (defined(__arm64__) || defined(__aarch64__)) && \ + defined(ARM_UNIFIED_THREAD_STATE) + nub_thread_t thread = DNBProcessGetCurrentThreadMachPort(pid); + kern_return_t kr; + arm_unified_thread_state_t gp_regs; + mach_msg_type_number_t gp_count = ARM_UNIFIED_THREAD_STATE_COUNT; + kr = thread_get_state(thread, ARM_UNIFIED_THREAD_STATE, + (thread_state_t)&gp_regs, &gp_count); + if (kr == KERN_SUCCESS) { + if (gp_regs.ash.flavor == ARM_THREAD_STATE64) + rep << "ptrsize:8;"; + else + rep << "ptrsize:4;"; } +#endif + } - if (m_dispatch_queue_offsets.IsValid()) - return &m_dispatch_queue_offsets; - else - return nullptr; -} - -void -RNBRemote::EnableCompressionNextSendPacket (compression_types type) -{ - m_compression_mode = type; - m_enable_compression_next_send_packet = true; + return SendPacket(rep.str()); } -compression_types -RNBRemote::GetCompressionType () -{ - // The first packet we send back to the debugger after a QEnableCompression request - // should be uncompressed -- so we can indicate whether the compression was enabled - // or not via OK / Enn returns. After that, all packets sent will be using the - // compression protocol. - - if (m_enable_compression_next_send_packet) - { - // One time, we send back "None" as our compression type - m_enable_compression_next_send_packet = false; - return compression_types::none; - } - return m_compression_mode; +const RNBRemote::DispatchQueueOffsets *RNBRemote::GetDispatchQueueOffsets() { + if (!m_dispatch_queue_offsets.IsValid() && + m_dispatch_queue_offsets_addr != INVALID_NUB_ADDRESS && + m_ctx.HasValidProcessID()) { + nub_process_t pid = m_ctx.ProcessID(); + nub_size_t bytes_read = DNBProcessMemoryRead( + pid, m_dispatch_queue_offsets_addr, sizeof(m_dispatch_queue_offsets), + &m_dispatch_queue_offsets); + if (bytes_read != sizeof(m_dispatch_queue_offsets)) + m_dispatch_queue_offsets.Clear(); + } + + if (m_dispatch_queue_offsets.IsValid()) + return &m_dispatch_queue_offsets; + else + return nullptr; +} + +void RNBRemote::EnableCompressionNextSendPacket(compression_types type) { + m_compression_mode = type; + m_enable_compression_next_send_packet = true; +} + +compression_types RNBRemote::GetCompressionType() { + // The first packet we send back to the debugger after a QEnableCompression + // request + // should be uncompressed -- so we can indicate whether the compression was + // enabled + // or not via OK / Enn returns. After that, all packets sent will be using + // the + // compression protocol. + + if (m_enable_compression_next_send_packet) { + // One time, we send back "None" as our compression type + m_enable_compression_next_send_packet = false; + return compression_types::none; + } + return m_compression_mode; } diff --git a/lldb/tools/debugserver/source/RNBRemote.h b/lldb/tools/debugserver/source/RNBRemote.h index 57c2a22e8df..0c9c9856308 100644 --- a/lldb/tools/debugserver/source/RNBRemote.h +++ b/lldb/tools/debugserver/source/RNBRemote.h @@ -14,15 +14,15 @@ #ifndef __RNBRemote_h__ #define __RNBRemote_h__ -#include "RNBDefs.h" #include "DNB.h" +#include "PThreadMutex.h" #include "RNBContext.h" +#include "RNBDefs.h" #include "RNBSocket.h" -#include "PThreadMutex.h" -#include <string> -#include <vector> #include <deque> #include <map> +#include <string> +#include <vector> class RNBSocket; class RNBContext; @@ -32,411 +32,383 @@ enum event_loop_mode { debug_nub, gdb_remote_protocol, done }; enum class compression_types { zlib_deflate, lz4, lzma, lzfse, none }; -class RNBRemote -{ +class RNBRemote { public: - - typedef enum { - invalid_packet = 0, - ack, // '+' - nack, // '-' - halt, // ^C (async halt) - use_extended_mode, // '!' - why_halted, // '?' - set_argv, // 'A' - set_bp, // 'B' - cont, // 'c' - continue_with_sig, // 'C' - detach, // 'D' - read_general_regs, // 'g' - write_general_regs, // 'G' - set_thread, // 'H' - step_inferior_one_cycle, // 'i' - signal_and_step_inf_one_cycle, // 'I' - kill, // 'k' - read_memory, // 'm' - write_memory, // 'M' - read_register, // 'p' - write_register, // 'P' - restart, // 'R' - single_step, // 's' - single_step_with_sig, // 'S' - search_mem_backwards, // 't' - thread_alive_p, // 'T' - vattach, // 'vAttach;pid' - vattachwait, // 'vAttachWait:XX...' where XX is one or more hex encoded process name ASCII bytes - vattachorwait, // 'vAttachOrWait:XX...' where XX is one or more hex encoded process name ASCII bytes - vattachname, // 'vAttachName:XX...' where XX is one or more hex encoded process name ASCII bytes - vcont, // 'vCont' - vcont_list_actions, // 'vCont?' - read_data_from_memory, // 'x' - write_data_to_memory, // 'X' - insert_mem_bp, // 'Z0' - remove_mem_bp, // 'z0' - insert_hardware_bp, // 'Z1' - remove_hardware_bp, // 'z1' - insert_write_watch_bp, // 'Z2' - remove_write_watch_bp, // 'z2' - insert_read_watch_bp, // 'Z3' - remove_read_watch_bp, // 'z3' - insert_access_watch_bp, // 'Z4' - remove_access_watch_bp, // 'z4' - - query_monitor, // 'qRcmd' - query_current_thread_id, // 'qC' - query_get_pid, // 'qGetPid' - query_echo, // 'qEcho' - query_thread_ids_first, // 'qfThreadInfo' - query_thread_ids_subsequent, // 'qsThreadInfo' - query_thread_extra_info, // 'qThreadExtraInfo' - query_thread_stop_info, // 'qThreadStopInfo' - query_image_offsets, // 'qOffsets' - query_symbol_lookup, // 'qSymbol' - query_launch_success, // 'qLaunchSuccess' - query_register_info, // 'qRegisterInfo' - query_shlib_notify_info_addr, // 'qShlibInfoAddr' - query_step_packet_supported, // 'qStepPacketSupported' - query_supported_features, // 'qSupported' - query_vattachorwait_supported, // 'qVAttachOrWaitSupported' - query_sync_thread_state_supported,// 'QSyncThreadState' - query_host_info, // 'qHostInfo' - query_gdb_server_version, // 'qGDBServerVersion' - query_process_info, // 'qProcessInfo' - json_query_thread_extended_info,// 'jThreadExtendedInfo' - json_query_get_loaded_dynamic_libraries_infos, // 'jGetLoadedDynamicLibrariesInfos' - json_query_threads_info, // 'jThreadsInfo' - json_query_get_shared_cache_info, // 'jGetSharedCacheInfo' - pass_signals_to_inferior, // 'QPassSignals' - start_noack_mode, // 'QStartNoAckMode' - prefix_reg_packets_with_tid, // 'QPrefixRegisterPacketsWithThreadID - set_logging_mode, // 'QSetLogging:' - set_max_packet_size, // 'QSetMaxPacketSize:' - set_max_payload_size, // 'QSetMaxPayloadSize:' - set_environment_variable, // 'QEnvironment:' - set_environment_variable_hex, // 'QEnvironmentHexEncoded:' - set_launch_arch, // 'QLaunchArch:' - set_disable_aslr, // 'QSetDisableASLR:' - set_stdin, // 'QSetSTDIN:' - set_stdout, // 'QSetSTDOUT:' - set_stderr, // 'QSetSTDERR:' - set_working_dir, // 'QSetWorkingDir:' - set_list_threads_in_stop_reply, // 'QListThreadsInStopReply:' - sync_thread_state, // 'QSyncThreadState:' - memory_region_info, // 'qMemoryRegionInfo:' - get_profile_data, // 'qGetProfileData' - set_enable_profiling, // 'QSetEnableAsyncProfiling' - enable_compression, // 'QEnableCompression:' - watchpoint_support_info, // 'qWatchpointSupportInfo:' - allocate_memory, // '_M' - deallocate_memory, // '_m' - set_process_event, // 'QSetProcessEvent:' - save_register_state, // '_g' - restore_register_state, // '_G' - speed_test, // 'qSpeedTest:' - set_detach_on_error, // 'QSetDetachOnError:' - query_transfer, // 'qXfer:' - query_supported_async_json_packets, // 'QSupportedAsyncJSONPackets' - configure_darwin_log, // 'ConfigureDarwinLog:' - unknown_type - } PacketEnum; - - typedef rnb_err_t (RNBRemote::*HandlePacketCallback)(const char *p); - - RNBRemote (); - ~RNBRemote (); - - void Initialize(); - - bool InitializeRegisters (bool force = false); - - rnb_err_t HandleAsyncPacket(PacketEnum *type = NULL); - rnb_err_t HandleReceivedPacket(PacketEnum *type = NULL); - - nub_thread_t GetContinueThread () const - { - return m_continue_thread; - } - - void SetContinueThread (nub_thread_t tid) - { - m_continue_thread = tid; - } - - nub_thread_t GetCurrentThread () const - { - if (m_thread == 0 || m_thread == (nub_thread_t)-1) - return DNBProcessGetCurrentThread (m_ctx.ProcessID()); - return m_thread; - } - - void SetCurrentThread (nub_thread_t tid) - { - DNBProcessSetCurrentThread (m_ctx.ProcessID(), tid); - m_thread = tid; - } - - static void* ThreadFunctionReadRemoteData(void *arg); - void StartReadRemoteDataThread (); - void StopReadRemoteDataThread (); - - void NotifyThatProcessStopped (void); - - rnb_err_t HandlePacket_A (const char *p); - rnb_err_t HandlePacket_H (const char *p); - rnb_err_t HandlePacket_qC (const char *p); - rnb_err_t HandlePacket_qRcmd (const char *p); - rnb_err_t HandlePacket_qGetPid (const char *p); - rnb_err_t HandlePacket_qEcho (const char *p); - rnb_err_t HandlePacket_qLaunchSuccess (const char *p); - rnb_err_t HandlePacket_qRegisterInfo (const char *p); - rnb_err_t HandlePacket_qShlibInfoAddr (const char *p); - rnb_err_t HandlePacket_qStepPacketSupported (const char *p); - rnb_err_t HandlePacket_qVAttachOrWaitSupported (const char *p); - rnb_err_t HandlePacket_qSyncThreadStateSupported (const char *p); - rnb_err_t HandlePacket_qThreadInfo (const char *p); - rnb_err_t HandlePacket_jThreadExtendedInfo (const char *p); - rnb_err_t HandlePacket_jGetLoadedDynamicLibrariesInfos (const char *p); - rnb_err_t HandlePacket_jThreadsInfo (const char *p); - rnb_err_t HandlePacket_jGetSharedCacheInfo (const char *p); - rnb_err_t HandlePacket_qThreadExtraInfo (const char *p); - rnb_err_t HandlePacket_qThreadStopInfo (const char *p); - rnb_err_t HandlePacket_qHostInfo (const char *p); - rnb_err_t HandlePacket_qGDBServerVersion (const char *p); - rnb_err_t HandlePacket_qProcessInfo (const char *p); - rnb_err_t HandlePacket_qSymbol (const char *p); - rnb_err_t HandlePacket_QStartNoAckMode (const char *p); - rnb_err_t HandlePacket_QThreadSuffixSupported (const char *p); - rnb_err_t HandlePacket_QSetLogging (const char *p); - rnb_err_t HandlePacket_QSetDisableASLR (const char *p); - rnb_err_t HandlePacket_QSetSTDIO (const char *p); - rnb_err_t HandlePacket_QSetWorkingDir (const char *p); - rnb_err_t HandlePacket_QSetMaxPayloadSize (const char *p); - rnb_err_t HandlePacket_QSetMaxPacketSize (const char *p); - rnb_err_t HandlePacket_QEnvironment (const char *p); - rnb_err_t HandlePacket_QEnvironmentHexEncoded (const char *p); - rnb_err_t HandlePacket_QLaunchArch (const char *p); - rnb_err_t HandlePacket_QListThreadsInStopReply (const char *p); - rnb_err_t HandlePacket_QSyncThreadState (const char *p); - rnb_err_t HandlePacket_QPrefixRegisterPacketsWithThreadID (const char *p); - rnb_err_t HandlePacket_QSetProcessEvent (const char *p); - rnb_err_t HandlePacket_last_signal (const char *p); - rnb_err_t HandlePacket_m (const char *p); - rnb_err_t HandlePacket_M (const char *p); - rnb_err_t HandlePacket_x (const char *p); - rnb_err_t HandlePacket_X (const char *p); - rnb_err_t HandlePacket_g (const char *p); - rnb_err_t HandlePacket_G (const char *p); - rnb_err_t HandlePacket_z (const char *p); - rnb_err_t HandlePacket_T (const char *p); - rnb_err_t HandlePacket_p (const char *p); - rnb_err_t HandlePacket_P (const char *p); - rnb_err_t HandlePacket_c (const char *p); - rnb_err_t HandlePacket_C (const char *p); - rnb_err_t HandlePacket_D (const char *p); - rnb_err_t HandlePacket_k (const char *p); - rnb_err_t HandlePacket_s (const char *p); - rnb_err_t HandlePacket_S (const char *p); - rnb_err_t HandlePacket_qSupported (const char *p); - rnb_err_t HandlePacket_v (const char *p); - rnb_err_t HandlePacket_UNIMPLEMENTED (const char *p); - rnb_err_t HandlePacket_ILLFORMED (const char *file, int line, const char *p, const char *description); - rnb_err_t HandlePacket_AllocateMemory (const char *p); - rnb_err_t HandlePacket_DeallocateMemory (const char *p); - rnb_err_t HandlePacket_SaveRegisterState (const char *p); - rnb_err_t HandlePacket_RestoreRegisterState (const char *p); - rnb_err_t HandlePacket_MemoryRegionInfo (const char *p); - rnb_err_t HandlePacket_GetProfileData(const char *p); - rnb_err_t HandlePacket_SetEnableAsyncProfiling(const char *p); - rnb_err_t HandlePacket_QEnableCompression(const char *p); - rnb_err_t HandlePacket_WatchpointSupportInfo (const char *p); - rnb_err_t HandlePacket_qSpeedTest (const char *p); - rnb_err_t HandlePacket_qXfer (const char *p); - rnb_err_t HandlePacket_stop_process (const char *p); - rnb_err_t HandlePacket_QSetDetachOnError (const char *p); - rnb_err_t HandlePacket_qStructuredDataPlugins (const char *p); - rnb_err_t HandlePacket_QConfigureDarwinLog (const char *p); - - rnb_err_t SendStopReplyPacketForThread (nub_thread_t tid); - rnb_err_t SendHexEncodedBytePacket (const char *header, const void *buf, size_t buf_len, const char *footer); - rnb_err_t SendSTDOUTPacket (char *buf, nub_size_t buf_size); - rnb_err_t SendSTDERRPacket (char *buf, nub_size_t buf_size); - void FlushSTDIO (); - void SendAsyncProfileData (); - rnb_err_t SendAsyncProfileDataPacket (char *buf, nub_size_t buf_size); - void SendAsyncDarwinLogData (); - rnb_err_t SendAsyncJSONPacket (const JSONGenerator::Dictionary &dictionary); - - RNBContext& Context() { return m_ctx; } - RNBSocket& Comm() { return m_comm; } + typedef enum { + invalid_packet = 0, + ack, // '+' + nack, // '-' + halt, // ^C (async halt) + use_extended_mode, // '!' + why_halted, // '?' + set_argv, // 'A' + set_bp, // 'B' + cont, // 'c' + continue_with_sig, // 'C' + detach, // 'D' + read_general_regs, // 'g' + write_general_regs, // 'G' + set_thread, // 'H' + step_inferior_one_cycle, // 'i' + signal_and_step_inf_one_cycle, // 'I' + kill, // 'k' + read_memory, // 'm' + write_memory, // 'M' + read_register, // 'p' + write_register, // 'P' + restart, // 'R' + single_step, // 's' + single_step_with_sig, // 'S' + search_mem_backwards, // 't' + thread_alive_p, // 'T' + vattach, // 'vAttach;pid' + vattachwait, // 'vAttachWait:XX...' where XX is one or more hex encoded + // process name ASCII bytes + vattachorwait, // 'vAttachOrWait:XX...' where XX is one or more hex encoded + // process name ASCII bytes + vattachname, // 'vAttachName:XX...' where XX is one or more hex encoded + // process name ASCII bytes + vcont, // 'vCont' + vcont_list_actions, // 'vCont?' + read_data_from_memory, // 'x' + write_data_to_memory, // 'X' + insert_mem_bp, // 'Z0' + remove_mem_bp, // 'z0' + insert_hardware_bp, // 'Z1' + remove_hardware_bp, // 'z1' + insert_write_watch_bp, // 'Z2' + remove_write_watch_bp, // 'z2' + insert_read_watch_bp, // 'Z3' + remove_read_watch_bp, // 'z3' + insert_access_watch_bp, // 'Z4' + remove_access_watch_bp, // 'z4' + + query_monitor, // 'qRcmd' + query_current_thread_id, // 'qC' + query_get_pid, // 'qGetPid' + query_echo, // 'qEcho' + query_thread_ids_first, // 'qfThreadInfo' + query_thread_ids_subsequent, // 'qsThreadInfo' + query_thread_extra_info, // 'qThreadExtraInfo' + query_thread_stop_info, // 'qThreadStopInfo' + query_image_offsets, // 'qOffsets' + query_symbol_lookup, // 'qSymbol' + query_launch_success, // 'qLaunchSuccess' + query_register_info, // 'qRegisterInfo' + query_shlib_notify_info_addr, // 'qShlibInfoAddr' + query_step_packet_supported, // 'qStepPacketSupported' + query_supported_features, // 'qSupported' + query_vattachorwait_supported, // 'qVAttachOrWaitSupported' + query_sync_thread_state_supported, // 'QSyncThreadState' + query_host_info, // 'qHostInfo' + query_gdb_server_version, // 'qGDBServerVersion' + query_process_info, // 'qProcessInfo' + json_query_thread_extended_info, // 'jThreadExtendedInfo' + json_query_get_loaded_dynamic_libraries_infos, // 'jGetLoadedDynamicLibrariesInfos' + json_query_threads_info, // 'jThreadsInfo' + json_query_get_shared_cache_info, // 'jGetSharedCacheInfo' + pass_signals_to_inferior, // 'QPassSignals' + start_noack_mode, // 'QStartNoAckMode' + prefix_reg_packets_with_tid, // 'QPrefixRegisterPacketsWithThreadID + set_logging_mode, // 'QSetLogging:' + set_max_packet_size, // 'QSetMaxPacketSize:' + set_max_payload_size, // 'QSetMaxPayloadSize:' + set_environment_variable, // 'QEnvironment:' + set_environment_variable_hex, // 'QEnvironmentHexEncoded:' + set_launch_arch, // 'QLaunchArch:' + set_disable_aslr, // 'QSetDisableASLR:' + set_stdin, // 'QSetSTDIN:' + set_stdout, // 'QSetSTDOUT:' + set_stderr, // 'QSetSTDERR:' + set_working_dir, // 'QSetWorkingDir:' + set_list_threads_in_stop_reply, // 'QListThreadsInStopReply:' + sync_thread_state, // 'QSyncThreadState:' + memory_region_info, // 'qMemoryRegionInfo:' + get_profile_data, // 'qGetProfileData' + set_enable_profiling, // 'QSetEnableAsyncProfiling' + enable_compression, // 'QEnableCompression:' + watchpoint_support_info, // 'qWatchpointSupportInfo:' + allocate_memory, // '_M' + deallocate_memory, // '_m' + set_process_event, // 'QSetProcessEvent:' + save_register_state, // '_g' + restore_register_state, // '_G' + speed_test, // 'qSpeedTest:' + set_detach_on_error, // 'QSetDetachOnError:' + query_transfer, // 'qXfer:' + query_supported_async_json_packets, // 'QSupportedAsyncJSONPackets' + configure_darwin_log, // 'ConfigureDarwinLog:' + unknown_type + } PacketEnum; + + typedef rnb_err_t (RNBRemote::*HandlePacketCallback)(const char *p); + + RNBRemote(); + ~RNBRemote(); + + void Initialize(); + + bool InitializeRegisters(bool force = false); + + rnb_err_t HandleAsyncPacket(PacketEnum *type = NULL); + rnb_err_t HandleReceivedPacket(PacketEnum *type = NULL); + + nub_thread_t GetContinueThread() const { return m_continue_thread; } + + void SetContinueThread(nub_thread_t tid) { m_continue_thread = tid; } + + nub_thread_t GetCurrentThread() const { + if (m_thread == 0 || m_thread == (nub_thread_t)-1) + return DNBProcessGetCurrentThread(m_ctx.ProcessID()); + return m_thread; + } + + void SetCurrentThread(nub_thread_t tid) { + DNBProcessSetCurrentThread(m_ctx.ProcessID(), tid); + m_thread = tid; + } + + static void *ThreadFunctionReadRemoteData(void *arg); + void StartReadRemoteDataThread(); + void StopReadRemoteDataThread(); + + void NotifyThatProcessStopped(void); + + rnb_err_t HandlePacket_A(const char *p); + rnb_err_t HandlePacket_H(const char *p); + rnb_err_t HandlePacket_qC(const char *p); + rnb_err_t HandlePacket_qRcmd(const char *p); + rnb_err_t HandlePacket_qGetPid(const char *p); + rnb_err_t HandlePacket_qEcho(const char *p); + rnb_err_t HandlePacket_qLaunchSuccess(const char *p); + rnb_err_t HandlePacket_qRegisterInfo(const char *p); + rnb_err_t HandlePacket_qShlibInfoAddr(const char *p); + rnb_err_t HandlePacket_qStepPacketSupported(const char *p); + rnb_err_t HandlePacket_qVAttachOrWaitSupported(const char *p); + rnb_err_t HandlePacket_qSyncThreadStateSupported(const char *p); + rnb_err_t HandlePacket_qThreadInfo(const char *p); + rnb_err_t HandlePacket_jThreadExtendedInfo(const char *p); + rnb_err_t HandlePacket_jGetLoadedDynamicLibrariesInfos(const char *p); + rnb_err_t HandlePacket_jThreadsInfo(const char *p); + rnb_err_t HandlePacket_jGetSharedCacheInfo(const char *p); + rnb_err_t HandlePacket_qThreadExtraInfo(const char *p); + rnb_err_t HandlePacket_qThreadStopInfo(const char *p); + rnb_err_t HandlePacket_qHostInfo(const char *p); + rnb_err_t HandlePacket_qGDBServerVersion(const char *p); + rnb_err_t HandlePacket_qProcessInfo(const char *p); + rnb_err_t HandlePacket_qSymbol(const char *p); + rnb_err_t HandlePacket_QStartNoAckMode(const char *p); + rnb_err_t HandlePacket_QThreadSuffixSupported(const char *p); + rnb_err_t HandlePacket_QSetLogging(const char *p); + rnb_err_t HandlePacket_QSetDisableASLR(const char *p); + rnb_err_t HandlePacket_QSetSTDIO(const char *p); + rnb_err_t HandlePacket_QSetWorkingDir(const char *p); + rnb_err_t HandlePacket_QSetMaxPayloadSize(const char *p); + rnb_err_t HandlePacket_QSetMaxPacketSize(const char *p); + rnb_err_t HandlePacket_QEnvironment(const char *p); + rnb_err_t HandlePacket_QEnvironmentHexEncoded(const char *p); + rnb_err_t HandlePacket_QLaunchArch(const char *p); + rnb_err_t HandlePacket_QListThreadsInStopReply(const char *p); + rnb_err_t HandlePacket_QSyncThreadState(const char *p); + rnb_err_t HandlePacket_QPrefixRegisterPacketsWithThreadID(const char *p); + rnb_err_t HandlePacket_QSetProcessEvent(const char *p); + rnb_err_t HandlePacket_last_signal(const char *p); + rnb_err_t HandlePacket_m(const char *p); + rnb_err_t HandlePacket_M(const char *p); + rnb_err_t HandlePacket_x(const char *p); + rnb_err_t HandlePacket_X(const char *p); + rnb_err_t HandlePacket_g(const char *p); + rnb_err_t HandlePacket_G(const char *p); + rnb_err_t HandlePacket_z(const char *p); + rnb_err_t HandlePacket_T(const char *p); + rnb_err_t HandlePacket_p(const char *p); + rnb_err_t HandlePacket_P(const char *p); + rnb_err_t HandlePacket_c(const char *p); + rnb_err_t HandlePacket_C(const char *p); + rnb_err_t HandlePacket_D(const char *p); + rnb_err_t HandlePacket_k(const char *p); + rnb_err_t HandlePacket_s(const char *p); + rnb_err_t HandlePacket_S(const char *p); + rnb_err_t HandlePacket_qSupported(const char *p); + rnb_err_t HandlePacket_v(const char *p); + rnb_err_t HandlePacket_UNIMPLEMENTED(const char *p); + rnb_err_t HandlePacket_ILLFORMED(const char *file, int line, const char *p, + const char *description); + rnb_err_t HandlePacket_AllocateMemory(const char *p); + rnb_err_t HandlePacket_DeallocateMemory(const char *p); + rnb_err_t HandlePacket_SaveRegisterState(const char *p); + rnb_err_t HandlePacket_RestoreRegisterState(const char *p); + rnb_err_t HandlePacket_MemoryRegionInfo(const char *p); + rnb_err_t HandlePacket_GetProfileData(const char *p); + rnb_err_t HandlePacket_SetEnableAsyncProfiling(const char *p); + rnb_err_t HandlePacket_QEnableCompression(const char *p); + rnb_err_t HandlePacket_WatchpointSupportInfo(const char *p); + rnb_err_t HandlePacket_qSpeedTest(const char *p); + rnb_err_t HandlePacket_qXfer(const char *p); + rnb_err_t HandlePacket_stop_process(const char *p); + rnb_err_t HandlePacket_QSetDetachOnError(const char *p); + rnb_err_t HandlePacket_qStructuredDataPlugins(const char *p); + rnb_err_t HandlePacket_QConfigureDarwinLog(const char *p); + + rnb_err_t SendStopReplyPacketForThread(nub_thread_t tid); + rnb_err_t SendHexEncodedBytePacket(const char *header, const void *buf, + size_t buf_len, const char *footer); + rnb_err_t SendSTDOUTPacket(char *buf, nub_size_t buf_size); + rnb_err_t SendSTDERRPacket(char *buf, nub_size_t buf_size); + void FlushSTDIO(); + void SendAsyncProfileData(); + rnb_err_t SendAsyncProfileDataPacket(char *buf, nub_size_t buf_size); + void SendAsyncDarwinLogData(); + rnb_err_t SendAsyncJSONPacket(const JSONGenerator::Dictionary &dictionary); + + RNBContext &Context() { return m_ctx; } + RNBSocket &Comm() { return m_comm; } private: - // Outlaw some constructors - RNBRemote (const RNBRemote &); + // Outlaw some constructors + RNBRemote(const RNBRemote &); protected: - - rnb_err_t GetCommData (); - void CommDataReceived(const std::string& data); - struct Packet - { - typedef std::vector<Packet> collection; - typedef collection::iterator iterator; - typedef collection::const_iterator const_iterator; - PacketEnum type; - HandlePacketCallback normal; // Function to call when inferior is halted - HandlePacketCallback async; // Function to call when inferior is running - std::string abbrev; - std::string printable_name; - - bool - IsPlatformPacket () const - { - switch (type) - { - case set_logging_mode: - case query_host_info: - return true; - default: - break; - } - return false; - } - Packet() : - type(invalid_packet), - normal (NULL), - async (NULL), - abbrev (), - printable_name () - { - } - - Packet( PacketEnum in_type, - HandlePacketCallback in_normal, - HandlePacketCallback in_async, - const char *in_abbrev, - const char *in_printable_name) : - type (in_type), - normal (in_normal), - async (in_async), - abbrev (in_abbrev), - printable_name (in_printable_name) - { - } - }; - - - struct DispatchQueueOffsets - { - uint16_t dqo_version; - uint16_t dqo_label; - uint16_t dqo_label_size; - uint16_t dqo_flags; - uint16_t dqo_flags_size; - uint16_t dqo_serialnum; - uint16_t dqo_serialnum_size; - uint16_t dqo_width; - uint16_t dqo_width_size; - uint16_t dqo_running; - uint16_t dqo_running_size; - uint16_t dqo_suspend_cnt; // version 5 and later, starting with Mac OS X 10.10/iOS 8 - uint16_t dqo_suspend_cnt_size; // version 5 and later, starting with Mac OS X 10.10/iOS 8 - uint16_t dqo_target_queue; // version 5 and later, starting with Mac OS X 10.10/iOS 8 - uint16_t dqo_target_queue_size; // version 5 and later, starting with Mac OS X 10.10/iOS 8 - uint16_t dqo_priority; // version 5 and later, starting with Mac OS X 10.10/iOS 8 - uint16_t dqo_priority_size; // version 5 and later, starting with Mac OS X 10.10/iOS 8 - - DispatchQueueOffsets () - { - Clear(); - } - - void - Clear() - { - dqo_version = UINT16_MAX; - dqo_label = UINT16_MAX; - dqo_label_size = UINT16_MAX; - dqo_flags = UINT16_MAX; - dqo_flags_size = UINT16_MAX; - dqo_serialnum = UINT16_MAX; - dqo_serialnum_size = UINT16_MAX; - dqo_width = UINT16_MAX; - dqo_width_size = UINT16_MAX; - dqo_running = UINT16_MAX; - dqo_running_size = UINT16_MAX; - dqo_suspend_cnt = UINT16_MAX; - dqo_suspend_cnt_size = UINT16_MAX; - dqo_target_queue = UINT16_MAX; - dqo_target_queue_size = UINT16_MAX; - dqo_priority = UINT16_MAX; - dqo_priority_size = UINT16_MAX; - } - - bool - IsValid () const - { - return dqo_version != UINT16_MAX; - } - - void - GetThreadQueueInfo (nub_process_t pid, - nub_addr_t dispatch_qaddr, + rnb_err_t GetCommData(); + void CommDataReceived(const std::string &data); + struct Packet { + typedef std::vector<Packet> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + PacketEnum type; + HandlePacketCallback normal; // Function to call when inferior is halted + HandlePacketCallback async; // Function to call when inferior is running + std::string abbrev; + std::string printable_name; + + bool IsPlatformPacket() const { + switch (type) { + case set_logging_mode: + case query_host_info: + return true; + default: + break; + } + return false; + } + Packet() + : type(invalid_packet), normal(NULL), async(NULL), abbrev(), + printable_name() {} + + Packet(PacketEnum in_type, HandlePacketCallback in_normal, + HandlePacketCallback in_async, const char *in_abbrev, + const char *in_printable_name) + : type(in_type), normal(in_normal), async(in_async), abbrev(in_abbrev), + printable_name(in_printable_name) {} + }; + + struct DispatchQueueOffsets { + uint16_t dqo_version; + uint16_t dqo_label; + uint16_t dqo_label_size; + uint16_t dqo_flags; + uint16_t dqo_flags_size; + uint16_t dqo_serialnum; + uint16_t dqo_serialnum_size; + uint16_t dqo_width; + uint16_t dqo_width_size; + uint16_t dqo_running; + uint16_t dqo_running_size; + uint16_t dqo_suspend_cnt; // version 5 and later, starting with Mac OS X + // 10.10/iOS 8 + uint16_t dqo_suspend_cnt_size; // version 5 and later, starting with Mac OS + // X 10.10/iOS 8 + uint16_t dqo_target_queue; // version 5 and later, starting with Mac OS X + // 10.10/iOS 8 + uint16_t dqo_target_queue_size; // version 5 and later, starting with Mac OS + // X 10.10/iOS 8 + uint16_t + dqo_priority; // version 5 and later, starting with Mac OS X 10.10/iOS 8 + uint16_t dqo_priority_size; // version 5 and later, starting with Mac OS X + // 10.10/iOS 8 + + DispatchQueueOffsets() { Clear(); } + + void Clear() { + dqo_version = UINT16_MAX; + dqo_label = UINT16_MAX; + dqo_label_size = UINT16_MAX; + dqo_flags = UINT16_MAX; + dqo_flags_size = UINT16_MAX; + dqo_serialnum = UINT16_MAX; + dqo_serialnum_size = UINT16_MAX; + dqo_width = UINT16_MAX; + dqo_width_size = UINT16_MAX; + dqo_running = UINT16_MAX; + dqo_running_size = UINT16_MAX; + dqo_suspend_cnt = UINT16_MAX; + dqo_suspend_cnt_size = UINT16_MAX; + dqo_target_queue = UINT16_MAX; + dqo_target_queue_size = UINT16_MAX; + dqo_priority = UINT16_MAX; + dqo_priority_size = UINT16_MAX; + } + + bool IsValid() const { return dqo_version != UINT16_MAX; } + + void GetThreadQueueInfo(nub_process_t pid, nub_addr_t dispatch_qaddr, nub_addr_t &dispatch_queue_t, - std::string &queue_name, - uint64_t &queue_width, + std::string &queue_name, uint64_t &queue_width, uint64_t &queue_serialnum) const; - }; - - rnb_err_t GetPacket (std::string &packet_data, RNBRemote::Packet& packet_info, bool wait); - rnb_err_t SendPacket (const std::string &); - std::string CompressString (const std::string &); - - void CreatePacketTable (); - rnb_err_t GetPacketPayload (std::string &); - - nub_thread_t - ExtractThreadIDFromThreadSuffix (const char *p); - - void - EnableCompressionNextSendPacket (compression_types); - - compression_types - GetCompressionType (); - - const DispatchQueueOffsets * - GetDispatchQueueOffsets(); - - JSONGenerator::ObjectSP - GetJSONThreadsInfo (bool threads_with_valid_stop_info_only); - - RNBContext m_ctx; // process context - RNBSocket m_comm; // communication port - std::string m_arch; - nub_thread_t m_continue_thread; // thread to continue; 0 for any, -1 for all - nub_thread_t m_thread; // thread for other ops; 0 for any, -1 for all - PThreadMutex m_mutex; // Mutex that protects - DispatchQueueOffsets m_dispatch_queue_offsets; - nub_addr_t m_dispatch_queue_offsets_addr; - uint32_t m_qSymbol_index; - uint32_t m_packets_recvd; - Packet::collection m_packets; - std::deque<std::string> m_rx_packets; - std::string m_rx_partial_data; // For packets that may come in more than one batch, anything left over can be left here - pthread_t m_rx_pthread; - uint32_t m_max_payload_size; // the maximum sized payload we should send to gdb - bool m_extended_mode; // are we in extended mode? - bool m_noack_mode; // are we in no-ack mode? - bool m_thread_suffix_supported; // Set to true if the 'p', 'P', 'g', and 'G' packets should be prefixed with the thread ID and colon: - // "$pRR;thread:TTTT;" instead of "$pRR" - // "$PRR=VVVVVVVV;thread:TTTT;" instead of "$PRR=VVVVVVVV" - // "$g;thread:TTTT" instead of "$g" - // "$GVVVVVVVVVVVVVV;thread:TTTT;#00 instead of "$GVVVVVVVVVVVVVV" - bool m_list_threads_in_stop_reply; - - size_t m_compression_minsize; // only packets larger than this size will be compressed - bool m_enable_compression_next_send_packet; - - compression_types m_compression_mode; + }; + + rnb_err_t GetPacket(std::string &packet_data, RNBRemote::Packet &packet_info, + bool wait); + rnb_err_t SendPacket(const std::string &); + std::string CompressString(const std::string &); + + void CreatePacketTable(); + rnb_err_t GetPacketPayload(std::string &); + + nub_thread_t ExtractThreadIDFromThreadSuffix(const char *p); + + void EnableCompressionNextSendPacket(compression_types); + + compression_types GetCompressionType(); + + const DispatchQueueOffsets *GetDispatchQueueOffsets(); + + JSONGenerator::ObjectSP + GetJSONThreadsInfo(bool threads_with_valid_stop_info_only); + + RNBContext m_ctx; // process context + RNBSocket m_comm; // communication port + std::string m_arch; + nub_thread_t m_continue_thread; // thread to continue; 0 for any, -1 for all + nub_thread_t m_thread; // thread for other ops; 0 for any, -1 for all + PThreadMutex m_mutex; // Mutex that protects + DispatchQueueOffsets m_dispatch_queue_offsets; + nub_addr_t m_dispatch_queue_offsets_addr; + uint32_t m_qSymbol_index; + uint32_t m_packets_recvd; + Packet::collection m_packets; + std::deque<std::string> m_rx_packets; + std::string m_rx_partial_data; // For packets that may come in more than one + // batch, anything left over can be left here + pthread_t m_rx_pthread; + uint32_t + m_max_payload_size; // the maximum sized payload we should send to gdb + bool m_extended_mode; // are we in extended mode? + bool m_noack_mode; // are we in no-ack mode? + bool m_thread_suffix_supported; // Set to true if the 'p', 'P', 'g', and 'G' + // packets should be prefixed with the thread + // ID and colon: + // "$pRR;thread:TTTT;" instead of "$pRR" + // "$PRR=VVVVVVVV;thread:TTTT;" instead of "$PRR=VVVVVVVV" + // "$g;thread:TTTT" instead of "$g" + // "$GVVVVVVVVVVVVVV;thread:TTTT;#00 instead of "$GVVVVVVVVVVVVVV" + bool m_list_threads_in_stop_reply; + + size_t m_compression_minsize; // only packets larger than this size will be + // compressed + bool m_enable_compression_next_send_packet; + + compression_types m_compression_mode; }; /* We translate the /usr/include/mach/exception_types.h exception types @@ -445,12 +417,12 @@ protected: coded values for TARGET_EXC_BAD_ACCESS et al must match the gdb values in its include/gdb/signals.h. */ -#define TARGET_EXC_BAD_ACCESS 0x91 +#define TARGET_EXC_BAD_ACCESS 0x91 #define TARGET_EXC_BAD_INSTRUCTION 0x92 -#define TARGET_EXC_ARITHMETIC 0x93 -#define TARGET_EXC_EMULATION 0x94 -#define TARGET_EXC_SOFTWARE 0x95 -#define TARGET_EXC_BREAKPOINT 0x96 +#define TARGET_EXC_ARITHMETIC 0x93 +#define TARGET_EXC_EMULATION 0x94 +#define TARGET_EXC_SOFTWARE 0x95 +#define TARGET_EXC_BREAKPOINT 0x96 /* Generally speaking, you can't assume gdb can receive more than 399 bytes at a time with a random gdb. This bufsize constant is only specifying diff --git a/lldb/tools/debugserver/source/RNBServices.cpp b/lldb/tools/debugserver/source/RNBServices.cpp index ebd390267f4..d0b7e099d23 100644 --- a/lldb/tools/debugserver/source/RNBServices.cpp +++ b/lldb/tools/debugserver/source/RNBServices.cpp @@ -13,214 +13,223 @@ #include "RNBServices.h" +#include "CFString.h" +#include "DNBLog.h" +#include "MacOSX/CFUtils.h" #include <CoreFoundation/CoreFoundation.h> #include <libproc.h> -#include <unistd.h> #include <sys/sysctl.h> -#include "CFString.h" +#include <unistd.h> #include <vector> -#include "DNBLog.h" -#include "MacOSX/CFUtils.h" -// For now only SpringBoard has a notion of "Applications" that it can list for us. +// For now only SpringBoard has a notion of "Applications" that it can list for +// us. // So we have to use the SpringBoard API's here. -#if defined (WITH_SPRINGBOARD) || defined (WITH_BKS) +#if defined(WITH_SPRINGBOARD) || defined(WITH_BKS) #include <SpringBoardServices/SpringBoardServices.h> #endif // From DNB.cpp -size_t GetAllInfos (std::vector<struct kinfo_proc>& proc_infos); - -int -GetProcesses (CFMutableArrayRef plistMutableArray, bool all_users) -{ - if (plistMutableArray == NULL) - return -1; - - // Running as root, get all processes - std::vector<struct kinfo_proc> proc_infos; - const size_t num_proc_infos = GetAllInfos(proc_infos); - if (num_proc_infos > 0) - { - const pid_t our_pid = getpid(); - const uid_t our_uid = getuid(); - uint32_t i; - CFAllocatorRef alloc = kCFAllocatorDefault; - - for (i=0; i<num_proc_infos; i++) - { - struct kinfo_proc &proc_info = proc_infos[i]; - - bool kinfo_user_matches; - // Special case, if lldb is being run as root we can attach to anything. - if (all_users) - kinfo_user_matches = true; - else - kinfo_user_matches = proc_info.kp_eproc.e_pcred.p_ruid == our_uid; - - - const pid_t pid = proc_info.kp_proc.p_pid; - // Skip zombie processes and processes with unset status - if (kinfo_user_matches == false || // User is acceptable - pid == our_pid || // Skip this process - pid == 0 || // Skip kernel (kernel pid is zero) - proc_info.kp_proc.p_stat == SZOMB || // Zombies are bad, they like brains... - proc_info.kp_proc.p_flag & P_TRACED || // Being debugged? - proc_info.kp_proc.p_flag & P_WEXIT || // Working on exiting? - proc_info.kp_proc.p_flag & P_TRANSLATED) // Skip translated ppc (Rosetta) - continue; - - // Create a new mutable dictionary for each application - CFReleaser<CFMutableDictionaryRef> appInfoDict (::CFDictionaryCreateMutable (alloc, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); - - // Get the process id for the app (if there is one) - const int32_t pid_int32 = pid; - CFReleaser<CFNumberRef> pidCFNumber (::CFNumberCreate (alloc, kCFNumberSInt32Type, &pid_int32)); - ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_PID_KEY, pidCFNumber.get()); - - // Set the a boolean to indicate if this is the front most - ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY, kCFBooleanFalse); - - const char *pid_basename = proc_info.kp_proc.p_comm; - char proc_path_buf[PATH_MAX]; - - int return_val = proc_pidpath (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. - - pid_basename = strrchr(proc_path_buf, '/'); - if (pid_basename) - { - // Skip the '/' - ++pid_basename; - } - else - { - // We didn't find a directory delimiter in the process argv[0], just use what was in there - pid_basename = proc_path_buf; - } - CFString cf_pid_path (proc_path_buf); - if (cf_pid_path.get()) - ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_PATH_KEY, cf_pid_path.get()); - } - - if (pid_basename && pid_basename[0]) - { - CFString pid_name (pid_basename); - ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_DISPLAY_NAME_KEY, pid_name.get()); - } - - // Append the application info to the plist array - ::CFArrayAppendValue (plistMutableArray, appInfoDict.get()); - } - } - return 0; -} -int -ListApplications(std::string& plist, bool opt_runningApps, bool opt_debuggable) -{ - int result = -1; - - CFAllocatorRef alloc = kCFAllocatorDefault; - - // Create a mutable array that we can populate. Specify zero so it can be of any size. - CFReleaser<CFMutableArrayRef> plistMutableArray (::CFArrayCreateMutable (alloc, 0, &kCFTypeArrayCallBacks)); +size_t GetAllInfos(std::vector<struct kinfo_proc> &proc_infos); + +int GetProcesses(CFMutableArrayRef plistMutableArray, bool all_users) { + if (plistMutableArray == NULL) + return -1; + // Running as root, get all processes + std::vector<struct kinfo_proc> proc_infos; + const size_t num_proc_infos = GetAllInfos(proc_infos); + if (num_proc_infos > 0) { + const pid_t our_pid = getpid(); const uid_t our_uid = getuid(); + uint32_t i; + CFAllocatorRef alloc = kCFAllocatorDefault; -#if defined (WITH_SPRINGBOARD) || defined (WITH_BKS) - - if (our_uid == 0) - { - bool all_users = true; - result = GetProcesses (plistMutableArray.get(), all_users); - } - else - { - CFReleaser<CFStringRef> sbsFrontAppID (::SBSCopyFrontmostApplicationDisplayIdentifier ()); - CFReleaser<CFArrayRef> sbsAppIDs (::SBSCopyApplicationDisplayIdentifiers (opt_runningApps, opt_debuggable)); - - // Need to check the return value from SBSCopyApplicationDisplayIdentifiers. - CFIndex count = sbsAppIDs.get() ? ::CFArrayGetCount (sbsAppIDs.get()) : 0; - CFIndex i = 0; - for (i = 0; i < count; i++) - { - CFStringRef displayIdentifier = (CFStringRef)::CFArrayGetValueAtIndex (sbsAppIDs.get(), i); - - // Create a new mutable dictionary for each application - CFReleaser<CFMutableDictionaryRef> appInfoDict (::CFDictionaryCreateMutable (alloc, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); - - // Get the process id for the app (if there is one) - pid_t pid = INVALID_NUB_PROCESS; - if (::SBSProcessIDForDisplayIdentifier ((CFStringRef)displayIdentifier, &pid) == true) - { - CFReleaser<CFNumberRef> pidCFNumber (::CFNumberCreate (alloc, kCFNumberSInt32Type, &pid)); - ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_PID_KEY, pidCFNumber.get()); - } - - // Set the a boolean to indicate if this is the front most - if (sbsFrontAppID.get() && displayIdentifier && (::CFStringCompare (sbsFrontAppID.get(), displayIdentifier, 0) == kCFCompareEqualTo)) - ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY, kCFBooleanTrue); - else - ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY, kCFBooleanFalse); - - - CFReleaser<CFStringRef> executablePath (::SBSCopyExecutablePathForDisplayIdentifier (displayIdentifier)); - if (executablePath.get() != NULL) - { - ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_PATH_KEY, executablePath.get()); - } - - CFReleaser<CFStringRef> iconImagePath (::SBSCopyIconImagePathForDisplayIdentifier (displayIdentifier)) ; - if (iconImagePath.get() != NULL) - { - ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_ICON_PATH_KEY, iconImagePath.get()); - } - - CFReleaser<CFStringRef> localizedDisplayName (::SBSCopyLocalizedApplicationNameForDisplayIdentifier (displayIdentifier)); - if (localizedDisplayName.get() != NULL) - { - ::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_DISPLAY_NAME_KEY, localizedDisplayName.get()); - } - - // Append the application info to the plist array - ::CFArrayAppendValue (plistMutableArray.get(), appInfoDict.get()); + for (i = 0; i < num_proc_infos; i++) { + struct kinfo_proc &proc_info = proc_infos[i]; + + bool kinfo_user_matches; + // Special case, if lldb is being run as root we can attach to anything. + if (all_users) + kinfo_user_matches = true; + else + kinfo_user_matches = proc_info.kp_eproc.e_pcred.p_ruid == our_uid; + + const pid_t pid = proc_info.kp_proc.p_pid; + // Skip zombie processes and processes with unset status + if (kinfo_user_matches == false || // User is acceptable + pid == our_pid || // Skip this process + pid == 0 || // Skip kernel (kernel pid is zero) + proc_info.kp_proc.p_stat == + SZOMB || // Zombies are bad, they like brains... + proc_info.kp_proc.p_flag & P_TRACED || // Being debugged? + proc_info.kp_proc.p_flag & P_WEXIT || // Working on exiting? + proc_info.kp_proc.p_flag & + P_TRANSLATED) // Skip translated ppc (Rosetta) + continue; + + // Create a new mutable dictionary for each application + CFReleaser<CFMutableDictionaryRef> appInfoDict( + ::CFDictionaryCreateMutable(alloc, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + + // Get the process id for the app (if there is one) + const int32_t pid_int32 = pid; + CFReleaser<CFNumberRef> pidCFNumber( + ::CFNumberCreate(alloc, kCFNumberSInt32Type, &pid_int32)); + ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_PID_KEY, + pidCFNumber.get()); + + // Set the a boolean to indicate if this is the front most + ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY, + kCFBooleanFalse); + + const char *pid_basename = proc_info.kp_proc.p_comm; + char proc_path_buf[PATH_MAX]; + + int return_val = proc_pidpath(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. + + pid_basename = strrchr(proc_path_buf, '/'); + if (pid_basename) { + // Skip the '/' + ++pid_basename; + } else { + // We didn't find a directory delimiter in the process argv[0], just + // use what was in there + pid_basename = proc_path_buf; } + CFString cf_pid_path(proc_path_buf); + if (cf_pid_path.get()) + ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_PATH_KEY, + cf_pid_path.get()); + } + + if (pid_basename && pid_basename[0]) { + CFString pid_name(pid_basename); + ::CFDictionarySetValue(appInfoDict.get(), + DTSERVICES_APP_DISPLAY_NAME_KEY, pid_name.get()); + } + + // Append the application info to the plist array + ::CFArrayAppendValue(plistMutableArray, appInfoDict.get()); + } + } + return 0; +} +int ListApplications(std::string &plist, bool opt_runningApps, + bool opt_debuggable) { + int result = -1; + + CFAllocatorRef alloc = kCFAllocatorDefault; + + // Create a mutable array that we can populate. Specify zero so it can be of + // any size. + CFReleaser<CFMutableArrayRef> plistMutableArray( + ::CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks)); + + const uid_t our_uid = getuid(); + +#if defined(WITH_SPRINGBOARD) || defined(WITH_BKS) + + if (our_uid == 0) { + bool all_users = true; + result = GetProcesses(plistMutableArray.get(), all_users); + } else { + CFReleaser<CFStringRef> sbsFrontAppID( + ::SBSCopyFrontmostApplicationDisplayIdentifier()); + CFReleaser<CFArrayRef> sbsAppIDs(::SBSCopyApplicationDisplayIdentifiers( + opt_runningApps, opt_debuggable)); + + // Need to check the return value from SBSCopyApplicationDisplayIdentifiers. + CFIndex count = sbsAppIDs.get() ? ::CFArrayGetCount(sbsAppIDs.get()) : 0; + CFIndex i = 0; + for (i = 0; i < count; i++) { + CFStringRef displayIdentifier = + (CFStringRef)::CFArrayGetValueAtIndex(sbsAppIDs.get(), i); + + // Create a new mutable dictionary for each application + CFReleaser<CFMutableDictionaryRef> appInfoDict( + ::CFDictionaryCreateMutable(alloc, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + + // Get the process id for the app (if there is one) + pid_t pid = INVALID_NUB_PROCESS; + if (::SBSProcessIDForDisplayIdentifier((CFStringRef)displayIdentifier, + &pid) == true) { + CFReleaser<CFNumberRef> pidCFNumber( + ::CFNumberCreate(alloc, kCFNumberSInt32Type, &pid)); + ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_PID_KEY, + pidCFNumber.get()); + } + + // Set the a boolean to indicate if this is the front most + if (sbsFrontAppID.get() && displayIdentifier && + (::CFStringCompare(sbsFrontAppID.get(), displayIdentifier, 0) == + kCFCompareEqualTo)) + ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY, + kCFBooleanTrue); + else + ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY, + kCFBooleanFalse); + + CFReleaser<CFStringRef> executablePath( + ::SBSCopyExecutablePathForDisplayIdentifier(displayIdentifier)); + if (executablePath.get() != NULL) { + ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_PATH_KEY, + executablePath.get()); + } + + CFReleaser<CFStringRef> iconImagePath( + ::SBSCopyIconImagePathForDisplayIdentifier(displayIdentifier)); + if (iconImagePath.get() != NULL) { + ::CFDictionarySetValue(appInfoDict.get(), DTSERVICES_APP_ICON_PATH_KEY, + iconImagePath.get()); + } + + CFReleaser<CFStringRef> localizedDisplayName( + ::SBSCopyLocalizedApplicationNameForDisplayIdentifier( + displayIdentifier)); + if (localizedDisplayName.get() != NULL) { + ::CFDictionarySetValue(appInfoDict.get(), + DTSERVICES_APP_DISPLAY_NAME_KEY, + localizedDisplayName.get()); + } + + // Append the application info to the plist array + ::CFArrayAppendValue(plistMutableArray.get(), appInfoDict.get()); } + } #else // #if defined (WITH_SPRINGBOARD) || defined (WITH_BKS) - // When root, show all processes - bool all_users = (our_uid == 0); - GetProcesses (plistMutableArray.get(), all_users); + // When root, show all processes + bool all_users = (our_uid == 0); + GetProcesses(plistMutableArray.get(), all_users); #endif - - CFReleaser<CFDataRef> plistData (::CFPropertyListCreateXMLData (alloc, plistMutableArray.get())); - - // write plist to service port - if (plistData.get() != NULL) - { - CFIndex size = ::CFDataGetLength (plistData.get()); - const UInt8 *bytes = ::CFDataGetBytePtr (plistData.get()); - if (bytes != NULL && size > 0) - { - plist.assign((char *)bytes, size); - return 0; // Success - } - else - { - DNBLogError("empty application property list."); - result = -2; - } - } - else - { - DNBLogError("serializing task list."); - result = -3; + + CFReleaser<CFDataRef> plistData( + ::CFPropertyListCreateXMLData(alloc, plistMutableArray.get())); + + // write plist to service port + if (plistData.get() != NULL) { + CFIndex size = ::CFDataGetLength(plistData.get()); + const UInt8 *bytes = ::CFDataGetBytePtr(plistData.get()); + if (bytes != NULL && size > 0) { + plist.assign((char *)bytes, size); + return 0; // Success + } else { + DNBLogError("empty application property list."); + result = -2; } - - return result; + } else { + DNBLogError("serializing task list."); + result = -3; + } + return result; } diff --git a/lldb/tools/debugserver/source/RNBServices.h b/lldb/tools/debugserver/source/RNBServices.h index b0b9c219357..caa2b0fd199 100644 --- a/lldb/tools/debugserver/source/RNBServices.h +++ b/lldb/tools/debugserver/source/RNBServices.h @@ -14,15 +14,16 @@ #ifndef __RNBServices_h__ #define __RNBServices_h__ -#include <string> #include "RNBDefs.h" +#include <string> -#define DTSERVICES_APP_FRONTMOST_KEY CFSTR("isFrontApp") -#define DTSERVICES_APP_PATH_KEY CFSTR("executablePath") -#define DTSERVICES_APP_ICON_PATH_KEY CFSTR("iconPath") +#define DTSERVICES_APP_FRONTMOST_KEY CFSTR("isFrontApp") +#define DTSERVICES_APP_PATH_KEY CFSTR("executablePath") +#define DTSERVICES_APP_ICON_PATH_KEY CFSTR("iconPath") #define DTSERVICES_APP_DISPLAY_NAME_KEY CFSTR("displayName") -#define DTSERVICES_APP_PID_KEY CFSTR("pid") +#define DTSERVICES_APP_PID_KEY CFSTR("pid") -int ListApplications (std::string &plist, bool opt_runningApps, bool opt_debuggable); +int ListApplications(std::string &plist, bool opt_runningApps, + bool opt_debuggable); -#endif // __RNBServices_h__ +#endif // __RNBServices_h__ diff --git a/lldb/tools/debugserver/source/RNBSocket.cpp b/lldb/tools/debugserver/source/RNBSocket.cpp index ce4886ab9df..a8d119e455f 100644 --- a/lldb/tools/debugserver/source/RNBSocket.cpp +++ b/lldb/tools/debugserver/source/RNBSocket.cpp @@ -12,6 +12,8 @@ //===----------------------------------------------------------------------===// #include "RNBSocket.h" +#include "DNBError.h" +#include "DNBLog.h" #include <arpa/inet.h> #include <errno.h> #include <fcntl.h> @@ -19,8 +21,6 @@ #include <netinet/in.h> #include <netinet/tcp.h> #include <termios.h> -#include "DNBLog.h" -#include "DNBError.h" #ifdef WITH_LOCKDOWN #include "lockdown.h" @@ -30,392 +30,357 @@ this function is called to wait for an incoming connection. This function blocks while waiting for that connection. */ -bool -ResolveIPV4HostName (const char *hostname, in_addr_t &addr) -{ - if (hostname == NULL || - hostname[0] == '\0' || - strcmp(hostname, "localhost") == 0 || - strcmp(hostname, "127.0.0.1") == 0) - { - addr = htonl (INADDR_LOOPBACK); +bool ResolveIPV4HostName(const char *hostname, in_addr_t &addr) { + if (hostname == NULL || hostname[0] == '\0' || + strcmp(hostname, "localhost") == 0 || + strcmp(hostname, "127.0.0.1") == 0) { + addr = htonl(INADDR_LOOPBACK); + return true; + } else if (strcmp(hostname, "*") == 0) { + addr = htonl(INADDR_ANY); + return true; + } else { + // See if an IP address was specified as numbers + int inet_pton_result = ::inet_pton(AF_INET, hostname, &addr); + + if (inet_pton_result == 1) + return true; + + struct hostent *host_entry = gethostbyname(hostname); + if (host_entry) { + std::string ip_str( + ::inet_ntoa(*(struct in_addr *)*host_entry->h_addr_list)); + inet_pton_result = ::inet_pton(AF_INET, ip_str.c_str(), &addr); + if (inet_pton_result == 1) return true; } - else if (strcmp(hostname, "*") == 0) - { - addr = htonl (INADDR_ANY); - return true; - } - else - { - // See if an IP address was specified as numbers - int inet_pton_result = ::inet_pton (AF_INET, hostname, &addr); - - if (inet_pton_result == 1) - return true; - - struct hostent *host_entry = gethostbyname (hostname); - if (host_entry) - { - std::string ip_str (::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list)); - inet_pton_result = ::inet_pton (AF_INET, ip_str.c_str(), &addr); - if (inet_pton_result == 1) - return true; - } - } - return false; + } + return false; } -rnb_err_t -RNBSocket::Listen (const char *listen_host, uint16_t port, PortBoundCallback callback, const void *callback_baton) -{ - //DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s called", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); - // Disconnect without saving errno - Disconnect (false); - - // Now figure out the hostname that will be attaching and palce it into - struct sockaddr_in listen_addr; - ::memset (&listen_addr, 0, sizeof listen_addr); - listen_addr.sin_len = sizeof listen_addr; - listen_addr.sin_family = AF_INET; - listen_addr.sin_port = htons (port); - listen_addr.sin_addr.s_addr = INADDR_ANY; - - if (!ResolveIPV4HostName(listen_host, listen_addr.sin_addr.s_addr)) - { - DNBLogThreaded("error: failed to resolve connecting host '%s'", listen_host); - return rnb_err; +rnb_err_t RNBSocket::Listen(const char *listen_host, uint16_t port, + PortBoundCallback callback, + const void *callback_baton) { + // DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s called", + // (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); + // Disconnect without saving errno + Disconnect(false); + + // Now figure out the hostname that will be attaching and palce it into + struct sockaddr_in listen_addr; + ::memset(&listen_addr, 0, sizeof listen_addr); + listen_addr.sin_len = sizeof listen_addr; + listen_addr.sin_family = AF_INET; + listen_addr.sin_port = htons(port); + listen_addr.sin_addr.s_addr = INADDR_ANY; + + if (!ResolveIPV4HostName(listen_host, listen_addr.sin_addr.s_addr)) { + DNBLogThreaded("error: failed to resolve connecting host '%s'", + listen_host); + return rnb_err; + } + + DNBError err; + int listen_fd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (listen_fd == -1) + err.SetError(errno, DNBError::POSIX); + + if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) + err.LogThreaded("::socket ( domain = AF_INET, type = SOCK_STREAM, protocol " + "= IPPROTO_TCP ) => socket = %i", + listen_fd); + + if (err.Fail()) + return rnb_err; + + // enable local address reuse + SetSocketOption(listen_fd, SOL_SOCKET, SO_REUSEADDR, 1); + + struct sockaddr_in sa; + ::memset(&sa, 0, sizeof sa); + sa.sin_len = sizeof sa; + sa.sin_family = AF_INET; + sa.sin_port = htons(port); + sa.sin_addr.s_addr = INADDR_ANY; // Let incoming connections bind to any host + // network interface (this is NOT who can + // connect to us) + int error = ::bind(listen_fd, (struct sockaddr *)&sa, sizeof(sa)); + if (error == -1) + err.SetError(errno, DNBError::POSIX); + + if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) + err.LogThreaded( + "::bind ( socket = %i, (struct sockaddr *) &sa, sizeof(sa)) )", + listen_fd); + + if (err.Fail()) { + ClosePort(listen_fd, false); + return rnb_err; + } + + error = ::listen(listen_fd, 5); + if (error == -1) + err.SetError(errno, DNBError::POSIX); + + if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) + err.LogThreaded("::listen ( socket = %i, backlog = 1 )", listen_fd); + + if (err.Fail()) { + ClosePort(listen_fd, false); + return rnb_err; + } + + if (callback) { + // We were asked to listen on port zero which means we + // must now read the actual port that was given to us + // as port zero is a special code for "find an open port + // for me". + if (port == 0) { + socklen_t sa_len = sizeof(sa); + if (getsockname(listen_fd, (struct sockaddr *)&sa, &sa_len) == 0) { + port = ntohs(sa.sin_port); + callback(callback_baton, port); + } + } else { + callback(callback_baton, port); } - - DNBError err; - int listen_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (listen_fd == -1) - err.SetError(errno, DNBError::POSIX); + } - if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) - err.LogThreaded("::socket ( domain = AF_INET, type = SOCK_STREAM, protocol = IPPROTO_TCP ) => socket = %i", listen_fd); + struct sockaddr_in accept_addr; + ::memset(&accept_addr, 0, sizeof accept_addr); + accept_addr.sin_len = sizeof accept_addr; - if (err.Fail()) - return rnb_err; + bool accept_connection = false; - // enable local address reuse - SetSocketOption (listen_fd, SOL_SOCKET, SO_REUSEADDR, 1); + // Loop until we are happy with our connection + while (!accept_connection) { + socklen_t accept_addr_len = sizeof accept_addr; + m_fd = + ::accept(listen_fd, (struct sockaddr *)&accept_addr, &accept_addr_len); - struct sockaddr_in sa; - ::memset (&sa, 0, sizeof sa); - sa.sin_len = sizeof sa; - sa.sin_family = AF_INET; - sa.sin_port = htons (port); - sa.sin_addr.s_addr = INADDR_ANY; // Let incoming connections bind to any host network interface (this is NOT who can connect to us) - int error = ::bind (listen_fd, (struct sockaddr *) &sa, sizeof(sa)); - if (error == -1) - err.SetError(errno, DNBError::POSIX); + if (m_fd == -1) + err.SetError(errno, DNBError::POSIX); if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) - err.LogThreaded("::bind ( socket = %i, (struct sockaddr *) &sa, sizeof(sa)) )", listen_fd); + err.LogThreaded( + "::accept ( socket = %i, address = %p, address_len = %u )", listen_fd, + &accept_addr, accept_addr_len); if (err.Fail()) - { - ClosePort (listen_fd, false); - return rnb_err; + break; + + if (listen_addr.sin_addr.s_addr == INADDR_ANY) + accept_connection = true; + else { + if (accept_addr_len == listen_addr.sin_len && + accept_addr.sin_addr.s_addr == listen_addr.sin_addr.s_addr) { + accept_connection = true; + } else { + ::close(m_fd); + m_fd = -1; + const uint8_t *accept_ip = + (const uint8_t *)&accept_addr.sin_addr.s_addr; + const uint8_t *listen_ip = + (const uint8_t *)&listen_addr.sin_addr.s_addr; + ::fprintf(stderr, "error: rejecting incoming connection from " + "%u.%u.%u.%u (expecting %u.%u.%u.%u)\n", + accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], + listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); + DNBLogThreaded("error: rejecting connection from %u.%u.%u.%u " + "(expecting %u.%u.%u.%u)", + accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], + listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); + } } + } - error = ::listen (listen_fd, 5); - if (error == -1) - err.SetError(errno, DNBError::POSIX); + ClosePort(listen_fd, false); - if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) - err.LogThreaded("::listen ( socket = %i, backlog = 1 )", listen_fd); + if (err.Fail()) { + return rnb_err; + } else { + // Keep our TCP packets coming without any delays. + SetSocketOption(m_fd, IPPROTO_TCP, TCP_NODELAY, 1); + } - if (err.Fail()) - { - ClosePort (listen_fd, false); - return rnb_err; - } - - if (callback) - { - // We were asked to listen on port zero which means we - // must now read the actual port that was given to us - // as port zero is a special code for "find an open port - // for me". - if (port == 0) - { - socklen_t sa_len = sizeof (sa); - if (getsockname(listen_fd, (struct sockaddr *)&sa, &sa_len) == 0) - { - port = ntohs (sa.sin_port); - callback (callback_baton, port); - } - } - else - { - callback (callback_baton, port); - } - } + return rnb_success; +} - struct sockaddr_in accept_addr; - ::memset (&accept_addr, 0, sizeof accept_addr); - accept_addr.sin_len = sizeof accept_addr; - - bool accept_connection = false; - - // Loop until we are happy with our connection - while (!accept_connection) - { - socklen_t accept_addr_len = sizeof accept_addr; - m_fd = ::accept (listen_fd, (struct sockaddr *)&accept_addr, &accept_addr_len); - - if (m_fd == -1) - err.SetError(errno, DNBError::POSIX); - - if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) - err.LogThreaded("::accept ( socket = %i, address = %p, address_len = %u )", listen_fd, &accept_addr, accept_addr_len); - - if (err.Fail()) - break; - - if (listen_addr.sin_addr.s_addr == INADDR_ANY) - accept_connection = true; - else - { - if (accept_addr_len == listen_addr.sin_len && - accept_addr.sin_addr.s_addr == listen_addr.sin_addr.s_addr) - { - accept_connection = true; - } - else - { - ::close (m_fd); - m_fd = -1; - const uint8_t *accept_ip = (const uint8_t *)&accept_addr.sin_addr.s_addr; - const uint8_t *listen_ip = (const uint8_t *)&listen_addr.sin_addr.s_addr; - ::fprintf (stderr, - "error: rejecting incoming connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)\n", - accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], - listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); - DNBLogThreaded ("error: rejecting connection from %u.%u.%u.%u (expecting %u.%u.%u.%u)", - accept_ip[0], accept_ip[1], accept_ip[2], accept_ip[3], - listen_ip[0], listen_ip[1], listen_ip[2], listen_ip[3]); - } - } - } +rnb_err_t RNBSocket::Connect(const char *host, uint16_t port) { + Disconnect(false); - ClosePort (listen_fd, false); + // Create the socket + m_fd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (m_fd == -1) + return rnb_err; - if (err.Fail()) - { - return rnb_err; - } - else - { - // Keep our TCP packets coming without any delays. - SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); - } + // Enable local address reuse + SetSocketOption(m_fd, SOL_SOCKET, SO_REUSEADDR, 1); - return rnb_success; -} + struct sockaddr_in sa; + ::memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_port = htons(port); -rnb_err_t -RNBSocket::Connect (const char *host, uint16_t port) -{ - Disconnect (false); + if (!ResolveIPV4HostName(host, sa.sin_addr.s_addr)) { + DNBLogThreaded("error: failed to resolve host '%s'", host); + Disconnect(false); + return rnb_err; + } - // Create the socket - m_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (m_fd == -1) - return rnb_err; - - // Enable local address reuse - SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1); - - struct sockaddr_in sa; - ::memset (&sa, 0, sizeof (sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons (port); - - if (!ResolveIPV4HostName(host, sa.sin_addr.s_addr)) - { - DNBLogThreaded("error: failed to resolve host '%s'", host); - Disconnect (false); - return rnb_err; - } - - if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa))) - { - Disconnect (false); - return rnb_err; - } - - // Keep our TCP packets coming without any delays. - SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); - return rnb_success; + if (-1 == ::connect(m_fd, (const struct sockaddr *)&sa, sizeof(sa))) { + Disconnect(false); + return rnb_err; + } + + // Keep our TCP packets coming without any delays. + SetSocketOption(m_fd, IPPROTO_TCP, TCP_NODELAY, 1); + return rnb_success; } -rnb_err_t -RNBSocket::useFD(int fd) -{ - if (fd < 0) { - DNBLogThreadedIf(LOG_RNB_COMM, "Bad file descriptor passed in."); - return rnb_err; - } - - m_fd = fd; - return rnb_success; +rnb_err_t RNBSocket::useFD(int fd) { + if (fd < 0) { + DNBLogThreadedIf(LOG_RNB_COMM, "Bad file descriptor passed in."); + return rnb_err; + } + + m_fd = fd; + return rnb_success; } #ifdef WITH_LOCKDOWN -rnb_err_t -RNBSocket::ConnectToService() -{ - DNBLog("Connecting to com.apple.%s service...", DEBUGSERVER_PROGRAM_NAME); - // Disconnect from any previous connections - Disconnect(false); - if (::secure_lockdown_checkin (&m_ld_conn, NULL, NULL) != kLDESuccess) - { - DNBLogThreadedIf(LOG_RNB_COMM, "::secure_lockdown_checkin(&m_fd, NULL, NULL) failed"); - m_fd = -1; - return rnb_not_connected; - } - m_fd = ::lockdown_get_socket (m_ld_conn); - if (m_fd == -1) - { - DNBLogThreadedIf(LOG_RNB_COMM, "::lockdown_get_socket() failed"); - return rnb_not_connected; - } - m_fd_from_lockdown = true; - return rnb_success; +rnb_err_t RNBSocket::ConnectToService() { + DNBLog("Connecting to com.apple.%s service...", DEBUGSERVER_PROGRAM_NAME); + // Disconnect from any previous connections + Disconnect(false); + if (::secure_lockdown_checkin(&m_ld_conn, NULL, NULL) != kLDESuccess) { + DNBLogThreadedIf(LOG_RNB_COMM, + "::secure_lockdown_checkin(&m_fd, NULL, NULL) failed"); + m_fd = -1; + return rnb_not_connected; + } + m_fd = ::lockdown_get_socket(m_ld_conn); + if (m_fd == -1) { + DNBLogThreadedIf(LOG_RNB_COMM, "::lockdown_get_socket() failed"); + return rnb_not_connected; + } + m_fd_from_lockdown = true; + return rnb_success; } #endif -rnb_err_t -RNBSocket::OpenFile (const char *path) -{ - DNBError err; - m_fd = open (path, O_RDWR); - if (m_fd == -1) - { - err.SetError(errno, DNBError::POSIX); - err.LogThreaded ("can't open file '%s'", path); - return rnb_not_connected; +rnb_err_t RNBSocket::OpenFile(const char *path) { + DNBError err; + m_fd = open(path, O_RDWR); + if (m_fd == -1) { + err.SetError(errno, DNBError::POSIX); + err.LogThreaded("can't open file '%s'", path); + return rnb_not_connected; + } else { + struct termios stdin_termios; + + if (::tcgetattr(m_fd, &stdin_termios) == 0) { + stdin_termios.c_lflag &= ~ECHO; // Turn off echoing + stdin_termios.c_lflag &= ~ICANON; // Get one char at a time + ::tcsetattr(m_fd, TCSANOW, &stdin_termios); } - else - { - struct termios stdin_termios; - - if (::tcgetattr (m_fd, &stdin_termios) == 0) - { - stdin_termios.c_lflag &= ~ECHO; // Turn off echoing - stdin_termios.c_lflag &= ~ICANON; // Get one char at a time - ::tcsetattr (m_fd, TCSANOW, &stdin_termios); - } - } - return rnb_success; + } + return rnb_success; } -int -RNBSocket::SetSocketOption(int fd, int level, int option_name, int option_value) -{ - return ::setsockopt(fd, level, option_name, &option_value, sizeof(option_value)); +int RNBSocket::SetSocketOption(int fd, int level, int option_name, + int option_value) { + return ::setsockopt(fd, level, option_name, &option_value, + sizeof(option_value)); } -rnb_err_t -RNBSocket::Disconnect (bool save_errno) -{ +rnb_err_t RNBSocket::Disconnect(bool save_errno) { #ifdef WITH_LOCKDOWN - if (m_fd_from_lockdown) - { - m_fd_from_lockdown = false; - m_fd = -1; - lockdown_disconnect (m_ld_conn); - return rnb_success; - } + if (m_fd_from_lockdown) { + m_fd_from_lockdown = false; + m_fd = -1; + lockdown_disconnect(m_ld_conn); + return rnb_success; + } #endif - return ClosePort (m_fd, save_errno); + return ClosePort(m_fd, save_errno); } - -rnb_err_t -RNBSocket::Read (std::string &p) -{ - char buf[1024]; - p.clear(); - - // Note that BUF is on the stack so we must be careful to keep any - // writes to BUF from overflowing or we'll have security issues. - - if (m_fd == -1) - return rnb_err; - - //DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s calling read()", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); - DNBError err; - ssize_t bytesread = read (m_fd, buf, sizeof (buf)); - if (bytesread <= 0) - err.SetError(errno, DNBError::POSIX); - else - p.append(buf, bytesread); - - if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) - err.LogThreaded("::read ( %i, %p, %llu ) => %i", m_fd, buf, sizeof (buf), (uint64_t)bytesread); - - // Our port went away - we have to mark this so IsConnected will return the truth. - if (bytesread == 0) - { - m_fd = -1; - return rnb_not_connected; - } - else if (bytesread == -1) - { - m_fd = -1; - return rnb_err; - } - // Strip spaces from the end of the buffer - while (!p.empty() && isspace (p[p.size() - 1])) - p.erase (p.size () - 1); - - // Most data in the debugserver packets valid printable characters... - DNBLogThreadedIf(LOG_RNB_COMM, "read: %s", p.c_str()); - return rnb_success; +rnb_err_t RNBSocket::Read(std::string &p) { + char buf[1024]; + p.clear(); + + // Note that BUF is on the stack so we must be careful to keep any + // writes to BUF from overflowing or we'll have security issues. + + if (m_fd == -1) + return rnb_err; + + // DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s calling read()", + // (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__); + DNBError err; + ssize_t bytesread = read(m_fd, buf, sizeof(buf)); + if (bytesread <= 0) + err.SetError(errno, DNBError::POSIX); + else + p.append(buf, bytesread); + + if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) + err.LogThreaded("::read ( %i, %p, %llu ) => %i", m_fd, buf, sizeof(buf), + (uint64_t)bytesread); + + // Our port went away - we have to mark this so IsConnected will return the + // truth. + if (bytesread == 0) { + m_fd = -1; + return rnb_not_connected; + } else if (bytesread == -1) { + m_fd = -1; + return rnb_err; + } + // Strip spaces from the end of the buffer + while (!p.empty() && isspace(p[p.size() - 1])) + p.erase(p.size() - 1); + + // Most data in the debugserver packets valid printable characters... + DNBLogThreadedIf(LOG_RNB_COMM, "read: %s", p.c_str()); + return rnb_success; } -rnb_err_t -RNBSocket::Write (const void *buffer, size_t length) -{ - if (m_fd == -1) - return rnb_err; +rnb_err_t RNBSocket::Write(const void *buffer, size_t length) { + if (m_fd == -1) + return rnb_err; - DNBError err; - ssize_t bytessent = write (m_fd, buffer, length); - if (bytessent < 0) - err.SetError(errno, DNBError::POSIX); + DNBError err; + ssize_t bytessent = write(m_fd, buffer, length); + if (bytessent < 0) + err.SetError(errno, DNBError::POSIX); - if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) - err.LogThreaded("::write ( socket = %i, buffer = %p, length = %llu) => %i", m_fd, buffer, length, (uint64_t)bytessent); + if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM)) + err.LogThreaded("::write ( socket = %i, buffer = %p, length = %llu) => %i", + m_fd, buffer, length, (uint64_t)bytessent); - if (bytessent < 0) - return rnb_err; + if (bytessent < 0) + return rnb_err; - if ((size_t)bytessent != length) - return rnb_err; + if ((size_t)bytessent != length) + return rnb_err; - DNBLogThreadedIf(LOG_RNB_PACKETS, "putpkt: %*s", (int)length, (char *)buffer); // All data is string based in debugserver, so this is safe - DNBLogThreadedIf(LOG_RNB_COMM, "sent: %*s", (int)length, (char *)buffer); + DNBLogThreadedIf( + LOG_RNB_PACKETS, "putpkt: %*s", (int)length, + (char *) + buffer); // All data is string based in debugserver, so this is safe + DNBLogThreadedIf(LOG_RNB_COMM, "sent: %*s", (int)length, (char *)buffer); - return rnb_success; + return rnb_success; } - -rnb_err_t -RNBSocket::ClosePort (int& fd, bool save_errno) -{ - int close_err = 0; - if (fd > 0) - { - errno = 0; - close_err = close (fd); - fd = -1; - } - return close_err != 0 ? rnb_err : rnb_success; +rnb_err_t RNBSocket::ClosePort(int &fd, bool save_errno) { + int close_err = 0; + if (fd > 0) { + errno = 0; + close_err = close(fd); + fd = -1; + } + return close_err != 0 ? rnb_err : rnb_success; } - - diff --git a/lldb/tools/debugserver/source/RNBSocket.h b/lldb/tools/debugserver/source/RNBSocket.h index 32f4ebeed2a..9f636d85562 100644 --- a/lldb/tools/debugserver/source/RNBSocket.h +++ b/lldb/tools/debugserver/source/RNBSocket.h @@ -14,72 +14,66 @@ #ifndef __RNBSocket_h__ #define __RNBSocket_h__ +#include "DNBTimer.h" #include "RNBDefs.h" +#include <string> #include <sys/socket.h> #include <sys/types.h> -#include <string> -#include "DNBTimer.h" #ifdef WITH_LOCKDOWN #include "lockdown.h" #endif -class RNBSocket -{ +class RNBSocket { public: - typedef void (*PortBoundCallback) (const void *baton, uint16_t port); + typedef void (*PortBoundCallback)(const void *baton, uint16_t port); - RNBSocket () : - m_fd (-1), + RNBSocket() + : m_fd(-1), #ifdef WITH_LOCKDOWN - m_fd_from_lockdown (false), - m_ld_conn (), + m_fd_from_lockdown(false), m_ld_conn(), #endif - m_timer (true) // Make a thread safe timer - { - } - ~RNBSocket (void) - { - Disconnect (false); - } - - rnb_err_t Listen (const char *listen_host, - uint16_t port, - PortBoundCallback callback, - const void *callback_baton); - rnb_err_t Connect (const char *host, uint16_t port); - - rnb_err_t useFD(int fd); + m_timer(true) // Make a thread safe timer + { + } + ~RNBSocket(void) { Disconnect(false); } + + rnb_err_t Listen(const char *listen_host, uint16_t port, + PortBoundCallback callback, const void *callback_baton); + rnb_err_t Connect(const char *host, uint16_t port); + + rnb_err_t useFD(int fd); #ifdef WITH_LOCKDOWN - rnb_err_t ConnectToService(); + rnb_err_t ConnectToService(); #endif - rnb_err_t OpenFile (const char *path); - rnb_err_t Disconnect (bool save_errno); - rnb_err_t Read (std::string &p); - rnb_err_t Write (const void *buffer, size_t length); + rnb_err_t OpenFile(const char *path); + rnb_err_t Disconnect(bool save_errno); + rnb_err_t Read(std::string &p); + rnb_err_t Write(const void *buffer, size_t length); - bool IsConnected () const { return m_fd != -1; } - void SaveErrno (int curr_errno); - DNBTimer& Timer() { return m_timer; } + bool IsConnected() const { return m_fd != -1; } + void SaveErrno(int curr_errno); + DNBTimer &Timer() { return m_timer; } + + static int SetSocketOption(int fd, int level, int option_name, + int option_value); - static int SetSocketOption(int fd, int level, int option_name, int option_value); private: - // Outlaw some constructors - RNBSocket (const RNBSocket &); + // Outlaw some constructors + RNBSocket(const RNBSocket &); protected: - rnb_err_t ClosePort (int& fd, bool save_errno); + rnb_err_t ClosePort(int &fd, bool save_errno); - int m_fd; // Socket we use to communicate once conn established + int m_fd; // Socket we use to communicate once conn established #ifdef WITH_LOCKDOWN - bool m_fd_from_lockdown; - lockdown_connection m_ld_conn; + bool m_fd_from_lockdown; + lockdown_connection m_ld_conn; #endif - DNBTimer m_timer; + DNBTimer m_timer; }; - #endif // #ifndef __RNBSocket_h__ diff --git a/lldb/tools/debugserver/source/SysSignal.cpp b/lldb/tools/debugserver/source/SysSignal.cpp index 69f34ed605c..c2995f362c0 100644 --- a/lldb/tools/debugserver/source/SysSignal.cpp +++ b/lldb/tools/debugserver/source/SysSignal.cpp @@ -15,52 +15,81 @@ #include <signal.h> #include <stddef.h> -const char * -SysSignal::Name(int signal) -{ - switch (signal) - { - case SIGHUP: return "SIGHUP"; // 1 hangup - case SIGINT: return "SIGINT"; // 2 interrupt - case SIGQUIT: return "SIGQUIT"; // 3 quit - case SIGILL: return "SIGILL"; // 4 illegal instruction (not reset when caught) - case SIGTRAP: return "SIGTRAP"; // 5 trace trap (not reset when caught) - case SIGABRT: return "SIGABRT"; // 6 abort() -#if defined(_POSIX_C_SOURCE) - case SIGPOLL: return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported) -#else // !_POSIX_C_SOURCE - case SIGEMT: return "SIGEMT"; // 7 EMT instruction -#endif // !_POSIX_C_SOURCE - case SIGFPE: return "SIGFPE"; // 8 floating point exception - case SIGKILL: return "SIGKILL"; // 9 kill (cannot be caught or ignored) - case SIGBUS: return "SIGBUS"; // 10 bus error - case SIGSEGV: return "SIGSEGV"; // 11 segmentation violation - case SIGSYS: return "SIGSYS"; // 12 bad argument to system call - case SIGPIPE: return "SIGPIPE"; // 13 write on a pipe with no one to read it - case SIGALRM: return "SIGALRM"; // 14 alarm clock - case SIGTERM: return "SIGTERM"; // 15 software termination signal from kill - case SIGURG: return "SIGURG"; // 16 urgent condition on IO channel - case SIGSTOP: return "SIGSTOP"; // 17 sendable stop signal not from tty - case SIGTSTP: return "SIGTSTP"; // 18 stop signal from tty - case SIGCONT: return "SIGCONT"; // 19 continue a stopped process - case SIGCHLD: return "SIGCHLD"; // 20 to parent on child stop or exit - case SIGTTIN: return "SIGTTIN"; // 21 to readers pgrp upon background tty read - case SIGTTOU: return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local<OSTOP) -#if !defined(_POSIX_C_SOURCE) - case SIGIO: return "SIGIO"; // 23 input/output possible signal +const char *SysSignal::Name(int signal) { + switch (signal) { + case SIGHUP: + return "SIGHUP"; // 1 hangup + case SIGINT: + return "SIGINT"; // 2 interrupt + case SIGQUIT: + return "SIGQUIT"; // 3 quit + case SIGILL: + return "SIGILL"; // 4 illegal instruction (not reset when caught) + case SIGTRAP: + return "SIGTRAP"; // 5 trace trap (not reset when caught) + case SIGABRT: + return "SIGABRT"; // 6 abort() +#if defined(_POSIX_C_SOURCE) + case SIGPOLL: + return "SIGPOLL"; // 7 pollable event ([XSR] generated, not supported) +#else // !_POSIX_C_SOURCE + case SIGEMT: + return "SIGEMT"; // 7 EMT instruction +#endif // !_POSIX_C_SOURCE + case SIGFPE: + return "SIGFPE"; // 8 floating point exception + case SIGKILL: + return "SIGKILL"; // 9 kill (cannot be caught or ignored) + case SIGBUS: + return "SIGBUS"; // 10 bus error + case SIGSEGV: + return "SIGSEGV"; // 11 segmentation violation + case SIGSYS: + return "SIGSYS"; // 12 bad argument to system call + case SIGPIPE: + return "SIGPIPE"; // 13 write on a pipe with no one to read it + case SIGALRM: + return "SIGALRM"; // 14 alarm clock + case SIGTERM: + return "SIGTERM"; // 15 software termination signal from kill + case SIGURG: + return "SIGURG"; // 16 urgent condition on IO channel + case SIGSTOP: + return "SIGSTOP"; // 17 sendable stop signal not from tty + case SIGTSTP: + return "SIGTSTP"; // 18 stop signal from tty + case SIGCONT: + return "SIGCONT"; // 19 continue a stopped process + case SIGCHLD: + return "SIGCHLD"; // 20 to parent on child stop or exit + case SIGTTIN: + return "SIGTTIN"; // 21 to readers pgrp upon background tty read + case SIGTTOU: + return "SIGTTOU"; // 22 like TTIN for output if (tp->t_local<OSTOP) +#if !defined(_POSIX_C_SOURCE) + case SIGIO: + return "SIGIO"; // 23 input/output possible signal #endif - case SIGXCPU: return "SIGXCPU"; // 24 exceeded CPU time limit - case SIGXFSZ: return "SIGXFSZ"; // 25 exceeded file size limit - case SIGVTALRM: return "SIGVTALRM"; // 26 virtual time alarm - case SIGPROF: return "SIGPROF"; // 27 profiling time alarm -#if !defined(_POSIX_C_SOURCE) - case SIGWINCH: return "SIGWINCH"; // 28 window size changes - case SIGINFO: return "SIGINFO"; // 29 information request + case SIGXCPU: + return "SIGXCPU"; // 24 exceeded CPU time limit + case SIGXFSZ: + return "SIGXFSZ"; // 25 exceeded file size limit + case SIGVTALRM: + return "SIGVTALRM"; // 26 virtual time alarm + case SIGPROF: + return "SIGPROF"; // 27 profiling time alarm +#if !defined(_POSIX_C_SOURCE) + case SIGWINCH: + return "SIGWINCH"; // 28 window size changes + case SIGINFO: + return "SIGINFO"; // 29 information request #endif - case SIGUSR1: return "SIGUSR1"; // 30 user defined signal 1 - case SIGUSR2: return "SIGUSR2"; // 31 user defined signal 2 - default: - break; - } - return NULL; + case SIGUSR1: + return "SIGUSR1"; // 30 user defined signal 1 + case SIGUSR2: + return "SIGUSR2"; // 31 user defined signal 2 + default: + break; + } + return NULL; } diff --git a/lldb/tools/debugserver/source/SysSignal.h b/lldb/tools/debugserver/source/SysSignal.h index 438d137f310..c9827126c18 100644 --- a/lldb/tools/debugserver/source/SysSignal.h +++ b/lldb/tools/debugserver/source/SysSignal.h @@ -14,10 +14,9 @@ #ifndef __SysSignal_h__ #define __SysSignal_h__ -class SysSignal -{ +class SysSignal { public: - static const char *Name(int signal); + static const char *Name(int signal); }; #endif diff --git a/lldb/tools/debugserver/source/TTYState.cpp b/lldb/tools/debugserver/source/TTYState.cpp index 28bc956dc28..5f10050fcdd 100644 --- a/lldb/tools/debugserver/source/TTYState.cpp +++ b/lldb/tools/debugserver/source/TTYState.cpp @@ -13,110 +13,82 @@ #include "TTYState.h" #include <fcntl.h> -#include <unistd.h> #include <sys/signal.h> +#include <unistd.h> -TTYState::TTYState() : - m_fd(-1), - m_tflags(-1), - m_ttystateErr(-1), - m_processGroup(-1) -{ -} +TTYState::TTYState() + : m_fd(-1), m_tflags(-1), m_ttystateErr(-1), m_processGroup(-1) {} -TTYState::~TTYState() -{ -} +TTYState::~TTYState() {} -bool -TTYState::GetTTYState (int fd, bool saveProcessGroup) -{ - if (fd >= 0 && ::isatty (fd)) - { - m_fd = fd; - m_tflags = fcntl (fd, F_GETFL, 0); - m_ttystateErr = tcgetattr (fd, &m_ttystate); - if (saveProcessGroup) - m_processGroup = tcgetpgrp (0); - else - m_processGroup = -1; - } +bool TTYState::GetTTYState(int fd, bool saveProcessGroup) { + if (fd >= 0 && ::isatty(fd)) { + m_fd = fd; + m_tflags = fcntl(fd, F_GETFL, 0); + m_ttystateErr = tcgetattr(fd, &m_ttystate); + if (saveProcessGroup) + m_processGroup = tcgetpgrp(0); else - { - m_fd = -1; - m_tflags = -1; - m_ttystateErr = -1; - m_processGroup = -1; - } - return m_ttystateErr == 0; + m_processGroup = -1; + } else { + m_fd = -1; + m_tflags = -1; + m_ttystateErr = -1; + m_processGroup = -1; + } + return m_ttystateErr == 0; } -bool -TTYState::SetTTYState () const -{ - int result = 0; - if (IsValid()) - { - if (TFlagsValid()) - result = fcntl (m_fd, F_SETFL, m_tflags); - - if (TTYStateValid()) - result = tcsetattr (m_fd, TCSANOW, &m_ttystate); - - if (ProcessGroupValid()) - { - // Save the original signal handler. - void (*saved_sigttou_callback) (int) = NULL; - saved_sigttou_callback = (void (*)(int)) signal (SIGTTOU, SIG_IGN); - // Set the process group - result = tcsetpgrp (m_fd, m_processGroup); - // Restore the original signal handler. - signal (SIGTTOU, saved_sigttou_callback); - } - return true; +bool TTYState::SetTTYState() const { + int result = 0; + if (IsValid()) { + if (TFlagsValid()) + result = fcntl(m_fd, F_SETFL, m_tflags); + + if (TTYStateValid()) + result = tcsetattr(m_fd, TCSANOW, &m_ttystate); + + if (ProcessGroupValid()) { + // Save the original signal handler. + void (*saved_sigttou_callback)(int) = NULL; + saved_sigttou_callback = (void (*)(int))signal(SIGTTOU, SIG_IGN); + // Set the process group + result = tcsetpgrp(m_fd, m_processGroup); + // Restore the original signal handler. + signal(SIGTTOU, saved_sigttou_callback); } - return false; + return true; + } + return false; } +TTYStateSwitcher::TTYStateSwitcher() : m_currentState(~0) {} +TTYStateSwitcher::~TTYStateSwitcher() {} -TTYStateSwitcher::TTYStateSwitcher() : - m_currentState(~0) -{ +bool TTYStateSwitcher::GetState(uint32_t idx, int fd, bool saveProcessGroup) { + if (ValidStateIndex(idx)) + return m_ttystates[idx].GetTTYState(fd, saveProcessGroup); + return false; } -TTYStateSwitcher::~TTYStateSwitcher() -{ -} - -bool -TTYStateSwitcher::GetState(uint32_t idx, int fd, bool saveProcessGroup) -{ - if (ValidStateIndex(idx)) - return m_ttystates[idx].GetTTYState(fd, saveProcessGroup); +bool TTYStateSwitcher::SetState(uint32_t idx) const { + if (!ValidStateIndex(idx)) return false; -} - -bool -TTYStateSwitcher::SetState(uint32_t idx) const -{ - if (!ValidStateIndex(idx)) - return false; - - // See if we already are in this state? - if (ValidStateIndex(m_currentState) && (idx == m_currentState) && m_ttystates[idx].IsValid()) - return true; - // Set the state to match the index passed in and only update the - // current state if there are no errors. - if (m_ttystates[idx].SetTTYState()) - { - m_currentState = idx; - return true; - } - - // We failed to set the state. The tty state was invalid or not - // initialized. - return false; + // See if we already are in this state? + if (ValidStateIndex(m_currentState) && (idx == m_currentState) && + m_ttystates[idx].IsValid()) + return true; + + // Set the state to match the index passed in and only update the + // current state if there are no errors. + if (m_ttystates[idx].SetTTYState()) { + m_currentState = idx; + return true; + } + + // We failed to set the state. The tty state was invalid or not + // initialized. + return false; } - diff --git a/lldb/tools/debugserver/source/TTYState.h b/lldb/tools/debugserver/source/TTYState.h index c01d5125543..ab34015e1a4 100644 --- a/lldb/tools/debugserver/source/TTYState.h +++ b/lldb/tools/debugserver/source/TTYState.h @@ -14,48 +14,46 @@ #ifndef __TTYState_h__ #define __TTYState_h__ -#include <termios.h> #include <stdint.h> +#include <termios.h> -class TTYState -{ +class TTYState { public: - TTYState(); - ~TTYState(); + TTYState(); + ~TTYState(); - bool GetTTYState (int fd, bool saveProcessGroup); - bool SetTTYState () const; + bool GetTTYState(int fd, bool saveProcessGroup); + bool SetTTYState() const; - bool IsValid() const { return FileDescriptorValid() && TFlagsValid() && TTYStateValid(); } - bool FileDescriptorValid() const { return m_fd >= 0; } - bool TFlagsValid() const { return m_tflags != -1; } - bool TTYStateValid() const { return m_ttystateErr == 0; } - bool ProcessGroupValid() const { return m_processGroup != -1; } + bool IsValid() const { + return FileDescriptorValid() && TFlagsValid() && TTYStateValid(); + } + bool FileDescriptorValid() const { return m_fd >= 0; } + bool TFlagsValid() const { return m_tflags != -1; } + bool TTYStateValid() const { return m_ttystateErr == 0; } + bool ProcessGroupValid() const { return m_processGroup != -1; } protected: - int m_fd; // File descriptor - int m_tflags; - int m_ttystateErr; - struct termios m_ttystate; - pid_t m_processGroup; - + int m_fd; // File descriptor + int m_tflags; + int m_ttystateErr; + struct termios m_ttystate; + pid_t m_processGroup; }; - -class TTYStateSwitcher -{ +class TTYStateSwitcher { public: - TTYStateSwitcher(); - ~TTYStateSwitcher(); + TTYStateSwitcher(); + ~TTYStateSwitcher(); - bool GetState(uint32_t idx, int fd, bool saveProcessGroup); - bool SetState(uint32_t idx) const; - uint32_t NumStates() const { return sizeof(m_ttystates)/sizeof(TTYState); } - bool ValidStateIndex(uint32_t idx) const { return idx < NumStates(); } + bool GetState(uint32_t idx, int fd, bool saveProcessGroup); + bool SetState(uint32_t idx) const; + uint32_t NumStates() const { return sizeof(m_ttystates) / sizeof(TTYState); } + bool ValidStateIndex(uint32_t idx) const { return idx < NumStates(); } protected: - mutable uint32_t m_currentState; - TTYState m_ttystates[2]; + mutable uint32_t m_currentState; + TTYState m_ttystates[2]; }; #endif
\ No newline at end of file diff --git a/lldb/tools/debugserver/source/debugserver.cpp b/lldb/tools/debugserver/source/debugserver.cpp index e1ee2c12131..0cb72f4ece4 100644 --- a/lldb/tools/debugserver/source/debugserver.cpp +++ b/lldb/tools/debugserver/source/debugserver.cpp @@ -7,27 +7,28 @@ // //===----------------------------------------------------------------------===// -#include <sys/socket.h> -#include <sys/types.h> +#include <arpa/inet.h> +#include <asl.h> +#include <crt_externs.h> // for _NSGetEnviron() #include <errno.h> #include <getopt.h> -#include <netinet/in.h> -#include <sys/select.h> -#include <sys/sysctl.h> -#include <string> -#include <vector> -#include <asl.h> -#include <arpa/inet.h> #include <netdb.h> #include <netinet/in.h> +#include <netinet/in.h> #include <netinet/tcp.h> -#include <sys/un.h> +#include <string> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/sysctl.h> #include <sys/types.h> -#include <crt_externs.h> // for _NSGetEnviron() +#include <sys/types.h> +#include <sys/un.h> +#include <vector> -#if defined (__APPLE__) +#if defined(__APPLE__) #include <sched.h> -extern "C" int proc_set_wakemon_params(pid_t, int, int); // <libproc_internal.h> SPI +extern "C" int proc_set_wakemon_params(pid_t, int, + int); // <libproc_internal.h> SPI #endif #include "CFString.h" @@ -37,9 +38,9 @@ extern "C" int proc_set_wakemon_params(pid_t, int, int); // <libproc_internal.h> #include "OsLogger.h" #include "PseudoTerminal.h" #include "RNBContext.h" +#include "RNBRemote.h" #include "RNBServices.h" #include "RNBSocket.h" -#include "RNBRemote.h" #include "SysSignal.h" // Global PID in case we get a signal and need to stop the process... @@ -48,23 +49,21 @@ nub_process_t g_pid = INVALID_NUB_PROCESS; //---------------------------------------------------------------------- // Run loop modes which determine which run loop function will be called //---------------------------------------------------------------------- -typedef enum -{ - eRNBRunLoopModeInvalid = 0, - eRNBRunLoopModeGetStartModeFromRemoteProtocol, - eRNBRunLoopModeInferiorAttaching, - eRNBRunLoopModeInferiorLaunching, - eRNBRunLoopModeInferiorExecuting, - eRNBRunLoopModePlatformMode, - eRNBRunLoopModeExit +typedef enum { + eRNBRunLoopModeInvalid = 0, + eRNBRunLoopModeGetStartModeFromRemoteProtocol, + eRNBRunLoopModeInferiorAttaching, + eRNBRunLoopModeInferiorLaunching, + eRNBRunLoopModeInferiorExecuting, + eRNBRunLoopModePlatformMode, + eRNBRunLoopModeExit } RNBRunLoopMode; - //---------------------------------------------------------------------- // Global Variables //---------------------------------------------------------------------- RNBRemoteSP g_remoteSP; -static int g_lockdown_opt = 0; +static int g_lockdown_opt = 0; static int g_applist_opt = 0; static nub_launch_flavor_t g_launch_flavor = eLaunchFlavorDefault; int g_disable_aslr = 0; @@ -72,8 +71,22 @@ int g_disable_aslr = 0; int g_isatty = 0; bool g_detach_on_error = true; -#define RNBLogSTDOUT(fmt, ...) do { if (g_isatty) { fprintf(stdout, fmt, ## __VA_ARGS__); } else { _DNBLog(0, fmt, ## __VA_ARGS__); } } while (0) -#define RNBLogSTDERR(fmt, ...) do { if (g_isatty) { fprintf(stderr, fmt, ## __VA_ARGS__); } else { _DNBLog(0, fmt, ## __VA_ARGS__); } } while (0) +#define RNBLogSTDOUT(fmt, ...) \ + do { \ + if (g_isatty) { \ + fprintf(stdout, fmt, ##__VA_ARGS__); \ + } else { \ + _DNBLog(0, fmt, ##__VA_ARGS__); \ + } \ + } while (0) +#define RNBLogSTDERR(fmt, ...) \ + do { \ + if (g_isatty) { \ + fprintf(stderr, fmt, ##__VA_ARGS__); \ + } else { \ + _DNBLog(0, fmt, ##__VA_ARGS__); \ + } \ + } while (0) //---------------------------------------------------------------------- // Get our program path and arguments from the remote connection. @@ -81,306 +94,290 @@ bool g_detach_on_error = true; // arguments, wait for the new process to finish launching and hit its // entry point, and then return the run loop mode that should come next. //---------------------------------------------------------------------- -RNBRunLoopMode -RNBRunLoopGetStartModeFromRemote (RNBRemote* remote) -{ - std::string packet; - - if (remote) - { - RNBContext& ctx = remote->Context(); - uint32_t event_mask = RNBContext::event_read_packet_available | - RNBContext::event_read_thread_exiting; - - // Spin waiting to get the A packet. - while (1) - { - DNBLogThreadedIf (LOG_RNB_MAX, "%s ctx.Events().WaitForSetEvents( 0x%08x ) ...",__FUNCTION__, event_mask); - nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); - DNBLogThreadedIf (LOG_RNB_MAX, "%s ctx.Events().WaitForSetEvents( 0x%08x ) => 0x%08x", __FUNCTION__, event_mask, set_events); - - if (set_events & RNBContext::event_read_thread_exiting) - { - RNBLogSTDERR ("error: packet read thread exited.\n"); - return eRNBRunLoopModeExit; - } +RNBRunLoopMode RNBRunLoopGetStartModeFromRemote(RNBRemote *remote) { + std::string packet; + + if (remote) { + RNBContext &ctx = remote->Context(); + uint32_t event_mask = RNBContext::event_read_packet_available | + RNBContext::event_read_thread_exiting; + + // Spin waiting to get the A packet. + while (1) { + DNBLogThreadedIf(LOG_RNB_MAX, + "%s ctx.Events().WaitForSetEvents( 0x%08x ) ...", + __FUNCTION__, event_mask); + nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); + DNBLogThreadedIf(LOG_RNB_MAX, + "%s ctx.Events().WaitForSetEvents( 0x%08x ) => 0x%08x", + __FUNCTION__, event_mask, set_events); + + if (set_events & RNBContext::event_read_thread_exiting) { + RNBLogSTDERR("error: packet read thread exited.\n"); + return eRNBRunLoopModeExit; + } - if (set_events & RNBContext::event_read_packet_available) - { - rnb_err_t err = rnb_err; - RNBRemote::PacketEnum type; - - err = remote->HandleReceivedPacket (&type); - - // check if we tried to attach to a process - if (type == RNBRemote::vattach || type == RNBRemote::vattachwait || type == RNBRemote::vattachorwait) - { - if (err == rnb_success) - { - RNBLogSTDOUT ("Attach succeeded, ready to debug.\n"); - return eRNBRunLoopModeInferiorExecuting; - } - else - { - RNBLogSTDERR ("error: attach failed.\n"); - return eRNBRunLoopModeExit; - } - } - - if (err == rnb_success) - { - // If we got our arguments we are ready to launch using the arguments - // and any environment variables we received. - if (type == RNBRemote::set_argv) - { - return eRNBRunLoopModeInferiorLaunching; - } - } - else if (err == rnb_not_connected) - { - RNBLogSTDERR ("error: connection lost.\n"); - return eRNBRunLoopModeExit; - } - else - { - // a catch all for any other gdb remote packets that failed - DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Error getting packet.",__FUNCTION__); - continue; - } - - DNBLogThreadedIf (LOG_RNB_MINIMAL, "#### %s", __FUNCTION__); - } - else - { - DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Connection closed before getting \"A\" packet.", __FUNCTION__); - return eRNBRunLoopModeExit; - } + if (set_events & RNBContext::event_read_packet_available) { + rnb_err_t err = rnb_err; + RNBRemote::PacketEnum type; + + err = remote->HandleReceivedPacket(&type); + + // check if we tried to attach to a process + if (type == RNBRemote::vattach || type == RNBRemote::vattachwait || + type == RNBRemote::vattachorwait) { + if (err == rnb_success) { + RNBLogSTDOUT("Attach succeeded, ready to debug.\n"); + return eRNBRunLoopModeInferiorExecuting; + } else { + RNBLogSTDERR("error: attach failed.\n"); + return eRNBRunLoopModeExit; + } } + + if (err == rnb_success) { + // If we got our arguments we are ready to launch using the arguments + // and any environment variables we received. + if (type == RNBRemote::set_argv) { + return eRNBRunLoopModeInferiorLaunching; + } + } else if (err == rnb_not_connected) { + RNBLogSTDERR("error: connection lost.\n"); + return eRNBRunLoopModeExit; + } else { + // a catch all for any other gdb remote packets that failed + DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s Error getting packet.", + __FUNCTION__); + continue; + } + + DNBLogThreadedIf(LOG_RNB_MINIMAL, "#### %s", __FUNCTION__); + } else { + DNBLogThreadedIf(LOG_RNB_MINIMAL, + "%s Connection closed before getting \"A\" packet.", + __FUNCTION__); + return eRNBRunLoopModeExit; + } } - return eRNBRunLoopModeExit; + } + return eRNBRunLoopModeExit; } - //---------------------------------------------------------------------- // This run loop mode will wait for the process to launch and hit its // entry point. It will currently ignore all events except for the // process state changed event, where it watches for the process stopped // or crash process state. //---------------------------------------------------------------------- -RNBRunLoopMode -RNBRunLoopLaunchInferior (RNBRemote *remote, const char *stdin_path, const char *stdout_path, const char *stderr_path, bool no_stdio) -{ - RNBContext& ctx = remote->Context(); +RNBRunLoopMode RNBRunLoopLaunchInferior(RNBRemote *remote, + const char *stdin_path, + const char *stdout_path, + const char *stderr_path, + bool no_stdio) { + RNBContext &ctx = remote->Context(); - // The Process stuff takes a c array, the RNBContext has a vector... - // So make up a c array. + // The Process stuff takes a c array, the RNBContext has a vector... + // So make up a c array. - DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Launching '%s'...", __FUNCTION__, ctx.ArgumentAtIndex(0)); + DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s Launching '%s'...", __FUNCTION__, + ctx.ArgumentAtIndex(0)); - size_t inferior_argc = ctx.ArgumentCount(); - // Initialize inferior_argv with inferior_argc + 1 NULLs - std::vector<const char *> inferior_argv(inferior_argc + 1, NULL); + size_t inferior_argc = ctx.ArgumentCount(); + // Initialize inferior_argv with inferior_argc + 1 NULLs + std::vector<const char *> inferior_argv(inferior_argc + 1, NULL); - size_t i; - for (i = 0; i < inferior_argc; i++) - inferior_argv[i] = ctx.ArgumentAtIndex(i); + size_t i; + for (i = 0; i < inferior_argc; i++) + inferior_argv[i] = ctx.ArgumentAtIndex(i); - // Pass the environment array the same way: + // Pass the environment array the same way: - size_t inferior_envc = ctx.EnvironmentCount(); - // Initialize inferior_argv with inferior_argc + 1 NULLs - std::vector<const char *> inferior_envp(inferior_envc + 1, NULL); + size_t inferior_envc = ctx.EnvironmentCount(); + // Initialize inferior_argv with inferior_argc + 1 NULLs + std::vector<const char *> inferior_envp(inferior_envc + 1, NULL); - for (i = 0; i < inferior_envc; i++) - inferior_envp[i] = ctx.EnvironmentAtIndex(i); + for (i = 0; i < inferior_envc; i++) + inferior_envp[i] = ctx.EnvironmentAtIndex(i); - // Our launch type hasn't been set to anything concrete, so we need to - // figure our how we are going to launch automatically. + // Our launch type hasn't been set to anything concrete, so we need to + // figure our how we are going to launch automatically. - nub_launch_flavor_t launch_flavor = g_launch_flavor; - if (launch_flavor == eLaunchFlavorDefault) - { - // Our default launch method is posix spawn - launch_flavor = eLaunchFlavorPosixSpawn; + nub_launch_flavor_t launch_flavor = g_launch_flavor; + if (launch_flavor == eLaunchFlavorDefault) { + // Our default launch method is posix spawn + launch_flavor = eLaunchFlavorPosixSpawn; #if defined WITH_FBS - // Check if we have an app bundle, if so launch using BackBoard Services. - if (strstr(inferior_argv[0], ".app")) - { - launch_flavor = eLaunchFlavorFBS; - } -#elif defined WITH_BKS - // Check if we have an app bundle, if so launch using BackBoard Services. - if (strstr(inferior_argv[0], ".app")) - { - launch_flavor = eLaunchFlavorBKS; - } -#elif defined WITH_SPRINGBOARD - // Check if we have an app bundle, if so launch using SpringBoard. - if (strstr(inferior_argv[0], ".app")) - { - launch_flavor = eLaunchFlavorSpringBoard; - } -#endif + // Check if we have an app bundle, if so launch using BackBoard Services. + if (strstr(inferior_argv[0], ".app")) { + launch_flavor = eLaunchFlavorFBS; } - - ctx.SetLaunchFlavor(launch_flavor); - char resolved_path[PATH_MAX]; - - // If we fail to resolve the path to our executable, then just use what we - // were given and hope for the best - if ( !DNBResolveExecutablePath (inferior_argv[0], resolved_path, sizeof(resolved_path)) ) - ::strncpy(resolved_path, inferior_argv[0], sizeof(resolved_path)); - - char launch_err_str[PATH_MAX]; - launch_err_str[0] = '\0'; - const char * cwd = (ctx.GetWorkingDirPath() != NULL ? ctx.GetWorkingDirPath() - : ctx.GetWorkingDirectory()); - const char *process_event = ctx.GetProcessEvent(); - nub_process_t pid = DNBProcessLaunch (resolved_path, - &inferior_argv[0], - &inferior_envp[0], - cwd, - stdin_path, - stdout_path, - stderr_path, - no_stdio, - launch_flavor, - g_disable_aslr, - process_event, - launch_err_str, - sizeof(launch_err_str)); - - g_pid = pid; - - if (pid == INVALID_NUB_PROCESS && strlen (launch_err_str) > 0) - { - DNBLogThreaded ("%s DNBProcessLaunch() returned error: '%s'", __FUNCTION__, launch_err_str); - ctx.LaunchStatus().SetError(-1, DNBError::Generic); - ctx.LaunchStatus().SetErrorString(launch_err_str); +#elif defined WITH_BKS + // Check if we have an app bundle, if so launch using BackBoard Services. + if (strstr(inferior_argv[0], ".app")) { + launch_flavor = eLaunchFlavorBKS; } - else if (pid == INVALID_NUB_PROCESS) - { - DNBLogThreaded ("%s DNBProcessLaunch() failed to launch process, unknown failure", __FUNCTION__); - ctx.LaunchStatus().SetError(-1, DNBError::Generic); - ctx.LaunchStatus().SetErrorString("<unknown failure>"); +#elif defined WITH_SPRINGBOARD + // Check if we have an app bundle, if so launch using SpringBoard. + if (strstr(inferior_argv[0], ".app")) { + launch_flavor = eLaunchFlavorSpringBoard; } - else - { - ctx.LaunchStatus().Clear(); +#endif + } + + ctx.SetLaunchFlavor(launch_flavor); + char resolved_path[PATH_MAX]; + + // If we fail to resolve the path to our executable, then just use what we + // were given and hope for the best + if (!DNBResolveExecutablePath(inferior_argv[0], resolved_path, + sizeof(resolved_path))) + ::strncpy(resolved_path, inferior_argv[0], sizeof(resolved_path)); + + char launch_err_str[PATH_MAX]; + launch_err_str[0] = '\0'; + const char *cwd = + (ctx.GetWorkingDirPath() != NULL ? ctx.GetWorkingDirPath() + : ctx.GetWorkingDirectory()); + const char *process_event = ctx.GetProcessEvent(); + nub_process_t pid = DNBProcessLaunch( + resolved_path, &inferior_argv[0], &inferior_envp[0], cwd, stdin_path, + stdout_path, stderr_path, no_stdio, launch_flavor, g_disable_aslr, + process_event, launch_err_str, sizeof(launch_err_str)); + + g_pid = pid; + + if (pid == INVALID_NUB_PROCESS && strlen(launch_err_str) > 0) { + DNBLogThreaded("%s DNBProcessLaunch() returned error: '%s'", __FUNCTION__, + launch_err_str); + ctx.LaunchStatus().SetError(-1, DNBError::Generic); + ctx.LaunchStatus().SetErrorString(launch_err_str); + } else if (pid == INVALID_NUB_PROCESS) { + DNBLogThreaded( + "%s DNBProcessLaunch() failed to launch process, unknown failure", + __FUNCTION__); + ctx.LaunchStatus().SetError(-1, DNBError::Generic); + ctx.LaunchStatus().SetErrorString("<unknown failure>"); + } else { + ctx.LaunchStatus().Clear(); + } + + if (remote->Comm().IsConnected()) { + // It we are connected already, the next thing gdb will do is ask + // whether the launch succeeded, and if not, whether there is an + // error code. So we need to fetch one packet from gdb before we wait + // on the stop from the target. + + uint32_t event_mask = RNBContext::event_read_packet_available; + nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); + + if (set_events & RNBContext::event_read_packet_available) { + rnb_err_t err = rnb_err; + RNBRemote::PacketEnum type; + + err = remote->HandleReceivedPacket(&type); + + if (err != rnb_success) { + DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s Error getting packet.", + __FUNCTION__); + return eRNBRunLoopModeExit; + } + if (type != RNBRemote::query_launch_success) { + DNBLogThreadedIf(LOG_RNB_MINIMAL, + "%s Didn't get the expected qLaunchSuccess packet.", + __FUNCTION__); + } } + } + + while (pid != INVALID_NUB_PROCESS) { + // Wait for process to start up and hit entry point + DNBLogThreadedIf(LOG_RNB_EVENTS, "%s DNBProcessWaitForEvent (%4.4x, " + "eEventProcessRunningStateChanged | " + "eEventProcessStoppedStateChanged, true, " + "INFINITE)...", + __FUNCTION__, pid); + nub_event_t set_events = + DNBProcessWaitForEvents(pid, eEventProcessRunningStateChanged | + eEventProcessStoppedStateChanged, + true, NULL); + DNBLogThreadedIf(LOG_RNB_EVENTS, "%s DNBProcessWaitForEvent (%4.4x, " + "eEventProcessRunningStateChanged | " + "eEventProcessStoppedStateChanged, true, " + "INFINITE) => 0x%8.8x", + __FUNCTION__, pid, set_events); + + if (set_events == 0) { + pid = INVALID_NUB_PROCESS; + g_pid = pid; + } else { + if (set_events & (eEventProcessRunningStateChanged | + eEventProcessStoppedStateChanged)) { + nub_state_t pid_state = DNBProcessGetState(pid); + DNBLogThreadedIf( + LOG_RNB_EVENTS, + "%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 - if (remote->Comm().IsConnected()) - { - // It we are connected already, the next thing gdb will do is ask - // whether the launch succeeded, and if not, whether there is an - // error code. So we need to fetch one packet from gdb before we wait - // on the stop from the target. - - uint32_t event_mask = RNBContext::event_read_packet_available; - nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); - - if (set_events & RNBContext::event_read_packet_available) - { - rnb_err_t err = rnb_err; - RNBRemote::PacketEnum type; - - err = remote->HandleReceivedPacket (&type); + case eStateRunning: + case eStateStepping: + // Still waiting to stop at entry point... + break; - if (err != rnb_success) - { - DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Error getting packet.", __FUNCTION__); - return eRNBRunLoopModeExit; - } - if (type != RNBRemote::query_launch_success) - { - DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Didn't get the expected qLaunchSuccess packet.", __FUNCTION__); - } - } - } + case eStateStopped: + case eStateCrashed: + ctx.SetProcessID(pid); + return eRNBRunLoopModeInferiorExecuting; - while (pid != INVALID_NUB_PROCESS) - { - // Wait for process to start up and hit entry point - DNBLogThreadedIf (LOG_RNB_EVENTS, "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE)...", __FUNCTION__, pid); - nub_event_t set_events = DNBProcessWaitForEvents (pid, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, NULL); - DNBLogThreadedIf (LOG_RNB_EVENTS, "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE) => 0x%8.8x", __FUNCTION__, pid, set_events); - - if (set_events == 0) - { - pid = INVALID_NUB_PROCESS; - g_pid = pid; + case eStateDetached: + case eStateExited: + pid = INVALID_NUB_PROCESS; + g_pid = pid; + return eRNBRunLoopModeExit; } - else - { - if (set_events & (eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged)) - { - nub_state_t pid_state = DNBProcessGetState (pid); - DNBLogThreadedIf (LOG_RNB_EVENTS, "%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: - ctx.SetProcessID(pid); - return eRNBRunLoopModeInferiorExecuting; - - case eStateDetached: - case eStateExited: - pid = INVALID_NUB_PROCESS; - g_pid = pid; - return eRNBRunLoopModeExit; - } - } + } - DNBProcessResetEvents(pid, set_events); - } + DNBProcessResetEvents(pid, set_events); } + } - return eRNBRunLoopModeExit; + return eRNBRunLoopModeExit; } - //---------------------------------------------------------------------- // This run loop mode will wait for the process to launch and hit its // entry point. It will currently ignore all events except for the // process state changed event, where it watches for the process stopped // or crash process state. //---------------------------------------------------------------------- -RNBRunLoopMode -RNBRunLoopLaunchAttaching (RNBRemote *remote, nub_process_t attach_pid, nub_process_t& pid) -{ - RNBContext& ctx = remote->Context(); - - DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Attaching to pid %i...", __FUNCTION__, attach_pid); - char err_str[1024]; - pid = DNBProcessAttach (attach_pid, NULL, err_str, sizeof(err_str)); - g_pid = pid; - - if (pid == INVALID_NUB_PROCESS) - { - ctx.LaunchStatus().SetError(-1, DNBError::Generic); - if (err_str[0]) - ctx.LaunchStatus().SetErrorString(err_str); - return eRNBRunLoopModeExit; - } - else - { - ctx.SetProcessID(pid); - return eRNBRunLoopModeInferiorExecuting; - } +RNBRunLoopMode RNBRunLoopLaunchAttaching(RNBRemote *remote, + nub_process_t attach_pid, + nub_process_t &pid) { + RNBContext &ctx = remote->Context(); + + DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s Attaching to pid %i...", __FUNCTION__, + attach_pid); + char err_str[1024]; + pid = DNBProcessAttach(attach_pid, NULL, err_str, sizeof(err_str)); + g_pid = pid; + + if (pid == INVALID_NUB_PROCESS) { + ctx.LaunchStatus().SetError(-1, DNBError::Generic); + if (err_str[0]) + ctx.LaunchStatus().SetErrorString(err_str); + return eRNBRunLoopModeExit; + } else { + ctx.SetProcessID(pid); + return eRNBRunLoopModeInferiorExecuting; + } } //---------------------------------------------------------------------- @@ -390,284 +387,271 @@ RNBRunLoopLaunchAttaching (RNBRemote *remote, nub_process_t attach_pid, nub_proc //---------------------------------------------------------------------- int g_sigint_received = 0; int g_sigpipe_received = 0; -void -signal_handler(int signo) -{ - DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s (%s)", __FUNCTION__, SysSignal::Name(signo)); - - switch (signo) - { - case SIGINT: - g_sigint_received++; - if (g_pid != INVALID_NUB_PROCESS) - { - // Only send a SIGINT once... - if (g_sigint_received == 1) - { - switch (DNBProcessGetState (g_pid)) - { - case eStateRunning: - case eStateStepping: - DNBProcessSignal (g_pid, SIGSTOP); - return; - default: - break; - } - } - } - exit (SIGINT); - break; - - case SIGPIPE: - g_sigpipe_received = 1; - break; +void signal_handler(int signo) { + DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s (%s)", __FUNCTION__, + SysSignal::Name(signo)); + + switch (signo) { + case SIGINT: + g_sigint_received++; + if (g_pid != INVALID_NUB_PROCESS) { + // Only send a SIGINT once... + if (g_sigint_received == 1) { + switch (DNBProcessGetState(g_pid)) { + case eStateRunning: + case eStateStepping: + DNBProcessSignal(g_pid, SIGSTOP); + return; + default: + break; + } + } } + exit(SIGINT); + break; + + case SIGPIPE: + g_sigpipe_received = 1; + break; + } } // Return the new run loop mode based off of the current process state -RNBRunLoopMode -HandleProcessStateChange (RNBRemote *remote, bool initialize) -{ - RNBContext& ctx = remote->Context(); - nub_process_t pid = ctx.ProcessID(); - - if (pid == INVALID_NUB_PROCESS) - { - DNBLogThreadedIf (LOG_RNB_MINIMAL, "#### %s error: pid invalid, exiting...", __FUNCTION__); - return eRNBRunLoopModeExit; - } - nub_state_t pid_state = DNBProcessGetState (pid); - - DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) pid_state = %s", __FUNCTION__, (int)initialize, DNBStateAsString (pid_state)); - - switch (pid_state) - { - case eStateInvalid: - case eStateUnloaded: - // Something bad happened - return eRNBRunLoopModeExit; - break; - - case eStateAttaching: - case eStateLaunching: - return eRNBRunLoopModeInferiorExecuting; +RNBRunLoopMode HandleProcessStateChange(RNBRemote *remote, bool initialize) { + RNBContext &ctx = remote->Context(); + nub_process_t pid = ctx.ProcessID(); - case eStateSuspended: - case eStateCrashed: - case eStateStopped: - // If we stop due to a signal, so clear the fact that we got a SIGINT - // so we can stop ourselves again (but only while our inferior - // process is running..) - g_sigint_received = 0; - if (initialize == false) - { - // Compare the last stop count to our current notion of a stop count - // to make sure we don't notify more than once for a given stop. - nub_size_t prev_pid_stop_count = ctx.GetProcessStopCount(); - bool pid_stop_count_changed = ctx.SetProcessStopCount(DNBProcessGetStopCount(pid)); - if (pid_stop_count_changed) - { - remote->FlushSTDIO(); - - if (ctx.GetProcessStopCount() == 1) - { - DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) pid_state = %s pid_stop_count %llu (old %llu)) Notify??? no, first stop...", __FUNCTION__, (int)initialize, DNBStateAsString (pid_state), (uint64_t)ctx.GetProcessStopCount(), (uint64_t)prev_pid_stop_count); - } - else - { - - DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) pid_state = %s pid_stop_count %llu (old %llu)) Notify??? YES!!!", __FUNCTION__, (int)initialize, DNBStateAsString (pid_state), (uint64_t)ctx.GetProcessStopCount(), (uint64_t)prev_pid_stop_count); - remote->NotifyThatProcessStopped (); - } - } - else - { - DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) pid_state = %s pid_stop_count %llu (old %llu)) Notify??? skipping...", __FUNCTION__, (int)initialize, DNBStateAsString (pid_state), (uint64_t)ctx.GetProcessStopCount(), (uint64_t)prev_pid_stop_count); - } - } - return eRNBRunLoopModeInferiorExecuting; - - case eStateStepping: - case eStateRunning: - return eRNBRunLoopModeInferiorExecuting; + if (pid == INVALID_NUB_PROCESS) { + DNBLogThreadedIf(LOG_RNB_MINIMAL, "#### %s error: pid invalid, exiting...", + __FUNCTION__); + return eRNBRunLoopModeExit; + } + nub_state_t pid_state = DNBProcessGetState(pid); - case eStateExited: - remote->HandlePacket_last_signal(NULL); - case eStateDetached: - return eRNBRunLoopModeExit; + DNBLogThreadedIf(LOG_RNB_MINIMAL, + "%s (&remote, initialize=%i) pid_state = %s", __FUNCTION__, + (int)initialize, DNBStateAsString(pid_state)); + switch (pid_state) { + case eStateInvalid: + case eStateUnloaded: + // Something bad happened + return eRNBRunLoopModeExit; + break; + + case eStateAttaching: + case eStateLaunching: + return eRNBRunLoopModeInferiorExecuting; + + case eStateSuspended: + case eStateCrashed: + case eStateStopped: + // If we stop due to a signal, so clear the fact that we got a SIGINT + // so we can stop ourselves again (but only while our inferior + // process is running..) + g_sigint_received = 0; + if (initialize == false) { + // Compare the last stop count to our current notion of a stop count + // to make sure we don't notify more than once for a given stop. + nub_size_t prev_pid_stop_count = ctx.GetProcessStopCount(); + bool pid_stop_count_changed = + ctx.SetProcessStopCount(DNBProcessGetStopCount(pid)); + if (pid_stop_count_changed) { + remote->FlushSTDIO(); + + if (ctx.GetProcessStopCount() == 1) { + DNBLogThreadedIf( + LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) pid_state = %s " + "pid_stop_count %llu (old %llu)) Notify??? no, " + "first stop...", + __FUNCTION__, (int)initialize, DNBStateAsString(pid_state), + (uint64_t)ctx.GetProcessStopCount(), + (uint64_t)prev_pid_stop_count); + } else { + + DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) " + "pid_state = %s pid_stop_count " + "%llu (old %llu)) Notify??? YES!!!", + __FUNCTION__, (int)initialize, + DNBStateAsString(pid_state), + (uint64_t)ctx.GetProcessStopCount(), + (uint64_t)prev_pid_stop_count); + remote->NotifyThatProcessStopped(); + } + } else { + DNBLogThreadedIf( + LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) pid_state = %s " + "pid_stop_count %llu (old %llu)) Notify??? " + "skipping...", + __FUNCTION__, (int)initialize, DNBStateAsString(pid_state), + (uint64_t)ctx.GetProcessStopCount(), (uint64_t)prev_pid_stop_count); + } } + return eRNBRunLoopModeInferiorExecuting; + + case eStateStepping: + case eStateRunning: + return eRNBRunLoopModeInferiorExecuting; - // Catch all... + case eStateExited: + remote->HandlePacket_last_signal(NULL); + case eStateDetached: return eRNBRunLoopModeExit; + } + + // Catch all... + return eRNBRunLoopModeExit; } // This function handles the case where our inferior program is stopped and // we are waiting for gdb remote protocol packets. When a packet occurs that // makes the inferior run, we need to leave this function with a new state // as the return code. -RNBRunLoopMode -RNBRunLoopInferiorExecuting (RNBRemote *remote) -{ - DNBLogThreadedIf (LOG_RNB_MINIMAL, "#### %s", __FUNCTION__); - RNBContext& ctx = remote->Context(); - - // Init our mode and set 'is_running' based on the current process state - RNBRunLoopMode mode = HandleProcessStateChange (remote, true); - - while (ctx.ProcessID() != INVALID_NUB_PROCESS) - { - - std::string set_events_str; - uint32_t event_mask = ctx.NormalEventBits(); - - if (!ctx.ProcessStateRunning()) - { - // Clear some bits if we are not running so we don't send any async packets - event_mask &= ~RNBContext::event_proc_stdio_available; - event_mask &= ~RNBContext::event_proc_profile_data; - // When we enable async structured data packets over another logical channel, - // this can be relaxed. - event_mask &= ~RNBContext::event_darwin_log_data_available; - } - - // We want to make sure we consume all process state changes and have - // whomever is notifying us to wait for us to reset the event bit before - // continuing. - //ctx.Events().SetResetAckMask (RNBContext::event_proc_state_changed); - - DNBLogThreadedIf (LOG_RNB_EVENTS, "%s ctx.Events().WaitForSetEvents(0x%08x) ...",__FUNCTION__, event_mask); - nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); - DNBLogThreadedIf (LOG_RNB_EVENTS, "%s ctx.Events().WaitForSetEvents(0x%08x) => 0x%08x (%s)",__FUNCTION__, event_mask, set_events, ctx.EventsAsString(set_events, set_events_str)); - - if (set_events) - { - if ((set_events & RNBContext::event_proc_thread_exiting) || - (set_events & RNBContext::event_proc_stdio_available)) - { - remote->FlushSTDIO(); - } - - if (set_events & RNBContext::event_proc_profile_data) - { - remote->SendAsyncProfileData(); - } - - if (set_events & RNBContext::event_darwin_log_data_available) - { - remote->SendAsyncDarwinLogData(); - } - - if (set_events & RNBContext::event_read_packet_available) - { - // handleReceivedPacket will take care of resetting the - // event_read_packet_available events when there are no more... - set_events ^= RNBContext::event_read_packet_available; - - if (ctx.ProcessStateRunning()) - { - if (remote->HandleAsyncPacket() == rnb_not_connected) - { - // TODO: connect again? Exit? - } - } - else - { - if (remote->HandleReceivedPacket() == rnb_not_connected) - { - // TODO: connect again? Exit? - } - } - } - - if (set_events & RNBContext::event_proc_state_changed) - { - mode = HandleProcessStateChange (remote, false); - ctx.Events().ResetEvents(RNBContext::event_proc_state_changed); - set_events ^= RNBContext::event_proc_state_changed; - } +RNBRunLoopMode RNBRunLoopInferiorExecuting(RNBRemote *remote) { + DNBLogThreadedIf(LOG_RNB_MINIMAL, "#### %s", __FUNCTION__); + RNBContext &ctx = remote->Context(); + + // Init our mode and set 'is_running' based on the current process state + RNBRunLoopMode mode = HandleProcessStateChange(remote, true); + + while (ctx.ProcessID() != INVALID_NUB_PROCESS) { + + std::string set_events_str; + uint32_t event_mask = ctx.NormalEventBits(); + + if (!ctx.ProcessStateRunning()) { + // Clear some bits if we are not running so we don't send any async + // packets + event_mask &= ~RNBContext::event_proc_stdio_available; + event_mask &= ~RNBContext::event_proc_profile_data; + // When we enable async structured data packets over another logical + // channel, + // this can be relaxed. + event_mask &= ~RNBContext::event_darwin_log_data_available; + } - if (set_events & RNBContext::event_proc_thread_exiting) - { - mode = eRNBRunLoopModeExit; + // We want to make sure we consume all process state changes and have + // whomever is notifying us to wait for us to reset the event bit before + // continuing. + // ctx.Events().SetResetAckMask (RNBContext::event_proc_state_changed); + + DNBLogThreadedIf(LOG_RNB_EVENTS, + "%s ctx.Events().WaitForSetEvents(0x%08x) ...", + __FUNCTION__, event_mask); + nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); + DNBLogThreadedIf(LOG_RNB_EVENTS, + "%s ctx.Events().WaitForSetEvents(0x%08x) => 0x%08x (%s)", + __FUNCTION__, event_mask, set_events, + ctx.EventsAsString(set_events, set_events_str)); + + if (set_events) { + if ((set_events & RNBContext::event_proc_thread_exiting) || + (set_events & RNBContext::event_proc_stdio_available)) { + remote->FlushSTDIO(); + } + + if (set_events & RNBContext::event_proc_profile_data) { + remote->SendAsyncProfileData(); + } + + if (set_events & RNBContext::event_darwin_log_data_available) { + remote->SendAsyncDarwinLogData(); + } + + if (set_events & RNBContext::event_read_packet_available) { + // handleReceivedPacket will take care of resetting the + // event_read_packet_available events when there are no more... + set_events ^= RNBContext::event_read_packet_available; + + if (ctx.ProcessStateRunning()) { + if (remote->HandleAsyncPacket() == rnb_not_connected) { + // TODO: connect again? Exit? + } + } else { + if (remote->HandleReceivedPacket() == rnb_not_connected) { + // TODO: connect again? Exit? + } + } + } + + if (set_events & RNBContext::event_proc_state_changed) { + mode = HandleProcessStateChange(remote, false); + ctx.Events().ResetEvents(RNBContext::event_proc_state_changed); + set_events ^= RNBContext::event_proc_state_changed; + } + + if (set_events & RNBContext::event_proc_thread_exiting) { + mode = eRNBRunLoopModeExit; + } + + if (set_events & RNBContext::event_read_thread_exiting) { + // Out remote packet receiving thread exited, exit for now. + if (ctx.HasValidProcessID()) { + // TODO: We should add code that will leave the current process + // in its current state and listen for another connection... + if (ctx.ProcessStateRunning()) { + if (ctx.GetDetachOnError()) { + DNBLog("debugserver's event read thread is exiting, detaching " + "from the inferior process."); + DNBProcessDetach(ctx.ProcessID()); + } else { + DNBLog("debugserver's event read thread is exiting, killing the " + "inferior process."); + DNBProcessKill(ctx.ProcessID()); } - - if (set_events & RNBContext::event_read_thread_exiting) - { - // Out remote packet receiving thread exited, exit for now. - if (ctx.HasValidProcessID()) - { - // TODO: We should add code that will leave the current process - // in its current state and listen for another connection... - if (ctx.ProcessStateRunning()) - { - if (ctx.GetDetachOnError()) - { - DNBLog ("debugserver's event read thread is exiting, detaching from the inferior process."); - DNBProcessDetach (ctx.ProcessID()); - } - else - { - DNBLog ("debugserver's event read thread is exiting, killing the inferior process."); - DNBProcessKill (ctx.ProcessID()); - } - } - else - { - if (ctx.GetDetachOnError()) - { - DNBLog ("debugserver's event read thread is exiting, detaching from the inferior process."); - DNBProcessDetach (ctx.ProcessID()); - } - } - } - mode = eRNBRunLoopModeExit; + } else { + if (ctx.GetDetachOnError()) { + DNBLog("debugserver's event read thread is exiting, detaching " + "from the inferior process."); + DNBProcessDetach(ctx.ProcessID()); } + } } - - // Reset all event bits that weren't reset for now... - if (set_events != 0) - ctx.Events().ResetEvents(set_events); - - if (mode != eRNBRunLoopModeInferiorExecuting) - break; + mode = eRNBRunLoopModeExit; + } } - return mode; -} + // Reset all event bits that weren't reset for now... + if (set_events != 0) + ctx.Events().ResetEvents(set_events); + if (mode != eRNBRunLoopModeInferiorExecuting) + break; + } -RNBRunLoopMode -RNBRunLoopPlatform (RNBRemote *remote) -{ - RNBRunLoopMode mode = eRNBRunLoopModePlatformMode; - RNBContext& ctx = remote->Context(); - - while (mode == eRNBRunLoopModePlatformMode) - { - std::string set_events_str; - const uint32_t event_mask = RNBContext::event_read_packet_available | - RNBContext::event_read_thread_exiting; - - DNBLogThreadedIf (LOG_RNB_EVENTS, "%s ctx.Events().WaitForSetEvents(0x%08x) ...",__FUNCTION__, event_mask); - nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); - DNBLogThreadedIf (LOG_RNB_EVENTS, "%s ctx.Events().WaitForSetEvents(0x%08x) => 0x%08x (%s)",__FUNCTION__, event_mask, set_events, ctx.EventsAsString(set_events, set_events_str)); - - if (set_events) - { - if (set_events & RNBContext::event_read_packet_available) - { - if (remote->HandleReceivedPacket() == rnb_not_connected) - mode = eRNBRunLoopModeExit; - } + return mode; +} - if (set_events & RNBContext::event_read_thread_exiting) - { - mode = eRNBRunLoopModeExit; - } - ctx.Events().ResetEvents(set_events); - } +RNBRunLoopMode RNBRunLoopPlatform(RNBRemote *remote) { + RNBRunLoopMode mode = eRNBRunLoopModePlatformMode; + RNBContext &ctx = remote->Context(); + + while (mode == eRNBRunLoopModePlatformMode) { + std::string set_events_str; + const uint32_t event_mask = RNBContext::event_read_packet_available | + RNBContext::event_read_thread_exiting; + + DNBLogThreadedIf(LOG_RNB_EVENTS, + "%s ctx.Events().WaitForSetEvents(0x%08x) ...", + __FUNCTION__, event_mask); + nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); + DNBLogThreadedIf(LOG_RNB_EVENTS, + "%s ctx.Events().WaitForSetEvents(0x%08x) => 0x%08x (%s)", + __FUNCTION__, event_mask, set_events, + ctx.EventsAsString(set_events, set_events_str)); + + if (set_events) { + if (set_events & RNBContext::event_read_packet_available) { + if (remote->HandleReceivedPacket() == rnb_not_connected) + mode = eRNBRunLoopModeExit; + } + + if (set_events & RNBContext::event_read_thread_exiting) { + mode = eRNBRunLoopModeExit; + } + ctx.Events().ResetEvents(set_events); } - return eRNBRunLoopModeExit; + } + return eRNBRunLoopModeExit; } //---------------------------------------------------------------------- @@ -675,1070 +659,1014 @@ RNBRunLoopPlatform (RNBRemote *remote) // Returns 1 for success 0 for failure. //---------------------------------------------------------------------- -static void -PortWasBoundCallbackUnixSocket (const void *baton, in_port_t port) -{ - //::printf ("PortWasBoundCallbackUnixSocket (baton = %p, port = %u)\n", baton, port); - - const char *unix_socket_name = (const char *)baton; - - if (unix_socket_name && unix_socket_name[0]) - { - // We were given a unix socket name to use to communicate the port - // that we ended up binding to back to our parent process - 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, 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); +static void PortWasBoundCallbackUnixSocket(const void *baton, in_port_t port) { + //::printf ("PortWasBoundCallbackUnixSocket (baton = %p, port = %u)\n", baton, + //port); - if (::connect (s, (struct sockaddr *)&saddr_un, static_cast<socklen_t>(SUN_LEN (&saddr_un))) < 0) - { - perror("error: connect (socket, &saddr_un, saddr_un_len)"); - exit(1); - } + const char *unix_socket_name = (const char *)baton; - //::printf ("connect () sucess!!\n"); + if (unix_socket_name && unix_socket_name[0]) { + // We were given a unix socket name to use to communicate the port + // that we ended up binding to back to our parent process + 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, + 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); - // We were able to connect to the socket, now write our PID so whomever - // launched us will know this process's ID - RNBLogSTDOUT ("Listening to port %i...\n", port); + if (::connect(s, (struct sockaddr *)&saddr_un, + static_cast<socklen_t>(SUN_LEN(&saddr_un))) < 0) { + perror("error: connect (socket, &saddr_un, saddr_un_len)"); + exit(1); + } - char pid_str[64]; - const int pid_str_len = ::snprintf (pid_str, sizeof(pid_str), "%u", port); - const ssize_t bytes_sent = ::send (s, pid_str, pid_str_len, 0); + //::printf ("connect () sucess!!\n"); - if (pid_str_len != bytes_sent) - { - perror("error: send (s, pid_str, pid_str_len, 0)"); - exit (1); - } + // We were able to connect to the socket, now write our PID so whomever + // launched us will know this process's ID + RNBLogSTDOUT("Listening to port %i...\n", port); - //::printf ("send () sucess!!\n"); + char pid_str[64]; + const int pid_str_len = ::snprintf(pid_str, sizeof(pid_str), "%u", port); + const ssize_t bytes_sent = ::send(s, pid_str, pid_str_len, 0); - // We are done with the socket - close (s); + if (pid_str_len != bytes_sent) { + perror("error: send (s, pid_str, pid_str_len, 0)"); + exit(1); } + + //::printf ("send () sucess!!\n"); + + // We are done with the socket + close(s); + } } -static void -PortWasBoundCallbackNamedPipe (const void *baton, uint16_t port) -{ - const char *named_pipe = (const char *)baton; - if (named_pipe && named_pipe[0]) - { - int fd = ::open(named_pipe, O_WRONLY); - if (fd > -1) - { - char port_str[64]; - const ssize_t port_str_len = ::snprintf (port_str, sizeof(port_str), "%u", port); - // Write the port number as a C string with the NULL terminator - ::write (fd, port_str, port_str_len + 1); - close (fd); - } +static void PortWasBoundCallbackNamedPipe(const void *baton, uint16_t port) { + const char *named_pipe = (const char *)baton; + if (named_pipe && named_pipe[0]) { + int fd = ::open(named_pipe, O_WRONLY); + if (fd > -1) { + char port_str[64]; + const ssize_t port_str_len = + ::snprintf(port_str, sizeof(port_str), "%u", port); + // Write the port number as a C string with the NULL terminator + ::write(fd, port_str, port_str_len + 1); + close(fd); } + } } -static int -ConnectRemote (RNBRemote *remote, - const char *host, - int port, - bool reverse_connect, - const char *named_pipe_path, - const char *unix_socket_name) -{ - if (!remote->Comm().IsConnected()) - { - if (reverse_connect) - { - if (port == 0) - { - DNBLogThreaded("error: invalid port supplied for reverse connection: %i.\n", port); - return 0; - } - if (remote->Comm().Connect(host, port) != rnb_success) - { - DNBLogThreaded("Failed to reverse connect to %s:%i.\n", host, port); - return 0; - } +static int ConnectRemote(RNBRemote *remote, const char *host, int port, + bool reverse_connect, const char *named_pipe_path, + const char *unix_socket_name) { + if (!remote->Comm().IsConnected()) { + if (reverse_connect) { + if (port == 0) { + DNBLogThreaded( + "error: invalid port supplied for reverse connection: %i.\n", port); + return 0; + } + if (remote->Comm().Connect(host, port) != rnb_success) { + DNBLogThreaded("Failed to reverse connect to %s:%i.\n", host, port); + return 0; + } + } else { + if (port != 0) + RNBLogSTDOUT("Listening to port %i for a connection from %s...\n", port, + host ? host : "127.0.0.1"); + if (unix_socket_name && unix_socket_name[0]) { + if (remote->Comm().Listen(host, port, PortWasBoundCallbackUnixSocket, + unix_socket_name) != rnb_success) { + RNBLogSTDERR("Failed to get connection from a remote gdb process.\n"); + return 0; } - else - { - if (port != 0) - RNBLogSTDOUT ("Listening to port %i for a connection from %s...\n", port, host ? host : "127.0.0.1"); - if (unix_socket_name && unix_socket_name[0]) - { - if (remote->Comm().Listen(host, port, PortWasBoundCallbackUnixSocket, unix_socket_name) != rnb_success) - { - RNBLogSTDERR ("Failed to get connection from a remote gdb process.\n"); - return 0; - } - } - else - { - if (remote->Comm().Listen(host, port, PortWasBoundCallbackNamedPipe, named_pipe_path) != rnb_success) - { - RNBLogSTDERR ("Failed to get connection from a remote gdb process.\n"); - return 0; - } - } + } else { + if (remote->Comm().Listen(host, port, PortWasBoundCallbackNamedPipe, + named_pipe_path) != rnb_success) { + RNBLogSTDERR("Failed to get connection from a remote gdb process.\n"); + return 0; } - remote->StartReadRemoteDataThread(); + } } - return 1; + remote->StartReadRemoteDataThread(); + } + return 1; } //---------------------------------------------------------------------- // ASL Logging callback that can be registered with DNBLogSetLogCallback //---------------------------------------------------------------------- -void -ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args) -{ - if (format == NULL) - return; - static aslmsg g_aslmsg = NULL; - if (g_aslmsg == NULL) - { - g_aslmsg = ::asl_new (ASL_TYPE_MSG); - char asl_key_sender[PATH_MAX]; - snprintf(asl_key_sender, sizeof(asl_key_sender), "com.apple.%s-%s", DEBUGSERVER_PROGRAM_NAME, DEBUGSERVER_VERSION_STR); - ::asl_set (g_aslmsg, ASL_KEY_SENDER, asl_key_sender); - } - - int asl_level; - if (flags & DNBLOG_FLAG_FATAL) asl_level = ASL_LEVEL_CRIT; - else if (flags & DNBLOG_FLAG_ERROR) asl_level = ASL_LEVEL_ERR; - else if (flags & DNBLOG_FLAG_WARNING) asl_level = ASL_LEVEL_WARNING; - else if (flags & DNBLOG_FLAG_VERBOSE) asl_level = ASL_LEVEL_WARNING; //ASL_LEVEL_INFO; - else asl_level = ASL_LEVEL_WARNING; //ASL_LEVEL_DEBUG; - - ::asl_vlog (NULL, g_aslmsg, asl_level, format, args); +void ASLLogCallback(void *baton, uint32_t flags, const char *format, + va_list args) { + if (format == NULL) + return; + static aslmsg g_aslmsg = NULL; + if (g_aslmsg == NULL) { + g_aslmsg = ::asl_new(ASL_TYPE_MSG); + char asl_key_sender[PATH_MAX]; + snprintf(asl_key_sender, sizeof(asl_key_sender), "com.apple.%s-%s", + DEBUGSERVER_PROGRAM_NAME, DEBUGSERVER_VERSION_STR); + ::asl_set(g_aslmsg, ASL_KEY_SENDER, asl_key_sender); + } + + int asl_level; + if (flags & DNBLOG_FLAG_FATAL) + asl_level = ASL_LEVEL_CRIT; + else if (flags & DNBLOG_FLAG_ERROR) + asl_level = ASL_LEVEL_ERR; + else if (flags & DNBLOG_FLAG_WARNING) + asl_level = ASL_LEVEL_WARNING; + else if (flags & DNBLOG_FLAG_VERBOSE) + asl_level = ASL_LEVEL_WARNING; // ASL_LEVEL_INFO; + else + asl_level = ASL_LEVEL_WARNING; // ASL_LEVEL_DEBUG; + + ::asl_vlog(NULL, g_aslmsg, asl_level, format, args); } //---------------------------------------------------------------------- // FILE based Logging callback that can be registered with // DNBLogSetLogCallback //---------------------------------------------------------------------- -void -FileLogCallback(void *baton, uint32_t flags, const char *format, va_list args) -{ - if (baton == NULL || format == NULL) - return; - - ::vfprintf((FILE *)baton, format, args); - ::fprintf((FILE *)baton, "\n"); - ::fflush((FILE *)baton); +void FileLogCallback(void *baton, uint32_t flags, const char *format, + va_list args) { + if (baton == NULL || format == NULL) + return; + + ::vfprintf((FILE *)baton, format, args); + ::fprintf((FILE *)baton, "\n"); + ::fflush((FILE *)baton); } - -void -show_usage_and_exit (int exit_code) -{ - RNBLogSTDERR ("Usage:\n %s host:port [program-name program-arg1 program-arg2 ...]\n", DEBUGSERVER_PROGRAM_NAME); - RNBLogSTDERR (" %s /path/file [program-name program-arg1 program-arg2 ...]\n", DEBUGSERVER_PROGRAM_NAME); - RNBLogSTDERR (" %s host:port --attach=<pid>\n", DEBUGSERVER_PROGRAM_NAME); - RNBLogSTDERR (" %s /path/file --attach=<pid>\n", DEBUGSERVER_PROGRAM_NAME); - RNBLogSTDERR (" %s host:port --attach=<process_name>\n", DEBUGSERVER_PROGRAM_NAME); - RNBLogSTDERR (" %s /path/file --attach=<process_name>\n", DEBUGSERVER_PROGRAM_NAME); - exit (exit_code); +void show_usage_and_exit(int exit_code) { + RNBLogSTDERR( + "Usage:\n %s host:port [program-name program-arg1 program-arg2 ...]\n", + DEBUGSERVER_PROGRAM_NAME); + RNBLogSTDERR(" %s /path/file [program-name program-arg1 program-arg2 ...]\n", + DEBUGSERVER_PROGRAM_NAME); + RNBLogSTDERR(" %s host:port --attach=<pid>\n", DEBUGSERVER_PROGRAM_NAME); + RNBLogSTDERR(" %s /path/file --attach=<pid>\n", DEBUGSERVER_PROGRAM_NAME); + RNBLogSTDERR(" %s host:port --attach=<process_name>\n", + DEBUGSERVER_PROGRAM_NAME); + RNBLogSTDERR(" %s /path/file --attach=<process_name>\n", + DEBUGSERVER_PROGRAM_NAME); + exit(exit_code); } - //---------------------------------------------------------------------- // option descriptors for getopt_long_only() //---------------------------------------------------------------------- -static struct option g_long_options[] = -{ - { "attach", required_argument, NULL, 'a' }, - { "arch", required_argument, NULL, 'A' }, - { "debug", no_argument, NULL, 'g' }, - { "kill-on-error", no_argument, NULL, 'K' }, - { "verbose", no_argument, NULL, 'v' }, - { "lockdown", no_argument, &g_lockdown_opt, 1 }, // short option "-k" - { "applist", no_argument, &g_applist_opt, 1 }, // short option "-t" - { "log-file", required_argument, NULL, 'l' }, - { "log-flags", required_argument, NULL, 'f' }, - { "launch", required_argument, NULL, 'x' }, // Valid values are "auto", "posix-spawn", "fork-exec", "springboard" (arm only) - { "waitfor", required_argument, NULL, 'w' }, // Wait for a process whose name starts with ARG - { "waitfor-interval", required_argument, NULL, 'i' }, // Time in usecs to wait between sampling the pid list when waiting for a process by name - { "waitfor-duration", required_argument, NULL, 'd' }, // The time in seconds to wait for a process to show up by name - { "native-regs", no_argument, NULL, 'r' }, // Specify to use the native registers instead of the gdb defaults for the architecture. - { "stdio-path", required_argument, NULL, 's' }, // Set the STDIO path to be used when launching applications (STDIN, STDOUT and STDERR) (only if debugserver launches the process) - { "stdin-path", required_argument, NULL, 'I' }, // Set the STDIN path to be used when launching applications (only if debugserver launches the process) - { "stdout-path", required_argument, NULL, 'O' }, // Set the STDOUT path to be used when launching applications (only if debugserver launches the process) - { "stderr-path", required_argument, NULL, 'E' }, // Set the STDERR path to be used when launching applications (only if debugserver launches the process) - { "no-stdio", no_argument, NULL, 'n' }, // Do not set up any stdio (perhaps the program is a GUI program) (only if debugserver launches the process) - { "setsid", no_argument, NULL, 'S' }, // call setsid() to make debugserver run in its own session - { "disable-aslr", no_argument, NULL, 'D' }, // Use _POSIX_SPAWN_DISABLE_ASLR to avoid shared library randomization - { "working-dir", required_argument, NULL, 'W' }, // The working directory that the inferior process should have (only if debugserver launches the process) - { "platform", required_argument, NULL, 'p' }, // Put this executable into a remote platform mode - { "unix-socket", required_argument, NULL, 'u' }, // If we need to handshake with our parent process, an option will be passed down that specifies a unix socket name to use - { "fd", required_argument, NULL, 'FDSC' }, // A file descriptor was passed to this process when spawned that is already open and ready for communication - { "named-pipe", required_argument, NULL, 'P' }, - { "reverse-connect", no_argument, NULL, 'R' }, - { "env", required_argument, NULL, 'e' }, // When debugserver launches the process, set a single environment entry as specified by the option value ("./debugserver -e FOO=1 -e BAR=2 localhost:1234 -- /bin/ls") - { "forward-env", no_argument, NULL, 'F' }, // When debugserver launches the process, forward debugserver's current environment variables to the child process ("./debugserver -F localhost:1234 -- /bin/ls" - { NULL, 0, NULL, 0 } -}; - +static struct option g_long_options[] = { + {"attach", required_argument, NULL, 'a'}, + {"arch", required_argument, NULL, 'A'}, + {"debug", no_argument, NULL, 'g'}, + {"kill-on-error", no_argument, NULL, 'K'}, + {"verbose", no_argument, NULL, 'v'}, + {"lockdown", no_argument, &g_lockdown_opt, 1}, // short option "-k" + {"applist", no_argument, &g_applist_opt, 1}, // short option "-t" + {"log-file", required_argument, NULL, 'l'}, + {"log-flags", required_argument, NULL, 'f'}, + {"launch", required_argument, NULL, 'x'}, // Valid values are "auto", + // "posix-spawn", "fork-exec", + // "springboard" (arm only) + {"waitfor", required_argument, NULL, + 'w'}, // Wait for a process whose name starts with ARG + {"waitfor-interval", required_argument, NULL, + 'i'}, // Time in usecs to wait between sampling the pid list when waiting + // for a process by name + {"waitfor-duration", required_argument, NULL, + 'd'}, // The time in seconds to wait for a process to show up by name + {"native-regs", no_argument, NULL, 'r'}, // Specify to use the native + // registers instead of the gdb + // defaults for the architecture. + {"stdio-path", required_argument, NULL, + 's'}, // Set the STDIO path to be used when launching applications (STDIN, + // STDOUT and STDERR) (only if debugserver launches the process) + {"stdin-path", required_argument, NULL, + 'I'}, // Set the STDIN path to be used when launching applications (only if + // debugserver launches the process) + {"stdout-path", required_argument, NULL, + 'O'}, // Set the STDOUT path to be used when launching applications (only + // if debugserver launches the process) + {"stderr-path", required_argument, NULL, + 'E'}, // Set the STDERR path to be used when launching applications (only + // if debugserver launches the process) + {"no-stdio", no_argument, NULL, + 'n'}, // Do not set up any stdio (perhaps the program is a GUI program) + // (only if debugserver launches the process) + {"setsid", no_argument, NULL, + 'S'}, // call setsid() to make debugserver run in its own session + {"disable-aslr", no_argument, NULL, 'D'}, // Use _POSIX_SPAWN_DISABLE_ASLR + // to avoid shared library + // randomization + {"working-dir", required_argument, NULL, + 'W'}, // The working directory that the inferior process should have (only + // if debugserver launches the process) + {"platform", required_argument, NULL, + 'p'}, // Put this executable into a remote platform mode + {"unix-socket", required_argument, NULL, + 'u'}, // If we need to handshake with our parent process, an option will be + // passed down that specifies a unix socket name to use + {"fd", required_argument, NULL, + 'FDSC'}, // A file descriptor was passed to this process when spawned that + // is already open and ready for communication + {"named-pipe", required_argument, NULL, 'P'}, + {"reverse-connect", no_argument, NULL, 'R'}, + {"env", required_argument, NULL, + 'e'}, // When debugserver launches the process, set a single environment + // entry as specified by the option value ("./debugserver -e FOO=1 -e + // BAR=2 localhost:1234 -- /bin/ls") + {"forward-env", no_argument, NULL, + 'F'}, // When debugserver launches the process, forward debugserver's + // current environment variables to the child process ("./debugserver + // -F localhost:1234 -- /bin/ls" + {NULL, 0, NULL, 0}}; //---------------------------------------------------------------------- // main //---------------------------------------------------------------------- -int -main (int argc, char *argv[]) -{ - // If debugserver is launched with DYLD_INSERT_LIBRARIES, unset it so we - // don't spawn child processes with this enabled. - unsetenv("DYLD_INSERT_LIBRARIES"); - - const char *argv_sub_zero = argv[0]; // save a copy of argv[0] for error reporting post-launch - -#if defined (__APPLE__) - pthread_setname_np ("main 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); - } - - ::proc_set_wakemon_params (getpid(), 500, 0); // Allow up to 500 wakeups/sec to avoid EXC_RESOURCE for normal use. +int main(int argc, char *argv[]) { + // If debugserver is launched with DYLD_INSERT_LIBRARIES, unset it so we + // don't spawn child processes with this enabled. + unsetenv("DYLD_INSERT_LIBRARIES"); + + const char *argv_sub_zero = + argv[0]; // save a copy of argv[0] for error reporting post-launch + +#if defined(__APPLE__) + pthread_setname_np("main 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); + } + + ::proc_set_wakemon_params( + getpid(), 500, + 0); // Allow up to 500 wakeups/sec to avoid EXC_RESOURCE for normal use. #endif #endif - g_isatty = ::isatty (STDIN_FILENO); - - // ::printf ("uid=%u euid=%u gid=%u egid=%u\n", - // getuid(), - // geteuid(), - // getgid(), - // getegid()); - - - // signal (SIGINT, signal_handler); - signal (SIGPIPE, signal_handler); - signal (SIGHUP, signal_handler); - - // We're always sitting in waitpid or kevent waiting on our target process' death, - // we don't need no stinking SIGCHLD's... - - sigset_t sigset; - sigemptyset(&sigset); - sigaddset(&sigset, SIGCHLD); - sigprocmask(SIG_BLOCK, &sigset, NULL); - - g_remoteSP.reset (new RNBRemote ()); - - - RNBRemote *remote = g_remoteSP.get(); - if (remote == NULL) - { - RNBLogSTDERR ("error: failed to create a remote connection class\n"); - return -1; - } - - RNBContext& ctx = remote->Context(); - - int i; - int attach_pid = INVALID_NUB_PROCESS; - - FILE* log_file = NULL; - uint32_t log_flags = 0; - // Parse our options - int ch; - int long_option_index = 0; - int debug = 0; - int communication_fd = -1; - std::string compile_options; - std::string waitfor_pid_name; // Wait for a process that starts with this name - std::string attach_pid_name; - std::string arch_name; - std::string working_dir; // The new working directory to use for the inferior - std::string unix_socket_name; // If we need to handshake with our parent process, an option will be passed down that specifies a unix socket name to use - std::string named_pipe_path; // If we need to handshake with our parent process, an option will be passed down that specifies a named pipe to use - useconds_t waitfor_interval = 1000; // Time in usecs between process lists polls when waiting for a process by name, default 1 msec. - useconds_t waitfor_duration = 0; // Time in seconds to wait for a process by name, 0 means wait forever. - bool no_stdio = false; - bool reverse_connect = false; // Set to true by an option to indicate we should reverse connect to the host:port supplied as the first debugserver argument - -#if !defined (DNBLOG_ENABLED) - compile_options += "(no-logging) "; + g_isatty = ::isatty(STDIN_FILENO); + + // ::printf ("uid=%u euid=%u gid=%u egid=%u\n", + // getuid(), + // geteuid(), + // getgid(), + // getegid()); + + // signal (SIGINT, signal_handler); + signal(SIGPIPE, signal_handler); + signal(SIGHUP, signal_handler); + + // We're always sitting in waitpid or kevent waiting on our target process' + // death, + // we don't need no stinking SIGCHLD's... + + sigset_t sigset; + sigemptyset(&sigset); + sigaddset(&sigset, SIGCHLD); + sigprocmask(SIG_BLOCK, &sigset, NULL); + + g_remoteSP.reset(new RNBRemote()); + + RNBRemote *remote = g_remoteSP.get(); + if (remote == NULL) { + RNBLogSTDERR("error: failed to create a remote connection class\n"); + return -1; + } + + RNBContext &ctx = remote->Context(); + + int i; + int attach_pid = INVALID_NUB_PROCESS; + + FILE *log_file = NULL; + uint32_t log_flags = 0; + // Parse our options + int ch; + int long_option_index = 0; + int debug = 0; + int communication_fd = -1; + std::string compile_options; + std::string waitfor_pid_name; // Wait for a process that starts with this name + std::string attach_pid_name; + std::string arch_name; + std::string working_dir; // The new working directory to use for the inferior + std::string unix_socket_name; // If we need to handshake with our parent + // process, an option will be passed down that + // specifies a unix socket name to use + std::string named_pipe_path; // If we need to handshake with our parent + // process, an option will be passed down that + // specifies a named pipe to use + useconds_t waitfor_interval = 1000; // Time in usecs between process lists + // polls when waiting for a process by + // name, default 1 msec. + useconds_t waitfor_duration = + 0; // Time in seconds to wait for a process by name, 0 means wait forever. + bool no_stdio = false; + bool reverse_connect = false; // Set to true by an option to indicate we + // should reverse connect to the host:port + // supplied as the first debugserver argument + +#if !defined(DNBLOG_ENABLED) + compile_options += "(no-logging) "; #endif - RNBRunLoopMode start_mode = eRNBRunLoopModeExit; - - char short_options[512]; - uint32_t short_options_idx = 0; - - // Handle the two case that don't have short options in g_long_options - short_options[short_options_idx++] = 'k'; - short_options[short_options_idx++] = 't'; - - for (i=0; g_long_options[i].name != NULL; ++i) - { - if (isalpha(g_long_options[i].val)) - { - short_options[short_options_idx++] = g_long_options[i].val; - switch (g_long_options[i].has_arg) - { - default: - case no_argument: - break; - - case optional_argument: - short_options[short_options_idx++] = ':'; - // Fall through to required_argument case below... - case required_argument: - short_options[short_options_idx++] = ':'; - break; - } - } + RNBRunLoopMode start_mode = eRNBRunLoopModeExit; + + char short_options[512]; + uint32_t short_options_idx = 0; + + // Handle the two case that don't have short options in g_long_options + short_options[short_options_idx++] = 'k'; + short_options[short_options_idx++] = 't'; + + for (i = 0; g_long_options[i].name != NULL; ++i) { + if (isalpha(g_long_options[i].val)) { + short_options[short_options_idx++] = g_long_options[i].val; + switch (g_long_options[i].has_arg) { + default: + case no_argument: + break; + + case optional_argument: + short_options[short_options_idx++] = ':'; + // Fall through to required_argument case below... + case required_argument: + short_options[short_options_idx++] = ':'; + break; + } } - // NULL terminate the short option string. - short_options[short_options_idx++] = '\0'; + } + // NULL terminate the short option string. + short_options[short_options_idx++] = '\0'; #if __GLIBC__ - optind = 0; + optind = 0; #else - optreset = 1; - optind = 1; + optreset = 1; + optind = 1; #endif - while ((ch = getopt_long_only(argc, argv, short_options, g_long_options, &long_option_index)) != -1) - { - DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n", - ch, (uint8_t)ch, - g_long_options[long_option_index].name, - g_long_options[long_option_index].has_arg ? '=' : ' ', - optarg ? optarg : ""); - switch (ch) - { - case 0: // Any optional that auto set themselves will return 0 - break; - - case 'A': - if (optarg && optarg[0]) - arch_name.assign(optarg); - break; - - case 'a': - if (optarg && optarg[0]) - { - if (isdigit(optarg[0])) - { - char *end = NULL; - attach_pid = static_cast<int>(strtoul(optarg, &end, 0)); - if (end == NULL || *end != '\0') - { - RNBLogSTDERR ("error: invalid pid option '%s'\n", optarg); - exit (4); - } - } - else - { - attach_pid_name = optarg; - } - start_mode = eRNBRunLoopModeInferiorAttaching; - } - break; - - // --waitfor=NAME - case 'w': - if (optarg && optarg[0]) - { - waitfor_pid_name = optarg; - start_mode = eRNBRunLoopModeInferiorAttaching; - } - break; - - // --waitfor-interval=USEC - case 'i': - if (optarg && optarg[0]) - { - char *end = NULL; - waitfor_interval = static_cast<useconds_t>(strtoul(optarg, &end, 0)); - if (end == NULL || *end != '\0') - { - RNBLogSTDERR ("error: invalid waitfor-interval option value '%s'.\n", optarg); - exit (6); - } - } - break; - - // --waitfor-duration=SEC - case 'd': - if (optarg && optarg[0]) - { - char *end = NULL; - waitfor_duration = static_cast<useconds_t>(strtoul(optarg, &end, 0)); - if (end == NULL || *end != '\0') - { - RNBLogSTDERR ("error: invalid waitfor-duration option value '%s'.\n", optarg); - exit (7); - } - } - break; - - case 'K': - g_detach_on_error = false; - break; - case 'W': - if (optarg && optarg[0]) - working_dir.assign(optarg); - break; - - case 'x': - if (optarg && optarg[0]) - { - if (strcasecmp(optarg, "auto") == 0) - g_launch_flavor = eLaunchFlavorDefault; - else if (strcasestr(optarg, "posix") == optarg) - g_launch_flavor = eLaunchFlavorPosixSpawn; - else if (strcasestr(optarg, "fork") == optarg) - g_launch_flavor = eLaunchFlavorForkExec; + while ((ch = getopt_long_only(argc, argv, short_options, g_long_options, + &long_option_index)) != -1) { + DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n", ch, (uint8_t)ch, + g_long_options[long_option_index].name, + g_long_options[long_option_index].has_arg ? '=' : ' ', + optarg ? optarg : ""); + switch (ch) { + case 0: // Any optional that auto set themselves will return 0 + break; + + case 'A': + if (optarg && optarg[0]) + arch_name.assign(optarg); + break; + + case 'a': + if (optarg && optarg[0]) { + if (isdigit(optarg[0])) { + char *end = NULL; + attach_pid = static_cast<int>(strtoul(optarg, &end, 0)); + if (end == NULL || *end != '\0') { + RNBLogSTDERR("error: invalid pid option '%s'\n", optarg); + exit(4); + } + } else { + attach_pid_name = optarg; + } + start_mode = eRNBRunLoopModeInferiorAttaching; + } + break; + + // --waitfor=NAME + case 'w': + if (optarg && optarg[0]) { + waitfor_pid_name = optarg; + start_mode = eRNBRunLoopModeInferiorAttaching; + } + break; + + // --waitfor-interval=USEC + case 'i': + if (optarg && optarg[0]) { + char *end = NULL; + waitfor_interval = static_cast<useconds_t>(strtoul(optarg, &end, 0)); + if (end == NULL || *end != '\0') { + RNBLogSTDERR("error: invalid waitfor-interval option value '%s'.\n", + optarg); + exit(6); + } + } + break; + + // --waitfor-duration=SEC + case 'd': + if (optarg && optarg[0]) { + char *end = NULL; + waitfor_duration = static_cast<useconds_t>(strtoul(optarg, &end, 0)); + if (end == NULL || *end != '\0') { + RNBLogSTDERR("error: invalid waitfor-duration option value '%s'.\n", + optarg); + exit(7); + } + } + break; + + case 'K': + g_detach_on_error = false; + break; + case 'W': + if (optarg && optarg[0]) + working_dir.assign(optarg); + break; + + case 'x': + if (optarg && optarg[0]) { + if (strcasecmp(optarg, "auto") == 0) + g_launch_flavor = eLaunchFlavorDefault; + else if (strcasestr(optarg, "posix") == optarg) + g_launch_flavor = eLaunchFlavorPosixSpawn; + else if (strcasestr(optarg, "fork") == optarg) + g_launch_flavor = eLaunchFlavorForkExec; #ifdef WITH_SPRINGBOARD - else if (strcasestr(optarg, "spring") == optarg) - g_launch_flavor = eLaunchFlavorSpringBoard; + else if (strcasestr(optarg, "spring") == optarg) + g_launch_flavor = eLaunchFlavorSpringBoard; #endif #ifdef WITH_BKS - else if (strcasestr(optarg, "backboard") == optarg) - g_launch_flavor = eLaunchFlavorBKS; + else if (strcasestr(optarg, "backboard") == optarg) + g_launch_flavor = eLaunchFlavorBKS; #endif #ifdef WITH_FBS - else if (strcasestr(optarg, "frontboard") == optarg) - g_launch_flavor = eLaunchFlavorFBS; + else if (strcasestr(optarg, "frontboard") == optarg) + g_launch_flavor = eLaunchFlavorFBS; #endif - else - { - RNBLogSTDERR ("error: invalid TYPE for the --launch=TYPE (-x TYPE) option: '%s'\n", optarg); - RNBLogSTDERR ("Valid values TYPE are:\n"); - RNBLogSTDERR (" auto Auto-detect the best launch method to use.\n"); - RNBLogSTDERR (" posix Launch the executable using posix_spawn.\n"); - RNBLogSTDERR (" fork Launch the executable using fork and exec.\n"); + else { + RNBLogSTDERR("error: invalid TYPE for the --launch=TYPE (-x TYPE) " + "option: '%s'\n", + optarg); + RNBLogSTDERR("Valid values TYPE are:\n"); + RNBLogSTDERR( + " auto Auto-detect the best launch method to use.\n"); + RNBLogSTDERR( + " posix Launch the executable using posix_spawn.\n"); + RNBLogSTDERR( + " fork Launch the executable using fork and exec.\n"); #ifdef WITH_SPRINGBOARD - RNBLogSTDERR (" spring Launch the executable through Springboard.\n"); + RNBLogSTDERR( + " spring Launch the executable through Springboard.\n"); #endif #ifdef WITH_BKS - RNBLogSTDERR (" backboard Launch the executable through BackBoard Services.\n"); + RNBLogSTDERR(" backboard Launch the executable through BackBoard " + "Services.\n"); #endif #ifdef WITH_FBS - RNBLogSTDERR (" frontboard Launch the executable through FrontBoard Services.\n"); + RNBLogSTDERR(" frontboard Launch the executable through FrontBoard " + "Services.\n"); #endif - exit (5); - } - } - break; - - case 'l': // Set Log File - if (optarg && optarg[0]) - { - if (strcasecmp(optarg, "stdout") == 0) - log_file = stdout; - else if (strcasecmp(optarg, "stderr") == 0) - log_file = stderr; - else - { - log_file = fopen(optarg, "w"); - if (log_file != NULL) - setlinebuf(log_file); - } - - if (log_file == NULL) - { - const char *errno_str = strerror(errno); - RNBLogSTDERR ("Failed to open log file '%s' for writing: errno = %i (%s)", optarg, errno, errno_str ? errno_str : "unknown error"); - } - } - break; - - case 'f': // Log Flags - if (optarg && optarg[0]) - log_flags = static_cast<uint32_t>(strtoul(optarg, NULL, 0)); - break; - - case 'g': - debug = 1; - DNBLogSetDebug(debug); - break; - - case 't': - g_applist_opt = 1; - break; - - case 'k': - g_lockdown_opt = 1; - break; - - case 'r': - // Do nothing, native regs is the default these days - break; - - case 'R': - reverse_connect = true; - break; - case 'v': - DNBLogSetVerbose(1); - break; - - case 's': - ctx.GetSTDIN().assign(optarg); - ctx.GetSTDOUT().assign(optarg); - ctx.GetSTDERR().assign(optarg); - break; - - case 'I': - ctx.GetSTDIN().assign(optarg); - break; - - case 'O': - ctx.GetSTDOUT().assign(optarg); - break; - - case 'E': - ctx.GetSTDERR().assign(optarg); - break; - - case 'n': - no_stdio = true; - break; - - case 'S': - // Put debugserver into a new session. Terminals group processes - // into sessions and when a special terminal key sequences - // (like control+c) are typed they can cause signals to go out to - // all processes in a session. Using this --setsid (-S) option - // will cause debugserver to run in its own sessions and be free - // from such issues. - // - // This is useful when debugserver is spawned from a command - // line application that uses debugserver to do the debugging, - // yet that application doesn't want debugserver receiving the - // signals sent to the session (i.e. dying when anyone hits ^C). - setsid(); - break; - case 'D': - g_disable_aslr = 1; - break; - - case 'p': - start_mode = eRNBRunLoopModePlatformMode; - break; - - case 'u': - unix_socket_name.assign (optarg); - break; - - case 'P': - named_pipe_path.assign (optarg); - break; - - case 'e': - // Pass a single specified environment variable down to the process that gets launched - remote->Context().PushEnvironment(optarg); - break; - - case 'F': - // Pass the current environment down to the process that gets launched - { - char **host_env = *_NSGetEnviron(); - char *env_entry; - size_t i; - for (i=0; (env_entry = host_env[i]) != NULL; ++i) - remote->Context().PushEnvironment(env_entry); - } - break; - - case 'FDSC': - // File descriptor passed to this process during fork/exec and is already - // open and ready for communication. - communication_fd = atoi(optarg); - break; + exit(5); } + } + break; + + case 'l': // Set Log File + if (optarg && optarg[0]) { + if (strcasecmp(optarg, "stdout") == 0) + log_file = stdout; + else if (strcasecmp(optarg, "stderr") == 0) + log_file = stderr; + else { + log_file = fopen(optarg, "w"); + if (log_file != NULL) + setlinebuf(log_file); + } + + if (log_file == NULL) { + const char *errno_str = strerror(errno); + RNBLogSTDERR( + "Failed to open log file '%s' for writing: errno = %i (%s)", + optarg, errno, errno_str ? errno_str : "unknown error"); + } + } + break; + + case 'f': // Log Flags + if (optarg && optarg[0]) + log_flags = static_cast<uint32_t>(strtoul(optarg, NULL, 0)); + break; + + case 'g': + debug = 1; + DNBLogSetDebug(debug); + break; + + case 't': + g_applist_opt = 1; + break; + + case 'k': + g_lockdown_opt = 1; + break; + + case 'r': + // Do nothing, native regs is the default these days + break; + + case 'R': + reverse_connect = true; + break; + case 'v': + DNBLogSetVerbose(1); + break; + + case 's': + ctx.GetSTDIN().assign(optarg); + ctx.GetSTDOUT().assign(optarg); + ctx.GetSTDERR().assign(optarg); + break; + + case 'I': + ctx.GetSTDIN().assign(optarg); + break; + + case 'O': + ctx.GetSTDOUT().assign(optarg); + break; + + case 'E': + ctx.GetSTDERR().assign(optarg); + break; + + case 'n': + no_stdio = true; + break; + + case 'S': + // Put debugserver into a new session. Terminals group processes + // into sessions and when a special terminal key sequences + // (like control+c) are typed they can cause signals to go out to + // all processes in a session. Using this --setsid (-S) option + // will cause debugserver to run in its own sessions and be free + // from such issues. + // + // This is useful when debugserver is spawned from a command + // line application that uses debugserver to do the debugging, + // yet that application doesn't want debugserver receiving the + // signals sent to the session (i.e. dying when anyone hits ^C). + setsid(); + break; + case 'D': + g_disable_aslr = 1; + break; + + case 'p': + start_mode = eRNBRunLoopModePlatformMode; + break; + + case 'u': + unix_socket_name.assign(optarg); + break; + + case 'P': + named_pipe_path.assign(optarg); + break; + + case 'e': + // Pass a single specified environment variable down to the process that + // gets launched + remote->Context().PushEnvironment(optarg); + break; + + case 'F': + // Pass the current environment down to the process that gets launched + { + char **host_env = *_NSGetEnviron(); + char *env_entry; + size_t i; + for (i = 0; (env_entry = host_env[i]) != NULL; ++i) + remote->Context().PushEnvironment(env_entry); + } + break; + + case 'FDSC': + // File descriptor passed to this process during fork/exec and is already + // open and ready for communication. + communication_fd = atoi(optarg); + break; } + } - if (arch_name.empty()) - { -#if defined (__arm__) - arch_name.assign ("arm"); + if (arch_name.empty()) { +#if defined(__arm__) + arch_name.assign("arm"); #endif + } else { + DNBSetArchitecture(arch_name.c_str()); + } + + // if (arch_name.empty()) + // { + // fprintf(stderr, "error: no architecture was specified\n"); + // exit (8); + // } + // Skip any options we consumed with getopt_long_only + argc -= optind; + argv += optind; + + if (!working_dir.empty()) { + if (remote->Context().SetWorkingDirectory(working_dir.c_str()) == false) { + RNBLogSTDERR("error: working directory doesn't exist '%s'.\n", + working_dir.c_str()); + exit(8); } - else - { - DNBSetArchitecture (arch_name.c_str()); - } + } -// if (arch_name.empty()) -// { -// fprintf(stderr, "error: no architecture was specified\n"); -// exit (8); -// } - // Skip any options we consumed with getopt_long_only - argc -= optind; - argv += optind; - - - if (!working_dir.empty()) - { - if (remote->Context().SetWorkingDirectory (working_dir.c_str()) == false) - { - RNBLogSTDERR ("error: working directory doesn't exist '%s'.\n", working_dir.c_str()); - exit (8); - } - } + remote->Context().SetDetachOnError(g_detach_on_error); - remote->Context().SetDetachOnError(g_detach_on_error); + remote->Initialize(); - remote->Initialize(); + // It is ok for us to set NULL as the logfile (this will disable any logging) - // It is ok for us to set NULL as the logfile (this will disable any logging) + if (log_file != NULL) { + DNBLogSetLogCallback(FileLogCallback, log_file); + // If our log file was set, yet we have no log flags, log everything! + if (log_flags == 0) + log_flags = LOG_ALL | LOG_RNB_ALL; - if (log_file != NULL) - { - DNBLogSetLogCallback(FileLogCallback, log_file); - // If our log file was set, yet we have no log flags, log everything! - if (log_flags == 0) - log_flags = LOG_ALL | LOG_RNB_ALL; + DNBLogSetLogMask(log_flags); + } else { + // Enable DNB logging - DNBLogSetLogMask (log_flags); + // if os_log() support is available, log through that. + auto log_callback = OsLogger::GetLogFunction(); + if (log_callback) { + DNBLogSetLogCallback(log_callback, nullptr); + DNBLog("debugserver will use os_log for internal logging."); + } else { + // Fall back to ASL support. + DNBLogSetLogCallback(ASLLogCallback, NULL); + DNBLog("debugserver will use ASL for internal logging."); } - else - { - // Enable DNB logging - - // if os_log() support is available, log through that. - auto log_callback = OsLogger::GetLogFunction(); - if (log_callback) - { - DNBLogSetLogCallback(log_callback, nullptr); - DNBLog("debugserver will use os_log for internal logging."); - } - else - { - // Fall back to ASL support. - DNBLogSetLogCallback(ASLLogCallback, NULL); - DNBLog("debugserver will use ASL for internal logging."); - } - DNBLogSetLogMask (log_flags); + DNBLogSetLogMask(log_flags); + } - } - - if (DNBLogEnabled()) - { - for (i=0; i<argc; i++) - DNBLogDebug("argv[%i] = %s", i, argv[i]); - } + if (DNBLogEnabled()) { + for (i = 0; i < argc; i++) + DNBLogDebug("argv[%i] = %s", i, argv[i]); + } - // as long as we're dropping remotenub in as a replacement for gdbserver, - // explicitly note that this is not gdbserver. - - RNBLogSTDOUT ("%s-%s %sfor %s.\n", - DEBUGSERVER_PROGRAM_NAME, - DEBUGSERVER_VERSION_STR, - compile_options.c_str(), - RNB_ARCH); - - std::string host; - int port = INT32_MAX; - char str[PATH_MAX]; - str[0] = '\0'; - - if (g_lockdown_opt == 0 && g_applist_opt == 0 && communication_fd == -1) - { - // Make sure we at least have port - if (argc < 1) - { - show_usage_and_exit (1); - } - // accept 'localhost:' prefix on port number + // as long as we're dropping remotenub in as a replacement for gdbserver, + // explicitly note that this is not gdbserver. - int items_scanned = ::sscanf (argv[0], "%[^:]:%i", str, &port); - if (items_scanned == 2) - { - host = str; - DNBLogDebug("host = '%s' port = %i", host.c_str(), port); - } - else - { - // No hostname means "localhost" - int items_scanned = ::sscanf (argv[0], "%i", &port); - if (items_scanned == 1) - { - host = "127.0.0.1"; - DNBLogDebug("host = '%s' port = %i", host.c_str(), port); - } - else if (argv[0][0] == '/') - { - port = INT32_MAX; - strncpy(str, argv[0], sizeof(str)); - } - else - { - show_usage_and_exit (2); - } - } + RNBLogSTDOUT("%s-%s %sfor %s.\n", DEBUGSERVER_PROGRAM_NAME, + DEBUGSERVER_VERSION_STR, compile_options.c_str(), RNB_ARCH); - // We just used the 'host:port' or the '/path/file' arg... - argc--; - argv++; + std::string host; + int port = INT32_MAX; + char str[PATH_MAX]; + str[0] = '\0'; + if (g_lockdown_opt == 0 && g_applist_opt == 0 && communication_fd == -1) { + // Make sure we at least have port + if (argc < 1) { + show_usage_and_exit(1); + } + // accept 'localhost:' prefix on port number + + int items_scanned = ::sscanf(argv[0], "%[^:]:%i", str, &port); + if (items_scanned == 2) { + host = str; + DNBLogDebug("host = '%s' port = %i", host.c_str(), port); + } else { + // No hostname means "localhost" + int items_scanned = ::sscanf(argv[0], "%i", &port); + if (items_scanned == 1) { + host = "127.0.0.1"; + DNBLogDebug("host = '%s' port = %i", host.c_str(), port); + } else if (argv[0][0] == '/') { + port = INT32_MAX; + strncpy(str, argv[0], sizeof(str)); + } else { + show_usage_and_exit(2); + } } - // If we know we're waiting to attach, we don't need any of this other info. - if (start_mode != eRNBRunLoopModeInferiorAttaching && - start_mode != eRNBRunLoopModePlatformMode) - { - if (argc == 0 || g_lockdown_opt) - { - if (g_lockdown_opt != 0) - { - // Work around for SIGPIPE crashes due to posix_spawn issue. - // We have to close STDOUT and STDERR, else the first time we - // try and do any, we get SIGPIPE and die as posix_spawn is - // doing bad things with our file descriptors at the moment. - int null = open("/dev/null", O_RDWR); - dup2(null, STDOUT_FILENO); - dup2(null, STDERR_FILENO); - } - else if (g_applist_opt != 0) - { - // List all applications we are able to see - std::string applist_plist; - int err = ListApplications(applist_plist, false, false); - if (err == 0) - { - fputs (applist_plist.c_str(), stdout); - } - else - { - RNBLogSTDERR ("error: ListApplications returned error %i\n", err); - } - // Exit with appropriate error if we were asked to list the applications - // with no other args were given (and we weren't trying to do this over - // lockdown) - return err; - } - - DNBLogDebug("Get args from remote protocol..."); - start_mode = eRNBRunLoopModeGetStartModeFromRemoteProtocol; - } - else - { - start_mode = eRNBRunLoopModeInferiorLaunching; - // Fill in the argv array in the context from the rest of our args. - // Skip the name of this executable and the port number - for (int i = 0; i < argc; i++) - { - DNBLogDebug("inferior_argv[%i] = '%s'", i, argv[i]); - ctx.PushArgument (argv[i]); - } + // We just used the 'host:port' or the '/path/file' arg... + argc--; + argv++; + } + + // If we know we're waiting to attach, we don't need any of this other info. + if (start_mode != eRNBRunLoopModeInferiorAttaching && + start_mode != eRNBRunLoopModePlatformMode) { + if (argc == 0 || g_lockdown_opt) { + if (g_lockdown_opt != 0) { + // Work around for SIGPIPE crashes due to posix_spawn issue. + // We have to close STDOUT and STDERR, else the first time we + // try and do any, we get SIGPIPE and die as posix_spawn is + // doing bad things with our file descriptors at the moment. + int null = open("/dev/null", O_RDWR); + dup2(null, STDOUT_FILENO); + dup2(null, STDERR_FILENO); + } else if (g_applist_opt != 0) { + // List all applications we are able to see + std::string applist_plist; + int err = ListApplications(applist_plist, false, false); + if (err == 0) { + fputs(applist_plist.c_str(), stdout); + } else { + RNBLogSTDERR("error: ListApplications returned error %i\n", err); } + // Exit with appropriate error if we were asked to list the applications + // with no other args were given (and we weren't trying to do this over + // lockdown) + return err; + } + + DNBLogDebug("Get args from remote protocol..."); + start_mode = eRNBRunLoopModeGetStartModeFromRemoteProtocol; + } else { + start_mode = eRNBRunLoopModeInferiorLaunching; + // Fill in the argv array in the context from the rest of our args. + // Skip the name of this executable and the port number + for (int i = 0; i < argc; i++) { + DNBLogDebug("inferior_argv[%i] = '%s'", i, argv[i]); + ctx.PushArgument(argv[i]); + } } + } - if (start_mode == eRNBRunLoopModeExit) - return -1; + if (start_mode == eRNBRunLoopModeExit) + return -1; - RNBRunLoopMode mode = start_mode; - char err_str[1024] = {'\0'}; + RNBRunLoopMode mode = start_mode; + char err_str[1024] = {'\0'}; - while (mode != eRNBRunLoopModeExit) - { - switch (mode) - { - case eRNBRunLoopModeGetStartModeFromRemoteProtocol: + while (mode != eRNBRunLoopModeExit) { + switch (mode) { + case eRNBRunLoopModeGetStartModeFromRemoteProtocol: #ifdef WITH_LOCKDOWN - if (g_lockdown_opt) - { - if (!remote->Comm().IsConnected()) - { - if (remote->Comm().ConnectToService () != rnb_success) - { - RNBLogSTDERR ("Failed to get connection from a remote gdb process.\n"); - mode = eRNBRunLoopModeExit; - } - else if (g_applist_opt != 0) - { - // List all applications we are able to see - std::string applist_plist; - if (ListApplications(applist_plist, false, false) == 0) - { - DNBLogDebug("Task list: %s", applist_plist.c_str()); - - remote->Comm().Write(applist_plist.c_str(), applist_plist.size()); - // Issue a read that will never yield any data until the other side - // closes the socket so this process doesn't just exit and cause the - // socket to close prematurely on the other end and cause data loss. - std::string buf; - remote->Comm().Read(buf); - } - remote->Comm().Disconnect(false); - mode = eRNBRunLoopModeExit; - break; - } - else - { - // Start watching for remote packets - remote->StartReadRemoteDataThread(); - } - } - } - else + if (g_lockdown_opt) { + if (!remote->Comm().IsConnected()) { + if (remote->Comm().ConnectToService() != rnb_success) { + RNBLogSTDERR( + "Failed to get connection from a remote gdb process.\n"); + mode = eRNBRunLoopModeExit; + } else if (g_applist_opt != 0) { + // List all applications we are able to see + std::string applist_plist; + if (ListApplications(applist_plist, false, false) == 0) { + DNBLogDebug("Task list: %s", applist_plist.c_str()); + + remote->Comm().Write(applist_plist.c_str(), applist_plist.size()); + // Issue a read that will never yield any data until the other + // side + // closes the socket so this process doesn't just exit and cause + // the + // socket to close prematurely on the other end and cause data + // loss. + std::string buf; + remote->Comm().Read(buf); + } + remote->Comm().Disconnect(false); + mode = eRNBRunLoopModeExit; + break; + } else { + // Start watching for remote packets + remote->StartReadRemoteDataThread(); + } + } + } else #endif - if (port != INT32_MAX) - { - if (!ConnectRemote (remote, host.c_str(), port, reverse_connect, named_pipe_path.c_str(), unix_socket_name.c_str())) - mode = eRNBRunLoopModeExit; - } - else if (str[0] == '/') - { - if (remote->Comm().OpenFile (str)) - mode = eRNBRunLoopModeExit; - } - else if (communication_fd >= 0) - { - // We were passed a file descriptor to use during fork/exec that is already open - // in our process, so lets just use it! - if (remote->Comm().useFD(communication_fd)) - mode = eRNBRunLoopModeExit; - else - remote->StartReadRemoteDataThread(); - } - - if (mode != eRNBRunLoopModeExit) - { - RNBLogSTDOUT ("Got a connection, waiting for process information for launching or attaching.\n"); - - mode = RNBRunLoopGetStartModeFromRemote (remote); - } - break; - - case eRNBRunLoopModeInferiorAttaching: - if (!waitfor_pid_name.empty()) - { - // Set our end wait time if we are using a waitfor-duration - // option that may have been specified - struct timespec attach_timeout_abstime, *timeout_ptr = NULL; - if (waitfor_duration != 0) - { - DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, waitfor_duration, 0); - timeout_ptr = &attach_timeout_abstime; - } - nub_launch_flavor_t launch_flavor = g_launch_flavor; - if (launch_flavor == eLaunchFlavorDefault) - { - // Our default launch method is posix spawn - launch_flavor = eLaunchFlavorPosixSpawn; + if (port != INT32_MAX) { + if (!ConnectRemote(remote, host.c_str(), port, reverse_connect, + named_pipe_path.c_str(), unix_socket_name.c_str())) + mode = eRNBRunLoopModeExit; + } else if (str[0] == '/') { + if (remote->Comm().OpenFile(str)) + mode = eRNBRunLoopModeExit; + } else if (communication_fd >= 0) { + // We were passed a file descriptor to use during fork/exec that is + // already open + // in our process, so lets just use it! + if (remote->Comm().useFD(communication_fd)) + mode = eRNBRunLoopModeExit; + else + remote->StartReadRemoteDataThread(); + } + + if (mode != eRNBRunLoopModeExit) { + RNBLogSTDOUT("Got a connection, waiting for process information for " + "launching or attaching.\n"); + + mode = RNBRunLoopGetStartModeFromRemote(remote); + } + break; + + case eRNBRunLoopModeInferiorAttaching: + if (!waitfor_pid_name.empty()) { + // Set our end wait time if we are using a waitfor-duration + // option that may have been specified + struct timespec attach_timeout_abstime, *timeout_ptr = NULL; + if (waitfor_duration != 0) { + DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, waitfor_duration, + 0); + timeout_ptr = &attach_timeout_abstime; + } + nub_launch_flavor_t launch_flavor = g_launch_flavor; + if (launch_flavor == eLaunchFlavorDefault) { + // Our default launch method is posix spawn + launch_flavor = eLaunchFlavorPosixSpawn; #if defined WITH_FBS - // Check if we have an app bundle, if so launch using SpringBoard. - if (waitfor_pid_name.find (".app") != std::string::npos) - { - launch_flavor = eLaunchFlavorFBS; - } + // Check if we have an app bundle, if so launch using SpringBoard. + if (waitfor_pid_name.find(".app") != std::string::npos) { + launch_flavor = eLaunchFlavorFBS; + } #elif defined WITH_BKS - // Check if we have an app bundle, if so launch using SpringBoard. - if (waitfor_pid_name.find (".app") != std::string::npos) - { - launch_flavor = eLaunchFlavorBKS; - } + // Check if we have an app bundle, if so launch using SpringBoard. + if (waitfor_pid_name.find(".app") != std::string::npos) { + launch_flavor = eLaunchFlavorBKS; + } #elif defined WITH_SPRINGBOARD - // Check if we have an app bundle, if so launch using SpringBoard. - if (waitfor_pid_name.find (".app") != std::string::npos) - { - launch_flavor = eLaunchFlavorSpringBoard; - } + // Check if we have an app bundle, if so launch using SpringBoard. + if (waitfor_pid_name.find(".app") != std::string::npos) { + launch_flavor = eLaunchFlavorSpringBoard; + } #endif - } - - ctx.SetLaunchFlavor(launch_flavor); - bool ignore_existing = false; - RNBLogSTDOUT ("Waiting to attach to process %s...\n", waitfor_pid_name.c_str()); - nub_process_t pid = DNBProcessAttachWait (waitfor_pid_name.c_str(), launch_flavor, ignore_existing, timeout_ptr, waitfor_interval, err_str, sizeof(err_str)); - g_pid = pid; - - if (pid == INVALID_NUB_PROCESS) - { - ctx.LaunchStatus().SetError(-1, DNBError::Generic); - if (err_str[0]) - ctx.LaunchStatus().SetErrorString(err_str); - RNBLogSTDERR ("error: failed to attach to process named: \"%s\" %s\n", waitfor_pid_name.c_str(), err_str); - mode = eRNBRunLoopModeExit; - } - else - { - ctx.SetProcessID(pid); - mode = eRNBRunLoopModeInferiorExecuting; - } - } - else if (attach_pid != INVALID_NUB_PROCESS) - { - - RNBLogSTDOUT ("Attaching to process %i...\n", attach_pid); - nub_process_t attached_pid; - mode = RNBRunLoopLaunchAttaching (remote, attach_pid, attached_pid); - if (mode != eRNBRunLoopModeInferiorExecuting) - { - const char *error_str = remote->Context().LaunchStatus().AsString(); - RNBLogSTDERR ("error: failed to attach process %i: %s\n", attach_pid, error_str ? error_str : "unknown error."); - mode = eRNBRunLoopModeExit; - } - } - else if (!attach_pid_name.empty ()) - { - struct timespec attach_timeout_abstime, *timeout_ptr = NULL; - if (waitfor_duration != 0) - { - DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, waitfor_duration, 0); - timeout_ptr = &attach_timeout_abstime; - } - - RNBLogSTDOUT ("Attaching to process %s...\n", attach_pid_name.c_str()); - nub_process_t pid = DNBProcessAttachByName (attach_pid_name.c_str(), timeout_ptr, err_str, sizeof(err_str)); - g_pid = pid; - if (pid == INVALID_NUB_PROCESS) - { - ctx.LaunchStatus().SetError(-1, DNBError::Generic); - if (err_str[0]) - ctx.LaunchStatus().SetErrorString(err_str); - RNBLogSTDERR ("error: failed to attach to process named: \"%s\" %s\n", waitfor_pid_name.c_str(), err_str); - mode = eRNBRunLoopModeExit; - } - else - { - ctx.SetProcessID(pid); - mode = eRNBRunLoopModeInferiorExecuting; - } - - } - else - { - RNBLogSTDERR ("error: asked to attach with empty name and invalid PID.\n"); - mode = eRNBRunLoopModeExit; - } - - if (mode != eRNBRunLoopModeExit) - { - if (port != INT32_MAX) - { - if (!ConnectRemote (remote, host.c_str(), port, reverse_connect, named_pipe_path.c_str(), unix_socket_name.c_str())) - mode = eRNBRunLoopModeExit; - } - else if (str[0] == '/') - { - if (remote->Comm().OpenFile (str)) - mode = eRNBRunLoopModeExit; - } - else if (communication_fd >= 0) - { - // We were passed a file descriptor to use during fork/exec that is already open - // in our process, so lets just use it! - if (remote->Comm().useFD(communication_fd)) - mode = eRNBRunLoopModeExit; - else - remote->StartReadRemoteDataThread(); - } - - if (mode != eRNBRunLoopModeExit) - RNBLogSTDOUT ("Waiting for debugger instructions for process %d.\n", attach_pid); - } - break; - - case eRNBRunLoopModeInferiorLaunching: - { - mode = RNBRunLoopLaunchInferior (remote, - ctx.GetSTDINPath(), - ctx.GetSTDOUTPath(), - ctx.GetSTDERRPath(), - no_stdio); - - if (mode == eRNBRunLoopModeInferiorExecuting) - { - if (port != INT32_MAX) - { - if (!ConnectRemote (remote, host.c_str(), port, reverse_connect, named_pipe_path.c_str(), unix_socket_name.c_str())) - mode = eRNBRunLoopModeExit; - } - else if (str[0] == '/') - { - if (remote->Comm().OpenFile (str)) - mode = eRNBRunLoopModeExit; - } - else if (communication_fd >= 0) - { - // We were passed a file descriptor to use during fork/exec that is already open - // in our process, so lets just use it! - if (remote->Comm().useFD(communication_fd)) - mode = eRNBRunLoopModeExit; - else - remote->StartReadRemoteDataThread(); - } - - if (mode != eRNBRunLoopModeExit) - { - const char *proc_name = "<unknown>"; - if (ctx.ArgumentCount() > 0) - proc_name = ctx.ArgumentAtIndex(0); - RNBLogSTDOUT ("Got a connection, launched process %s (pid = %d).\n", proc_name, ctx.ProcessID()); - } - } - else - { - const char *error_str = remote->Context().LaunchStatus().AsString(); - RNBLogSTDERR ("error: failed to launch process %s: %s\n", argv_sub_zero, error_str ? error_str : "unknown error."); - } - } - break; - - case eRNBRunLoopModeInferiorExecuting: - mode = RNBRunLoopInferiorExecuting(remote); - break; - - case eRNBRunLoopModePlatformMode: - if (port != INT32_MAX) - { - if (!ConnectRemote (remote, host.c_str(), port, reverse_connect, named_pipe_path.c_str(), unix_socket_name.c_str())) - mode = eRNBRunLoopModeExit; - } - else if (str[0] == '/') - { - if (remote->Comm().OpenFile (str)) - mode = eRNBRunLoopModeExit; - } - else if (communication_fd >= 0) - { - // We were passed a file descriptor to use during fork/exec that is already open - // in our process, so lets just use it! - if (remote->Comm().useFD(communication_fd)) - mode = eRNBRunLoopModeExit; - else - remote->StartReadRemoteDataThread(); - } - - if (mode != eRNBRunLoopModeExit) - mode = RNBRunLoopPlatform (remote); - break; - - default: - mode = eRNBRunLoopModeExit; - case eRNBRunLoopModeExit: - break; } + + ctx.SetLaunchFlavor(launch_flavor); + bool ignore_existing = false; + RNBLogSTDOUT("Waiting to attach to process %s...\n", + waitfor_pid_name.c_str()); + nub_process_t pid = DNBProcessAttachWait( + waitfor_pid_name.c_str(), launch_flavor, ignore_existing, + timeout_ptr, waitfor_interval, err_str, sizeof(err_str)); + g_pid = pid; + + if (pid == INVALID_NUB_PROCESS) { + ctx.LaunchStatus().SetError(-1, DNBError::Generic); + if (err_str[0]) + ctx.LaunchStatus().SetErrorString(err_str); + RNBLogSTDERR("error: failed to attach to process named: \"%s\" %s\n", + waitfor_pid_name.c_str(), err_str); + mode = eRNBRunLoopModeExit; + } else { + ctx.SetProcessID(pid); + mode = eRNBRunLoopModeInferiorExecuting; + } + } else if (attach_pid != INVALID_NUB_PROCESS) { + + RNBLogSTDOUT("Attaching to process %i...\n", attach_pid); + nub_process_t attached_pid; + mode = RNBRunLoopLaunchAttaching(remote, attach_pid, attached_pid); + if (mode != eRNBRunLoopModeInferiorExecuting) { + const char *error_str = remote->Context().LaunchStatus().AsString(); + RNBLogSTDERR("error: failed to attach process %i: %s\n", attach_pid, + error_str ? error_str : "unknown error."); + mode = eRNBRunLoopModeExit; + } + } else if (!attach_pid_name.empty()) { + struct timespec attach_timeout_abstime, *timeout_ptr = NULL; + if (waitfor_duration != 0) { + DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, waitfor_duration, + 0); + timeout_ptr = &attach_timeout_abstime; + } + + RNBLogSTDOUT("Attaching to process %s...\n", attach_pid_name.c_str()); + nub_process_t pid = DNBProcessAttachByName( + attach_pid_name.c_str(), timeout_ptr, err_str, sizeof(err_str)); + g_pid = pid; + if (pid == INVALID_NUB_PROCESS) { + ctx.LaunchStatus().SetError(-1, DNBError::Generic); + if (err_str[0]) + ctx.LaunchStatus().SetErrorString(err_str); + RNBLogSTDERR("error: failed to attach to process named: \"%s\" %s\n", + waitfor_pid_name.c_str(), err_str); + mode = eRNBRunLoopModeExit; + } else { + ctx.SetProcessID(pid); + mode = eRNBRunLoopModeInferiorExecuting; + } + + } else { + RNBLogSTDERR( + "error: asked to attach with empty name and invalid PID.\n"); + mode = eRNBRunLoopModeExit; + } + + if (mode != eRNBRunLoopModeExit) { + if (port != INT32_MAX) { + if (!ConnectRemote(remote, host.c_str(), port, reverse_connect, + named_pipe_path.c_str(), unix_socket_name.c_str())) + mode = eRNBRunLoopModeExit; + } else if (str[0] == '/') { + if (remote->Comm().OpenFile(str)) + mode = eRNBRunLoopModeExit; + } else if (communication_fd >= 0) { + // We were passed a file descriptor to use during fork/exec that is + // already open + // in our process, so lets just use it! + if (remote->Comm().useFD(communication_fd)) + mode = eRNBRunLoopModeExit; + else + remote->StartReadRemoteDataThread(); + } + + if (mode != eRNBRunLoopModeExit) + RNBLogSTDOUT("Waiting for debugger instructions for process %d.\n", + attach_pid); + } + break; + + case eRNBRunLoopModeInferiorLaunching: { + mode = RNBRunLoopLaunchInferior(remote, ctx.GetSTDINPath(), + ctx.GetSTDOUTPath(), ctx.GetSTDERRPath(), + no_stdio); + + if (mode == eRNBRunLoopModeInferiorExecuting) { + if (port != INT32_MAX) { + if (!ConnectRemote(remote, host.c_str(), port, reverse_connect, + named_pipe_path.c_str(), unix_socket_name.c_str())) + mode = eRNBRunLoopModeExit; + } else if (str[0] == '/') { + if (remote->Comm().OpenFile(str)) + mode = eRNBRunLoopModeExit; + } else if (communication_fd >= 0) { + // We were passed a file descriptor to use during fork/exec that is + // already open + // in our process, so lets just use it! + if (remote->Comm().useFD(communication_fd)) + mode = eRNBRunLoopModeExit; + else + remote->StartReadRemoteDataThread(); + } + + if (mode != eRNBRunLoopModeExit) { + const char *proc_name = "<unknown>"; + if (ctx.ArgumentCount() > 0) + proc_name = ctx.ArgumentAtIndex(0); + RNBLogSTDOUT("Got a connection, launched process %s (pid = %d).\n", + proc_name, ctx.ProcessID()); + } + } else { + const char *error_str = remote->Context().LaunchStatus().AsString(); + RNBLogSTDERR("error: failed to launch process %s: %s\n", argv_sub_zero, + error_str ? error_str : "unknown error."); + } + } break; + + case eRNBRunLoopModeInferiorExecuting: + mode = RNBRunLoopInferiorExecuting(remote); + break; + + case eRNBRunLoopModePlatformMode: + if (port != INT32_MAX) { + if (!ConnectRemote(remote, host.c_str(), port, reverse_connect, + named_pipe_path.c_str(), unix_socket_name.c_str())) + mode = eRNBRunLoopModeExit; + } else if (str[0] == '/') { + if (remote->Comm().OpenFile(str)) + mode = eRNBRunLoopModeExit; + } else if (communication_fd >= 0) { + // We were passed a file descriptor to use during fork/exec that is + // already open + // in our process, so lets just use it! + if (remote->Comm().useFD(communication_fd)) + mode = eRNBRunLoopModeExit; + else + remote->StartReadRemoteDataThread(); + } + + if (mode != eRNBRunLoopModeExit) + mode = RNBRunLoopPlatform(remote); + break; + + default: + mode = eRNBRunLoopModeExit; + case eRNBRunLoopModeExit: + break; } + } - remote->StopReadRemoteDataThread (); - remote->Context().SetProcessID(INVALID_NUB_PROCESS); - RNBLogSTDOUT ("Exiting.\n"); + remote->StopReadRemoteDataThread(); + remote->Context().SetProcessID(INVALID_NUB_PROCESS); + RNBLogSTDOUT("Exiting.\n"); - return 0; + return 0; } diff --git a/lldb/tools/debugserver/source/libdebugserver.cpp b/lldb/tools/debugserver/source/libdebugserver.cpp index 63d76eb26ae..0d27cfd89a3 100644 --- a/lldb/tools/debugserver/source/libdebugserver.cpp +++ b/lldb/tools/debugserver/source/libdebugserver.cpp @@ -7,36 +7,34 @@ // //===----------------------------------------------------------------------===// -#include <sys/socket.h> -#include <sys/types.h> #include <errno.h> #include <getopt.h> #include <netinet/in.h> #include <sys/select.h> +#include <sys/socket.h> #include <sys/sysctl.h> +#include <sys/types.h> #include "DNB.h" #include "DNBLog.h" #include "DNBTimer.h" #include "PseudoTerminal.h" #include "RNBContext.h" +#include "RNBRemote.h" #include "RNBServices.h" #include "RNBSocket.h" -#include "RNBRemote.h" #include "SysSignal.h" //---------------------------------------------------------------------- // Run loop modes which determine which run loop function will be called //---------------------------------------------------------------------- -typedef enum -{ - eRNBRunLoopModeInvalid = 0, - eRNBRunLoopModeGetStartModeFromRemoteProtocol, - eRNBRunLoopModeInferiorExecuting, - eRNBRunLoopModeExit +typedef enum { + eRNBRunLoopModeInvalid = 0, + eRNBRunLoopModeGetStartModeFromRemoteProtocol, + eRNBRunLoopModeInferiorExecuting, + eRNBRunLoopModeExit } RNBRunLoopMode; - //---------------------------------------------------------------------- // Global Variables //---------------------------------------------------------------------- @@ -44,9 +42,22 @@ RNBRemoteSP g_remoteSP; int g_disable_aslr = 0; int g_isatty = 0; -#define RNBLogSTDOUT(fmt, ...) do { if (g_isatty) { fprintf(stdout, fmt, ## __VA_ARGS__); } else { _DNBLog(0, fmt, ## __VA_ARGS__); } } while (0) -#define RNBLogSTDERR(fmt, ...) do { if (g_isatty) { fprintf(stderr, fmt, ## __VA_ARGS__); } else { _DNBLog(0, fmt, ## __VA_ARGS__); } } while (0) - +#define RNBLogSTDOUT(fmt, ...) \ + do { \ + if (g_isatty) { \ + fprintf(stdout, fmt, ##__VA_ARGS__); \ + } else { \ + _DNBLog(0, fmt, ##__VA_ARGS__); \ + } \ + } while (0) +#define RNBLogSTDERR(fmt, ...) \ + do { \ + if (g_isatty) { \ + fprintf(stderr, fmt, ##__VA_ARGS__); \ + } else { \ + _DNBLog(0, fmt, ##__VA_ARGS__); \ + } \ + } while (0) //---------------------------------------------------------------------- // Get our program path and arguments from the remote connection. @@ -54,74 +65,65 @@ int g_isatty = 0; // arguments, wait for the new process to finish launching and hit its // entry point, and then return the run loop mode that should come next. //---------------------------------------------------------------------- -RNBRunLoopMode -RNBRunLoopGetStartModeFromRemote (RNBRemoteSP &remoteSP) -{ - std::string packet; - - if (remoteSP.get() != NULL) - { - RNBRemote* remote = remoteSP.get(); - RNBContext& ctx = remote->Context(); - uint32_t event_mask = RNBContext::event_read_packet_available; - - // Spin waiting to get the A packet. - while (1) - { - DNBLogThreadedIf (LOG_RNB_MAX, "%s ctx.Events().WaitForSetEvents( 0x%08x ) ...",__FUNCTION__, event_mask); - nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); - DNBLogThreadedIf (LOG_RNB_MAX, "%s ctx.Events().WaitForSetEvents( 0x%08x ) => 0x%08x", __FUNCTION__, event_mask, set_events); - - if (set_events & RNBContext::event_read_packet_available) - { - rnb_err_t err = rnb_err; - RNBRemote::PacketEnum type; - - err = remote->HandleReceivedPacket (&type); - - // check if we tried to attach to a process - if (type == RNBRemote::vattach || type == RNBRemote::vattachwait) - { - if (err == rnb_success) - return eRNBRunLoopModeInferiorExecuting; - else - { - RNBLogSTDERR ("error: attach failed."); - return eRNBRunLoopModeExit; - } - } - - - if (err == rnb_success) - { - DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Got success...",__FUNCTION__); - continue; - } - else if (err == rnb_not_connected) - { - RNBLogSTDERR ("error: connection lost."); - return eRNBRunLoopModeExit; - } - else - { - // a catch all for any other gdb remote packets that failed - DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Error getting packet.",__FUNCTION__); - continue; - } - - DNBLogThreadedIf (LOG_RNB_MINIMAL, "#### %s", __FUNCTION__); - } - else - { - DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s Connection closed before getting \"A\" packet.", __FUNCTION__); - return eRNBRunLoopModeExit; - } +RNBRunLoopMode RNBRunLoopGetStartModeFromRemote(RNBRemoteSP &remoteSP) { + std::string packet; + + if (remoteSP.get() != NULL) { + RNBRemote *remote = remoteSP.get(); + RNBContext &ctx = remote->Context(); + uint32_t event_mask = RNBContext::event_read_packet_available; + + // Spin waiting to get the A packet. + while (1) { + DNBLogThreadedIf(LOG_RNB_MAX, + "%s ctx.Events().WaitForSetEvents( 0x%08x ) ...", + __FUNCTION__, event_mask); + nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); + DNBLogThreadedIf(LOG_RNB_MAX, + "%s ctx.Events().WaitForSetEvents( 0x%08x ) => 0x%08x", + __FUNCTION__, event_mask, set_events); + + if (set_events & RNBContext::event_read_packet_available) { + rnb_err_t err = rnb_err; + RNBRemote::PacketEnum type; + + err = remote->HandleReceivedPacket(&type); + + // check if we tried to attach to a process + if (type == RNBRemote::vattach || type == RNBRemote::vattachwait) { + if (err == rnb_success) + return eRNBRunLoopModeInferiorExecuting; + else { + RNBLogSTDERR("error: attach failed."); + return eRNBRunLoopModeExit; + } + } + + if (err == rnb_success) { + DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s Got success...", __FUNCTION__); + continue; + } else if (err == rnb_not_connected) { + RNBLogSTDERR("error: connection lost."); + return eRNBRunLoopModeExit; + } else { + // a catch all for any other gdb remote packets that failed + DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s Error getting packet.", + __FUNCTION__); + continue; } + + DNBLogThreadedIf(LOG_RNB_MINIMAL, "#### %s", __FUNCTION__); + } else { + DNBLogThreadedIf(LOG_RNB_MINIMAL, + "%s Connection closed before getting \"A\" packet.", + __FUNCTION__); + return eRNBRunLoopModeExit; + } } - return eRNBRunLoopModeExit; + } + return eRNBRunLoopModeExit; } - //---------------------------------------------------------------------- // Watch for signals: // SIGINT: so we can halt our inferior. (disabled for now) @@ -129,269 +131,253 @@ RNBRunLoopGetStartModeFromRemote (RNBRemoteSP &remoteSP) //---------------------------------------------------------------------- nub_process_t g_pid; int g_sigpipe_received = 0; -void -signal_handler(int signo) -{ - DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s (%s)", __FUNCTION__, SysSignal::Name(signo)); - - switch (signo) - { - // case SIGINT: - // DNBProcessKill (g_pid, signo); - // break; - - case SIGPIPE: - g_sigpipe_received = 1; - break; - } +void signal_handler(int signo) { + DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s (%s)", __FUNCTION__, + SysSignal::Name(signo)); + + switch (signo) { + // case SIGINT: + // DNBProcessKill (g_pid, signo); + // break; + + case SIGPIPE: + g_sigpipe_received = 1; + break; + } } // Return the new run loop mode based off of the current process state -RNBRunLoopMode -HandleProcessStateChange (RNBRemoteSP &remote, bool initialize) -{ - RNBContext& ctx = remote->Context(); - nub_process_t pid = ctx.ProcessID(); - - if (pid == INVALID_NUB_PROCESS) - { - DNBLogThreadedIf (LOG_RNB_MINIMAL, "#### %s error: pid invalid, exiting...", __FUNCTION__); - return eRNBRunLoopModeExit; - } - nub_state_t pid_state = DNBProcessGetState (pid); - - DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) pid_state = %s", __FUNCTION__, (int)initialize, DNBStateAsString (pid_state)); - - switch (pid_state) - { - case eStateInvalid: - case eStateUnloaded: - // Something bad happened - return eRNBRunLoopModeExit; - break; - - case eStateAttaching: - case eStateLaunching: - return eRNBRunLoopModeInferiorExecuting; - - case eStateSuspended: - case eStateCrashed: - case eStateStopped: - if (initialize == false) - { - // Compare the last stop count to our current notion of a stop count - // to make sure we don't notify more than once for a given stop. - nub_size_t prev_pid_stop_count = ctx.GetProcessStopCount(); - bool pid_stop_count_changed = ctx.SetProcessStopCount(DNBProcessGetStopCount(pid)); - if (pid_stop_count_changed) - { - remote->FlushSTDIO(); - - if (ctx.GetProcessStopCount() == 1) - { - DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) pid_state = %s pid_stop_count %zu (old %zu)) Notify??? no, first stop...", __FUNCTION__, (int)initialize, DNBStateAsString (pid_state), ctx.GetProcessStopCount(), prev_pid_stop_count); - } - else - { - - DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) pid_state = %s pid_stop_count %zu (old %zu)) Notify??? YES!!!", __FUNCTION__, (int)initialize, DNBStateAsString (pid_state), ctx.GetProcessStopCount(), prev_pid_stop_count); - remote->NotifyThatProcessStopped (); - } - } - else - { - DNBLogThreadedIf (LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) pid_state = %s pid_stop_count %zu (old %zu)) Notify??? skipping...", __FUNCTION__, (int)initialize, DNBStateAsString (pid_state), ctx.GetProcessStopCount(), prev_pid_stop_count); - } - } - return eRNBRunLoopModeInferiorExecuting; - - case eStateStepping: - case eStateRunning: - return eRNBRunLoopModeInferiorExecuting; - - case eStateExited: - remote->HandlePacket_last_signal(NULL); - return eRNBRunLoopModeExit; - case eStateDetached: - return eRNBRunLoopModeExit; - +RNBRunLoopMode HandleProcessStateChange(RNBRemoteSP &remote, bool initialize) { + RNBContext &ctx = remote->Context(); + nub_process_t pid = ctx.ProcessID(); + + if (pid == INVALID_NUB_PROCESS) { + DNBLogThreadedIf(LOG_RNB_MINIMAL, "#### %s error: pid invalid, exiting...", + __FUNCTION__); + return eRNBRunLoopModeExit; + } + nub_state_t pid_state = DNBProcessGetState(pid); + + DNBLogThreadedIf(LOG_RNB_MINIMAL, + "%s (&remote, initialize=%i) pid_state = %s", __FUNCTION__, + (int)initialize, DNBStateAsString(pid_state)); + + switch (pid_state) { + case eStateInvalid: + case eStateUnloaded: + // Something bad happened + return eRNBRunLoopModeExit; + break; + + case eStateAttaching: + case eStateLaunching: + return eRNBRunLoopModeInferiorExecuting; + + case eStateSuspended: + case eStateCrashed: + case eStateStopped: + if (initialize == false) { + // Compare the last stop count to our current notion of a stop count + // to make sure we don't notify more than once for a given stop. + nub_size_t prev_pid_stop_count = ctx.GetProcessStopCount(); + bool pid_stop_count_changed = + ctx.SetProcessStopCount(DNBProcessGetStopCount(pid)); + if (pid_stop_count_changed) { + remote->FlushSTDIO(); + + if (ctx.GetProcessStopCount() == 1) { + DNBLogThreadedIf( + LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) pid_state = %s " + "pid_stop_count %zu (old %zu)) Notify??? no, " + "first stop...", + __FUNCTION__, (int)initialize, DNBStateAsString(pid_state), + ctx.GetProcessStopCount(), prev_pid_stop_count); + } else { + + DNBLogThreadedIf( + LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) pid_state = %s " + "pid_stop_count %zu (old %zu)) Notify??? YES!!!", + __FUNCTION__, (int)initialize, DNBStateAsString(pid_state), + ctx.GetProcessStopCount(), prev_pid_stop_count); + remote->NotifyThatProcessStopped(); + } + } else { + DNBLogThreadedIf(LOG_RNB_MINIMAL, "%s (&remote, initialize=%i) " + "pid_state = %s pid_stop_count %zu " + "(old %zu)) Notify??? skipping...", + __FUNCTION__, (int)initialize, + DNBStateAsString(pid_state), ctx.GetProcessStopCount(), + prev_pid_stop_count); + } } - - // Catch all... - return eRNBRunLoopModeExit; + return eRNBRunLoopModeInferiorExecuting; + + case eStateStepping: + case eStateRunning: + return eRNBRunLoopModeInferiorExecuting; + + case eStateExited: + remote->HandlePacket_last_signal(NULL); + return eRNBRunLoopModeExit; + case eStateDetached: + return eRNBRunLoopModeExit; + } + + // Catch all... + return eRNBRunLoopModeExit; } // This function handles the case where our inferior program is stopped and // we are waiting for gdb remote protocol packets. When a packet occurs that // makes the inferior run, we need to leave this function with a new state // as the return code. -RNBRunLoopMode -RNBRunLoopInferiorExecuting (RNBRemoteSP &remote) -{ - DNBLogThreadedIf (LOG_RNB_MINIMAL, "#### %s", __FUNCTION__); - RNBContext& ctx = remote->Context(); - - // Init our mode and set 'is_running' based on the current process state - RNBRunLoopMode mode = HandleProcessStateChange (remote, true); - - while (ctx.ProcessID() != INVALID_NUB_PROCESS) - { - - std::string set_events_str; - uint32_t event_mask = ctx.NormalEventBits(); - - if (!ctx.ProcessStateRunning()) - { - // Clear the stdio bits if we are not running so we don't send any async packets - event_mask &= ~RNBContext::event_proc_stdio_available; +RNBRunLoopMode RNBRunLoopInferiorExecuting(RNBRemoteSP &remote) { + DNBLogThreadedIf(LOG_RNB_MINIMAL, "#### %s", __FUNCTION__); + RNBContext &ctx = remote->Context(); + + // Init our mode and set 'is_running' based on the current process state + RNBRunLoopMode mode = HandleProcessStateChange(remote, true); + + while (ctx.ProcessID() != INVALID_NUB_PROCESS) { + + std::string set_events_str; + uint32_t event_mask = ctx.NormalEventBits(); + + if (!ctx.ProcessStateRunning()) { + // Clear the stdio bits if we are not running so we don't send any async + // packets + event_mask &= ~RNBContext::event_proc_stdio_available; + } + + // We want to make sure we consume all process state changes and have + // whomever is notifying us to wait for us to reset the event bit before + // continuing. + // ctx.Events().SetResetAckMask (RNBContext::event_proc_state_changed); + + DNBLogThreadedIf(LOG_RNB_EVENTS, + "%s ctx.Events().WaitForSetEvents(0x%08x) ...", + __FUNCTION__, event_mask); + nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); + DNBLogThreadedIf(LOG_RNB_EVENTS, + "%s ctx.Events().WaitForSetEvents(0x%08x) => 0x%08x (%s)", + __FUNCTION__, event_mask, set_events, + ctx.EventsAsString(set_events, set_events_str)); + + if (set_events) { + if ((set_events & RNBContext::event_proc_thread_exiting) || + (set_events & RNBContext::event_proc_stdio_available)) { + remote->FlushSTDIO(); + } + + if (set_events & RNBContext::event_read_packet_available) { + // handleReceivedPacket will take care of resetting the + // event_read_packet_available events when there are no more... + set_events ^= RNBContext::event_read_packet_available; + + if (ctx.ProcessStateRunning()) { + if (remote->HandleAsyncPacket() == rnb_not_connected) { + // TODO: connect again? Exit? + } + } else { + if (remote->HandleReceivedPacket() == rnb_not_connected) { + // TODO: connect again? Exit? + } } - - // We want to make sure we consume all process state changes and have - // whomever is notifying us to wait for us to reset the event bit before - // continuing. - //ctx.Events().SetResetAckMask (RNBContext::event_proc_state_changed); - - DNBLogThreadedIf (LOG_RNB_EVENTS, "%s ctx.Events().WaitForSetEvents(0x%08x) ...",__FUNCTION__, event_mask); - nub_event_t set_events = ctx.Events().WaitForSetEvents(event_mask); - DNBLogThreadedIf (LOG_RNB_EVENTS, "%s ctx.Events().WaitForSetEvents(0x%08x) => 0x%08x (%s)",__FUNCTION__, event_mask, set_events, ctx.EventsAsString(set_events, set_events_str)); - - if (set_events) - { - if ((set_events & RNBContext::event_proc_thread_exiting) || - (set_events & RNBContext::event_proc_stdio_available)) - { - remote->FlushSTDIO(); - } - - if (set_events & RNBContext::event_read_packet_available) - { - // handleReceivedPacket will take care of resetting the - // event_read_packet_available events when there are no more... - set_events ^= RNBContext::event_read_packet_available; - - if (ctx.ProcessStateRunning()) - { - if (remote->HandleAsyncPacket() == rnb_not_connected) - { - // TODO: connect again? Exit? - } - } - else - { - if (remote->HandleReceivedPacket() == rnb_not_connected) - { - // TODO: connect again? Exit? - } - } - } - - if (set_events & RNBContext::event_proc_state_changed) - { - mode = HandleProcessStateChange (remote, false); - ctx.Events().ResetEvents(RNBContext::event_proc_state_changed); - set_events ^= RNBContext::event_proc_state_changed; - } - - if (set_events & RNBContext::event_proc_thread_exiting) - { - mode = eRNBRunLoopModeExit; - } - - if (set_events & RNBContext::event_read_thread_exiting) - { - // Out remote packet receiving thread exited, exit for now. - if (ctx.HasValidProcessID()) - { - // TODO: We should add code that will leave the current process - // in its current state and listen for another connection... - if (ctx.ProcessStateRunning()) - { - DNBProcessKill (ctx.ProcessID()); - } - } - mode = eRNBRunLoopModeExit; - } + } + + if (set_events & RNBContext::event_proc_state_changed) { + mode = HandleProcessStateChange(remote, false); + ctx.Events().ResetEvents(RNBContext::event_proc_state_changed); + set_events ^= RNBContext::event_proc_state_changed; + } + + if (set_events & RNBContext::event_proc_thread_exiting) { + mode = eRNBRunLoopModeExit; + } + + if (set_events & RNBContext::event_read_thread_exiting) { + // Out remote packet receiving thread exited, exit for now. + if (ctx.HasValidProcessID()) { + // TODO: We should add code that will leave the current process + // in its current state and listen for another connection... + if (ctx.ProcessStateRunning()) { + DNBProcessKill(ctx.ProcessID()); + } } - - // Reset all event bits that weren't reset for now... - if (set_events != 0) - ctx.Events().ResetEvents(set_events); - - if (mode != eRNBRunLoopModeInferiorExecuting) - break; + mode = eRNBRunLoopModeExit; + } } - - return mode; + + // Reset all event bits that weren't reset for now... + if (set_events != 0) + ctx.Events().ResetEvents(set_events); + + if (mode != eRNBRunLoopModeInferiorExecuting) + break; + } + + return mode; } -void -ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args) -{ +void ASLLogCallback(void *baton, uint32_t flags, const char *format, + va_list args) { #if 0 vprintf(format, args); #endif } -extern "C" int -debug_server_main(int fd) -{ +extern "C" int debug_server_main(int fd) { #if 1 - g_isatty = 0; + g_isatty = 0; #else - g_isatty = ::isatty (STDIN_FILENO); + g_isatty = ::isatty(STDIN_FILENO); - DNBLogSetDebug(1); - DNBLogSetVerbose(1); - DNBLogSetLogMask(-1); - DNBLogSetLogCallback(ASLLogCallback, NULL); + DNBLogSetDebug(1); + DNBLogSetVerbose(1); + DNBLogSetLogMask(-1); + DNBLogSetLogCallback(ASLLogCallback, NULL); #endif - - signal (SIGPIPE, signal_handler); - - g_remoteSP.reset (new RNBRemote); - - RNBRemote *remote = g_remoteSP.get(); - if (remote == NULL) - { - RNBLogSTDERR ("error: failed to create a remote connection class\n"); - return -1; - } - - - RNBRunLoopMode mode = eRNBRunLoopModeGetStartModeFromRemoteProtocol; - - while (mode != eRNBRunLoopModeExit) - { - switch (mode) - { - case eRNBRunLoopModeGetStartModeFromRemoteProtocol: - if (g_remoteSP->Comm().useFD(fd) == rnb_success) { - RNBLogSTDOUT("Starting remote data thread.\n"); - g_remoteSP->StartReadRemoteDataThread(); - - RNBLogSTDOUT("Waiting for start mode from remote.\n"); - mode = RNBRunLoopGetStartModeFromRemote(g_remoteSP); - } - else - { - mode = eRNBRunLoopModeExit; - } - break; - - case eRNBRunLoopModeInferiorExecuting: - mode = RNBRunLoopInferiorExecuting(g_remoteSP); - break; - - default: - mode = eRNBRunLoopModeExit; - break; - - case eRNBRunLoopModeExit: - break; - } + + signal(SIGPIPE, signal_handler); + + g_remoteSP.reset(new RNBRemote); + + RNBRemote *remote = g_remoteSP.get(); + if (remote == NULL) { + RNBLogSTDERR("error: failed to create a remote connection class\n"); + return -1; + } + + RNBRunLoopMode mode = eRNBRunLoopModeGetStartModeFromRemoteProtocol; + + while (mode != eRNBRunLoopModeExit) { + switch (mode) { + case eRNBRunLoopModeGetStartModeFromRemoteProtocol: + if (g_remoteSP->Comm().useFD(fd) == rnb_success) { + RNBLogSTDOUT("Starting remote data thread.\n"); + g_remoteSP->StartReadRemoteDataThread(); + + RNBLogSTDOUT("Waiting for start mode from remote.\n"); + mode = RNBRunLoopGetStartModeFromRemote(g_remoteSP); + } else { + mode = eRNBRunLoopModeExit; + } + break; + + case eRNBRunLoopModeInferiorExecuting: + mode = RNBRunLoopInferiorExecuting(g_remoteSP); + break; + + default: + mode = eRNBRunLoopModeExit; + break; + + case eRNBRunLoopModeExit: + break; } - - g_remoteSP->StopReadRemoteDataThread (); - g_remoteSP->Context().SetProcessID(INVALID_NUB_PROCESS); - - return 0; + } + + g_remoteSP->StopReadRemoteDataThread(); + g_remoteSP->Context().SetProcessID(INVALID_NUB_PROCESS); + + return 0; } diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp index c057d71a830..db950153753 100644 --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -9,16 +9,16 @@ #include "Driver.h" +#include <fcntl.h> +#include <limits.h> #include <stdio.h> -#include <string.h> #include <stdlib.h> -#include <limits.h> -#include <fcntl.h> +#include <string.h> // Includes for pipe() #if defined(_WIN32) -#include <io.h> #include <fcntl.h> +#include <io.h> #elif defined(__ANDROID_NDK__) #include <errno.h> #else @@ -50,7 +50,7 @@ using namespace lldb; -static void reset_stdin_termios (); +static void reset_stdin_termios(); static bool g_old_stdin_termios_is_valid = false; static struct termios g_old_stdin_termios; @@ -58,1253 +58,1155 @@ static Driver *g_driver = NULL; // In the Driver::MainLoop, we change the terminal settings. This function is // added as an atexit handler to make sure we clean them up. -static void -reset_stdin_termios () -{ - if (g_old_stdin_termios_is_valid) - { - g_old_stdin_termios_is_valid = false; - ::tcsetattr (STDIN_FILENO, TCSANOW, &g_old_stdin_termios); - } +static void reset_stdin_termios() { + if (g_old_stdin_termios_is_valid) { + g_old_stdin_termios_is_valid = false; + ::tcsetattr(STDIN_FILENO, TCSANOW, &g_old_stdin_termios); + } } -typedef struct -{ - uint32_t usage_mask; // Used to mark options that can be used together. If (1 << n & usage_mask) != 0 - // then this option belongs to option set n. - bool required; // This option is required (in the current usage level) - const char * long_option; // Full name for this option. - int short_option; // Single character for this option. - int option_has_arg; // no_argument, required_argument or optional_argument - uint32_t completion_type; // Cookie the option class can use to do define the argument completion. - lldb::CommandArgumentType argument_type; // Type of argument this option takes - const char * usage_text; // Full text explaining what this options does and what (if any) argument to - // pass it. +typedef struct { + uint32_t usage_mask; // Used to mark options that can be used together. If (1 + // << n & usage_mask) != 0 + // then this option belongs to option set n. + bool required; // This option is required (in the current usage level) + const char *long_option; // Full name for this option. + int short_option; // Single character for this option. + int option_has_arg; // no_argument, required_argument or optional_argument + uint32_t completion_type; // Cookie the option class can use to do define the + // argument completion. + lldb::CommandArgumentType argument_type; // Type of argument this option takes + const char *usage_text; // Full text explaining what this options does and + // what (if any) argument to + // pass it. } OptionDefinition; -#define LLDB_3_TO_5 LLDB_OPT_SET_3|LLDB_OPT_SET_4|LLDB_OPT_SET_5 -#define LLDB_4_TO_5 LLDB_OPT_SET_4|LLDB_OPT_SET_5 - -static OptionDefinition g_options[] = -{ - { LLDB_OPT_SET_1, true , "help" , 'h', no_argument , 0, eArgTypeNone, - "Prints out the usage information for the LLDB debugger." }, - { LLDB_OPT_SET_2, true , "version" , 'v', no_argument , 0, eArgTypeNone, - "Prints out the current version number of the LLDB debugger." }, - { LLDB_OPT_SET_3, true , "arch" , 'a', required_argument, 0, eArgTypeArchitecture, - "Tells the debugger to use the specified architecture when starting and running the program. <architecture> must " - "be one of the architectures for which the program was compiled." }, - { LLDB_OPT_SET_3, true , "file" , 'f', required_argument, 0, eArgTypeFilename, - "Tells the debugger to use the file <filename> as the program to be debugged." }, - { LLDB_OPT_SET_3, false, "core" , 'c', required_argument, 0, eArgTypeFilename, - "Tells the debugger to use the fullpath to <path> as the core file." }, - { LLDB_OPT_SET_5, true , "attach-pid" , 'p', required_argument, 0, eArgTypePid, - "Tells the debugger to attach to a process with the given pid." }, - { LLDB_OPT_SET_4, true , "attach-name" , 'n', required_argument, 0, eArgTypeProcessName, - "Tells the debugger to attach to a process with the given name." }, - { LLDB_OPT_SET_4, true , "wait-for" , 'w', no_argument , 0, eArgTypeNone, - "Tells the debugger to wait for a process with the given pid or name to launch before attaching." }, - { LLDB_3_TO_5, false, "source" , 's', required_argument, 0, eArgTypeFilename, - "Tells the debugger to read in and execute the lldb commands in the given file, after any file provided on the command line has been loaded." }, - { LLDB_3_TO_5, false, "one-line" , 'o', required_argument, 0, eArgTypeNone, - "Tells the debugger to execute this one-line lldb command after any file provided on the command line has been loaded." }, - { LLDB_3_TO_5, false, "source-before-file" , 'S', required_argument, 0, eArgTypeFilename, - "Tells the debugger to read in and execute the lldb commands in the given file, before any file provided on the command line has been loaded." }, - { LLDB_3_TO_5, false, "one-line-before-file" , 'O', required_argument, 0, eArgTypeNone, - "Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded." }, - { LLDB_3_TO_5, false, "one-line-on-crash" , 'k', required_argument, 0, eArgTypeNone, - "When in batch mode, tells the debugger to execute this one-line lldb command if the target crashes." }, - { LLDB_3_TO_5, false, "source-on-crash" , 'K', required_argument, 0, eArgTypeFilename, - "When in batch mode, tells the debugger to source this file of lldb commands if the target crashes." }, - { LLDB_3_TO_5, false, "source-quietly" , 'Q', no_argument , 0, eArgTypeNone, - "Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded." }, - { LLDB_3_TO_5, false, "batch" , 'b', no_argument , 0, eArgTypeNone, - "Tells the debugger to running the commands from -s, -S, -o & -O, and then quit. However if any run command stopped due to a signal or crash, " - "the debugger will return to the interactive prompt at the place of the crash." }, - { LLDB_3_TO_5, false, "editor" , 'e', no_argument , 0, eArgTypeNone, - "Tells the debugger to open source files using the host's \"external editor\" mechanism." }, - { LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , 0, eArgTypeNone, - "Do not automatically parse any '.lldbinit' files." }, - { LLDB_3_TO_5, false, "no-use-colors" , 'X', no_argument , 0, eArgTypeNone, - "Do not use colors." }, - { LLDB_OPT_SET_6, true , "python-path" , 'P', no_argument , 0, eArgTypeNone, - "Prints out the path to the lldb.py file for this version of lldb." }, - { LLDB_3_TO_5, false, "script-language", 'l', required_argument, 0, eArgTypeScriptLang, - "Tells the debugger to use the specified scripting language for user-defined scripts, rather than the default. " - "Valid scripting languages that can be specified include Python, Perl, Ruby and Tcl. Currently only the Python " - "extensions have been implemented." }, - { LLDB_3_TO_5, false, "debug" , 'd', no_argument , 0, eArgTypeNone, - "Tells the debugger to print out extra information for debugging itself." }, - { LLDB_OPT_SET_7, true , "repl" , 'r', optional_argument, 0, eArgTypeNone, - "Runs lldb in REPL mode with a stub process." }, - { LLDB_OPT_SET_7, true , "repl-language" , 'R', required_argument, 0, eArgTypeNone, - "Chooses the language for the REPL." }, - { 0, false, NULL , 0 , 0 , 0, eArgTypeNone, NULL } -}; +#define LLDB_3_TO_5 LLDB_OPT_SET_3 | LLDB_OPT_SET_4 | LLDB_OPT_SET_5 +#define LLDB_4_TO_5 LLDB_OPT_SET_4 | LLDB_OPT_SET_5 + +static OptionDefinition g_options[] = { + {LLDB_OPT_SET_1, true, "help", 'h', no_argument, 0, eArgTypeNone, + "Prints out the usage information for the LLDB debugger."}, + {LLDB_OPT_SET_2, true, "version", 'v', no_argument, 0, eArgTypeNone, + "Prints out the current version number of the LLDB debugger."}, + {LLDB_OPT_SET_3, true, "arch", 'a', required_argument, 0, + eArgTypeArchitecture, + "Tells the debugger to use the specified architecture when starting and " + "running the program. <architecture> must " + "be one of the architectures for which the program was compiled."}, + {LLDB_OPT_SET_3, true, "file", 'f', required_argument, 0, eArgTypeFilename, + "Tells the debugger to use the file <filename> as the program to be " + "debugged."}, + {LLDB_OPT_SET_3, false, "core", 'c', required_argument, 0, eArgTypeFilename, + "Tells the debugger to use the fullpath to <path> as the core file."}, + {LLDB_OPT_SET_5, true, "attach-pid", 'p', required_argument, 0, eArgTypePid, + "Tells the debugger to attach to a process with the given pid."}, + {LLDB_OPT_SET_4, true, "attach-name", 'n', required_argument, 0, + eArgTypeProcessName, + "Tells the debugger to attach to a process with the given name."}, + {LLDB_OPT_SET_4, true, "wait-for", 'w', no_argument, 0, eArgTypeNone, + "Tells the debugger to wait for a process with the given pid or name to " + "launch before attaching."}, + {LLDB_3_TO_5, false, "source", 's', required_argument, 0, eArgTypeFilename, + "Tells the debugger to read in and execute the lldb commands in the given " + "file, after any file provided on the command line has been loaded."}, + {LLDB_3_TO_5, false, "one-line", 'o', required_argument, 0, eArgTypeNone, + "Tells the debugger to execute this one-line lldb command after any file " + "provided on the command line has been loaded."}, + {LLDB_3_TO_5, false, "source-before-file", 'S', required_argument, 0, + eArgTypeFilename, "Tells the debugger to read in and execute the lldb " + "commands in the given file, before any file provided " + "on the command line has been loaded."}, + {LLDB_3_TO_5, false, "one-line-before-file", 'O', required_argument, 0, + eArgTypeNone, "Tells the debugger to execute this one-line lldb command " + "before any file provided on the command line has been " + "loaded."}, + {LLDB_3_TO_5, false, "one-line-on-crash", 'k', required_argument, 0, + eArgTypeNone, "When in batch mode, tells the debugger to execute this " + "one-line lldb command if the target crashes."}, + {LLDB_3_TO_5, false, "source-on-crash", 'K', required_argument, 0, + eArgTypeFilename, "When in batch mode, tells the debugger to source this " + "file of lldb commands if the target crashes."}, + {LLDB_3_TO_5, false, "source-quietly", 'Q', no_argument, 0, eArgTypeNone, + "Tells the debugger to execute this one-line lldb command before any file " + "provided on the command line has been loaded."}, + {LLDB_3_TO_5, false, "batch", 'b', no_argument, 0, eArgTypeNone, + "Tells the debugger to running the commands from -s, -S, -o & -O, and " + "then quit. However if any run command stopped due to a signal or crash, " + "the debugger will return to the interactive prompt at the place of the " + "crash."}, + {LLDB_3_TO_5, false, "editor", 'e', no_argument, 0, eArgTypeNone, + "Tells the debugger to open source files using the host's \"external " + "editor\" mechanism."}, + {LLDB_3_TO_5, false, "no-lldbinit", 'x', no_argument, 0, eArgTypeNone, + "Do not automatically parse any '.lldbinit' files."}, + {LLDB_3_TO_5, false, "no-use-colors", 'X', no_argument, 0, eArgTypeNone, + "Do not use colors."}, + {LLDB_OPT_SET_6, true, "python-path", 'P', no_argument, 0, eArgTypeNone, + "Prints out the path to the lldb.py file for this version of lldb."}, + {LLDB_3_TO_5, false, "script-language", 'l', required_argument, 0, + eArgTypeScriptLang, + "Tells the debugger to use the specified scripting language for " + "user-defined scripts, rather than the default. " + "Valid scripting languages that can be specified include Python, Perl, " + "Ruby and Tcl. Currently only the Python " + "extensions have been implemented."}, + {LLDB_3_TO_5, false, "debug", 'd', no_argument, 0, eArgTypeNone, + "Tells the debugger to print out extra information for debugging itself."}, + {LLDB_OPT_SET_7, true, "repl", 'r', optional_argument, 0, eArgTypeNone, + "Runs lldb in REPL mode with a stub process."}, + {LLDB_OPT_SET_7, true, "repl-language", 'R', required_argument, 0, + eArgTypeNone, "Chooses the language for the REPL."}, + {0, false, NULL, 0, 0, 0, eArgTypeNone, NULL}}; static const uint32_t last_option_set_with_args = 2; -Driver::Driver () : - SBBroadcaster ("Driver"), - m_debugger (SBDebugger::Create(false)), - m_option_data () -{ - // We want to be able to handle CTRL+D in the terminal to have it terminate - // certain input - m_debugger.SetCloseInputOnEOF (false); - g_driver = this; -} - -Driver::~Driver () -{ - g_driver = NULL; +Driver::Driver() + : SBBroadcaster("Driver"), m_debugger(SBDebugger::Create(false)), + m_option_data() { + // We want to be able to handle CTRL+D in the terminal to have it terminate + // certain input + m_debugger.SetCloseInputOnEOF(false); + g_driver = this; } +Driver::~Driver() { g_driver = NULL; } -// This function takes INDENT, which tells how many spaces to output at the front -// of each line; TEXT, which is the text that is to be output. It outputs the -// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the -// front of each line. It breaks lines on spaces, tabs or newlines, shortening -// the line if necessary to not break in the middle of a word. It assumes that +// This function takes INDENT, which tells how many spaces to output at the +// front +// of each line; TEXT, which is the text that is to be output. It outputs the +// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the +// front of each line. It breaks lines on spaces, tabs or newlines, shortening +// the line if necessary to not break in the middle of a word. It assumes that // each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters. -void -OutputFormattedUsageText (FILE *out, int indent, const char *text, int output_max_columns) -{ - int len = strlen (text); - std::string text_string (text); - - // Force indentation to be reasonable. - if (indent >= output_max_columns) - indent = 0; - - // Will it all fit on one line? - - if (len + indent < output_max_columns) - // Output as a single line - fprintf (out, "%*s%s\n", indent, "", text); - else - { - // We need to break it up into multiple lines. - int text_width = output_max_columns - indent - 1; - int start = 0; - int end = start; - int final_end = len; - int sub_len; - - while (end < final_end) - { - // Dont start the 'text' on a space, since we're already outputting the indentation. - while ((start < final_end) && (text[start] == ' ')) - start++; - - end = start + text_width; - if (end > final_end) - end = final_end; - else - { - // If we're not at the end of the text, make sure we break the line on white space. - while (end > start - && text[end] != ' ' && text[end] != '\t' && text[end] != '\n') - end--; - } - sub_len = end - start; - std::string substring = text_string.substr (start, sub_len); - fprintf (out, "%*s%s\n", indent, "", substring.c_str()); - start = end + 1; - } +void OutputFormattedUsageText(FILE *out, int indent, const char *text, + int output_max_columns) { + int len = strlen(text); + std::string text_string(text); + + // Force indentation to be reasonable. + if (indent >= output_max_columns) + indent = 0; + + // Will it all fit on one line? + + if (len + indent < output_max_columns) + // Output as a single line + fprintf(out, "%*s%s\n", indent, "", text); + else { + // We need to break it up into multiple lines. + int text_width = output_max_columns - indent - 1; + int start = 0; + int end = start; + int final_end = len; + int sub_len; + + while (end < final_end) { + // Dont start the 'text' on a space, since we're already outputting the + // indentation. + while ((start < final_end) && (text[start] == ' ')) + start++; + + end = start + text_width; + if (end > final_end) + end = final_end; + else { + // If we're not at the end of the text, make sure we break the line on + // white space. + while (end > start && text[end] != ' ' && text[end] != '\t' && + text[end] != '\n') + end--; + } + sub_len = end - start; + std::string substring = text_string.substr(start, sub_len); + fprintf(out, "%*s%s\n", indent, "", substring.c_str()); + start = end + 1; } + } } -void -ShowUsage (FILE *out, OptionDefinition *option_table, Driver::OptionData data) -{ - uint32_t screen_width = 80; - uint32_t indent_level = 0; - const char *name = "lldb"; - - fprintf (out, "\nUsage:\n\n"); - - indent_level += 2; - - - // First, show each usage level set of options, e.g. <cmd> [options-for-level-0] - // <cmd> [options-for-level-1] - // etc. - - uint32_t num_options; - uint32_t num_option_sets = 0; - - for (num_options = 0; option_table[num_options].long_option != NULL; ++num_options) - { - uint32_t this_usage_mask = option_table[num_options].usage_mask; - if (this_usage_mask == LLDB_OPT_SET_ALL) - { - if (num_option_sets == 0) - num_option_sets = 1; - } - else - { - for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++) - { - if (this_usage_mask & 1 << j) - { - if (num_option_sets <= j) - num_option_sets = j + 1; - } - } +void ShowUsage(FILE *out, OptionDefinition *option_table, + Driver::OptionData data) { + uint32_t screen_width = 80; + uint32_t indent_level = 0; + const char *name = "lldb"; + + fprintf(out, "\nUsage:\n\n"); + + indent_level += 2; + + // First, show each usage level set of options, e.g. <cmd> + // [options-for-level-0] + // <cmd> + // [options-for-level-1] + // etc. + + uint32_t num_options; + uint32_t num_option_sets = 0; + + for (num_options = 0; option_table[num_options].long_option != NULL; + ++num_options) { + uint32_t this_usage_mask = option_table[num_options].usage_mask; + if (this_usage_mask == LLDB_OPT_SET_ALL) { + if (num_option_sets == 0) + num_option_sets = 1; + } else { + for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++) { + if (this_usage_mask & 1 << j) { + if (num_option_sets <= j) + num_option_sets = j + 1; } + } } - - for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++) - { - uint32_t opt_set_mask; - - opt_set_mask = 1 << opt_set; - - if (opt_set > 0) - fprintf (out, "\n"); - fprintf (out, "%*s%s", indent_level, "", name); - bool is_help_line = false; - - for (uint32_t i = 0; i < num_options; ++i) - { - if (option_table[i].usage_mask & opt_set_mask) - { - CommandArgumentType arg_type = option_table[i].argument_type; - const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type); - // This is a bit of a hack, but there's no way to say certain options don't have arguments yet... - // so we do it by hand here. - if (option_table[i].short_option == 'h') - is_help_line = true; - - if (option_table[i].required) - { - if (option_table[i].option_has_arg == required_argument) - fprintf (out, " -%c <%s>", option_table[i].short_option, arg_name); - else if (option_table[i].option_has_arg == optional_argument) - fprintf (out, " -%c [<%s>]", option_table[i].short_option, arg_name); - else - fprintf (out, " -%c", option_table[i].short_option); - } - else - { - if (option_table[i].option_has_arg == required_argument) - fprintf (out, " [-%c <%s>]", option_table[i].short_option, arg_name); - else if (option_table[i].option_has_arg == optional_argument) - fprintf (out, " [-%c [<%s>]]", option_table[i].short_option, arg_name); - else - fprintf (out, " [-%c]", option_table[i].short_option); - } - } + } + + for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++) { + uint32_t opt_set_mask; + + opt_set_mask = 1 << opt_set; + + if (opt_set > 0) + fprintf(out, "\n"); + fprintf(out, "%*s%s", indent_level, "", name); + bool is_help_line = false; + + for (uint32_t i = 0; i < num_options; ++i) { + if (option_table[i].usage_mask & opt_set_mask) { + CommandArgumentType arg_type = option_table[i].argument_type; + const char *arg_name = + SBCommandInterpreter::GetArgumentTypeAsCString(arg_type); + // This is a bit of a hack, but there's no way to say certain options + // don't have arguments yet... + // so we do it by hand here. + if (option_table[i].short_option == 'h') + is_help_line = true; + + if (option_table[i].required) { + if (option_table[i].option_has_arg == required_argument) + fprintf(out, " -%c <%s>", option_table[i].short_option, arg_name); + else if (option_table[i].option_has_arg == optional_argument) + fprintf(out, " -%c [<%s>]", option_table[i].short_option, arg_name); + else + fprintf(out, " -%c", option_table[i].short_option); + } else { + if (option_table[i].option_has_arg == required_argument) + fprintf(out, " [-%c <%s>]", option_table[i].short_option, arg_name); + else if (option_table[i].option_has_arg == optional_argument) + fprintf(out, " [-%c [<%s>]]", option_table[i].short_option, + arg_name); + else + fprintf(out, " [-%c]", option_table[i].short_option); } - if (!is_help_line && (opt_set <= last_option_set_with_args)) - fprintf (out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]"); + } } - - fprintf (out, "\n\n"); - - // Now print out all the detailed information about the various options: long form, short form and help text: - // -- long_name <argument> - // - short <argument> - // help text - - // This variable is used to keep track of which options' info we've printed out, because some options can be in - // more than one usage level, but we only want to print the long form of its information once. - - Driver::OptionData::OptionSet options_seen; - Driver::OptionData::OptionSet::iterator pos; - - indent_level += 5; - - for (uint32_t i = 0; i < num_options; ++i) - { - // Only print this option if we haven't already seen it. - pos = options_seen.find (option_table[i].short_option); - if (pos == options_seen.end()) - { - CommandArgumentType arg_type = option_table[i].argument_type; - const char *arg_name = SBCommandInterpreter::GetArgumentTypeAsCString (arg_type); - - options_seen.insert (option_table[i].short_option); - fprintf (out, "%*s-%c ", indent_level, "", option_table[i].short_option); - if (arg_type != eArgTypeNone) - fprintf (out, "<%s>", arg_name); - fprintf (out, "\n"); - fprintf (out, "%*s--%s ", indent_level, "", option_table[i].long_option); - if (arg_type != eArgTypeNone) - fprintf (out, "<%s>", arg_name); - fprintf (out, "\n"); - indent_level += 5; - OutputFormattedUsageText (out, indent_level, option_table[i].usage_text, screen_width); - indent_level -= 5; - fprintf (out, "\n"); - } + if (!is_help_line && (opt_set <= last_option_set_with_args)) + fprintf(out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]"); + } + + fprintf(out, "\n\n"); + + // Now print out all the detailed information about the various options: long + // form, short form and help text: + // -- long_name <argument> + // - short <argument> + // help text + + // This variable is used to keep track of which options' info we've printed + // out, because some options can be in + // more than one usage level, but we only want to print the long form of its + // information once. + + Driver::OptionData::OptionSet options_seen; + Driver::OptionData::OptionSet::iterator pos; + + indent_level += 5; + + for (uint32_t i = 0; i < num_options; ++i) { + // Only print this option if we haven't already seen it. + pos = options_seen.find(option_table[i].short_option); + if (pos == options_seen.end()) { + CommandArgumentType arg_type = option_table[i].argument_type; + const char *arg_name = + SBCommandInterpreter::GetArgumentTypeAsCString(arg_type); + + options_seen.insert(option_table[i].short_option); + fprintf(out, "%*s-%c ", indent_level, "", option_table[i].short_option); + if (arg_type != eArgTypeNone) + fprintf(out, "<%s>", arg_name); + fprintf(out, "\n"); + fprintf(out, "%*s--%s ", indent_level, "", option_table[i].long_option); + if (arg_type != eArgTypeNone) + fprintf(out, "<%s>", arg_name); + fprintf(out, "\n"); + indent_level += 5; + OutputFormattedUsageText(out, indent_level, option_table[i].usage_text, + screen_width); + indent_level -= 5; + fprintf(out, "\n"); } - - indent_level -= 5; - - fprintf (out, "\n%*sNotes:\n", - indent_level, ""); - indent_level += 5; - - fprintf (out, "\n%*sMultiple \"-s\" and \"-o\" options can be provided. They will be processed" - "\n%*sfrom left to right in order, with the source files and commands" - "\n%*sinterleaved. The same is true of the \"-S\" and \"-O\" options. The before" - "\n%*sfile and after file sets can intermixed freely, the command parser will" - "\n%*ssort them out. The order of the file specifiers (\"-c\", \"-f\", etc.) is" - "\n%*snot significant in this regard.\n\n", - indent_level, "", - indent_level, "", - indent_level, "", - indent_level, "", - indent_level, "", - indent_level, ""); - - fprintf (out, "\n%*sIf you don't provide -f then the first argument will be the file to be" - "\n%*sdebugged which means that '%s -- <filename> [<ARG1> [<ARG2>]]' also" - "\n%*sworks. But remember to end the options with \"--\" if any of your" - "\n%*sarguments have a \"-\" in them.\n\n", - indent_level, "", - indent_level, "", - name, - indent_level, "", - indent_level, ""); + } + + indent_level -= 5; + + fprintf(out, "\n%*sNotes:\n", indent_level, ""); + indent_level += 5; + + fprintf(out, + "\n%*sMultiple \"-s\" and \"-o\" options can be provided. They will " + "be processed" + "\n%*sfrom left to right in order, with the source files and commands" + "\n%*sinterleaved. The same is true of the \"-S\" and \"-O\" " + "options. The before" + "\n%*sfile and after file sets can intermixed freely, the command " + "parser will" + "\n%*ssort them out. The order of the file specifiers (\"-c\", " + "\"-f\", etc.) is" + "\n%*snot significant in this regard.\n\n", + indent_level, "", indent_level, "", indent_level, "", indent_level, + "", indent_level, "", indent_level, ""); + + fprintf( + out, + "\n%*sIf you don't provide -f then the first argument will be the file " + "to be" + "\n%*sdebugged which means that '%s -- <filename> [<ARG1> [<ARG2>]]' also" + "\n%*sworks. But remember to end the options with \"--\" if any of your" + "\n%*sarguments have a \"-\" in them.\n\n", + indent_level, "", indent_level, "", name, indent_level, "", indent_level, + ""); } -void -BuildGetOptTable (OptionDefinition *expanded_option_table, std::vector<struct option> &getopt_table, - uint32_t num_options) -{ - if (num_options == 0) - return; - - uint32_t i; - uint32_t j; - std::bitset<256> option_seen; - - getopt_table.resize (num_options + 1); - - for (i = 0, j = 0; i < num_options; ++i) - { - char short_opt = expanded_option_table[i].short_option; - - if (option_seen.test(short_opt) == false) - { - getopt_table[j].name = expanded_option_table[i].long_option; - getopt_table[j].has_arg = expanded_option_table[i].option_has_arg; - getopt_table[j].flag = NULL; - getopt_table[j].val = expanded_option_table[i].short_option; - option_seen.set(short_opt); - ++j; - } - } +void BuildGetOptTable(OptionDefinition *expanded_option_table, + std::vector<struct option> &getopt_table, + uint32_t num_options) { + if (num_options == 0) + return; - getopt_table[j].name = NULL; - getopt_table[j].has_arg = 0; - getopt_table[j].flag = NULL; - getopt_table[j].val = 0; + uint32_t i; + uint32_t j; + std::bitset<256> option_seen; -} + getopt_table.resize(num_options + 1); -Driver::OptionData::OptionData () : - m_args(), - m_script_lang (lldb::eScriptLanguageDefault), - m_core_file (), - m_crash_log (), - m_initial_commands (), - m_after_file_commands (), - m_after_crash_commands(), - m_debug_mode (false), - m_source_quietly(false), - m_print_version (false), - m_print_python_path (false), - m_print_help (false), - m_wait_for(false), - m_repl (false), - m_repl_lang (eLanguageTypeUnknown), - m_repl_options (), - m_process_name(), - m_process_pid(LLDB_INVALID_PROCESS_ID), - m_use_external_editor(false), - m_batch(false), - m_seen_options() -{ -} + for (i = 0, j = 0; i < num_options; ++i) { + char short_opt = expanded_option_table[i].short_option; -Driver::OptionData::~OptionData () -{ -} - -void -Driver::OptionData::Clear () -{ - m_args.clear (); - m_script_lang = lldb::eScriptLanguageDefault; - m_initial_commands.clear (); - m_after_file_commands.clear (); - - // If there is a local .lldbinit, add that to the - // list of things to be sourced, if the settings - // permit it. - SBFileSpec local_lldbinit (".lldbinit", true); - - SBFileSpec homedir_dot_lldb = SBHostOS::GetUserHomeDirectory(); - homedir_dot_lldb.AppendPathComponent (".lldbinit"); - - // Only read .lldbinit in the current working directory - // if it's not the same as the .lldbinit in the home - // directory (which is already being read in). - if (local_lldbinit.Exists() - && strcmp (local_lldbinit.GetDirectory(), homedir_dot_lldb.GetDirectory()) != 0) - { - char path[2048]; - local_lldbinit.GetPath(path, 2047); - InitialCmdEntry entry(path, true, true, true); - m_after_file_commands.push_back (entry); + if (option_seen.test(short_opt) == false) { + getopt_table[j].name = expanded_option_table[i].long_option; + getopt_table[j].has_arg = expanded_option_table[i].option_has_arg; + getopt_table[j].flag = NULL; + getopt_table[j].val = expanded_option_table[i].short_option; + option_seen.set(short_opt); + ++j; } - - m_debug_mode = false; - m_source_quietly = false; - m_print_help = false; - m_print_version = false; - m_print_python_path = false; - m_use_external_editor = false; - m_wait_for = false; - m_process_name.erase(); - m_batch = false; - m_after_crash_commands.clear(); - - m_process_pid = LLDB_INVALID_PROCESS_ID; -} + } -void -Driver::OptionData::AddInitialCommand (const char *command, CommandPlacement placement, bool is_file, SBError &error) -{ - std::vector<InitialCmdEntry> *command_set; - switch (placement) - { - case eCommandPlacementBeforeFile: - command_set = &(m_initial_commands); - break; - case eCommandPlacementAfterFile: - command_set = &(m_after_file_commands); - break; - case eCommandPlacementAfterCrash: - command_set = &(m_after_crash_commands); - break; - } - - if (is_file) - { - SBFileSpec file(command); - if (file.Exists()) - command_set->push_back (InitialCmdEntry(command, is_file, false)); - else if (file.ResolveExecutableLocation()) - { - char final_path[PATH_MAX]; - file.GetPath (final_path, sizeof(final_path)); - command_set->push_back (InitialCmdEntry(final_path, is_file, false)); - } - else - error.SetErrorStringWithFormat("file specified in --source (-s) option doesn't exist: '%s'", optarg); - } - else - command_set->push_back (InitialCmdEntry(command, is_file, false)); + getopt_table[j].name = NULL; + getopt_table[j].has_arg = 0; + getopt_table[j].flag = NULL; + getopt_table[j].val = 0; } -void -Driver::ResetOptionValues () -{ - m_option_data.Clear (); +Driver::OptionData::OptionData() + : m_args(), m_script_lang(lldb::eScriptLanguageDefault), m_core_file(), + m_crash_log(), m_initial_commands(), m_after_file_commands(), + m_after_crash_commands(), m_debug_mode(false), m_source_quietly(false), + m_print_version(false), m_print_python_path(false), m_print_help(false), + m_wait_for(false), m_repl(false), m_repl_lang(eLanguageTypeUnknown), + m_repl_options(), m_process_name(), + m_process_pid(LLDB_INVALID_PROCESS_ID), m_use_external_editor(false), + m_batch(false), m_seen_options() {} + +Driver::OptionData::~OptionData() {} + +void Driver::OptionData::Clear() { + m_args.clear(); + m_script_lang = lldb::eScriptLanguageDefault; + m_initial_commands.clear(); + m_after_file_commands.clear(); + + // If there is a local .lldbinit, add that to the + // list of things to be sourced, if the settings + // permit it. + SBFileSpec local_lldbinit(".lldbinit", true); + + SBFileSpec homedir_dot_lldb = SBHostOS::GetUserHomeDirectory(); + homedir_dot_lldb.AppendPathComponent(".lldbinit"); + + // Only read .lldbinit in the current working directory + // if it's not the same as the .lldbinit in the home + // directory (which is already being read in). + if (local_lldbinit.Exists() && + strcmp(local_lldbinit.GetDirectory(), homedir_dot_lldb.GetDirectory()) != + 0) { + char path[2048]; + local_lldbinit.GetPath(path, 2047); + InitialCmdEntry entry(path, true, true, true); + m_after_file_commands.push_back(entry); + } + + m_debug_mode = false; + m_source_quietly = false; + m_print_help = false; + m_print_version = false; + m_print_python_path = false; + m_use_external_editor = false; + m_wait_for = false; + m_process_name.erase(); + m_batch = false; + m_after_crash_commands.clear(); + + m_process_pid = LLDB_INVALID_PROCESS_ID; } -const char * -Driver::GetFilename() const -{ - if (m_option_data.m_args.empty()) - return NULL; - return m_option_data.m_args.front().c_str(); +void Driver::OptionData::AddInitialCommand(const char *command, + CommandPlacement placement, + bool is_file, SBError &error) { + std::vector<InitialCmdEntry> *command_set; + switch (placement) { + case eCommandPlacementBeforeFile: + command_set = &(m_initial_commands); + break; + case eCommandPlacementAfterFile: + command_set = &(m_after_file_commands); + break; + case eCommandPlacementAfterCrash: + command_set = &(m_after_crash_commands); + break; + } + + if (is_file) { + SBFileSpec file(command); + if (file.Exists()) + command_set->push_back(InitialCmdEntry(command, is_file, false)); + else if (file.ResolveExecutableLocation()) { + char final_path[PATH_MAX]; + file.GetPath(final_path, sizeof(final_path)); + command_set->push_back(InitialCmdEntry(final_path, is_file, false)); + } else + error.SetErrorStringWithFormat( + "file specified in --source (-s) option doesn't exist: '%s'", optarg); + } else + command_set->push_back(InitialCmdEntry(command, is_file, false)); } -const char * -Driver::GetCrashLogFilename() const -{ - if (m_option_data.m_crash_log.empty()) - return NULL; - return m_option_data.m_crash_log.c_str(); +void Driver::ResetOptionValues() { m_option_data.Clear(); } + +const char *Driver::GetFilename() const { + if (m_option_data.m_args.empty()) + return NULL; + return m_option_data.m_args.front().c_str(); } -lldb::ScriptLanguage -Driver::GetScriptLanguage() const -{ - return m_option_data.m_script_lang; +const char *Driver::GetCrashLogFilename() const { + if (m_option_data.m_crash_log.empty()) + return NULL; + return m_option_data.m_crash_log.c_str(); } -void -Driver::WriteCommandsForSourcing (CommandPlacement placement, SBStream &strm) -{ - std::vector<OptionData::InitialCmdEntry> *command_set; - switch (placement) - { - case eCommandPlacementBeforeFile: - command_set = &m_option_data.m_initial_commands; - break; - case eCommandPlacementAfterFile: - command_set = &m_option_data.m_after_file_commands; - break; - case eCommandPlacementAfterCrash: - command_set = &m_option_data.m_after_crash_commands; - break; - } - - for (const auto &command_entry : *command_set) - { - const char *command = command_entry.contents.c_str(); - if (command_entry.is_file) - { - // If this command_entry is a file to be sourced, and it's the ./.lldbinit file (the .lldbinit - // file in the current working directory), only read it if target.load-cwd-lldbinit is 'true'. - if (command_entry.is_cwd_lldbinit_file_read) - { - SBStringList strlist = m_debugger.GetInternalVariableValue ("target.load-cwd-lldbinit", - m_debugger.GetInstanceName()); - if (strlist.GetSize() == 1 && strcmp (strlist.GetStringAtIndex(0), "warn") == 0) - { - FILE *output = m_debugger.GetOutputFileHandle (); - ::fprintf (output, - "There is a .lldbinit file in the current directory which is not being read.\n" - "To silence this warning without sourcing in the local .lldbinit,\n" - "add the following to the lldbinit file in your home directory:\n" - " settings set target.load-cwd-lldbinit false\n" - "To allow lldb to source .lldbinit files in the current working directory,\n" - "set the value of this variable to true. Only do so if you understand and\n" - "accept the security risk.\n"); - return; - } - if (strlist.GetSize() == 1 && strcmp (strlist.GetStringAtIndex(0), "false") == 0) - { - return; - } - } - bool source_quietly = m_option_data.m_source_quietly || command_entry.source_quietly; - strm.Printf("command source -s %i '%s'\n", source_quietly, command); - } - else - strm.Printf("%s\n", command); - } +lldb::ScriptLanguage Driver::GetScriptLanguage() const { + return m_option_data.m_script_lang; } -bool -Driver::GetDebugMode() const -{ - return m_option_data.m_debug_mode; +void Driver::WriteCommandsForSourcing(CommandPlacement placement, + SBStream &strm) { + std::vector<OptionData::InitialCmdEntry> *command_set; + switch (placement) { + case eCommandPlacementBeforeFile: + command_set = &m_option_data.m_initial_commands; + break; + case eCommandPlacementAfterFile: + command_set = &m_option_data.m_after_file_commands; + break; + case eCommandPlacementAfterCrash: + command_set = &m_option_data.m_after_crash_commands; + break; + } + + for (const auto &command_entry : *command_set) { + const char *command = command_entry.contents.c_str(); + if (command_entry.is_file) { + // If this command_entry is a file to be sourced, and it's the ./.lldbinit + // file (the .lldbinit + // file in the current working directory), only read it if + // target.load-cwd-lldbinit is 'true'. + if (command_entry.is_cwd_lldbinit_file_read) { + SBStringList strlist = m_debugger.GetInternalVariableValue( + "target.load-cwd-lldbinit", m_debugger.GetInstanceName()); + if (strlist.GetSize() == 1 && + strcmp(strlist.GetStringAtIndex(0), "warn") == 0) { + FILE *output = m_debugger.GetOutputFileHandle(); + ::fprintf( + output, + "There is a .lldbinit file in the current directory which is not " + "being read.\n" + "To silence this warning without sourcing in the local " + ".lldbinit,\n" + "add the following to the lldbinit file in your home directory:\n" + " settings set target.load-cwd-lldbinit false\n" + "To allow lldb to source .lldbinit files in the current working " + "directory,\n" + "set the value of this variable to true. Only do so if you " + "understand and\n" + "accept the security risk.\n"); + return; + } + if (strlist.GetSize() == 1 && + strcmp(strlist.GetStringAtIndex(0), "false") == 0) { + return; + } + } + bool source_quietly = + m_option_data.m_source_quietly || command_entry.source_quietly; + strm.Printf("command source -s %i '%s'\n", source_quietly, command); + } else + strm.Printf("%s\n", command); + } } +bool Driver::GetDebugMode() const { return m_option_data.m_debug_mode; } -// Check the arguments that were passed to this program to make sure they are valid and to get their -// argument values (if any). Return a boolean value indicating whether or not to start up the full -// debugger (i.e. the Command Interpreter) or not. Return FALSE if the arguments were invalid OR +// Check the arguments that were passed to this program to make sure they are +// valid and to get their +// argument values (if any). Return a boolean value indicating whether or not +// to start up the full +// debugger (i.e. the Command Interpreter) or not. Return FALSE if the +// arguments were invalid OR // if the user only wanted help or version information. -SBError -Driver::ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &exiting) -{ - ResetOptionValues (); - - SBCommandReturnObject result; +SBError Driver::ParseArgs(int argc, const char *argv[], FILE *out_fh, + bool &exiting) { + ResetOptionValues(); - SBError error; - std::string option_string; - struct option *long_options = NULL; - std::vector<struct option> long_options_vector; - uint32_t num_options; + SBCommandReturnObject result; - for (num_options = 0; g_options[num_options].long_option != NULL; ++num_options) - /* Do Nothing. */; + SBError error; + std::string option_string; + struct option *long_options = NULL; + std::vector<struct option> long_options_vector; + uint32_t num_options; - if (num_options == 0) - { - if (argc > 1) - error.SetErrorStringWithFormat ("invalid number of options"); - return error; - } + for (num_options = 0; g_options[num_options].long_option != NULL; + ++num_options) + /* Do Nothing. */; - BuildGetOptTable (g_options, long_options_vector, num_options); + if (num_options == 0) { + if (argc > 1) + error.SetErrorStringWithFormat("invalid number of options"); + return error; + } - if (long_options_vector.empty()) - long_options = NULL; - else - long_options = &long_options_vector.front(); + BuildGetOptTable(g_options, long_options_vector, num_options); - if (long_options == NULL) - { - error.SetErrorStringWithFormat ("invalid long options"); - return error; - } + if (long_options_vector.empty()) + long_options = NULL; + else + long_options = &long_options_vector.front(); - // Build the option_string argument for call to getopt_long_only. - - for (int i = 0; long_options[i].name != NULL; ++i) - { - if (long_options[i].flag == NULL) - { - option_string.push_back ((char) long_options[i].val); - switch (long_options[i].has_arg) - { - default: - case no_argument: - break; - case required_argument: - option_string.push_back (':'); - break; - case optional_argument: - option_string.append ("::"); - break; - } - } - } + if (long_options == NULL) { + error.SetErrorStringWithFormat("invalid long options"); + return error; + } - // This is kind of a pain, but since we make the debugger in the Driver's constructor, we can't - // know at that point whether we should read in init files yet. So we don't read them in in the - // Driver constructor, then set the flags back to "read them in" here, and then if we see the - // "-n" flag, we'll turn it off again. Finally we have to read them in by hand later in the - // main loop. - - m_debugger.SkipLLDBInitFiles (false); - m_debugger.SkipAppInitFiles (false); + // Build the option_string argument for call to getopt_long_only. - // Prepare for & make calls to getopt_long_only. + for (int i = 0; long_options[i].name != NULL; ++i) { + if (long_options[i].flag == NULL) { + option_string.push_back((char)long_options[i].val); + switch (long_options[i].has_arg) { + default: + case no_argument: + break; + case required_argument: + option_string.push_back(':'); + break; + case optional_argument: + option_string.append("::"); + break; + } + } + } + + // This is kind of a pain, but since we make the debugger in the Driver's + // constructor, we can't + // know at that point whether we should read in init files yet. So we don't + // read them in in the + // Driver constructor, then set the flags back to "read them in" here, and + // then if we see the + // "-n" flag, we'll turn it off again. Finally we have to read them in by + // hand later in the + // main loop. + + m_debugger.SkipLLDBInitFiles(false); + m_debugger.SkipAppInitFiles(false); + +// Prepare for & make calls to getopt_long_only. #if __GLIBC__ - optind = 0; + optind = 0; #else - optreset = 1; - optind = 1; + optreset = 1; + optind = 1; #endif - int val; - while (1) - { - int long_options_index = -1; - val = ::getopt_long_only (argc, const_cast<char **>(argv), option_string.c_str(), long_options, &long_options_index); - - if (val == -1) + int val; + while (1) { + int long_options_index = -1; + val = ::getopt_long_only(argc, const_cast<char **>(argv), + option_string.c_str(), long_options, + &long_options_index); + + if (val == -1) + break; + else if (val == '?') { + m_option_data.m_print_help = true; + error.SetErrorStringWithFormat("unknown or ambiguous option"); + break; + } else if (val == 0) + continue; + else { + m_option_data.m_seen_options.insert((char)val); + if (long_options_index == -1) { + for (int i = 0; long_options[i].name || long_options[i].has_arg || + long_options[i].flag || long_options[i].val; + ++i) { + if (long_options[i].val == val) { + long_options_index = i; break; - else if (val == '?') - { - m_option_data.m_print_help = true; - error.SetErrorStringWithFormat ("unknown or ambiguous option"); - break; - } - else if (val == 0) - continue; - else - { - m_option_data.m_seen_options.insert ((char) val); - if (long_options_index == -1) - { - for (int i = 0; - long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val; - ++i) - { - if (long_options[i].val == val) - { - long_options_index = i; - break; - } - } - } - - if (long_options_index >= 0) - { - const int short_option = g_options[long_options_index].short_option; - - switch (short_option) - { - case 'h': - m_option_data.m_print_help = true; - break; - - case 'v': - m_option_data.m_print_version = true; - break; - - case 'P': - m_option_data.m_print_python_path = true; - break; - - case 'b': - m_option_data.m_batch = true; - break; - - case 'c': - { - SBFileSpec file(optarg); - if (file.Exists()) - { - m_option_data.m_core_file = optarg; - } - else - error.SetErrorStringWithFormat("file specified in --core (-c) option doesn't exist: '%s'", optarg); - } - break; - - case 'e': - m_option_data.m_use_external_editor = true; - break; - - case 'x': - m_debugger.SkipLLDBInitFiles (true); - m_debugger.SkipAppInitFiles (true); - break; - - case 'X': - m_debugger.SetUseColor (false); - break; - - case 'f': - { - SBFileSpec file(optarg); - if (file.Exists()) - { - m_option_data.m_args.push_back (optarg); - } - else if (file.ResolveExecutableLocation()) - { - char path[PATH_MAX]; - file.GetPath (path, sizeof(path)); - m_option_data.m_args.push_back (path); - } - else - error.SetErrorStringWithFormat("file specified in --file (-f) option doesn't exist: '%s'", optarg); - } - break; - - case 'a': - if (!m_debugger.SetDefaultArchitecture (optarg)) - error.SetErrorStringWithFormat("invalid architecture in the -a or --arch option: '%s'", optarg); - break; - - case 'l': - m_option_data.m_script_lang = m_debugger.GetScriptingLanguage (optarg); - break; - - case 'd': - m_option_data.m_debug_mode = true; - break; - - case 'Q': - m_option_data.m_source_quietly = true; - break; - - case 'K': - m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterCrash, true, error); - break; - case 'k': - m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterCrash, false, error); - break; - - case 'n': - m_option_data.m_process_name = optarg; - break; - - case 'w': - m_option_data.m_wait_for = true; - break; - - case 'p': - { - char *remainder; - m_option_data.m_process_pid = strtol (optarg, &remainder, 0); - if (remainder == optarg || *remainder != '\0') - error.SetErrorStringWithFormat ("Could not convert process PID: \"%s\" into a pid.", - optarg); - } - break; - - case 'r': - m_option_data.m_repl = true; - if (optarg && optarg[0]) - m_option_data.m_repl_options = optarg; - else - m_option_data.m_repl_options.clear(); - break; - - case 'R': - m_option_data.m_repl_lang = SBLanguageRuntime::GetLanguageTypeFromString (optarg); - if (m_option_data.m_repl_lang == eLanguageTypeUnknown) - { - error.SetErrorStringWithFormat ("Unrecognized language name: \"%s\"", optarg); - } - break; - - case 's': - m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterFile, true, error); - break; - case 'o': - m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterFile, false, error); - break; - case 'S': - m_option_data.AddInitialCommand(optarg, eCommandPlacementBeforeFile, true, error); - break; - case 'O': - m_option_data.AddInitialCommand(optarg, eCommandPlacementBeforeFile, false, error); - break; - default: - m_option_data.m_print_help = true; - error.SetErrorStringWithFormat ("unrecognized option %c", short_option); - break; - } - } - else - { - error.SetErrorStringWithFormat ("invalid option with value %i", val); - } - if (error.Fail()) - { - return error; - } + } } - } - - if (error.Fail() || m_option_data.m_print_help) - { - ShowUsage (out_fh, g_options, m_option_data); - exiting = true; - } - else if (m_option_data.m_print_version) - { - ::fprintf (out_fh, "%s\n", m_debugger.GetVersionString()); - exiting = true; - } - else if (m_option_data.m_print_python_path) - { - SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath(); - if (python_file_spec.IsValid()) - { - char python_path[PATH_MAX]; - size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX); - if (num_chars < PATH_MAX) - { - ::fprintf (out_fh, "%s\n", python_path); - } - else - ::fprintf (out_fh, "<PATH TOO LONG>\n"); + } + + if (long_options_index >= 0) { + const int short_option = g_options[long_options_index].short_option; + + switch (short_option) { + case 'h': + m_option_data.m_print_help = true; + break; + + case 'v': + m_option_data.m_print_version = true; + break; + + case 'P': + m_option_data.m_print_python_path = true; + break; + + case 'b': + m_option_data.m_batch = true; + break; + + case 'c': { + SBFileSpec file(optarg); + if (file.Exists()) { + m_option_data.m_core_file = optarg; + } else + error.SetErrorStringWithFormat( + "file specified in --core (-c) option doesn't exist: '%s'", + optarg); + } break; + + case 'e': + m_option_data.m_use_external_editor = true; + break; + + case 'x': + m_debugger.SkipLLDBInitFiles(true); + m_debugger.SkipAppInitFiles(true); + break; + + case 'X': + m_debugger.SetUseColor(false); + break; + + case 'f': { + SBFileSpec file(optarg); + if (file.Exists()) { + m_option_data.m_args.push_back(optarg); + } else if (file.ResolveExecutableLocation()) { + char path[PATH_MAX]; + file.GetPath(path, sizeof(path)); + m_option_data.m_args.push_back(path); + } else + error.SetErrorStringWithFormat( + "file specified in --file (-f) option doesn't exist: '%s'", + optarg); + } break; + + case 'a': + if (!m_debugger.SetDefaultArchitecture(optarg)) + error.SetErrorStringWithFormat( + "invalid architecture in the -a or --arch option: '%s'", + optarg); + break; + + case 'l': + m_option_data.m_script_lang = m_debugger.GetScriptingLanguage(optarg); + break; + + case 'd': + m_option_data.m_debug_mode = true; + break; + + case 'Q': + m_option_data.m_source_quietly = true; + break; + + case 'K': + m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterCrash, + true, error); + break; + case 'k': + m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterCrash, + false, error); + break; + + case 'n': + m_option_data.m_process_name = optarg; + break; + + case 'w': + m_option_data.m_wait_for = true; + break; + + case 'p': { + char *remainder; + m_option_data.m_process_pid = strtol(optarg, &remainder, 0); + if (remainder == optarg || *remainder != '\0') + error.SetErrorStringWithFormat( + "Could not convert process PID: \"%s\" into a pid.", optarg); + } break; + + case 'r': + m_option_data.m_repl = true; + if (optarg && optarg[0]) + m_option_data.m_repl_options = optarg; + else + m_option_data.m_repl_options.clear(); + break; + + case 'R': + m_option_data.m_repl_lang = + SBLanguageRuntime::GetLanguageTypeFromString(optarg); + if (m_option_data.m_repl_lang == eLanguageTypeUnknown) { + error.SetErrorStringWithFormat("Unrecognized language name: \"%s\"", + optarg); + } + break; + + case 's': + m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterFile, + true, error); + break; + case 'o': + m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterFile, + false, error); + break; + case 'S': + m_option_data.AddInitialCommand(optarg, eCommandPlacementBeforeFile, + true, error); + break; + case 'O': + m_option_data.AddInitialCommand(optarg, eCommandPlacementBeforeFile, + false, error); + break; + default: + m_option_data.m_print_help = true; + error.SetErrorStringWithFormat("unrecognized option %c", + short_option); + break; } - else - ::fprintf (out_fh, "<COULD NOT FIND PATH>\n"); - exiting = true; + } else { + error.SetErrorStringWithFormat("invalid option with value %i", val); + } + if (error.Fail()) { + return error; + } } - else if (m_option_data.m_process_name.empty() && m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID) - { - // Any arguments that are left over after option parsing are for - // the program. If a file was specified with -f then the filename - // is already in the m_option_data.m_args array, and any remaining args - // are arguments for the inferior program. If no file was specified with - // -f, then what is left is the program name followed by any arguments. - - // Skip any options we consumed with getopt_long_only - argc -= optind; - argv += optind; - - if (argc > 0) - { - for (int arg_idx=0; arg_idx<argc; ++arg_idx) - { - const char *arg = argv[arg_idx]; - if (arg) - m_option_data.m_args.push_back (arg); - } - } - + } + + if (error.Fail() || m_option_data.m_print_help) { + ShowUsage(out_fh, g_options, m_option_data); + exiting = true; + } else if (m_option_data.m_print_version) { + ::fprintf(out_fh, "%s\n", m_debugger.GetVersionString()); + exiting = true; + } else if (m_option_data.m_print_python_path) { + SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath(); + if (python_file_spec.IsValid()) { + char python_path[PATH_MAX]; + size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX); + if (num_chars < PATH_MAX) { + ::fprintf(out_fh, "%s\n", python_path); + } else + ::fprintf(out_fh, "<PATH TOO LONG>\n"); + } else + ::fprintf(out_fh, "<COULD NOT FIND PATH>\n"); + exiting = true; + } else if (m_option_data.m_process_name.empty() && + m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID) { + // Any arguments that are left over after option parsing are for + // the program. If a file was specified with -f then the filename + // is already in the m_option_data.m_args array, and any remaining args + // are arguments for the inferior program. If no file was specified with + // -f, then what is left is the program name followed by any arguments. + + // Skip any options we consumed with getopt_long_only + argc -= optind; + argv += optind; + + if (argc > 0) { + for (int arg_idx = 0; arg_idx < argc; ++arg_idx) { + const char *arg = argv[arg_idx]; + if (arg) + m_option_data.m_args.push_back(arg); + } } - else - { - // Skip any options we consumed with getopt_long_only - argc -= optind; - //argv += optind; // Commented out to keep static analyzer happy - if (argc > 0) - ::fprintf (out_fh, "Warning: program arguments are ignored when attaching.\n"); - } + } else { + // Skip any options we consumed with getopt_long_only + argc -= optind; + // argv += optind; // Commented out to keep static analyzer happy - return error; + if (argc > 0) + ::fprintf(out_fh, + "Warning: program arguments are ignored when attaching.\n"); + } + + return error; } -static ::FILE * -PrepareCommandsForSourcing (const char *commands_data, size_t commands_size, int fds[2]) -{ - enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE +static ::FILE *PrepareCommandsForSourcing(const char *commands_data, + size_t commands_size, int fds[2]) { + enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE - ::FILE *commands_file = NULL; - fds[0] = -1; - fds[1] = -1; - int err = 0; + ::FILE *commands_file = NULL; + fds[0] = -1; + fds[1] = -1; + int err = 0; #ifdef _WIN32 - err = _pipe(fds, commands_size, O_BINARY); + err = _pipe(fds, commands_size, O_BINARY); #else - err = pipe(fds); + err = pipe(fds); #endif - if (err == 0) - { - ssize_t nrwr = write(fds[WRITE], commands_data, commands_size); - if (nrwr < 0) - { - fprintf(stderr, "error: write(%i, %p, %" PRIu64 ") failed (errno = %i) " - "when trying to open LLDB commands pipe\n", - fds[WRITE], static_cast<const void *>(commands_data), - static_cast<uint64_t>(commands_size), errno); - } - else if (static_cast<size_t>(nrwr) == commands_size) - { - // Close the write end of the pipe so when we give the read end to - // the debugger/command interpreter it will exit when it consumes all - // of the data + if (err == 0) { + ssize_t nrwr = write(fds[WRITE], commands_data, commands_size); + if (nrwr < 0) { + fprintf(stderr, "error: write(%i, %p, %" PRIu64 ") failed (errno = %i) " + "when trying to open LLDB commands pipe\n", + fds[WRITE], static_cast<const void *>(commands_data), + static_cast<uint64_t>(commands_size), errno); + } else if (static_cast<size_t>(nrwr) == commands_size) { +// Close the write end of the pipe so when we give the read end to +// the debugger/command interpreter it will exit when it consumes all +// of the data #ifdef _WIN32 - _close(fds[WRITE]); fds[WRITE] = -1; + _close(fds[WRITE]); + fds[WRITE] = -1; #else - close(fds[WRITE]); fds[WRITE] = -1; + close(fds[WRITE]); + fds[WRITE] = -1; #endif - // Now open the read file descriptor in a FILE * that we can give to - // the debugger as an input handle - commands_file = fdopen(fds[READ], "r"); - if (commands_file) - { - fds[READ] = -1; // The FILE * 'commands_file' now owns the read descriptor - // Hand ownership if the FILE * over to the debugger for "commands_file". - } - else - { - fprintf(stderr, - "error: fdopen(%i, \"r\") failed (errno = %i) when " + // Now open the read file descriptor in a FILE * that we can give to + // the debugger as an input handle + commands_file = fdopen(fds[READ], "r"); + if (commands_file) { + fds[READ] = + -1; // The FILE * 'commands_file' now owns the read descriptor + // Hand ownership if the FILE * over to the debugger for + // "commands_file". + } else { + fprintf(stderr, "error: fdopen(%i, \"r\") failed (errno = %i) when " "trying to open LLDB commands pipe\n", - fds[READ], errno); - } - } - } - else - { - fprintf(stderr, "error: can't create pipe file descriptors for LLDB commands\n"); + fds[READ], errno); + } } + } else { + fprintf(stderr, + "error: can't create pipe file descriptors for LLDB commands\n"); + } - return commands_file; + return commands_file; } -void -CleanupAfterCommandSourcing (int fds[2]) -{ - enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE +void CleanupAfterCommandSourcing(int fds[2]) { + enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE - // Close any pipes that we still have ownership of - if ( fds[WRITE] != -1) - { + // Close any pipes that we still have ownership of + if (fds[WRITE] != -1) { #ifdef _WIN32 - _close(fds[WRITE]); fds[WRITE] = -1; + _close(fds[WRITE]); + fds[WRITE] = -1; #else - close(fds[WRITE]); fds[WRITE] = -1; + close(fds[WRITE]); + fds[WRITE] = -1; #endif - - } + } - if ( fds[READ] != -1) - { + if (fds[READ] != -1) { #ifdef _WIN32 - _close(fds[READ]); fds[READ] = -1; + _close(fds[READ]); + fds[READ] = -1; #else - close(fds[READ]); fds[READ] = -1; + close(fds[READ]); + fds[READ] = -1; #endif - } - + } } -std::string -EscapeString (std::string arg) -{ - std::string::size_type pos = 0; - while ((pos = arg.find_first_of("\"\\", pos)) != std::string::npos) - { - arg.insert (pos, 1, '\\'); - pos += 2; - } - return '"' + arg + '"'; +std::string EscapeString(std::string arg) { + std::string::size_type pos = 0; + while ((pos = arg.find_first_of("\"\\", pos)) != std::string::npos) { + arg.insert(pos, 1, '\\'); + pos += 2; + } + return '"' + arg + '"'; } -void -Driver::MainLoop () -{ - if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0) - { - g_old_stdin_termios_is_valid = true; - atexit (reset_stdin_termios); - } +void Driver::MainLoop() { + if (::tcgetattr(STDIN_FILENO, &g_old_stdin_termios) == 0) { + g_old_stdin_termios_is_valid = true; + atexit(reset_stdin_termios); + } #ifndef _MSC_VER - // Disabling stdin buffering with MSVC's 2015 CRT exposes a bug in fgets - // which causes it to miss newlines depending on whether there have been an - // odd or even number of characters. Bug has been reported to MS via Connect. - ::setbuf (stdin, NULL); + // Disabling stdin buffering with MSVC's 2015 CRT exposes a bug in fgets + // which causes it to miss newlines depending on whether there have been an + // odd or even number of characters. Bug has been reported to MS via Connect. + ::setbuf(stdin, NULL); #endif - ::setbuf (stdout, NULL); - - m_debugger.SetErrorFileHandle (stderr, false); - m_debugger.SetOutputFileHandle (stdout, false); - m_debugger.SetInputFileHandle (stdin, false); // Don't take ownership of STDIN yet... - - m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor); + ::setbuf(stdout, NULL); + + m_debugger.SetErrorFileHandle(stderr, false); + m_debugger.SetOutputFileHandle(stdout, false); + m_debugger.SetInputFileHandle(stdin, + false); // Don't take ownership of STDIN yet... + + m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor); + + struct winsize window_size; + if (isatty(STDIN_FILENO) && + ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) { + if (window_size.ws_col > 0) + m_debugger.SetTerminalWidth(window_size.ws_col); + } + + SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter(); + + // Before we handle any options from the command line, we parse the + // .lldbinit file in the user's home directory. + SBCommandReturnObject result; + sb_interpreter.SourceInitFileInHomeDirectory(result); + if (GetDebugMode()) { + result.PutError(m_debugger.GetErrorFileHandle()); + result.PutOutput(m_debugger.GetOutputFileHandle()); + } + + // Now we handle options we got from the command line + SBStream commands_stream; + + // First source in the commands specified to be run before the file arguments + // are processed. + WriteCommandsForSourcing(eCommandPlacementBeforeFile, commands_stream); + + const size_t num_args = m_option_data.m_args.size(); + if (num_args > 0) { + char arch_name[64]; + if (m_debugger.GetDefaultArchitecture(arch_name, sizeof(arch_name))) + commands_stream.Printf("target create --arch=%s %s", arch_name, + EscapeString(m_option_data.m_args[0]).c_str()); + else + commands_stream.Printf("target create %s", + EscapeString(m_option_data.m_args[0]).c_str()); - struct winsize window_size; - if (isatty (STDIN_FILENO) - && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) - { - if (window_size.ws_col > 0) - m_debugger.SetTerminalWidth (window_size.ws_col); + if (!m_option_data.m_core_file.empty()) { + commands_stream.Printf(" --core %s", + EscapeString(m_option_data.m_core_file).c_str()); } - - SBCommandInterpreter sb_interpreter = m_debugger.GetCommandInterpreter(); - - // Before we handle any options from the command line, we parse the - // .lldbinit file in the user's home directory. - SBCommandReturnObject result; - sb_interpreter.SourceInitFileInHomeDirectory(result); - if (GetDebugMode()) - { - result.PutError (m_debugger.GetErrorFileHandle()); - result.PutOutput (m_debugger.GetOutputFileHandle()); + commands_stream.Printf("\n"); + + if (num_args > 1) { + commands_stream.Printf("settings set -- target.run-args "); + for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx) + commands_stream.Printf( + " %s", EscapeString(m_option_data.m_args[arg_idx]).c_str()); + commands_stream.Printf("\n"); } - - // Now we handle options we got from the command line - SBStream commands_stream; - - // First source in the commands specified to be run before the file arguments are processed. - WriteCommandsForSourcing (eCommandPlacementBeforeFile, commands_stream); - - const size_t num_args = m_option_data.m_args.size(); - if (num_args > 0) - { - char arch_name[64]; - if (m_debugger.GetDefaultArchitecture (arch_name, sizeof (arch_name))) - commands_stream.Printf("target create --arch=%s %s", arch_name, EscapeString(m_option_data.m_args[0]).c_str()); - else - commands_stream.Printf("target create %s", EscapeString(m_option_data.m_args[0]).c_str()); - - if (!m_option_data.m_core_file.empty()) - { - commands_stream.Printf(" --core %s", EscapeString(m_option_data.m_core_file).c_str()); - } - commands_stream.Printf("\n"); - - if (num_args > 1) - { - commands_stream.Printf ("settings set -- target.run-args "); - for (size_t arg_idx = 1; arg_idx < num_args; ++arg_idx) - commands_stream.Printf(" %s", EscapeString(m_option_data.m_args[arg_idx]).c_str()); - commands_stream.Printf("\n"); - } - } - else if (!m_option_data.m_core_file.empty()) - { - commands_stream.Printf("target create --core %s\n", EscapeString(m_option_data.m_core_file).c_str()); + } else if (!m_option_data.m_core_file.empty()) { + commands_stream.Printf("target create --core %s\n", + EscapeString(m_option_data.m_core_file).c_str()); + } else if (!m_option_data.m_process_name.empty()) { + commands_stream.Printf("process attach --name %s", + EscapeString(m_option_data.m_process_name).c_str()); + + if (m_option_data.m_wait_for) + commands_stream.Printf(" --waitfor"); + + commands_stream.Printf("\n"); + + } else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid) { + commands_stream.Printf("process attach --pid %" PRIu64 "\n", + m_option_data.m_process_pid); + } + + WriteCommandsForSourcing(eCommandPlacementAfterFile, commands_stream); + + if (GetDebugMode()) { + result.PutError(m_debugger.GetErrorFileHandle()); + result.PutOutput(m_debugger.GetOutputFileHandle()); + } + + bool handle_events = true; + bool spawn_thread = false; + + if (m_option_data.m_repl) { + const char *repl_options = NULL; + if (!m_option_data.m_repl_options.empty()) + repl_options = m_option_data.m_repl_options.c_str(); + SBError error(m_debugger.RunREPL(m_option_data.m_repl_lang, repl_options)); + if (error.Fail()) { + const char *error_cstr = error.GetCString(); + if (error_cstr && error_cstr[0]) + fprintf(stderr, "error: %s\n", error_cstr); + else + fprintf(stderr, "error: %u\n", error.GetError()); } - else if (!m_option_data.m_process_name.empty()) - { - commands_stream.Printf ("process attach --name %s", EscapeString(m_option_data.m_process_name).c_str()); - - if (m_option_data.m_wait_for) - commands_stream.Printf(" --waitfor"); + } else { + // Check if we have any data in the commands stream, and if so, save it to a + // temp file + // so we can then run the command interpreter using the file contents. + const char *commands_data = commands_stream.GetData(); + const size_t commands_size = commands_stream.GetSize(); + + // The command file might have requested that we quit, this variable will + // track that. + bool quit_requested = false; + bool stopped_for_crash = false; + if (commands_data && commands_size) { + int initial_commands_fds[2]; + bool success = true; + FILE *commands_file = PrepareCommandsForSourcing( + commands_data, commands_size, initial_commands_fds); + if (commands_file) { + m_debugger.SetInputFileHandle(commands_file, true); + + // Set the debugger into Sync mode when running the command file. + // Otherwise command files + // that run the target won't run in a sensible way. + bool old_async = m_debugger.GetAsync(); + m_debugger.SetAsync(false); + int num_errors; + + SBCommandInterpreterRunOptions options; + options.SetStopOnError(true); + if (m_option_data.m_batch) + options.SetStopOnCrash(true); + + m_debugger.RunCommandInterpreter(handle_events, spawn_thread, options, + num_errors, quit_requested, + stopped_for_crash); + + if (m_option_data.m_batch && stopped_for_crash && + !m_option_data.m_after_crash_commands.empty()) { + int crash_command_fds[2]; + SBStream crash_commands_stream; + WriteCommandsForSourcing(eCommandPlacementAfterCrash, + crash_commands_stream); + const char *crash_commands_data = crash_commands_stream.GetData(); + const size_t crash_commands_size = crash_commands_stream.GetSize(); + commands_file = PrepareCommandsForSourcing( + crash_commands_data, crash_commands_size, crash_command_fds); + if (commands_file) { + bool local_quit_requested; + bool local_stopped_for_crash; + m_debugger.SetInputFileHandle(commands_file, true); + + m_debugger.RunCommandInterpreter( + handle_events, spawn_thread, options, num_errors, + local_quit_requested, local_stopped_for_crash); + if (local_quit_requested) + quit_requested = true; + } + } + m_debugger.SetAsync(old_async); + } else + success = false; - commands_stream.Printf("\n"); + // Close any pipes that we still have ownership of + CleanupAfterCommandSourcing(initial_commands_fds); - } - else if (LLDB_INVALID_PROCESS_ID != m_option_data.m_process_pid) - { - commands_stream.Printf ("process attach --pid %" PRIu64 "\n", m_option_data.m_process_pid); + // Something went wrong with command pipe + if (!success) { + exit(1); + } } - WriteCommandsForSourcing(eCommandPlacementAfterFile, commands_stream); - - if (GetDebugMode()) - { - result.PutError(m_debugger.GetErrorFileHandle()); - result.PutOutput(m_debugger.GetOutputFileHandle()); - } - - bool handle_events = true; - bool spawn_thread = false; - - if (m_option_data.m_repl) - { - const char *repl_options = NULL; - if (!m_option_data.m_repl_options.empty()) - repl_options = m_option_data.m_repl_options.c_str(); - SBError error (m_debugger.RunREPL(m_option_data.m_repl_lang, repl_options)); - if (error.Fail()) - { - const char *error_cstr = error.GetCString(); - if (error_cstr && error_cstr[0]) - fprintf (stderr, "error: %s\n", error_cstr); - else - fprintf (stderr, "error: %u\n", error.GetError()); - } - } - else - { - // Check if we have any data in the commands stream, and if so, save it to a temp file - // so we can then run the command interpreter using the file contents. - const char *commands_data = commands_stream.GetData(); - const size_t commands_size = commands_stream.GetSize(); - - // The command file might have requested that we quit, this variable will track that. - bool quit_requested = false; - bool stopped_for_crash = false; - if (commands_data && commands_size) - { - int initial_commands_fds[2]; - bool success = true; - FILE *commands_file = PrepareCommandsForSourcing (commands_data, commands_size, initial_commands_fds); - if (commands_file) - { - m_debugger.SetInputFileHandle (commands_file, true); - - // Set the debugger into Sync mode when running the command file. Otherwise command files - // that run the target won't run in a sensible way. - bool old_async = m_debugger.GetAsync(); - m_debugger.SetAsync(false); - int num_errors; - - SBCommandInterpreterRunOptions options; - options.SetStopOnError (true); - if (m_option_data.m_batch) - options.SetStopOnCrash (true); - - m_debugger.RunCommandInterpreter(handle_events, - spawn_thread, - options, - num_errors, - quit_requested, - stopped_for_crash); - - if (m_option_data.m_batch && stopped_for_crash && !m_option_data.m_after_crash_commands.empty()) - { - int crash_command_fds[2]; - SBStream crash_commands_stream; - WriteCommandsForSourcing (eCommandPlacementAfterCrash, crash_commands_stream); - const char *crash_commands_data = crash_commands_stream.GetData(); - const size_t crash_commands_size = crash_commands_stream.GetSize(); - commands_file = PrepareCommandsForSourcing (crash_commands_data, crash_commands_size, crash_command_fds); - if (commands_file) - { - bool local_quit_requested; - bool local_stopped_for_crash; - m_debugger.SetInputFileHandle (commands_file, true); - - m_debugger.RunCommandInterpreter(handle_events, - spawn_thread, - options, - num_errors, - local_quit_requested, - local_stopped_for_crash); - if (local_quit_requested) - quit_requested = true; - - } - } - m_debugger.SetAsync(old_async); - } - else - success = false; - - // Close any pipes that we still have ownership of - CleanupAfterCommandSourcing(initial_commands_fds); - - // Something went wrong with command pipe - if (!success) - { - exit(1); - } + // Now set the input file handle to STDIN and run the command + // interpreter again in interactive mode and let the debugger + // take ownership of stdin - } + bool go_interactive = true; + if (quit_requested) + go_interactive = false; + else if (m_option_data.m_batch && !stopped_for_crash) + go_interactive = false; - // Now set the input file handle to STDIN and run the command - // interpreter again in interactive mode and let the debugger - // take ownership of stdin + if (go_interactive) { + m_debugger.SetInputFileHandle(stdin, true); + m_debugger.RunCommandInterpreter(handle_events, spawn_thread); + } + } - bool go_interactive = true; - if (quit_requested) - go_interactive = false; - else if (m_option_data.m_batch && !stopped_for_crash) - go_interactive = false; + reset_stdin_termios(); + fclose(stdin); - if (go_interactive) - { - m_debugger.SetInputFileHandle (stdin, true); - m_debugger.RunCommandInterpreter(handle_events, spawn_thread); - } - } - - reset_stdin_termios(); - fclose (stdin); - - SBDebugger::Destroy (m_debugger); + SBDebugger::Destroy(m_debugger); } - -void -Driver::ResizeWindow (unsigned short col) -{ - GetDebugger().SetTerminalWidth (col); +void Driver::ResizeWindow(unsigned short col) { + GetDebugger().SetTerminalWidth(col); } -void -sigwinch_handler (int signo) -{ - struct winsize window_size; - if (isatty (STDIN_FILENO) - && ::ioctl (STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) - { - if ((window_size.ws_col > 0) && g_driver != NULL) - { - g_driver->ResizeWindow (window_size.ws_col); - } +void sigwinch_handler(int signo) { + struct winsize window_size; + if (isatty(STDIN_FILENO) && + ::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) { + if ((window_size.ws_col > 0) && g_driver != NULL) { + g_driver->ResizeWindow(window_size.ws_col); } + } } -void -sigint_handler (int signo) -{ - static bool g_interrupt_sent = false; - if (g_driver) - { - if (!g_interrupt_sent) - { - g_interrupt_sent = true; - g_driver->GetDebugger().DispatchInputInterrupt(); - g_interrupt_sent = false; - return; - } - } - - exit (signo); +void sigint_handler(int signo) { + static bool g_interrupt_sent = false; + if (g_driver) { + if (!g_interrupt_sent) { + g_interrupt_sent = true; + g_driver->GetDebugger().DispatchInputInterrupt(); + g_interrupt_sent = false; + return; + } + } + + exit(signo); } -void -sigtstp_handler (int signo) -{ - if (g_driver) - g_driver->GetDebugger().SaveInputTerminalState(); +void sigtstp_handler(int signo) { + if (g_driver) + g_driver->GetDebugger().SaveInputTerminalState(); - signal (signo, SIG_DFL); - kill (getpid(), signo); - signal (signo, sigtstp_handler); + signal(signo, SIG_DFL); + kill(getpid(), signo); + signal(signo, sigtstp_handler); } -void -sigcont_handler (int signo) -{ - if (g_driver) - g_driver->GetDebugger().RestoreInputTerminalState(); +void sigcont_handler(int signo) { + if (g_driver) + g_driver->GetDebugger().RestoreInputTerminalState(); - signal (signo, SIG_DFL); - kill (getpid(), signo); - signal (signo, sigcont_handler); + signal(signo, SIG_DFL); + kill(getpid(), signo); + signal(signo, sigcont_handler); } int @@ -1315,48 +1217,44 @@ main(int argc, char const *argv[]) #endif { #ifdef _WIN32 - // Convert wide arguments to UTF-8 - std::vector<std::string> argvStrings(argc); - std::vector<const char *> argvPointers(argc); - for (int i = 0; i != argc; ++i) - { - llvm::convertWideToUTF8(wargv[i], argvStrings[i]); - argvPointers[i] = argvStrings[i].c_str(); - } - const char **argv = argvPointers.data(); + // Convert wide arguments to UTF-8 + std::vector<std::string> argvStrings(argc); + std::vector<const char *> argvPointers(argc); + for (int i = 0; i != argc; ++i) { + llvm::convertWideToUTF8(wargv[i], argvStrings[i]); + argvPointers[i] = argvStrings[i].c_str(); + } + const char **argv = argvPointers.data(); #endif - SBDebugger::Initialize(); + SBDebugger::Initialize(); - SBHostOS::ThreadCreated("<lldb.driver.main-thread>"); + SBHostOS::ThreadCreated("<lldb.driver.main-thread>"); - signal(SIGINT, sigint_handler); + signal(SIGINT, sigint_handler); #if !defined(_MSC_VER) - signal(SIGPIPE, SIG_IGN); - signal(SIGWINCH, sigwinch_handler); - signal(SIGTSTP, sigtstp_handler); - signal(SIGCONT, sigcont_handler); + signal(SIGPIPE, SIG_IGN); + signal(SIGWINCH, sigwinch_handler); + signal(SIGTSTP, sigtstp_handler); + signal(SIGCONT, sigcont_handler); #endif - // Create a scope for driver so that the driver object will destroy itself - // before SBDebugger::Terminate() is called. - { - Driver driver; - - bool exiting = false; - SBError error(driver.ParseArgs(argc, argv, stdout, exiting)); - if (error.Fail()) - { - const char *error_cstr = error.GetCString(); - if (error_cstr) - ::fprintf(stderr, "error: %s\n", error_cstr); - } - else if (!exiting) - { - driver.MainLoop(); - } - } + // Create a scope for driver so that the driver object will destroy itself + // before SBDebugger::Terminate() is called. + { + Driver driver; + + bool exiting = false; + SBError error(driver.ParseArgs(argc, argv, stdout, exiting)); + if (error.Fail()) { + const char *error_cstr = error.GetCString(); + if (error_cstr) + ::fprintf(stderr, "error: %s\n", error_cstr); + } else if (!exiting) { + driver.MainLoop(); + } + } - SBDebugger::Terminate(); - return 0; + SBDebugger::Terminate(); + return 0; } diff --git a/lldb/tools/driver/Driver.h b/lldb/tools/driver/Driver.h index 8ac59240bc2..e6cff5180df 100644 --- a/lldb/tools/driver/Driver.h +++ b/lldb/tools/driver/Driver.h @@ -13,136 +13,113 @@ #include "Platform.h" #include "lldb/Utility/PseudoTerminal.h" -#include <set> #include <bitset> +#include <set> #include <string> #include <vector> -#include "lldb/API/SBDefines.h" #include "lldb/API/SBBroadcaster.h" #include "lldb/API/SBDebugger.h" +#include "lldb/API/SBDefines.h" #include "lldb/API/SBError.h" class IOChannel; -class Driver : public lldb::SBBroadcaster -{ +class Driver : public lldb::SBBroadcaster { public: - typedef enum CommandPlacement - { - eCommandPlacementBeforeFile, - eCommandPlacementAfterFile, - eCommandPlacementAfterCrash, - } CommandPlacement; - - Driver (); - - virtual - ~Driver (); - - void - MainLoop (); - - lldb::SBError - ParseArgs (int argc, const char *argv[], FILE *out_fh, bool &do_exit); - - const char * - GetFilename() const; - - const char * - GetCrashLogFilename() const; - - const char * - GetArchName() const; - - lldb::ScriptLanguage - GetScriptLanguage() const; - - void - WriteCommandsForSourcing (CommandPlacement placement, lldb::SBStream &strm); - - bool - GetDebugMode() const; - - - class OptionData - { - public: - OptionData (); - ~OptionData (); - - void - Clear(); - - void - AddInitialCommand (const char *command, CommandPlacement placement, bool is_file, lldb::SBError &error); - - //static OptionDefinition m_cmd_option_table[]; - - struct InitialCmdEntry - { - InitialCmdEntry (const char *in_contents, bool in_is_file, bool is_cwd_lldbinit_file_read, bool in_quiet = false) : - contents (in_contents), - is_file (in_is_file), - is_cwd_lldbinit_file_read (is_cwd_lldbinit_file_read), - source_quietly (in_quiet) - {} - - std::string contents; - bool is_file; - bool is_cwd_lldbinit_file_read; // if this is reading ./.lldbinit - so we may skip if not permitted - bool source_quietly; - }; - - std::vector<std::string> m_args; - lldb::ScriptLanguage m_script_lang; - std::string m_core_file; - std::string m_crash_log; - std::vector<InitialCmdEntry> m_initial_commands; - std::vector<InitialCmdEntry> m_after_file_commands; - std::vector<InitialCmdEntry> m_after_crash_commands; - bool m_debug_mode; - bool m_source_quietly; - bool m_print_version; - bool m_print_python_path; - bool m_print_help; - bool m_wait_for; - bool m_repl; - lldb::LanguageType m_repl_lang; - std::string m_repl_options; - std::string m_process_name; - lldb::pid_t m_process_pid; - bool m_use_external_editor; // FIXME: When we have set/show variables we can remove this from here. - bool m_batch; - typedef std::set<char> OptionSet; - OptionSet m_seen_options; - }; + typedef enum CommandPlacement { + eCommandPlacementBeforeFile, + eCommandPlacementAfterFile, + eCommandPlacementAfterCrash, + } CommandPlacement; + + Driver(); + + virtual ~Driver(); + + void MainLoop(); + + lldb::SBError ParseArgs(int argc, const char *argv[], FILE *out_fh, + bool &do_exit); + + const char *GetFilename() const; + const char *GetCrashLogFilename() const; - static lldb::SBError - SetOptionValue (int option_idx, - const char *option_arg, - Driver::OptionData &data); + const char *GetArchName() const; + lldb::ScriptLanguage GetScriptLanguage() const; + + void WriteCommandsForSourcing(CommandPlacement placement, + lldb::SBStream &strm); + + bool GetDebugMode() const; + + class OptionData { + public: + OptionData(); + ~OptionData(); + + void Clear(); + + void AddInitialCommand(const char *command, CommandPlacement placement, + bool is_file, lldb::SBError &error); + + // static OptionDefinition m_cmd_option_table[]; + + struct InitialCmdEntry { + InitialCmdEntry(const char *in_contents, bool in_is_file, + bool is_cwd_lldbinit_file_read, bool in_quiet = false) + : contents(in_contents), is_file(in_is_file), + is_cwd_lldbinit_file_read(is_cwd_lldbinit_file_read), + source_quietly(in_quiet) {} + + std::string contents; + bool is_file; + bool is_cwd_lldbinit_file_read; // if this is reading ./.lldbinit - so we + // may skip if not permitted + bool source_quietly; + }; - lldb::SBDebugger & - GetDebugger() - { - return m_debugger; - } - - void - ResizeWindow (unsigned short col); + std::vector<std::string> m_args; + lldb::ScriptLanguage m_script_lang; + std::string m_core_file; + std::string m_crash_log; + std::vector<InitialCmdEntry> m_initial_commands; + std::vector<InitialCmdEntry> m_after_file_commands; + std::vector<InitialCmdEntry> m_after_crash_commands; + bool m_debug_mode; + bool m_source_quietly; + bool m_print_version; + bool m_print_python_path; + bool m_print_help; + bool m_wait_for; + bool m_repl; + lldb::LanguageType m_repl_lang; + std::string m_repl_options; + std::string m_process_name; + lldb::pid_t m_process_pid; + bool m_use_external_editor; // FIXME: When we have set/show variables we can + // remove this from here. + bool m_batch; + typedef std::set<char> OptionSet; + OptionSet m_seen_options; + }; + + static lldb::SBError SetOptionValue(int option_idx, const char *option_arg, + Driver::OptionData &data); + + lldb::SBDebugger &GetDebugger() { return m_debugger; } + + void ResizeWindow(unsigned short col); private: - lldb::SBDebugger m_debugger; - OptionData m_option_data; + lldb::SBDebugger m_debugger; + OptionData m_option_data; - void - ResetOptionValues (); + void ResetOptionValues(); - void - ReadyForCommand (); + void ReadyForCommand(); }; #endif // lldb_Driver_h_ diff --git a/lldb/tools/driver/Platform.cpp b/lldb/tools/driver/Platform.cpp index 88c0aa1e95c..1a58d4de03e 100644 --- a/lldb/tools/driver/Platform.cpp +++ b/lldb/tools/driver/Platform.cpp @@ -8,65 +8,55 @@ //===----------------------------------------------------------------------===// // this file is only relevant for Visual C++ -#if defined( _WIN32 ) +#if defined(_WIN32) -#include <process.h> #include <assert.h> +#include <process.h> #include <stdlib.h> #include "Platform.h" -int -ioctl (int d, int request, ...) -{ - switch ( request ) - { - // request the console windows size - case ( TIOCGWINSZ ): - { - va_list vl; - va_start(vl,request); - // locate the window size structure on stack - winsize *ws = va_arg(vl, winsize*); - // get screen buffer information - CONSOLE_SCREEN_BUFFER_INFO info; - if ( GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE ), &info ) == TRUE ) - // fill in the columns - ws->ws_col = info.dwMaximumWindowSize.X; - va_end(vl); - return 0; - } - break; - default: - assert( !"Not implemented!" ); - } - return -1; +int ioctl(int d, int request, ...) { + switch (request) { + // request the console windows size + case (TIOCGWINSZ): { + va_list vl; + va_start(vl, request); + // locate the window size structure on stack + winsize *ws = va_arg(vl, winsize *); + // get screen buffer information + CONSOLE_SCREEN_BUFFER_INFO info; + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info) == + TRUE) + // fill in the columns + ws->ws_col = info.dwMaximumWindowSize.X; + va_end(vl); + return 0; + } break; + default: + assert(!"Not implemented!"); + } + return -1; } -int -kill (pid_t pid, int sig) -{ - // is the app trying to kill itself - if ( pid == getpid( ) ) - exit( sig ); - // - assert( !"Not implemented!" ); - return -1; +int kill(pid_t pid, int sig) { + // is the app trying to kill itself + if (pid == getpid()) + exit(sig); + // + assert(!"Not implemented!"); + return -1; } -int -tcsetattr (int fd, int optional_actions, const struct termios *termios_p) -{ - assert( !"Not implemented!" ); - return -1; +int tcsetattr(int fd, int optional_actions, const struct termios *termios_p) { + assert(!"Not implemented!"); + return -1; } -int -tcgetattr (int fildes, struct termios *termios_p) -{ -// assert( !"Not implemented!" ); - // error return value (0=success) - return -1; +int tcgetattr(int fildes, struct termios *termios_p) { + // assert( !"Not implemented!" ); + // error return value (0=success) + return -1; } #endif diff --git a/lldb/tools/driver/Platform.h b/lldb/tools/driver/Platform.h index 15e21f143bb..3af2e19cbc4 100644 --- a/lldb/tools/driver/Platform.h +++ b/lldb/tools/driver/Platform.h @@ -10,85 +10,81 @@ #ifndef lldb_Platform_h_ #define lldb_Platform_h_ -#if defined( _WIN32 ) +#if defined(_WIN32) - #include "lldb/Host/HostGetOpt.h" - #include <io.h> -#if defined( _MSC_VER ) - #include <eh.h> - #include <signal.h> +#include "lldb/Host/HostGetOpt.h" +#include <io.h> +#if defined(_MSC_VER) +#include <eh.h> +#include <signal.h> #endif - #include <inttypes.h> - #include "lldb/Host/windows/windows.h" - - struct winsize - { - long ws_col; - }; - - typedef unsigned char cc_t; - typedef unsigned int speed_t; - typedef unsigned int tcflag_t; - - // fcntl.h - #define O_NOCTTY 0400 - - // ioctls.h - #define TIOCGWINSZ 0x5413 - - // signal.h - #define SIGPIPE 13 - #define SIGCONT 18 - #define SIGTSTP 20 - #define SIGWINCH 28 - - // tcsetattr arguments - #define TCSANOW 0 - - #define NCCS 32 - struct termios - { - tcflag_t c_iflag; // input mode flags - tcflag_t c_oflag; // output mode flags - tcflag_t c_cflag; // control mode flags - tcflag_t c_lflag; // local mode flags - cc_t c_line; // line discipline - cc_t c_cc[NCCS]; // control characters - speed_t c_ispeed; // input speed - speed_t c_ospeed; // output speed - }; - - +#include "lldb/Host/windows/windows.h" +#include <inttypes.h> + +struct winsize { + long ws_col; +}; + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +// fcntl.h +#define O_NOCTTY 0400 + +// ioctls.h +#define TIOCGWINSZ 0x5413 + +// signal.h +#define SIGPIPE 13 +#define SIGCONT 18 +#define SIGTSTP 20 +#define SIGWINCH 28 + +// tcsetattr arguments +#define TCSANOW 0 + +#define NCCS 32 +struct termios { + tcflag_t c_iflag; // input mode flags + tcflag_t c_oflag; // output mode flags + tcflag_t c_cflag; // control mode flags + tcflag_t c_lflag; // local mode flags + cc_t c_line; // line discipline + cc_t c_cc[NCCS]; // control characters + speed_t c_ispeed; // input speed + speed_t c_ospeed; // output speed +}; #ifdef _MSC_VER - struct timeval - { - long tv_sec; - long tv_usec; - }; - typedef long pid_t; - #define snprintf _snprintf - #define PATH_MAX MAX_PATH +struct timeval { + long tv_sec; + long tv_usec; +}; +typedef long pid_t; +#define snprintf _snprintf +#define PATH_MAX MAX_PATH #endif - #define STDIN_FILENO 0 +#define STDIN_FILENO 0 - extern int ioctl( int d, int request, ... ); - extern int kill ( pid_t pid, int sig ); - extern int tcsetattr( int fd, int optional_actions, const struct termios *termios_p ); - extern int tcgetattr( int fildes, struct termios *termios_p ); +extern int ioctl(int d, int request, ...); +extern int kill(pid_t pid, int sig); +extern int tcsetattr(int fd, int optional_actions, + const struct termios *termios_p); +extern int tcgetattr(int fildes, struct termios *termios_p); #else - #include "lldb/Host/HostGetOpt.h" - #include <inttypes.h> +#include "lldb/Host/HostGetOpt.h" +#include <inttypes.h> - #include <libgen.h> - #include <sys/ioctl.h> - #include <termios.h> - #include <unistd.h> +#include <libgen.h> +#include <sys/ioctl.h> +#include <termios.h> +#include <unistd.h> - #include <pthread.h> - #include <sys/time.h> +#include <pthread.h> +#include <sys/time.h> #endif #endif // lldb_Platform_h_ diff --git a/lldb/tools/lldb-mi/MICmdArgContext.cpp b/lldb/tools/lldb-mi/MICmdArgContext.cpp index 8ce5bfb3c88..57f682bea22 100644 --- a/lldb/tools/lldb-mi/MICmdArgContext.cpp +++ b/lldb/tools/lldb-mi/MICmdArgContext.cpp @@ -10,68 +10,68 @@ // In-house headers: #include "MICmdArgContext.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgContext constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdArgContext::CMICmdArgContext() -{ -} +CMICmdArgContext::CMICmdArgContext() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgContext constructor. // Type: Method. -// Args: vrCmdLineArgsRaw - (R) The text description of the arguments options. +// Args: vrCmdLineArgsRaw - (R) The text description of the arguments +// options. // Return: None. // Throws: None. //-- CMICmdArgContext::CMICmdArgContext(const CMIUtilString &vrCmdLineArgsRaw) - : m_strCmdArgsAndOptions(vrCmdLineArgsRaw) -{ -} + : m_strCmdArgsAndOptions(vrCmdLineArgsRaw) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgContext destructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdArgContext::~CMICmdArgContext() -{ -} +CMICmdArgContext::~CMICmdArgContext() {} -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the remainder of the command's argument options left to parse. +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the remainder of the command's argument options left to +// parse. // Type: Method. // Args: None. // Return: CMIUtilString & - Argument options text. // Throws: None. //-- -const CMIUtilString & -CMICmdArgContext::GetArgsLeftToParse() const -{ - return m_strCmdArgsAndOptions; +const CMIUtilString &CMICmdArgContext::GetArgsLeftToParse() const { + return m_strCmdArgsAndOptions; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Ask if this arguments string has any arguments. // Type: Method. // Args: None. -// Return: bool - True = Has one or more arguments present, false = no arguments. +// Return: bool - True = Has one or more arguments present, false = no +// arguments. // Throws: None. //-- -bool -CMICmdArgContext::IsEmpty() const -{ - return m_strCmdArgsAndOptions.empty(); +bool CMICmdArgContext::IsEmpty() const { + return m_strCmdArgsAndOptions.empty(); } -//++ ------------------------------------------------------------------------------------ -// Details: Remove the argument from the options text and any space after the argument +//++ +//------------------------------------------------------------------------------------ +// Details: Remove the argument from the options text and any space after the +// argument // if applicable. // Type: Method. // Args: vArg - (R) The name of the argument. @@ -79,167 +79,154 @@ CMICmdArgContext::IsEmpty() const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdArgContext::RemoveArg(const CMIUtilString &vArg) -{ - if (vArg.empty()) - return MIstatus::success; - - const size_t nLen = vArg.length(); - const size_t nLenCntxt = m_strCmdArgsAndOptions.length(); - if (nLen > nLenCntxt) - return MIstatus::failure; - - size_t nExtraSpace = 0; - size_t nPos = m_strCmdArgsAndOptions.find(vArg); - while (1) - { - if (nPos == std::string::npos) - return MIstatus::success; - - bool bPass1 = false; - if (nPos != 0) - { - if (m_strCmdArgsAndOptions[nPos - 1] == ' ') - bPass1 = true; - } - else - bPass1 = true; - - const size_t nEnd = nPos + nLen; - - if (bPass1) - { - bool bPass2 = false; - if (nEnd < nLenCntxt) - { - if (m_strCmdArgsAndOptions[nEnd] == ' ') - { - bPass2 = true; - nExtraSpace = 1; - } - } - else - bPass2 = true; - - if (bPass2) - break; +bool CMICmdArgContext::RemoveArg(const CMIUtilString &vArg) { + if (vArg.empty()) + return MIstatus::success; + + const size_t nLen = vArg.length(); + const size_t nLenCntxt = m_strCmdArgsAndOptions.length(); + if (nLen > nLenCntxt) + return MIstatus::failure; + + size_t nExtraSpace = 0; + size_t nPos = m_strCmdArgsAndOptions.find(vArg); + while (1) { + if (nPos == std::string::npos) + return MIstatus::success; + + bool bPass1 = false; + if (nPos != 0) { + if (m_strCmdArgsAndOptions[nPos - 1] == ' ') + bPass1 = true; + } else + bPass1 = true; + + const size_t nEnd = nPos + nLen; + + if (bPass1) { + bool bPass2 = false; + if (nEnd < nLenCntxt) { + if (m_strCmdArgsAndOptions[nEnd] == ' ') { + bPass2 = true; + nExtraSpace = 1; } + } else + bPass2 = true; - nPos = m_strCmdArgsAndOptions.find(vArg, nEnd); + if (bPass2) + break; } - const size_t nPosEnd = nLen + nExtraSpace; - m_strCmdArgsAndOptions = m_strCmdArgsAndOptions.replace(nPos, nPosEnd, ""); - m_strCmdArgsAndOptions = m_strCmdArgsAndOptions.Trim(); + nPos = m_strCmdArgsAndOptions.find(vArg, nEnd); + } - return MIstatus::success; + const size_t nPosEnd = nLen + nExtraSpace; + m_strCmdArgsAndOptions = m_strCmdArgsAndOptions.replace(nPos, nPosEnd, ""); + m_strCmdArgsAndOptions = m_strCmdArgsAndOptions.Trim(); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Remove the argument at the Nth word position along in the context string. -// Any space after the argument is removed if applicable. A search is not -// performed as there may be more than one vArg with the same 'name' in the +//++ +//------------------------------------------------------------------------------------ +// Details: Remove the argument at the Nth word position along in the context +// string. +// Any space after the argument is removed if applicable. A search is +// not +// performed as there may be more than one vArg with the same 'name' in +// the // context string. // Type: Method. // Args: vArg - (R) The name of the argument. -// nArgIndex - (R) The word count position to which to remove the vArg word. +// nArgIndex - (R) The word count position to which to remove the +// vArg word. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdArgContext::RemoveArgAtPos(const CMIUtilString &vArg, size_t nArgIndex) -{ - size_t nWordIndex = 0; - CMIUtilString strBuildContextUp; - const CMIUtilString::VecString_t vecWords(GetArgs()); - const bool bSpaceRequired(GetNumberArgsPresent() > 2); - - CMIUtilString::VecString_t::const_iterator it = vecWords.begin(); - const CMIUtilString::VecString_t::const_iterator itEnd = vecWords.end(); - while (it != itEnd) - { - const CMIUtilString &rWord(*it); - if (nWordIndex++ != nArgIndex) - { - // Single words - strBuildContextUp += rWord; - if (bSpaceRequired) - strBuildContextUp += " "; - } - else - { - // If quoted loose quoted text - if (++it != itEnd) - { - CMIUtilString words = rWord; - while (vArg != words) - { - if (bSpaceRequired) - words += " "; - words += *it; - if (++it == itEnd) - break; - } - if (it != itEnd) - --it; - } +bool CMICmdArgContext::RemoveArgAtPos(const CMIUtilString &vArg, + size_t nArgIndex) { + size_t nWordIndex = 0; + CMIUtilString strBuildContextUp; + const CMIUtilString::VecString_t vecWords(GetArgs()); + const bool bSpaceRequired(GetNumberArgsPresent() > 2); + + CMIUtilString::VecString_t::const_iterator it = vecWords.begin(); + const CMIUtilString::VecString_t::const_iterator itEnd = vecWords.end(); + while (it != itEnd) { + const CMIUtilString &rWord(*it); + if (nWordIndex++ != nArgIndex) { + // Single words + strBuildContextUp += rWord; + if (bSpaceRequired) + strBuildContextUp += " "; + } else { + // If quoted loose quoted text + if (++it != itEnd) { + CMIUtilString words = rWord; + while (vArg != words) { + if (bSpaceRequired) + words += " "; + words += *it; + if (++it == itEnd) + break; } - - // Next if (it != itEnd) - ++it; + --it; + } } - m_strCmdArgsAndOptions = strBuildContextUp; - m_strCmdArgsAndOptions = m_strCmdArgsAndOptions.Trim(); + // Next + if (it != itEnd) + ++it; + } - return MIstatus::success; + m_strCmdArgsAndOptions = strBuildContextUp; + m_strCmdArgsAndOptions = m_strCmdArgsAndOptions.Trim(); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve number of arguments or options present in the command's option text. +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve number of arguments or options present in the command's +// option text. // Type: Method. // Args: None. // Return: size_t - 0 to n arguments present. // Throws: None. //-- -size_t -CMICmdArgContext::GetNumberArgsPresent() const -{ - CMIUtilString::VecString_t vecOptions; - return m_strCmdArgsAndOptions.SplitConsiderQuotes(" ", vecOptions); +size_t CMICmdArgContext::GetNumberArgsPresent() const { + CMIUtilString::VecString_t vecOptions; + return m_strCmdArgsAndOptions.SplitConsiderQuotes(" ", vecOptions); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve all the arguments or options remaining in *this context. // Type: Method. // Args: None. // Return: MIUtilString::VecString_t - List of args remaining. // Throws: None. //-- -CMIUtilString::VecString_t -CMICmdArgContext::GetArgs() const -{ - CMIUtilString::VecString_t vecOptions; - m_strCmdArgsAndOptions.SplitConsiderQuotes(" ", vecOptions); - return vecOptions; +CMIUtilString::VecString_t CMICmdArgContext::GetArgs() const { + CMIUtilString::VecString_t vecOptions; + m_strCmdArgsAndOptions.SplitConsiderQuotes(" ", vecOptions); + return vecOptions; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Copy assignment operator. // Type: Method. // Args: vOther - (R) The variable to copy from. // Return: CMIUtilString & - this object. // Throws: None. //-- -CMICmdArgContext &CMICmdArgContext::operator=(const CMICmdArgContext &vOther) -{ - if (this != &vOther) - { - m_strCmdArgsAndOptions = vOther.m_strCmdArgsAndOptions; - } +CMICmdArgContext &CMICmdArgContext::operator=(const CMICmdArgContext &vOther) { + if (this != &vOther) { + m_strCmdArgsAndOptions = vOther.m_strCmdArgsAndOptions; + } - return *this; + return *this; } diff --git a/lldb/tools/lldb-mi/MICmdArgContext.h b/lldb/tools/lldb-mi/MICmdArgContext.h index 2b32c4b8427..ed4f377d2fb 100644 --- a/lldb/tools/lldb-mi/MICmdArgContext.h +++ b/lldb/tools/lldb-mi/MICmdArgContext.h @@ -12,33 +12,33 @@ // In-house headers: #include "MIUtilString.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code class. Command arguments and options string. Holds // the context string. // Based on the Interpreter pattern. //-- -class CMICmdArgContext -{ - // Methods: - public: - /* ctor */ CMICmdArgContext(); - /* ctor */ CMICmdArgContext(const CMIUtilString &vrCmdLineArgsRaw); - // - const CMIUtilString &GetArgsLeftToParse() const; - size_t GetNumberArgsPresent() const; - CMIUtilString::VecString_t GetArgs() const; - bool IsEmpty() const; - bool RemoveArg(const CMIUtilString &vArg); - bool RemoveArgAtPos(const CMIUtilString &vArg, size_t nArgIndex); - // - CMICmdArgContext &operator=(const CMICmdArgContext &vOther); +class CMICmdArgContext { + // Methods: +public: + /* ctor */ CMICmdArgContext(); + /* ctor */ CMICmdArgContext(const CMIUtilString &vrCmdLineArgsRaw); + // + const CMIUtilString &GetArgsLeftToParse() const; + size_t GetNumberArgsPresent() const; + CMIUtilString::VecString_t GetArgs() const; + bool IsEmpty() const; + bool RemoveArg(const CMIUtilString &vArg); + bool RemoveArgAtPos(const CMIUtilString &vArg, size_t nArgIndex); + // + CMICmdArgContext &operator=(const CMICmdArgContext &vOther); - // Overridden: - public: - // From CMIUtilString - /* dtor */ virtual ~CMICmdArgContext(); + // Overridden: +public: + // From CMIUtilString + /* dtor */ virtual ~CMICmdArgContext(); - // Attributes: - private: - CMIUtilString m_strCmdArgsAndOptions; + // Attributes: +private: + CMIUtilString m_strCmdArgsAndOptions; }; diff --git a/lldb/tools/lldb-mi/MICmdArgSet.cpp b/lldb/tools/lldb-mi/MICmdArgSet.cpp index 9fe5b2d97dc..ca942148908 100644 --- a/lldb/tools/lldb-mi/MICmdArgSet.cpp +++ b/lldb/tools/lldb-mi/MICmdArgSet.cpp @@ -10,10 +10,11 @@ // In-house headers: #include "MICmdArgSet.h" #include "MICmdArgValBase.h" -#include "MICmnResources.h" #include "MICmnLog.h" +#include "MICmnResources.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgSet constructor. // Type: Method. // Args: None. @@ -21,136 +22,140 @@ // Throws: None. //-- CMICmdArgSet::CMICmdArgSet() - : m_bIsArgsPresentButNotHandledByCmd(false) - , m_constStrCommaSpc(", ") -{ -} + : m_bIsArgsPresentButNotHandledByCmd(false), m_constStrCommaSpc(", ") {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgSet destructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdArgSet::~CMICmdArgSet() -{ - // Tidy up - Destroy(); +CMICmdArgSet::~CMICmdArgSet() { + // Tidy up + Destroy(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release resources used by *this container object. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -void -CMICmdArgSet::Destroy() -{ - // Delete command argument objects - if (!m_setCmdArgs.empty()) - { - SetCmdArgs_t::iterator it = m_setCmdArgs.begin(); - while (it != m_setCmdArgs.end()) - { - CMICmdArgValBase *pArg(*it); - delete pArg; - - // Next - ++it; - } - m_setCmdArgs.clear(); +void CMICmdArgSet::Destroy() { + // Delete command argument objects + if (!m_setCmdArgs.empty()) { + SetCmdArgs_t::iterator it = m_setCmdArgs.begin(); + while (it != m_setCmdArgs.end()) { + CMICmdArgValBase *pArg(*it); + delete pArg; + + // Next + ++it; } - - m_setCmdArgsThatNotValid.clear(); - m_setCmdArgsThatAreMissing.clear(); - m_setCmdArgsNotHandledByCmd.clear(); - m_setCmdArgsMissingInfo.clear(); - m_bIsArgsPresentButNotHandledByCmd = false; + m_setCmdArgs.clear(); + } + + m_setCmdArgsThatNotValid.clear(); + m_setCmdArgsThatAreMissing.clear(); + m_setCmdArgsNotHandledByCmd.clear(); + m_setCmdArgsMissingInfo.clear(); + m_bIsArgsPresentButNotHandledByCmd = false; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the state flag indicating that the command set up ready to parse -// command arguments or options found that one or more arguments was indeed -// present but not handled. This is given as a warning in the MI log file. +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the state flag indicating that the command set up ready to +// parse +// command arguments or options found that one or more arguments was +// indeed +// present but not handled. This is given as a warning in the MI log +// file. // Type: Method. // Args: None. // Return: bool - True = one or more args not handled, false = all args handled // Throws: None. //-- -bool -CMICmdArgSet::IsArgsPresentButNotHandledByCmd() const -{ - return m_bIsArgsPresentButNotHandledByCmd; +bool CMICmdArgSet::IsArgsPresentButNotHandledByCmd() const { + return m_bIsArgsPresentButNotHandledByCmd; } -//++ ------------------------------------------------------------------------------------ -// Details: Add the list of command's arguments to parse and validate another one. +//++ +//------------------------------------------------------------------------------------ +// Details: Add the list of command's arguments to parse and validate another +// one. // Type: Method. // Args: vArg - (R) A command argument object. // Return: None. // Throws: None. //-- -void -CMICmdArgSet::Add(CMICmdArgValBase *vArg) -{ - m_setCmdArgs.push_back(vArg); -} - -//++ ------------------------------------------------------------------------------------ -// Details: After validating an options line of text (the context) and there is a failure, -// it is likely a mandatory command argument that is required is missing. This +void CMICmdArgSet::Add(CMICmdArgValBase *vArg) { m_setCmdArgs.push_back(vArg); } + +//++ +//------------------------------------------------------------------------------------ +// Details: After validating an options line of text (the context) and there is +// a failure, +// it is likely a mandatory command argument that is required is +// missing. This // function returns the argument that should be present. // Type: Method. // Args: None. // Return: SetCmdArgs_t & - Set of argument objects. // Throws: None. //-- -const CMICmdArgSet::SetCmdArgs_t & -CMICmdArgSet::GetArgsThatAreMissing() const -{ - return m_setCmdArgsThatAreMissing; +const CMICmdArgSet::SetCmdArgs_t &CMICmdArgSet::GetArgsThatAreMissing() const { + return m_setCmdArgsThatAreMissing; } -//++ ------------------------------------------------------------------------------------ -// Details: After validating an options line of text (the context) and there is a failure, -// it may be because one or more arguments were unable to extract a value. This +//++ +//------------------------------------------------------------------------------------ +// Details: After validating an options line of text (the context) and there is +// a failure, +// it may be because one or more arguments were unable to extract a +// value. This // function returns the argument that were found to be invalid. // Type: Method. // Args: None. // Return: SetCmdArgs_t & - Set of argument objects. // Throws: None. //-- -const CMICmdArgSet::SetCmdArgs_t & -CMICmdArgSet::GetArgsThatInvalid() const -{ - return m_setCmdArgsThatNotValid; +const CMICmdArgSet::SetCmdArgs_t &CMICmdArgSet::GetArgsThatInvalid() const { + return m_setCmdArgsThatNotValid; } -//++ ------------------------------------------------------------------------------------ -// Details: The list of argument or option (objects) that were specified by the command -// and so recognised when parsed but were not handled. Ideally the command -// should handle all arguments and options presented to it. The command sends -// warning to the MI log file to say that these options were not handled. -// Used as one way to determine option that maybe should really be implemented +//++ +//------------------------------------------------------------------------------------ +// Details: The list of argument or option (objects) that were specified by the +// command +// and so recognised when parsed but were not handled. Ideally the +// command +// should handle all arguments and options presented to it. The command +// sends +// warning to the MI log file to say that these options were not +// handled. +// Used as one way to determine option that maybe should really be +// implemented // and not just ignored. // Type: Method. // Args: None. // Return: SetCmdArgs_t & - Set of argument objects. // Throws: None. //-- -const CMICmdArgSet::SetCmdArgs_t & -CMICmdArgSet::GetArgsNotHandledByCmd() const -{ - return m_setCmdArgsNotHandledByCmd; +const CMICmdArgSet::SetCmdArgs_t &CMICmdArgSet::GetArgsNotHandledByCmd() const { + return m_setCmdArgsNotHandledByCmd; } -//++ ------------------------------------------------------------------------------------ -// Details: Given a set of command argument objects parse the context option string to -// find those argument and retrieve their value. If the function fails call -// GetArgsThatAreMissing() to see which commands that were mandatory were +//++ +//------------------------------------------------------------------------------------ +// Details: Given a set of command argument objects parse the context option +// string to +// find those argument and retrieve their value. If the function fails +// call +// GetArgsThatAreMissing() to see which commands that were mandatory +// were // missing or failed to parse. // Type: Method. // Args: vStrMiCmd - (R) Command's name. @@ -159,49 +164,45 @@ CMICmdArgSet::GetArgsNotHandledByCmd() const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdArgSet::Validate(const CMIUtilString &vStrMiCmd, CMICmdArgContext &vwCmdArgsText) -{ - m_cmdArgContext = vwCmdArgsText; - - // Iterate all the arguments or options required by a command - SetCmdArgs_t::const_iterator it = m_setCmdArgs.begin(); - while (it != m_setCmdArgs.end()) - { - CMICmdArgValBase *pArg = *it; - - if (!pArg->Validate(vwCmdArgsText)) - { - if (pArg->GetFound()) - { - if (pArg->GetIsMissingOptions()) - m_setCmdArgsMissingInfo.push_back(pArg); - else if (!pArg->GetValid()) - m_setCmdArgsThatNotValid.push_back(pArg); - } - else if (pArg->GetIsMandatory()) - m_setCmdArgsThatAreMissing.push_back(pArg); - } - - if (pArg->GetFound() && !pArg->GetIsHandledByCmd()) - { - m_bIsArgsPresentButNotHandledByCmd = true; - m_setCmdArgsNotHandledByCmd.push_back(pArg); - } - - // Next - ++it; +bool CMICmdArgSet::Validate(const CMIUtilString &vStrMiCmd, + CMICmdArgContext &vwCmdArgsText) { + m_cmdArgContext = vwCmdArgsText; + + // Iterate all the arguments or options required by a command + SetCmdArgs_t::const_iterator it = m_setCmdArgs.begin(); + while (it != m_setCmdArgs.end()) { + CMICmdArgValBase *pArg = *it; + + if (!pArg->Validate(vwCmdArgsText)) { + if (pArg->GetFound()) { + if (pArg->GetIsMissingOptions()) + m_setCmdArgsMissingInfo.push_back(pArg); + else if (!pArg->GetValid()) + m_setCmdArgsThatNotValid.push_back(pArg); + } else if (pArg->GetIsMandatory()) + m_setCmdArgsThatAreMissing.push_back(pArg); + } + + if (pArg->GetFound() && !pArg->GetIsHandledByCmd()) { + m_bIsArgsPresentButNotHandledByCmd = true; + m_setCmdArgsNotHandledByCmd.push_back(pArg); } - // report any issues with arguments/options - if (IsArgsPresentButNotHandledByCmd()) - WarningArgsNotHandledbyCmdLogFile(vStrMiCmd); + // Next + ++it; + } + + // report any issues with arguments/options + if (IsArgsPresentButNotHandledByCmd()) + WarningArgsNotHandledbyCmdLogFile(vStrMiCmd); - return ValidationFormErrorMessages(vwCmdArgsText); + return ValidationFormErrorMessages(vwCmdArgsText); } -//++ ------------------------------------------------------------------------------------ -// Details: Having validated the command's options text and failed for some reason form +//++ +//------------------------------------------------------------------------------------ +// Details: Having validated the command's options text and failed for some +// reason form // the error message made up with the faults found. // Type: Method. // vCmdArgsText - (RW) A command's options or argument. @@ -209,139 +210,134 @@ CMICmdArgSet::Validate(const CMIUtilString &vStrMiCmd, CMICmdArgContext &vwCmdAr // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdArgSet::ValidationFormErrorMessages(const CMICmdArgContext &vwCmdArgsText) -{ - CMIUtilString strListMissing; - CMIUtilString strListInvalid; - CMIUtilString strListMissingInfo; - const bool bArgsMissing = (m_setCmdArgsThatAreMissing.size() > 0); - const bool bArgsInvalid = (m_setCmdArgsThatNotValid.size() > 0); - const bool bArgsMissingInfo = (m_setCmdArgsMissingInfo.size() > 0); - if (!(bArgsMissing || bArgsInvalid || bArgsMissingInfo)) - return MIstatus::success; - if (bArgsMissing) - { - MIuint i = 0; - SetCmdArgs_t::const_iterator it = m_setCmdArgsThatAreMissing.begin(); - while (it != m_setCmdArgsThatAreMissing.end()) - { - if (i++ > 0) - strListMissing += m_constStrCommaSpc; - - const CMICmdArgValBase *pArg(*it); - strListMissing += pArg->GetName(); - - // Next - ++it; - } - } - if (bArgsInvalid) - { - MIuint i = 0; - SetCmdArgs_t::const_iterator it = m_setCmdArgsThatNotValid.begin(); - while (it != m_setCmdArgsThatNotValid.end()) - { - if (i++ > 0) - strListMissing += m_constStrCommaSpc; - - const CMICmdArgValBase *pArg(*it); - strListInvalid += pArg->GetName(); - - // Next - ++it; - } - } - if (bArgsMissingInfo) - { - MIuint i = 0; - SetCmdArgs_t::const_iterator it = m_setCmdArgsMissingInfo.begin(); - while (it != m_setCmdArgsMissingInfo.end()) - { - if (i++ > 0) - strListMissingInfo += m_constStrCommaSpc; - - const CMICmdArgValBase *pArg(*it); - strListMissingInfo += pArg->GetName(); - - // Next - ++it; - } - } - - bool bHaveOneError = false; - CMIUtilString strError = MIRSRC(IDS_CMD_ARGS_ERR_PREFIX_MSG); - if (bArgsMissing && bArgsInvalid) - { - bHaveOneError = true; - strError += CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_MAN_INVALID), strListMissing.c_str(), strListInvalid.c_str()); - } - if (bArgsMissing) - { - if (bHaveOneError) - strError += ". "; - bHaveOneError = true; - strError += CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_MANDATORY), strListMissing.c_str()); - } - if (bArgsMissingInfo) - { - if (bHaveOneError) - strError += ". "; - bHaveOneError = true; - strError += CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF), strListMissingInfo.c_str()); +bool CMICmdArgSet::ValidationFormErrorMessages( + const CMICmdArgContext &vwCmdArgsText) { + CMIUtilString strListMissing; + CMIUtilString strListInvalid; + CMIUtilString strListMissingInfo; + const bool bArgsMissing = (m_setCmdArgsThatAreMissing.size() > 0); + const bool bArgsInvalid = (m_setCmdArgsThatNotValid.size() > 0); + const bool bArgsMissingInfo = (m_setCmdArgsMissingInfo.size() > 0); + if (!(bArgsMissing || bArgsInvalid || bArgsMissingInfo)) + return MIstatus::success; + if (bArgsMissing) { + MIuint i = 0; + SetCmdArgs_t::const_iterator it = m_setCmdArgsThatAreMissing.begin(); + while (it != m_setCmdArgsThatAreMissing.end()) { + if (i++ > 0) + strListMissing += m_constStrCommaSpc; + + const CMICmdArgValBase *pArg(*it); + strListMissing += pArg->GetName(); + + // Next + ++it; } - if (bArgsInvalid) - { - if (bHaveOneError) - strError += ". "; - bHaveOneError = true; - strError += CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_INVALID), strListInvalid.c_str()); + } + if (bArgsInvalid) { + MIuint i = 0; + SetCmdArgs_t::const_iterator it = m_setCmdArgsThatNotValid.begin(); + while (it != m_setCmdArgsThatNotValid.end()) { + if (i++ > 0) + strListMissing += m_constStrCommaSpc; + + const CMICmdArgValBase *pArg(*it); + strListInvalid += pArg->GetName(); + + // Next + ++it; } - if (!vwCmdArgsText.IsEmpty()) - { - if (bHaveOneError) - strError += ". "; - bHaveOneError = true; - strError += CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_CONTEXT_NOT_ALL_EATTEN), vwCmdArgsText.GetArgsLeftToParse().c_str()); + } + if (bArgsMissingInfo) { + MIuint i = 0; + SetCmdArgs_t::const_iterator it = m_setCmdArgsMissingInfo.begin(); + while (it != m_setCmdArgsMissingInfo.end()) { + if (i++ > 0) + strListMissingInfo += m_constStrCommaSpc; + + const CMICmdArgValBase *pArg(*it); + strListMissingInfo += pArg->GetName(); + + // Next + ++it; } - + } + + bool bHaveOneError = false; + CMIUtilString strError = MIRSRC(IDS_CMD_ARGS_ERR_PREFIX_MSG); + if (bArgsMissing && bArgsInvalid) { + bHaveOneError = true; + strError += + CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_MAN_INVALID), + strListMissing.c_str(), strListInvalid.c_str()); + } + if (bArgsMissing) { if (bHaveOneError) - { - SetErrorDescription(strError); - return MIstatus::failure; - } - - return MIstatus::success; + strError += ". "; + bHaveOneError = true; + strError += CMIUtilString::Format( + MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_MANDATORY), strListMissing.c_str()); + } + if (bArgsMissingInfo) { + if (bHaveOneError) + strError += ". "; + bHaveOneError = true; + strError += + CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF), + strListMissingInfo.c_str()); + } + if (bArgsInvalid) { + if (bHaveOneError) + strError += ". "; + bHaveOneError = true; + strError += CMIUtilString::Format( + MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_INVALID), strListInvalid.c_str()); + } + if (!vwCmdArgsText.IsEmpty()) { + if (bHaveOneError) + strError += ". "; + bHaveOneError = true; + strError += + CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_CONTEXT_NOT_ALL_EATTEN), + vwCmdArgsText.GetArgsLeftToParse().c_str()); + } + + if (bHaveOneError) { + SetErrorDescription(strError); + return MIstatus::failure; + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Ask if the command's argument options text had any arguments. // Type: Method. // Args: None. -// Return: bool - True = Has one or more arguments present, false = no arguments. +// Return: bool - True = Has one or more arguments present, false = no +// arguments. // Throws: None. //-- -bool -CMICmdArgSet::IsArgContextEmpty() const -{ - return m_cmdArgContext.IsEmpty(); +bool CMICmdArgSet::IsArgContextEmpty() const { + return m_cmdArgContext.IsEmpty(); } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the number of arguments that are being used for the command. +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the number of arguments that are being used for the +// command. // Type: Method. // Args: None. // Return: size_t - Argument count. // Throws: None. //-- -size_t -CMICmdArgSet::GetCount() const -{ - return m_setCmdArgs.size(); -} +size_t CMICmdArgSet::GetCount() const { return m_setCmdArgs.size(); } -//++ ------------------------------------------------------------------------------------ -// Details: Given a set of command argument objects retrieve the argument with the +//++ +//------------------------------------------------------------------------------------ +// Details: Given a set of command argument objects retrieve the argument with +// the // specified name. // Type: Method. // Args: vpArg - (W) A pointer to a command's argument object. @@ -349,59 +345,57 @@ CMICmdArgSet::GetCount() const // False - Argument not found. // Throws: None. //-- -bool -CMICmdArgSet::GetArg(const CMIUtilString &vArgName, CMICmdArgValBase *&vpArg) const -{ - bool bFound = false; - SetCmdArgs_t::const_iterator it = m_setCmdArgs.begin(); - while (it != m_setCmdArgs.end()) - { - CMICmdArgValBase *pArg(*it); - if (pArg->GetName() == vArgName) - { - bFound = true; - vpArg = pArg; - break; - } - - // Next - ++it; +bool CMICmdArgSet::GetArg(const CMIUtilString &vArgName, + CMICmdArgValBase *&vpArg) const { + bool bFound = false; + SetCmdArgs_t::const_iterator it = m_setCmdArgs.begin(); + while (it != m_setCmdArgs.end()) { + CMICmdArgValBase *pArg(*it); + if (pArg->GetName() == vArgName) { + bFound = true; + vpArg = pArg; + break; } - return bFound; + // Next + ++it; + } + + return bFound; } -//++ ------------------------------------------------------------------------------------ -// Details: Write a warning message to the MI Log file about the command's arguments or +//++ +//------------------------------------------------------------------------------------ +// Details: Write a warning message to the MI Log file about the command's +// arguments or // options that were found present but not handled. // Type: Method. // Args: vrCmdName - (R) The command's name. // Return: None. // Throws: None. //-- -void -CMICmdArgSet::WarningArgsNotHandledbyCmdLogFile(const CMIUtilString &vrCmdName) -{ +void CMICmdArgSet::WarningArgsNotHandledbyCmdLogFile( + const CMIUtilString &vrCmdName) { #if MICONFIG_GIVE_WARNING_CMD_ARGS_NOT_HANDLED - CMIUtilString strArgsNotHandled; - const CMICmdArgSet::SetCmdArgs_t &rSetArgs = GetArgsNotHandledByCmd(); - MIuint nCnt = 0; - CMICmdArgSet::SetCmdArgs_t::const_iterator it = rSetArgs.begin(); - while (it != rSetArgs.end()) - { - if (nCnt++ > 0) - strArgsNotHandled += m_constStrCommaSpc; - const CMICmdArgValBase *pArg = *it; - strArgsNotHandled += pArg->GetName(); - - // Next - ++it; - } - - const CMIUtilString strWarningMsg( - CMIUtilString::Format(MIRSRC(IDS_CMD_WRN_ARGS_NOT_HANDLED), vrCmdName.c_str(), strArgsNotHandled.c_str())); - m_pLog->WriteLog(strWarningMsg); + CMIUtilString strArgsNotHandled; + const CMICmdArgSet::SetCmdArgs_t &rSetArgs = GetArgsNotHandledByCmd(); + MIuint nCnt = 0; + CMICmdArgSet::SetCmdArgs_t::const_iterator it = rSetArgs.begin(); + while (it != rSetArgs.end()) { + if (nCnt++ > 0) + strArgsNotHandled += m_constStrCommaSpc; + const CMICmdArgValBase *pArg = *it; + strArgsNotHandled += pArg->GetName(); + + // Next + ++it; + } + + const CMIUtilString strWarningMsg( + CMIUtilString::Format(MIRSRC(IDS_CMD_WRN_ARGS_NOT_HANDLED), + vrCmdName.c_str(), strArgsNotHandled.c_str())); + m_pLog->WriteLog(strWarningMsg); #endif // MICONFIG_GIVE_WARNING_CMD_ARGS_NOT_HANDLED } diff --git a/lldb/tools/lldb-mi/MICmdArgSet.h b/lldb/tools/lldb-mi/MICmdArgSet.h index 2b4392565e0..cb321f0204d 100644 --- a/lldb/tools/lldb-mi/MICmdArgSet.h +++ b/lldb/tools/lldb-mi/MICmdArgSet.h @@ -15,81 +15,98 @@ // Other libraries and framework includes // Project includes -#include "MICmnBase.h" #include "MICmdArgContext.h" +#include "MICmnBase.h" // Declarations: class CMICmdArgValBase; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code class. Command arguments container class. -// A command may have one or more arguments of which some may be optional. +// A command may have one or more arguments of which some may be +// optional. // *this class contains a list of the command's arguments which are -// validates against the commands argument options string (context string). +// validates against the commands argument options string (context +// string). // Each argument tries to extract the value it is looking for. -// Argument objects added to *this container are owned by this container -// and are deleted when this container goes out of scope. Allocate argument +// Argument objects added to *this container are owned by this +// container +// and are deleted when this container goes out of scope. Allocate +// argument // objects on the heap. -// It is assumed the arguments to be parsed are read from left to right in -// order. The order added to *this container is the order they will parsed. +// It is assumed the arguments to be parsed are read from left to right +// in +// order. The order added to *this container is the order they will +// parsed. //-- -class CMICmdArgSet : public CMICmnBase -{ - // Classes: +class CMICmdArgSet : public CMICmnBase { + // Classes: +public: + //++ + // Description: ArgSet's interface for command arguments to implement. + //-- + class IArg { public: - //++ - // Description: ArgSet's interface for command arguments to implement. - //-- - class IArg - { - public: - virtual bool GetFound() const = 0; - virtual bool GetIsHandledByCmd() const = 0; - virtual bool GetIsMandatory() const = 0; - virtual bool GetIsMissingOptions() const = 0; - virtual const CMIUtilString &GetName() const = 0; - virtual bool GetValid() const = 0; - virtual bool Validate(CMICmdArgContext &vwArgContext) = 0; + virtual bool GetFound() const = 0; + virtual bool GetIsHandledByCmd() const = 0; + virtual bool GetIsMandatory() const = 0; + virtual bool GetIsMissingOptions() const = 0; + virtual const CMIUtilString &GetName() const = 0; + virtual bool GetValid() const = 0; + virtual bool Validate(CMICmdArgContext &vwArgContext) = 0; - virtual ~IArg() = default; - }; + virtual ~IArg() = default; + }; - // Typedefs: - typedef std::vector<CMICmdArgValBase *> SetCmdArgs_t; + // Typedefs: + typedef std::vector<CMICmdArgValBase *> SetCmdArgs_t; - // Methods: - CMICmdArgSet(); + // Methods: + CMICmdArgSet(); - void Add(CMICmdArgValBase *vArg); - bool GetArg(const CMIUtilString &vArgName, CMICmdArgValBase *&vpArg) const; - const SetCmdArgs_t &GetArgsThatAreMissing() const; - const SetCmdArgs_t &GetArgsThatInvalid() const; - size_t GetCount() const; - bool IsArgContextEmpty() const; - bool IsArgsPresentButNotHandledByCmd() const; - void WarningArgsNotHandledbyCmdLogFile(const CMIUtilString &vrCmdName); - bool Validate(const CMIUtilString &vStrMiCmd, CMICmdArgContext &vwCmdArgsText); + void Add(CMICmdArgValBase *vArg); + bool GetArg(const CMIUtilString &vArgName, CMICmdArgValBase *&vpArg) const; + const SetCmdArgs_t &GetArgsThatAreMissing() const; + const SetCmdArgs_t &GetArgsThatInvalid() const; + size_t GetCount() const; + bool IsArgContextEmpty() const; + bool IsArgsPresentButNotHandledByCmd() const; + void WarningArgsNotHandledbyCmdLogFile(const CMIUtilString &vrCmdName); + bool Validate(const CMIUtilString &vStrMiCmd, + CMICmdArgContext &vwCmdArgsText); - // Overrideable: - ~CMICmdArgSet() override; + // Overrideable: + ~CMICmdArgSet() override; - // Methods: - private: - const SetCmdArgs_t &GetArgsNotHandledByCmd() const; - void - Destroy(); // Release resources used by *this object - bool ValidationFormErrorMessages(const CMICmdArgContext &vwCmdArgsText); + // Methods: +private: + const SetCmdArgs_t &GetArgsNotHandledByCmd() const; + void Destroy(); // Release resources used by *this object + bool ValidationFormErrorMessages(const CMICmdArgContext &vwCmdArgsText); - // Attributes: - bool m_bIsArgsPresentButNotHandledByCmd; // True = The driver's client presented the command with options recognised but not handled by - // a command, false = all args handled - SetCmdArgs_t m_setCmdArgs; // The set of arguments that are that the command is expecting to find in the options string - SetCmdArgs_t m_setCmdArgsThatAreMissing; // The set of arguments that are required by the command but are missing - SetCmdArgs_t m_setCmdArgsThatNotValid; // The set of arguments found in the text but for some reason unable to extract a value - SetCmdArgs_t - m_setCmdArgsNotHandledByCmd; // The set of arguments specified by the command which were present to the command but not handled - SetCmdArgs_t m_setCmdArgsMissingInfo; // The set of arguments that were present but were found to be missing additional information i.e. - // --thread 3 but 3 is missing - CMICmdArgContext m_cmdArgContext; // Copy of the command's argument options text before validate takes place (empties it of content) - const CMIUtilString m_constStrCommaSpc; + // Attributes: + bool m_bIsArgsPresentButNotHandledByCmd; // True = The driver's client + // presented the command with options + // recognised but not handled by + // a command, false = all args handled + SetCmdArgs_t m_setCmdArgs; // The set of arguments that are that the command + // is expecting to find in the options string + SetCmdArgs_t m_setCmdArgsThatAreMissing; // The set of arguments that are + // required by the command but are + // missing + SetCmdArgs_t m_setCmdArgsThatNotValid; // The set of arguments found in the + // text but for some reason unable to + // extract a value + SetCmdArgs_t m_setCmdArgsNotHandledByCmd; // The set of arguments specified by + // the command which were present to + // the command but not handled + SetCmdArgs_t m_setCmdArgsMissingInfo; // The set of arguments that were + // present but were found to be missing + // additional information i.e. + // --thread 3 but 3 is missing + CMICmdArgContext m_cmdArgContext; // Copy of the command's argument options + // text before validate takes place (empties + // it of content) + const CMIUtilString m_constStrCommaSpc; }; diff --git a/lldb/tools/lldb-mi/MICmdArgValBase.cpp b/lldb/tools/lldb-mi/MICmdArgValBase.cpp index ddbf957ea47..bedd983a06f 100644 --- a/lldb/tools/lldb-mi/MICmdArgValBase.cpp +++ b/lldb/tools/lldb-mi/MICmdArgValBase.cpp @@ -12,10 +12,11 @@ // Other libraries and framework includes // Project includes #include "MICmdArgValBase.h" -#include "MIUtilString.h" #include "MICmdArgContext.h" +#include "MIUtilString.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValBase constructor. // Type: Method. // Args: None. @@ -23,35 +24,32 @@ // Throws: None. //-- CMICmdArgValBase::CMICmdArgValBase() - : m_bFound(false) - , m_bValid(false) - , m_bMandatory(false) - , m_bHandled(false) - , m_bIsMissingOptions(false) -{ -} + : m_bFound(false), m_bValid(false), m_bMandatory(false), m_bHandled(false), + m_bIsMissingOptions(false) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValBase constructor. // Type: Method. // Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// vbMandatory - (R) True = Yes must be present, false = optional +// argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = +// not handled. // Return: None. // Throws: None. //-- -CMICmdArgValBase::CMICmdArgValBase(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd) - : m_bFound(false) - , m_bValid(false) - , m_bMandatory(vbMandatory) - , m_strArgName(vrArgName) - , m_bHandled(vbHandleByCmd) - , m_bIsMissingOptions(false) -{ -} +CMICmdArgValBase::CMICmdArgValBase(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd) + : m_bFound(false), m_bValid(false), m_bMandatory(vbMandatory), + m_strArgName(vrArgName), m_bHandled(vbHandleByCmd), + m_bIsMissingOptions(false) {} -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the state flag of whether the argument is handled by the command or +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the state flag of whether the argument is handled by the +// command or // not. // Type: Method. // Args: None. @@ -59,14 +57,14 @@ CMICmdArgValBase::CMICmdArgValBase(const CMIUtilString &vrArgName, const bool vb // False - All information is present as expected. // Throws: None. //-- -bool -CMICmdArgValBase::GetIsMissingOptions() const -{ - return m_bIsMissingOptions; +bool CMICmdArgValBase::GetIsMissingOptions() const { + return m_bIsMissingOptions; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the state flag of whether the argument is handled by the command or +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the state flag of whether the argument is handled by the +// command or // not. // Type: Method. // Args: None. @@ -74,27 +72,22 @@ CMICmdArgValBase::GetIsMissingOptions() const // False - Not handled (argument specified but ignored). // Throws: None. //-- -bool -CMICmdArgValBase::GetIsHandledByCmd() const -{ - return m_bHandled; -} +bool CMICmdArgValBase::GetIsHandledByCmd() const { return m_bHandled; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the name of *this argument. // Type: Method. // Args: None. // Return: CMIUtilString & - Return the text name. // Throws: None. //-- -const CMIUtilString & -CMICmdArgValBase::GetName() const -{ - return m_strArgName; -} +const CMIUtilString &CMICmdArgValBase::GetName() const { return m_strArgName; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the state flag of whether the argument was found in the command's +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the state flag of whether the argument was found in the +// command's // argument / options string. // Type: Method. // Args: None. @@ -102,14 +95,12 @@ CMICmdArgValBase::GetName() const // False - Argument not found. // Throws: None. //-- -bool -CMICmdArgValBase::GetFound() const -{ - return m_bFound; -} +bool CMICmdArgValBase::GetFound() const { return m_bFound; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the state flag indicating whether the value was obtained from the +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the state flag indicating whether the value was obtained +// from the // text arguments string and is valid. // Type: Method. // Args: None. @@ -117,14 +108,12 @@ CMICmdArgValBase::GetFound() const // False - Argument not valid. // Throws: None. //-- -bool -CMICmdArgValBase::GetValid() const -{ - return m_bValid; -} +bool CMICmdArgValBase::GetValid() const { return m_bValid; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the state flag indicating whether *this argument is a mandatory +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the state flag indicating whether *this argument is a +// mandatory // argument for the command or is optional to be present. // Type: Method. // Args: None. @@ -132,14 +121,12 @@ CMICmdArgValBase::GetValid() const // False - Optional. // Throws: None. //-- -bool -CMICmdArgValBase::GetIsMandatory() const -{ - return m_bMandatory; -} +bool CMICmdArgValBase::GetIsMandatory() const { return m_bMandatory; } -//++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract the value *this +//++ +//------------------------------------------------------------------------------------ +// Details: Parse the command's argument options string and try to extract the +// value *this // argument is looking for. // Type: Overrideable. // Args: vArgContext - (RW) The command's argument options string. @@ -147,12 +134,10 @@ CMICmdArgValBase::GetIsMandatory() const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdArgValBase::Validate(CMICmdArgContext &vwArgContext) -{ - MIunused(vwArgContext); +bool CMICmdArgValBase::Validate(CMICmdArgContext &vwArgContext) { + MIunused(vwArgContext); - // Override to implement + // Override to implement - return MIstatus::failure; + return MIstatus::failure; } diff --git a/lldb/tools/lldb-mi/MICmdArgValBase.h b/lldb/tools/lldb-mi/MICmdArgValBase.h index c343b3338c3..28847608280 100644 --- a/lldb/tools/lldb-mi/MICmdArgValBase.h +++ b/lldb/tools/lldb-mi/MICmdArgValBase.h @@ -13,10 +13,11 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "MIUtilString.h" #include "MICmdArgSet.h" +#include "MIUtilString.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code class. Command argument base class. Arguments objects // needing specialization derived from *this class. An argument knows // what type of argument it is and how it is to interpret the options @@ -27,89 +28,95 @@ // deleted when the container goes out of scope. Allocate argument // objects on the heap and pass in to the Add(). // Note the code is written such that a command will produce an error -// should it be presented with arguments or options it does not understand. +// should it be presented with arguments or options it does not +// understand. // A command can recognise an option or argument then ignore if it // wishes (a warning is sent to the MI's Log file). This is so it is // hardwired to fail and catch arguments or options that presented by // different driver clients. // Based on the Interpreter pattern. //-- -class CMICmdArgValBase : public CMICmdArgSet::IArg -{ - // Methods: - public: - CMICmdArgValBase(); - CMICmdArgValBase(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd); +class CMICmdArgValBase : public CMICmdArgSet::IArg { + // Methods: +public: + CMICmdArgValBase(); + CMICmdArgValBase(const CMIUtilString &vrArgName, const bool vbMandatory, + const bool vbHandleByCmd); - // Overrideable: - ~CMICmdArgValBase() override = default; + // Overrideable: + ~CMICmdArgValBase() override = default; - // Overridden: - // From CMICmdArgSet::IArg - bool GetFound() const override; - bool GetIsHandledByCmd() const override; - bool GetIsMandatory() const override; - bool GetIsMissingOptions() const override; - const CMIUtilString &GetName() const override; - bool GetValid() const override; - bool Validate(CMICmdArgContext &vwArgContext) override; + // Overridden: + // From CMICmdArgSet::IArg + bool GetFound() const override; + bool GetIsHandledByCmd() const override; + bool GetIsMandatory() const override; + bool GetIsMissingOptions() const override; + const CMIUtilString &GetName() const override; + bool GetValid() const override; + bool Validate(CMICmdArgContext &vwArgContext) override; - // Attributes: - protected: - bool m_bFound; // True = yes found in arguments options text, false = not found - bool m_bValid; // True = yes argument parsed and valid, false = not valid - bool m_bMandatory; // True = yes arg must be present, false = optional argument - CMIUtilString m_strArgName; - bool m_bHandled; // True = Command processes *this option, false = not handled - bool m_bIsMissingOptions; // True = Command needs more information, false = ok + // Attributes: +protected: + bool + m_bFound; // True = yes found in arguments options text, false = not found + bool m_bValid; // True = yes argument parsed and valid, false = not valid + bool + m_bMandatory; // True = yes arg must be present, false = optional argument + CMIUtilString m_strArgName; + bool m_bHandled; // True = Command processes *this option, false = not handled + bool m_bIsMissingOptions; // True = Command needs more information, false = ok }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code class. Templated command argument base class. //-- -template <class T> class CMICmdArgValBaseTemplate : public CMICmdArgValBase -{ - // Methods: - public: - CMICmdArgValBaseTemplate() = default; - CMICmdArgValBaseTemplate(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd); - // - const T &GetValue() const; +template <class T> class CMICmdArgValBaseTemplate : public CMICmdArgValBase { + // Methods: +public: + CMICmdArgValBaseTemplate() = default; + CMICmdArgValBaseTemplate(const CMIUtilString &vrArgName, + const bool vbMandatory, const bool vbHandleByCmd); + // + const T &GetValue() const; - // Overrideable: - ~CMICmdArgValBaseTemplate() override = default; + // Overrideable: + ~CMICmdArgValBaseTemplate() override = default; - // Attributes: - protected: - T m_argValue; + // Attributes: +protected: + T m_argValue; }; -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValBaseTemplate constructor. // Type: Method. // Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// vbMandatory - (R) True = Yes must be present, false = optional +// argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = +// not handled. // Return: None. // Throws: None. //-- template <class T> -CMICmdArgValBaseTemplate<T>::CMICmdArgValBaseTemplate(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd) - : CMICmdArgValBase(vrArgName, vbMandatory, vbHandleByCmd) -{ -} +CMICmdArgValBaseTemplate<T>::CMICmdArgValBaseTemplate( + const CMIUtilString &vrArgName, const bool vbMandatory, + const bool vbHandleByCmd) + : CMICmdArgValBase(vrArgName, vbMandatory, vbHandleByCmd) {} -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the value the argument parsed from the command's argument / options +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the value the argument parsed from the command's argument / +// options // text string. // Type: Method. // Args: None. // Return: Template type & - The arg value of *this object. // Throws: None. //-- -template <class T> -const T & -CMICmdArgValBaseTemplate<T>::GetValue() const -{ - return m_argValue; +template <class T> const T &CMICmdArgValBaseTemplate<T>::GetValue() const { + return m_argValue; } diff --git a/lldb/tools/lldb-mi/MICmdArgValConsume.cpp b/lldb/tools/lldb-mi/MICmdArgValConsume.cpp index 12d32912c37..5a76ab4b56f 100644 --- a/lldb/tools/lldb-mi/MICmdArgValConsume.cpp +++ b/lldb/tools/lldb-mi/MICmdArgValConsume.cpp @@ -11,43 +11,44 @@ #include "MICmdArgValConsume.h" #include "MICmdArgContext.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValConsume constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdArgValConsume::CMICmdArgValConsume() -{ -} +CMICmdArgValConsume::CMICmdArgValConsume() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValConsume constructor. // Type: Method. // Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. +// vbMandatory - (R) True = Yes must be present, false = optional +// argument. // Return: None. // Throws: None. //-- -CMICmdArgValConsume::CMICmdArgValConsume(const CMIUtilString &vrArgName, const bool vbMandatory) - : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, true) -{ -} +CMICmdArgValConsume::CMICmdArgValConsume(const CMIUtilString &vrArgName, + const bool vbMandatory) + : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, true) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValConsume destructor. // Type: Overidden. // Args: None. // Return: None. // Throws: None. //-- -CMICmdArgValConsume::~CMICmdArgValConsume() -{ -} +CMICmdArgValConsume::~CMICmdArgValConsume() {} -//++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract the value *this +//++ +//------------------------------------------------------------------------------------ +// Details: Parse the command's argument options string and try to extract the +// value *this // argument is looking for. // Type: Overridden. // Args: vwArgContext - (R) The command's argument options string. @@ -55,44 +56,39 @@ CMICmdArgValConsume::~CMICmdArgValConsume() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdArgValConsume::Validate(CMICmdArgContext &vwArgContext) -{ - if (vwArgContext.IsEmpty()) - return m_bMandatory ? MIstatus::failure : MIstatus::success; +bool CMICmdArgValConsume::Validate(CMICmdArgContext &vwArgContext) { + if (vwArgContext.IsEmpty()) + return m_bMandatory ? MIstatus::failure : MIstatus::success; - // Consume the optional file, line, linenum arguments till the mode '--' argument - const CMIUtilString::VecString_t vecOptions(vwArgContext.GetArgs()); - CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); - while (it != vecOptions.end()) - { - const CMIUtilString & rTxt( *it ); - - if ( rTxt.compare( "--" ) == 0 ) - { - m_bFound = true; - m_bValid = true; - if ( !vwArgContext.RemoveArg( rTxt ) ) - return MIstatus::failure; - return MIstatus::success; - } - // Next - ++it; + // Consume the optional file, line, linenum arguments till the mode '--' + // argument + const CMIUtilString::VecString_t vecOptions(vwArgContext.GetArgs()); + CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); + while (it != vecOptions.end()) { + const CMIUtilString &rTxt(*it); + + if (rTxt.compare("--") == 0) { + m_bFound = true; + m_bValid = true; + if (!vwArgContext.RemoveArg(rTxt)) + return MIstatus::failure; + return MIstatus::success; } + // Next + ++it; + } - return MIstatus::failure; + return MIstatus::failure; } -//++ ------------------------------------------------------------------------------------ -// Details: Nothing to examine as we just want to consume the argument or option (ignore +//++ +//------------------------------------------------------------------------------------ +// Details: Nothing to examine as we just want to consume the argument or option +// (ignore // it). // Type: Method. // Args: None. // Return: bool - True = yes ok, false = not ok. // Throws: None. //-- -bool -CMICmdArgValConsume::IsOk() const -{ - return true; -} +bool CMICmdArgValConsume::IsOk() const { return true; } diff --git a/lldb/tools/lldb-mi/MICmdArgValConsume.h b/lldb/tools/lldb-mi/MICmdArgValConsume.h index 792a9bed648..1169eb9a4ef 100644 --- a/lldb/tools/lldb-mi/MICmdArgValConsume.h +++ b/lldb/tools/lldb-mi/MICmdArgValConsume.h @@ -15,34 +15,40 @@ // Declarations: class CMICmdArgContext; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code class. Command argument class. Arguments object // needing specialization derived from the CMICmdArgValBase class. // An argument knows what type of argument it is and how it is to -// interpret the options (context) string to find and validate a matching -// argument. This type having recognised its argument name just consumes +// interpret the options (context) string to find and validate a +// matching +// argument. This type having recognised its argument name just +// consumes // that argument or option (ignores it). This is the so the validation -// process can then ask if all arguments or options have been recognised +// process can then ask if all arguments or options have been +// recognised // other an error will occurred "argument not recognised". For example -// this can be used to consume the "--" text which is not an argument in -// itself. Normally the GetValue() function (in base class) would return +// this can be used to consume the "--" text which is not an argument +// in +// itself. Normally the GetValue() function (in base class) would +// return // a value for the argument but is not the case for *this argument type // object. // Based on the Interpreter pattern. //-- -class CMICmdArgValConsume : public CMICmdArgValBaseTemplate<CMIUtilString> -{ - // Methods: - public: - /* ctor */ CMICmdArgValConsume(); - /* ctor */ CMICmdArgValConsume(const CMIUtilString &vrArgName, const bool vbMandatory); - // - bool IsOk() const; +class CMICmdArgValConsume : public CMICmdArgValBaseTemplate<CMIUtilString> { + // Methods: +public: + /* ctor */ CMICmdArgValConsume(); + /* ctor */ CMICmdArgValConsume(const CMIUtilString &vrArgName, + const bool vbMandatory); + // + bool IsOk() const; - // Overridden: - public: - // From CMICmdArgValBase - /* dtor */ ~CMICmdArgValConsume() override; - // From CMICmdArgSet::IArg - bool Validate(CMICmdArgContext &vwArgContext) override; + // Overridden: +public: + // From CMICmdArgValBase + /* dtor */ ~CMICmdArgValConsume() override; + // From CMICmdArgSet::IArg + bool Validate(CMICmdArgContext &vwArgContext) override; }; diff --git a/lldb/tools/lldb-mi/MICmdArgValFile.cpp b/lldb/tools/lldb-mi/MICmdArgValFile.cpp index 7f5b20ec314..77e9a6b2af8 100644 --- a/lldb/tools/lldb-mi/MICmdArgValFile.cpp +++ b/lldb/tools/lldb-mi/MICmdArgValFile.cpp @@ -11,44 +11,47 @@ #include "MICmdArgValFile.h" #include "MICmdArgContext.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValFile constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdArgValFile::CMICmdArgValFile() -{ -} +CMICmdArgValFile::CMICmdArgValFile() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValFile constructor. // Type: Method. // Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// vbMandatory - (R) True = Yes must be present, false = optional +// argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = +// not handled. // Return: None. // Throws: None. //-- -CMICmdArgValFile::CMICmdArgValFile(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd) - : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd) -{ -} +CMICmdArgValFile::CMICmdArgValFile(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd) + : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValFile destructor. // Type: Overridden. // Args: None. // Return: None. // Throws: None. //-- -CMICmdArgValFile::~CMICmdArgValFile() -{ -} +CMICmdArgValFile::~CMICmdArgValFile() {} -//++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract the value *this +//++ +//------------------------------------------------------------------------------------ +// Details: Parse the command's argument options string and try to extract the +// value *this // argument is looking for. // Type: Overridden. // Args: vwArgContext - (R) The command's argument options string. @@ -56,59 +59,52 @@ CMICmdArgValFile::~CMICmdArgValFile() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdArgValFile::Validate(CMICmdArgContext &vwArgContext) -{ - if (vwArgContext.IsEmpty()) - return m_bMandatory ? MIstatus::failure : MIstatus::success; - - // The GDB/MI spec suggests there is only parameter - - if (vwArgContext.GetNumberArgsPresent() == 1) - { - const CMIUtilString &rFile(vwArgContext.GetArgsLeftToParse()); - if (IsFilePath(rFile)) - { - m_bFound = true; - m_bValid = true; - m_argValue = rFile.Trim('"'); - vwArgContext.RemoveArg(rFile); - return MIstatus::success; - } - else - return MIstatus::failure; +bool CMICmdArgValFile::Validate(CMICmdArgContext &vwArgContext) { + if (vwArgContext.IsEmpty()) + return m_bMandatory ? MIstatus::failure : MIstatus::success; + + // The GDB/MI spec suggests there is only parameter + + if (vwArgContext.GetNumberArgsPresent() == 1) { + const CMIUtilString &rFile(vwArgContext.GetArgsLeftToParse()); + if (IsFilePath(rFile)) { + m_bFound = true; + m_bValid = true; + m_argValue = rFile.Trim('"'); + vwArgContext.RemoveArg(rFile); + return MIstatus::success; + } else + return MIstatus::failure; + } + + // In reality there are more than one option, if so the file option + // is the last one (don't handle that here - find the best looking one) + const CMIUtilString::VecString_t vecOptions(vwArgContext.GetArgs()); + CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); + while (it != vecOptions.end()) { + const CMIUtilString &rTxt(*it); + if (IsFilePath(rTxt)) { + m_bFound = true; + + if (vwArgContext.RemoveArg(rTxt)) { + m_bValid = true; + m_argValue = rTxt.Trim('"'); + return MIstatus::success; + } else + return MIstatus::success; } - // In reality there are more than one option, if so the file option - // is the last one (don't handle that here - find the best looking one) - const CMIUtilString::VecString_t vecOptions(vwArgContext.GetArgs()); - CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); - while (it != vecOptions.end()) - { - const CMIUtilString &rTxt(*it); - if (IsFilePath(rTxt)) - { - m_bFound = true; - - if (vwArgContext.RemoveArg(rTxt)) - { - m_bValid = true; - m_argValue = rTxt.Trim('"'); - return MIstatus::success; - } - else - return MIstatus::success; - } - - // Next - ++it; - } + // Next + ++it; + } - return MIstatus::failure; + return MIstatus::failure; } -//++ ------------------------------------------------------------------------------------ -// Details: Given some text extract the file name path from it. If a space is found in +//++ +//------------------------------------------------------------------------------------ +// Details: Given some text extract the file name path from it. If a space is +// found in // path done return the path surrounded in quotes. // Type: Method. // Args: vrTxt - (R) The text to extract the file name path from. @@ -116,82 +112,78 @@ CMICmdArgValFile::Validate(CMICmdArgContext &vwArgContext) // Throws: None. //-- CMIUtilString -CMICmdArgValFile::GetFileNamePath(const CMIUtilString &vrTxt) const -{ - CMIUtilString fileNamePath(vrTxt); +CMICmdArgValFile::GetFileNamePath(const CMIUtilString &vrTxt) const { + CMIUtilString fileNamePath(vrTxt); - // Look for a space in the path - const char cSpace = ' '; - const size_t nPos = fileNamePath.find(cSpace); - if (nPos != std::string::npos) - fileNamePath = CMIUtilString::Format("\"%s\"", fileNamePath.c_str()); + // Look for a space in the path + const char cSpace = ' '; + const size_t nPos = fileNamePath.find(cSpace); + if (nPos != std::string::npos) + fileNamePath = CMIUtilString::Format("\"%s\"", fileNamePath.c_str()); - return fileNamePath; + return fileNamePath; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Examine the string and determine if it is a valid file name path. // Type: Method. // Args: vrFileNamePath - (R) File's name and directory path. // Return: bool - True = yes valid file path, false = no. // Throws: None. //-- -bool -CMICmdArgValFile::IsFilePath(const CMIUtilString &vrFileNamePath) const -{ - if (vrFileNamePath.empty()) - return false; +bool CMICmdArgValFile::IsFilePath(const CMIUtilString &vrFileNamePath) const { + if (vrFileNamePath.empty()) + return false; - const bool bHavePosSlash = (vrFileNamePath.find('/') != std::string::npos); - const bool bHaveBckSlash = (vrFileNamePath.find('\\') != std::string::npos); + const bool bHavePosSlash = (vrFileNamePath.find('/') != std::string::npos); + const bool bHaveBckSlash = (vrFileNamePath.find('\\') != std::string::npos); - // Look for --someLongOption - size_t nPos = vrFileNamePath.find("--"); - const bool bLong = (nPos == 0); - if (bLong) - return false; + // Look for --someLongOption + size_t nPos = vrFileNamePath.find("--"); + const bool bLong = (nPos == 0); + if (bLong) + return false; - // Look for -f type short parameters - nPos = vrFileNamePath.find('-'); - const bool bShort = (nPos == 0); - if (bShort) - return false; + // Look for -f type short parameters + nPos = vrFileNamePath.find('-'); + const bool bShort = (nPos == 0); + if (bShort) + return false; - // Look for i1 i2 i3.... - nPos = vrFileNamePath.find('i'); - const bool bFoundI1 = ((nPos == 0) && (::isdigit(vrFileNamePath[1]))); - if (bFoundI1) - return false; + // Look for i1 i2 i3.... + nPos = vrFileNamePath.find('i'); + const bool bFoundI1 = ((nPos == 0) && (::isdigit(vrFileNamePath[1]))); + if (bFoundI1) + return false; - const bool bValidChars = IsValidChars(vrFileNamePath); - if (bValidChars || bHavePosSlash || bHaveBckSlash) - return true; + const bool bValidChars = IsValidChars(vrFileNamePath); + if (bValidChars || bHavePosSlash || bHaveBckSlash) + return true; - return false; + return false; } -//++ ------------------------------------------------------------------------------------ -// Details: Determine if the path contains valid characters for a file path. Letters can be +//++ +//------------------------------------------------------------------------------------ +// Details: Determine if the path contains valid characters for a file path. +// Letters can be // either upper or lower case. // Type: Method. // Args: vrText - (R) The text data to examine. // Return: bool - True = yes valid, false = one or more chars is valid. // Throws: None. //-- -bool -CMICmdArgValFile::IsValidChars(const CMIUtilString &vrText) const -{ - static CMIUtilString s_strSpecialCharacters(".'\"`@#$%^&*()_+-={}[]| "); - const char *pPtr = vrText.c_str(); - for (MIuint i = 0; i < vrText.length(); i++, pPtr++) - { - const char c = *pPtr; - if (::isalnum((int)c) == 0) - { - if (s_strSpecialCharacters.find(c) == CMIUtilString::npos) - return false; - } +bool CMICmdArgValFile::IsValidChars(const CMIUtilString &vrText) const { + static CMIUtilString s_strSpecialCharacters(".'\"`@#$%^&*()_+-={}[]| "); + const char *pPtr = vrText.c_str(); + for (MIuint i = 0; i < vrText.length(); i++, pPtr++) { + const char c = *pPtr; + if (::isalnum((int)c) == 0) { + if (s_strSpecialCharacters.find(c) == CMIUtilString::npos) + return false; } + } - return true; + return true; } diff --git a/lldb/tools/lldb-mi/MICmdArgValFile.h b/lldb/tools/lldb-mi/MICmdArgValFile.h index 25d9842ec07..def870e7649 100644 --- a/lldb/tools/lldb-mi/MICmdArgValFile.h +++ b/lldb/tools/lldb-mi/MICmdArgValFile.h @@ -15,32 +15,34 @@ // Declarations: class CMICmdArgContext; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code class. Command argument class. Arguments object // needing specialization derived from the CMICmdArgValBase class. // An argument knows what type of argument it is and how it is to -// interpret the options (context) string to find and validate a matching +// interpret the options (context) string to find and validate a +// matching // argument and so extract a value from it . // Based on the Interpreter pattern. //-- -class CMICmdArgValFile : public CMICmdArgValBaseTemplate<CMIUtilString> -{ - // Methods: - public: - /* ctor */ CMICmdArgValFile(); - /* ctor */ CMICmdArgValFile(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd); - // - bool IsFilePath(const CMIUtilString &vrFileNamePath) const; - CMIUtilString GetFileNamePath(const CMIUtilString &vrTxt) const; +class CMICmdArgValFile : public CMICmdArgValBaseTemplate<CMIUtilString> { + // Methods: +public: + /* ctor */ CMICmdArgValFile(); + /* ctor */ CMICmdArgValFile(const CMIUtilString &vrArgName, + const bool vbMandatory, const bool vbHandleByCmd); + // + bool IsFilePath(const CMIUtilString &vrFileNamePath) const; + CMIUtilString GetFileNamePath(const CMIUtilString &vrTxt) const; - // Overridden: - public: - // From CMICmdArgValBase - /* dtor */ ~CMICmdArgValFile() override; - // From CMICmdArgSet::IArg - bool Validate(CMICmdArgContext &vwArgContext) override; + // Overridden: +public: + // From CMICmdArgValBase + /* dtor */ ~CMICmdArgValFile() override; + // From CMICmdArgSet::IArg + bool Validate(CMICmdArgContext &vwArgContext) override; - // Methods: - private: - bool IsValidChars(const CMIUtilString &vrText) const; + // Methods: +private: + bool IsValidChars(const CMIUtilString &vrText) const; }; diff --git a/lldb/tools/lldb-mi/MICmdArgValListBase.cpp b/lldb/tools/lldb-mi/MICmdArgValListBase.cpp index 05396284e22..ff18abaac38 100644 --- a/lldb/tools/lldb-mi/MICmdArgValListBase.cpp +++ b/lldb/tools/lldb-mi/MICmdArgValListBase.cpp @@ -10,15 +10,16 @@ // In-house headers: #include "MICmdArgValListBase.h" #include "MICmdArgContext.h" +#include "MICmdArgValConsume.h" #include "MICmdArgValFile.h" #include "MICmdArgValNumber.h" #include "MICmdArgValOptionLong.h" #include "MICmdArgValOptionShort.h" #include "MICmdArgValString.h" #include "MICmdArgValThreadGrp.h" -#include "MICmdArgValConsume.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValListBase constructor. // Type: Method. // Args: None. @@ -26,80 +27,85 @@ // Throws: None. //-- CMICmdArgValListBase::CMICmdArgValListBase() - : m_eArgType(eArgValType_invalid) -{ -} + : m_eArgType(eArgValType_invalid) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValListBase constructor. // Type: Method. // Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// vbMandatory - (R) True = Yes must be present, false = optional +// argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = +// not handled. // Return: None. // Throws: None. //-- -CMICmdArgValListBase::CMICmdArgValListBase(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd) - : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd) - , m_eArgType(eArgValType_invalid) -{ -} +CMICmdArgValListBase::CMICmdArgValListBase(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd) + : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd), + m_eArgType(eArgValType_invalid) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValListBase constructor. // Type: Method. // Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// veType - (R) The type of argument to look for and create argument object of a certain type. +// vbMandatory - (R) True = Yes must be present, false = optional +// argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = +// not handled. +// veType - (R) The type of argument to look for and create +// argument object of a certain type. // Return: None. // Throws: None. //-- -CMICmdArgValListBase::CMICmdArgValListBase(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, +CMICmdArgValListBase::CMICmdArgValListBase(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd, const ArgValType_e veType) - : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd) - , m_eArgType(veType) -{ -} + : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd), + m_eArgType(veType) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValListBase destructor. // Type: Overridden. // Args: None. // Return: None. // Throws: None. //-- -CMICmdArgValListBase::~CMICmdArgValListBase() -{ - // Tidy up - Destroy(); +CMICmdArgValListBase::~CMICmdArgValListBase() { + // Tidy up + Destroy(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Tear down resources used by *this object. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -void -CMICmdArgValListBase::Destroy() -{ - // Tidy up - VecArgObjPtr_t::const_iterator it = m_argValue.begin(); - while (it != m_argValue.end()) - { - CMICmdArgValBase *pArgObj = *it; - delete pArgObj; +void CMICmdArgValListBase::Destroy() { + // Tidy up + VecArgObjPtr_t::const_iterator it = m_argValue.begin(); + while (it != m_argValue.end()) { + CMICmdArgValBase *pArgObj = *it; + delete pArgObj; - // Next - ++it; - } - m_argValue.clear(); + // Next + ++it; + } + m_argValue.clear(); } -//++ ------------------------------------------------------------------------------------ -// Details: Create an CMICmdArgValBase derived object matching the type specified +//++ +//------------------------------------------------------------------------------------ +// Details: Create an CMICmdArgValBase derived object matching the type +// specified // and put the option or argument's value inside it. // Type: Method. // Args: vrTxt - (R) Text version the option or argument. @@ -109,56 +115,56 @@ CMICmdArgValListBase::Destroy() // Throws: None. //-- CMICmdArgValBase * -CMICmdArgValListBase::CreationObj(const CMIUtilString &vrTxt, const ArgValType_e veType) const -{ - CMICmdArgValBase *pOptionObj = nullptr; - switch (veType) - { - case eArgValType_File: - pOptionObj = new CMICmdArgValFile(); - break; - case eArgValType_Consume: - pOptionObj = new CMICmdArgValConsume(); - break; - case eArgValType_Number: - pOptionObj = new CMICmdArgValNumber(); - break; - case eArgValType_OptionLong: - pOptionObj = new CMICmdArgValOptionLong(); - break; - case eArgValType_OptionShort: - pOptionObj = new CMICmdArgValOptionShort(); - break; - case eArgValType_String: - pOptionObj = new CMICmdArgValString(); - break; - case eArgValType_StringQuoted: - pOptionObj = new CMICmdArgValString(true, false, false); - break; - case eArgValType_StringQuotedNumber: - pOptionObj = new CMICmdArgValString(true, true, false); - break; - case eArgValType_StringQuotedNumberPath: - pOptionObj = new CMICmdArgValString(true, true, true); - break; - case eArgValType_StringAnything: - pOptionObj = new CMICmdArgValString(true); - break; - case eArgValType_ThreadGrp: - pOptionObj = new CMICmdArgValThreadGrp(); - break; - default: - return nullptr; - } +CMICmdArgValListBase::CreationObj(const CMIUtilString &vrTxt, + const ArgValType_e veType) const { + CMICmdArgValBase *pOptionObj = nullptr; + switch (veType) { + case eArgValType_File: + pOptionObj = new CMICmdArgValFile(); + break; + case eArgValType_Consume: + pOptionObj = new CMICmdArgValConsume(); + break; + case eArgValType_Number: + pOptionObj = new CMICmdArgValNumber(); + break; + case eArgValType_OptionLong: + pOptionObj = new CMICmdArgValOptionLong(); + break; + case eArgValType_OptionShort: + pOptionObj = new CMICmdArgValOptionShort(); + break; + case eArgValType_String: + pOptionObj = new CMICmdArgValString(); + break; + case eArgValType_StringQuoted: + pOptionObj = new CMICmdArgValString(true, false, false); + break; + case eArgValType_StringQuotedNumber: + pOptionObj = new CMICmdArgValString(true, true, false); + break; + case eArgValType_StringQuotedNumberPath: + pOptionObj = new CMICmdArgValString(true, true, true); + break; + case eArgValType_StringAnything: + pOptionObj = new CMICmdArgValString(true); + break; + case eArgValType_ThreadGrp: + pOptionObj = new CMICmdArgValThreadGrp(); + break; + default: + return nullptr; + } - CMICmdArgContext argCntxt(vrTxt); - if (!pOptionObj->Validate(argCntxt)) - return nullptr; + CMICmdArgContext argCntxt(vrTxt); + if (!pOptionObj->Validate(argCntxt)) + return nullptr; - return pOptionObj; + return pOptionObj; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Validate the option or argument is the correct type. // Type: Method. // Args: vrTxt - (R) Text version the option or argument. @@ -166,48 +172,46 @@ CMICmdArgValListBase::CreationObj(const CMIUtilString &vrTxt, const ArgValType_e // Return: bool - True = Yes expected type present, False = no. // Throws: None. //-- -bool -CMICmdArgValListBase::IsExpectedCorrectType(const CMIUtilString &vrTxt, const ArgValType_e veType) const -{ - bool bValid = false; - switch (veType) - { - case eArgValType_File: - bValid = CMICmdArgValFile().IsFilePath(vrTxt); - break; - case eArgValType_Consume: - bValid = CMICmdArgValConsume().IsOk(); - break; - case eArgValType_Number: - bValid = CMICmdArgValNumber().IsArgNumber(vrTxt); - break; - case eArgValType_OptionLong: - bValid = CMICmdArgValOptionLong().IsArgLongOption(vrTxt); - break; - case eArgValType_OptionShort: - bValid = CMICmdArgValOptionShort().IsArgShortOption(vrTxt); - break; - case eArgValType_String: - bValid = CMICmdArgValString().IsStringArg(vrTxt); - break; - case eArgValType_StringQuoted: - bValid = CMICmdArgValString(true, false, false).IsStringArg(vrTxt); - break; - case eArgValType_StringQuotedNumber: - bValid = CMICmdArgValString(true, true, false).IsStringArg(vrTxt); - break; - case eArgValType_StringQuotedNumberPath: - bValid = CMICmdArgValString(true, true, true).IsStringArg(vrTxt); - break; - case eArgValType_StringAnything: - bValid = CMICmdArgValString(true).IsStringArg(vrTxt); - break; - case eArgValType_ThreadGrp: - bValid = CMICmdArgValThreadGrp().IsArgThreadGrp(vrTxt); - break; - default: - return false; - } +bool CMICmdArgValListBase::IsExpectedCorrectType( + const CMIUtilString &vrTxt, const ArgValType_e veType) const { + bool bValid = false; + switch (veType) { + case eArgValType_File: + bValid = CMICmdArgValFile().IsFilePath(vrTxt); + break; + case eArgValType_Consume: + bValid = CMICmdArgValConsume().IsOk(); + break; + case eArgValType_Number: + bValid = CMICmdArgValNumber().IsArgNumber(vrTxt); + break; + case eArgValType_OptionLong: + bValid = CMICmdArgValOptionLong().IsArgLongOption(vrTxt); + break; + case eArgValType_OptionShort: + bValid = CMICmdArgValOptionShort().IsArgShortOption(vrTxt); + break; + case eArgValType_String: + bValid = CMICmdArgValString().IsStringArg(vrTxt); + break; + case eArgValType_StringQuoted: + bValid = CMICmdArgValString(true, false, false).IsStringArg(vrTxt); + break; + case eArgValType_StringQuotedNumber: + bValid = CMICmdArgValString(true, true, false).IsStringArg(vrTxt); + break; + case eArgValType_StringQuotedNumberPath: + bValid = CMICmdArgValString(true, true, true).IsStringArg(vrTxt); + break; + case eArgValType_StringAnything: + bValid = CMICmdArgValString(true).IsStringArg(vrTxt); + break; + case eArgValType_ThreadGrp: + bValid = CMICmdArgValThreadGrp().IsArgThreadGrp(vrTxt); + break; + default: + return false; + } - return bValid; + return bValid; } diff --git a/lldb/tools/lldb-mi/MICmdArgValListBase.h b/lldb/tools/lldb-mi/MICmdArgValListBase.h index 59ef3bb6019..03cef723e2e 100644 --- a/lldb/tools/lldb-mi/MICmdArgValListBase.h +++ b/lldb/tools/lldb-mi/MICmdArgValListBase.h @@ -18,72 +18,86 @@ // Declarations: class CMICmdArgContext; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code class. Command argument with addition options class. // For example --recurse 1 2 4 [group ...]. Arguments object that // require a list of options associated with them derive from the -// CMICmdArgValListBase class. Additional options are also extracted from +// CMICmdArgValListBase class. Additional options are also extracted +// from // the command arguments text string. // An argument knows what type of argument it is and how it is to -// interpret the options (context) string to find and validate a matching +// interpret the options (context) string to find and validate a +// matching // options and so extract a values from it . -// The CMICmdArgValBase objects are added to the derived argument class's -// container. The option arguments belong to that derived class and will +// The CMICmdArgValBase objects are added to the derived argument +// class's +// container. The option arguments belong to that derived class and +// will // be deleted that object goes out of scope. // Based on the Interpreter pattern. //-- -class CMICmdArgValListBase : public CMICmdArgValBaseTemplate<std::vector<CMICmdArgValBase *>> -{ - // Typedef: - public: - typedef std::vector<CMICmdArgValBase *> VecArgObjPtr_t; +class CMICmdArgValListBase + : public CMICmdArgValBaseTemplate<std::vector<CMICmdArgValBase *>> { + // Typedef: +public: + typedef std::vector<CMICmdArgValBase *> VecArgObjPtr_t; - // Enums: - public: - //++ --------------------------------------------------------------------------------- - // Details: CMICmdArgValListBase needs to know what type of argument to look for in - // the command options text. It also needs to create argument objects of - // a specific type. - //-- - enum ArgValType_e - { - eArgValType_File = 0, - eArgValType_Consume, - eArgValType_Number, - eArgValType_OptionLong, - eArgValType_OptionShort, - eArgValType_String, - eArgValType_StringQuoted, - eArgValType_StringQuotedNumber, - eArgValType_StringQuotedNumberPath, - eArgValType_StringAnything, // Accept any words for a string 'type' even if they look like --longOptions for example - eArgValType_ThreadGrp, - eArgValType_count, // Always the last one - eArgValType_invalid - }; + // Enums: +public: + //++ + //--------------------------------------------------------------------------------- + // Details: CMICmdArgValListBase needs to know what type of argument to look + // for in + // the command options text. It also needs to create argument objects + // of + // a specific type. + //-- + enum ArgValType_e { + eArgValType_File = 0, + eArgValType_Consume, + eArgValType_Number, + eArgValType_OptionLong, + eArgValType_OptionShort, + eArgValType_String, + eArgValType_StringQuoted, + eArgValType_StringQuotedNumber, + eArgValType_StringQuotedNumberPath, + eArgValType_StringAnything, // Accept any words for a string 'type' even if + // they look like --longOptions for example + eArgValType_ThreadGrp, + eArgValType_count, // Always the last one + eArgValType_invalid + }; - // Methods: - public: - /* ctor */ CMICmdArgValListBase(); - /* ctor */ CMICmdArgValListBase(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd); - /* ctor */ CMICmdArgValListBase(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, - const ArgValType_e veType); + // Methods: +public: + /* ctor */ CMICmdArgValListBase(); + /* ctor */ CMICmdArgValListBase(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd); + /* ctor */ CMICmdArgValListBase(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd, + const ArgValType_e veType); - // Overridden: - public: - // From CMICmdArgValBase - /* dtor */ ~CMICmdArgValListBase() override; + // Overridden: +public: + // From CMICmdArgValBase + /* dtor */ ~CMICmdArgValListBase() override; - // Methods: - protected: - bool IsExpectedCorrectType(const CMIUtilString &vrTxt, const ArgValType_e veType) const; - CMICmdArgValBase *CreationObj(const CMIUtilString &vrTxt, const ArgValType_e veType) const; + // Methods: +protected: + bool IsExpectedCorrectType(const CMIUtilString &vrTxt, + const ArgValType_e veType) const; + CMICmdArgValBase *CreationObj(const CMIUtilString &vrTxt, + const ArgValType_e veType) const; - // Attributes: - protected: - ArgValType_e m_eArgType; + // Attributes: +protected: + ArgValType_e m_eArgType; - // Methods: - private: - void Destroy(); + // Methods: +private: + void Destroy(); }; diff --git a/lldb/tools/lldb-mi/MICmdArgValListOfN.cpp b/lldb/tools/lldb-mi/MICmdArgValListOfN.cpp index 78f5fdc65f4..103008e9881 100644 --- a/lldb/tools/lldb-mi/MICmdArgValListOfN.cpp +++ b/lldb/tools/lldb-mi/MICmdArgValListOfN.cpp @@ -17,46 +17,50 @@ #include "MICmdArgValString.h" #include "MICmdArgValThreadGrp.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValListOfN constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdArgValListOfN::CMICmdArgValListOfN() -{ -} +CMICmdArgValListOfN::CMICmdArgValListOfN() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValListOfN constructor. // Type: Method. // Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// veType - (R) The type of argument to look for and create argument object of a certain type. +// vbMandatory - (R) True = Yes must be present, false = optional +// argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = +// not handled. +// veType - (R) The type of argument to look for and create +// argument object of a certain type. // Return: None. // Throws: None. //-- -CMICmdArgValListOfN::CMICmdArgValListOfN(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, +CMICmdArgValListOfN::CMICmdArgValListOfN(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd, const ArgValType_e veType) - : CMICmdArgValListBase(vrArgName, vbMandatory, vbHandleByCmd, veType) -{ -} + : CMICmdArgValListBase(vrArgName, vbMandatory, vbHandleByCmd, veType) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValListOfN destructor. // Type: Overridden. // Args: None. // Return: None. // Throws: None. //-- -CMICmdArgValListOfN::~CMICmdArgValListOfN() -{ -} +CMICmdArgValListOfN::~CMICmdArgValListOfN() {} -//++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract the list of +//++ +//------------------------------------------------------------------------------------ +// Details: Parse the command's argument options string and try to extract the +// list of // arguments based on the argument object type to look for. // Type: Overridden. // Args: vwArgContext - (RW) The command's argument options string. @@ -64,105 +68,101 @@ CMICmdArgValListOfN::~CMICmdArgValListOfN() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdArgValListOfN::Validate(CMICmdArgContext &vwArgContext) -{ - if (m_eArgType >= eArgValType_count) - { - m_eArgType = eArgValType_invalid; - return MIstatus::failure; - } - - if (vwArgContext.IsEmpty()) - return m_bMandatory ? MIstatus::failure : MIstatus::success; - - const CMIUtilString &rArg(vwArgContext.GetArgsLeftToParse()); - if (IsListOfN(rArg) && CreateList(rArg)) - { - m_bFound = true; - m_bValid = true; - vwArgContext.RemoveArg(rArg); - return MIstatus::success; - } - else - return MIstatus::failure; +bool CMICmdArgValListOfN::Validate(CMICmdArgContext &vwArgContext) { + if (m_eArgType >= eArgValType_count) { + m_eArgType = eArgValType_invalid; + return MIstatus::failure; + } + + if (vwArgContext.IsEmpty()) + return m_bMandatory ? MIstatus::failure : MIstatus::success; + + const CMIUtilString &rArg(vwArgContext.GetArgsLeftToParse()); + if (IsListOfN(rArg) && CreateList(rArg)) { + m_bFound = true; + m_bValid = true; + vwArgContext.RemoveArg(rArg); + return MIstatus::success; + } else + return MIstatus::failure; } -//++ ------------------------------------------------------------------------------------ -// Details: Create list of argument objects each holding a value extract from the command +//++ +//------------------------------------------------------------------------------------ +// Details: Create list of argument objects each holding a value extract from +// the command // options line. // Type: Method. // Args: vrTxt - (R) Some options text. // Return: bool - True = yes valid arg, false = no. // Throws: None. //-- -bool -CMICmdArgValListOfN::CreateList(const CMIUtilString &vrTxt) -{ - CMIUtilString::VecString_t vecOptions; - if ((m_eArgType == eArgValType_StringQuoted) || (m_eArgType == eArgValType_StringQuotedNumber) || - (m_eArgType == eArgValType_StringQuotedNumberPath) || (m_eArgType == eArgValType_StringAnything)) - { - if (vrTxt.SplitConsiderQuotes(" ", vecOptions) == 0) - return MIstatus::failure; - } - else if (vrTxt.Split(" ", vecOptions) == 0) - return MIstatus::failure; - - CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); - while (it != vecOptions.end()) - { - const CMIUtilString &rOption = *it; - CMICmdArgValBase *pOption = CreationObj(rOption, m_eArgType); - if (pOption != nullptr) - m_argValue.push_back(pOption); - else - return MIstatus::failure; - - // Next - ++it; - } +bool CMICmdArgValListOfN::CreateList(const CMIUtilString &vrTxt) { + CMIUtilString::VecString_t vecOptions; + if ((m_eArgType == eArgValType_StringQuoted) || + (m_eArgType == eArgValType_StringQuotedNumber) || + (m_eArgType == eArgValType_StringQuotedNumberPath) || + (m_eArgType == eArgValType_StringAnything)) { + if (vrTxt.SplitConsiderQuotes(" ", vecOptions) == 0) + return MIstatus::failure; + } else if (vrTxt.Split(" ", vecOptions) == 0) + return MIstatus::failure; + + CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); + while (it != vecOptions.end()) { + const CMIUtilString &rOption = *it; + CMICmdArgValBase *pOption = CreationObj(rOption, m_eArgType); + if (pOption != nullptr) + m_argValue.push_back(pOption); + else + return MIstatus::failure; - return MIstatus::success; + // Next + ++it; + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid string type argument. +//++ +//------------------------------------------------------------------------------------ +// Details: Examine the string and determine if it is a valid string type +// argument. // Type: Method. // Args: vrTxt - (R) Some text. // Return: bool - True = yes valid arg, false = no. // Throws: None. //-- -bool -CMICmdArgValListOfN::IsListOfN(const CMIUtilString &vrTxt) const -{ - CMIUtilString::VecString_t vecOptions; - if ((m_eArgType == eArgValType_StringQuoted) || (m_eArgType == eArgValType_StringQuotedNumber) || - (m_eArgType == eArgValType_StringQuotedNumberPath) || (m_eArgType == eArgValType_StringAnything)) - { - if (vrTxt.SplitConsiderQuotes(" ", vecOptions) == 0) - return false; - } - else if (vrTxt.Split(" ", vecOptions) == 0) - return false; - - CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); - while (it != vecOptions.end()) - { - const CMIUtilString &rOption = *it; - if (!IsExpectedCorrectType(rOption, m_eArgType)) - break; - - // Next - ++it; - } - - return true; +bool CMICmdArgValListOfN::IsListOfN(const CMIUtilString &vrTxt) const { + CMIUtilString::VecString_t vecOptions; + if ((m_eArgType == eArgValType_StringQuoted) || + (m_eArgType == eArgValType_StringQuotedNumber) || + (m_eArgType == eArgValType_StringQuotedNumberPath) || + (m_eArgType == eArgValType_StringAnything)) { + if (vrTxt.SplitConsiderQuotes(" ", vecOptions) == 0) + return false; + } else if (vrTxt.Split(" ", vecOptions) == 0) + return false; + + CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); + while (it != vecOptions.end()) { + const CMIUtilString &rOption = *it; + if (!IsExpectedCorrectType(rOption, m_eArgType)) + break; + + // Next + ++it; + } + + return true; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the list of CMICmdArgValBase derived option objects found following -// *this long option argument. For example "list-thread-groups [ --recurse 1 ]" +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the list of CMICmdArgValBase derived option objects found +// following +// *this long option argument. For example "list-thread-groups [ +// --recurse 1 ]" // where 1 is the list of expected option to follow. // Type: Method. // Args: None. @@ -170,7 +170,6 @@ CMICmdArgValListOfN::IsListOfN(const CMIUtilString &vrTxt) const // Throws: None. //-- const CMICmdArgValListBase::VecArgObjPtr_t & -CMICmdArgValListOfN::GetExpectedOptions() const -{ - return m_argValue; +CMICmdArgValListOfN::GetExpectedOptions() const { + return m_argValue; } diff --git a/lldb/tools/lldb-mi/MICmdArgValListOfN.h b/lldb/tools/lldb-mi/MICmdArgValListOfN.h index 7499a7f7e91..00297084167 100644 --- a/lldb/tools/lldb-mi/MICmdArgValListOfN.h +++ b/lldb/tools/lldb-mi/MICmdArgValListOfN.h @@ -18,11 +18,13 @@ // Declarations: class CMICmdArgContext; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code class. Command argument class. Arguments object // needing specialization derived from the CMICmdArgValBase class. // An argument knows what type of argument it is and how it is to -// interpret the options (context) string to find and validate a matching +// interpret the options (context) string to find and validate a +// matching // argument and so extract a value from it . // The CMICmdArgValBase objects added to *this ListOfN container belong // to this container and will be deleted when *this object goes out of @@ -32,57 +34,61 @@ class CMICmdArgContext; // otherwise assumed to be (...)* specification. // Based on the Interpreter pattern. //-- -class CMICmdArgValListOfN : public CMICmdArgValListBase -{ - // Methods: - public: - /* ctor */ CMICmdArgValListOfN(); - /* ctor */ CMICmdArgValListOfN(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, - const ArgValType_e veType); - // - const VecArgObjPtr_t &GetExpectedOptions() const; - template <class T1, typename T2> bool GetExpectedOption(T2 &vrwValue, const VecArgObjPtr_t::size_type vnAt = 0) const; +class CMICmdArgValListOfN : public CMICmdArgValListBase { + // Methods: +public: + /* ctor */ CMICmdArgValListOfN(); + /* ctor */ CMICmdArgValListOfN(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd, + const ArgValType_e veType); + // + const VecArgObjPtr_t &GetExpectedOptions() const; + template <class T1, typename T2> + bool GetExpectedOption(T2 &vrwValue, + const VecArgObjPtr_t::size_type vnAt = 0) const; - // Overridden: - public: - // From CMICmdArgValBase - /* dtor */ ~CMICmdArgValListOfN() override; - // From CMICmdArgSet::IArg - bool Validate(CMICmdArgContext &vArgContext) override; + // Overridden: +public: + // From CMICmdArgValBase + /* dtor */ ~CMICmdArgValListOfN() override; + // From CMICmdArgSet::IArg + bool Validate(CMICmdArgContext &vArgContext) override; - // Methods: - private: - bool IsListOfN(const CMIUtilString &vrTxt) const; - bool CreateList(const CMIUtilString &vrTxt); + // Methods: +private: + bool IsListOfN(const CMIUtilString &vrTxt) const; + bool CreateList(const CMIUtilString &vrTxt); }; -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the first argument or option value from the list of 1 or more options +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the first argument or option value from the list of 1 or +// more options // parsed from the command's options string. // Type: Template method. // Args: vrwValue - (W) Templated type return value. // vnAt - (R) Value at the specific position. -// T1 - The argument value's class type of the data hold in the list of options. +// T1 - The argument value's class type of the data hold in +// the list of options. // T2 - The type pf the variable which holds the value wanted. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. List of object was empty. // Throws: None. //-- template <class T1, typename T2> -bool -CMICmdArgValListOfN::GetExpectedOption(T2 &vrwValue, const VecArgObjPtr_t::size_type vnAt) const -{ - const VecArgObjPtr_t &rVecOptions(GetExpectedOptions()); - if (rVecOptions.size() <= vnAt) - return MIstatus::failure; +bool CMICmdArgValListOfN::GetExpectedOption( + T2 &vrwValue, const VecArgObjPtr_t::size_type vnAt) const { + const VecArgObjPtr_t &rVecOptions(GetExpectedOptions()); + if (rVecOptions.size() <= vnAt) + return MIstatus::failure; - VecArgObjPtr_t::const_iterator it2 = rVecOptions.begin() + vnAt; - if (it2 != rVecOptions.end()) - { - const T1 *pOption = static_cast<T1 *>(*it2); - vrwValue = pOption->GetValue(); - return MIstatus::success; - } + VecArgObjPtr_t::const_iterator it2 = rVecOptions.begin() + vnAt; + if (it2 != rVecOptions.end()) { + const T1 *pOption = static_cast<T1 *>(*it2); + vrwValue = pOption->GetValue(); + return MIstatus::success; + } - return MIstatus::failure; + return MIstatus::failure; } diff --git a/lldb/tools/lldb-mi/MICmdArgValNumber.cpp b/lldb/tools/lldb-mi/MICmdArgValNumber.cpp index 5d907ca9f1e..6ef6769391e 100644 --- a/lldb/tools/lldb-mi/MICmdArgValNumber.cpp +++ b/lldb/tools/lldb-mi/MICmdArgValNumber.cpp @@ -11,7 +11,8 @@ #include "MICmdArgValNumber.h" #include "MICmdArgContext.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValNumber constructor. // Type: Method. // Args: None. @@ -19,42 +20,45 @@ // Throws: None. //-- CMICmdArgValNumber::CMICmdArgValNumber() - : m_nNumberFormatMask(CMICmdArgValNumber::eArgValNumberFormat_Decimal) - , m_nNumber(0) -{ -} + : m_nNumberFormatMask(CMICmdArgValNumber::eArgValNumberFormat_Decimal), + m_nNumber(0) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValNumber constructor. // Type: Method. // Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// vnNumberFormatMask - (R) Mask of the number formats. (Dflt = CMICmdArgValNumber::eArgValNumberFormat_Decimal) +// vbMandatory - (R) True = Yes must be present, false = +// optional argument. +// vbHandleByCmd - (R) True = Command processes *this option, +// false = not handled. +// vnNumberFormatMask - (R) Mask of the number formats. (Dflt = +// CMICmdArgValNumber::eArgValNumberFormat_Decimal) // Return: None. // Throws: None. //-- -CMICmdArgValNumber::CMICmdArgValNumber(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, - const MIuint vnNumberFormatMask /* = CMICmdArgValNumber::eArgValNumberFormat_Decimal*/) - : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd) - , m_nNumberFormatMask(vnNumberFormatMask) - , m_nNumber(0) -{ -} - -//++ ------------------------------------------------------------------------------------ +CMICmdArgValNumber::CMICmdArgValNumber( + const CMIUtilString &vrArgName, const bool vbMandatory, + const bool vbHandleByCmd, + const MIuint + vnNumberFormatMask /* = CMICmdArgValNumber::eArgValNumberFormat_Decimal*/) + : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd), + m_nNumberFormatMask(vnNumberFormatMask), m_nNumber(0) {} + +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValNumber destructor. // Type: Overridden. // Args: None. // Return: None. // Throws: None. //-- -CMICmdArgValNumber::~CMICmdArgValNumber() -{ -} +CMICmdArgValNumber::~CMICmdArgValNumber() {} -//++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract the value *this +//++ +//------------------------------------------------------------------------------------ +// Details: Parse the command's argument options string and try to extract the +// value *this // argument is looking for. // Type: Overridden. // Args: vwArgContext - (RW) The command's argument options string. @@ -62,81 +66,76 @@ CMICmdArgValNumber::~CMICmdArgValNumber() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdArgValNumber::Validate(CMICmdArgContext &vwArgContext) -{ - if (vwArgContext.IsEmpty()) - return m_bMandatory ? MIstatus::failure : MIstatus::success; - - if (vwArgContext.GetNumberArgsPresent() == 1) - { - const CMIUtilString &rArg(vwArgContext.GetArgsLeftToParse()); - if (IsArgNumber(rArg) && ExtractNumber(rArg)) - { - m_bFound = true; - m_bValid = true; - m_argValue = GetNumber(); - vwArgContext.RemoveArg(rArg); - return MIstatus::success; - } - else - return MIstatus::failure; +bool CMICmdArgValNumber::Validate(CMICmdArgContext &vwArgContext) { + if (vwArgContext.IsEmpty()) + return m_bMandatory ? MIstatus::failure : MIstatus::success; + + if (vwArgContext.GetNumberArgsPresent() == 1) { + const CMIUtilString &rArg(vwArgContext.GetArgsLeftToParse()); + if (IsArgNumber(rArg) && ExtractNumber(rArg)) { + m_bFound = true; + m_bValid = true; + m_argValue = GetNumber(); + vwArgContext.RemoveArg(rArg); + return MIstatus::success; + } else + return MIstatus::failure; + } + + // More than one option... + const CMIUtilString::VecString_t vecOptions(vwArgContext.GetArgs()); + CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); + while (it != vecOptions.end()) { + const CMIUtilString &rArg(*it); + if (IsArgNumber(rArg) && ExtractNumber(rArg)) { + m_bFound = true; + + if (vwArgContext.RemoveArg(rArg)) { + m_bValid = true; + m_argValue = GetNumber(); + return MIstatus::success; + } else + return MIstatus::failure; } - // More than one option... - const CMIUtilString::VecString_t vecOptions(vwArgContext.GetArgs()); - CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); - while (it != vecOptions.end()) - { - const CMIUtilString &rArg(*it); - if (IsArgNumber(rArg) && ExtractNumber(rArg)) - { - m_bFound = true; - - if (vwArgContext.RemoveArg(rArg)) - { - m_bValid = true; - m_argValue = GetNumber(); - return MIstatus::success; - } - else - return MIstatus::failure; - } - - // Next - ++it; - } + // Next + ++it; + } - return MIstatus::failure; + return MIstatus::failure; } -//++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid string type argument. +//++ +//------------------------------------------------------------------------------------ +// Details: Examine the string and determine if it is a valid string type +// argument. // Type: Method. // Args: vrTxt - (R) Some text. // Return: bool - True = yes valid arg, false = no. // Throws: None. //-- -bool -CMICmdArgValNumber::IsArgNumber(const CMIUtilString &vrTxt) const -{ - const bool bFormatDecimal(m_nNumberFormatMask & CMICmdArgValNumber::eArgValNumberFormat_Decimal); - const bool bFormatHexadecimal(m_nNumberFormatMask & CMICmdArgValNumber::eArgValNumberFormat_Hexadecimal); - - // Look for --someLongOption - if (std::string::npos != vrTxt.find("--")) - return false; +bool CMICmdArgValNumber::IsArgNumber(const CMIUtilString &vrTxt) const { + const bool bFormatDecimal(m_nNumberFormatMask & + CMICmdArgValNumber::eArgValNumberFormat_Decimal); + const bool bFormatHexadecimal( + m_nNumberFormatMask & + CMICmdArgValNumber::eArgValNumberFormat_Hexadecimal); + + // Look for --someLongOption + if (std::string::npos != vrTxt.find("--")) + return false; - if (bFormatDecimal && vrTxt.IsNumber()) - return true; + if (bFormatDecimal && vrTxt.IsNumber()) + return true; - if (bFormatHexadecimal && vrTxt.IsHexadecimalNumber()) - return true; + if (bFormatHexadecimal && vrTxt.IsHexadecimalNumber()) + return true; - return false; + return false; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Extract the thread group number from the thread group argument. // Type: Method. // Args: vrTxt - (R) Some text. @@ -144,28 +143,22 @@ CMICmdArgValNumber::IsArgNumber(const CMIUtilString &vrTxt) const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdArgValNumber::ExtractNumber(const CMIUtilString &vrTxt) -{ - MIint64 nNumber = 0; - bool bOk = vrTxt.ExtractNumber(nNumber); - if (bOk) - { - m_nNumber = static_cast<MIint64>(nNumber); - } - - return bOk; +bool CMICmdArgValNumber::ExtractNumber(const CMIUtilString &vrTxt) { + MIint64 nNumber = 0; + bool bOk = vrTxt.ExtractNumber(nNumber); + if (bOk) { + m_nNumber = static_cast<MIint64>(nNumber); + } + + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the thread group ID found in the argument. // Type: Method. // Args: None. // Return: MIuint - Thread group ID. // Throws: None. //-- -MIint64 -CMICmdArgValNumber::GetNumber() const -{ - return m_nNumber; -} +MIint64 CMICmdArgValNumber::GetNumber() const { return m_nNumber; } diff --git a/lldb/tools/lldb-mi/MICmdArgValNumber.h b/lldb/tools/lldb-mi/MICmdArgValNumber.h index 0b05e57c6bf..5f94fc86893 100644 --- a/lldb/tools/lldb-mi/MICmdArgValNumber.h +++ b/lldb/tools/lldb-mi/MICmdArgValNumber.h @@ -15,51 +15,57 @@ // Declarations: class CMICmdArgContext; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code class. Command argument class. Arguments object // needing specialization derived from the CMICmdArgValBase class. // An argument knows what type of argument it is and how it is to -// interpret the options (context) string to find and validate a matching +// interpret the options (context) string to find and validate a +// matching // argument and so extract a value from it . // Based on the Interpreter pattern. //-- -class CMICmdArgValNumber : public CMICmdArgValBaseTemplate<MIint64> -{ - // Enums: - public: - //++ --------------------------------------------------------------------------------- - // Details: CMICmdArgValNumber needs to know what format of argument to look for in - // the command options text. - //-- - enum ArgValNumberFormat_e - { - eArgValNumberFormat_Decimal = (1u << 0), - eArgValNumberFormat_Hexadecimal = (1u << 1), - eArgValNumberFormat_Auto = ((eArgValNumberFormat_Hexadecimal << 1) - 1u) ///< Indicates to try and lookup everything up during a query. - }; +class CMICmdArgValNumber : public CMICmdArgValBaseTemplate<MIint64> { + // Enums: +public: + //++ + //--------------------------------------------------------------------------------- + // Details: CMICmdArgValNumber needs to know what format of argument to look + // for in + // the command options text. + //-- + enum ArgValNumberFormat_e { + eArgValNumberFormat_Decimal = (1u << 0), + eArgValNumberFormat_Hexadecimal = (1u << 1), + eArgValNumberFormat_Auto = + ((eArgValNumberFormat_Hexadecimal << 1) - + 1u) ///< Indicates to try and lookup everything up during a query. + }; - // Methods: - public: - /* ctor */ CMICmdArgValNumber(); - /* ctor */ CMICmdArgValNumber(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, - const MIuint vnNumberFormatMask = eArgValNumberFormat_Decimal); - // - bool IsArgNumber(const CMIUtilString &vrTxt) const; + // Methods: +public: + /* ctor */ CMICmdArgValNumber(); + /* ctor */ CMICmdArgValNumber( + const CMIUtilString &vrArgName, const bool vbMandatory, + const bool vbHandleByCmd, + const MIuint vnNumberFormatMask = eArgValNumberFormat_Decimal); + // + bool IsArgNumber(const CMIUtilString &vrTxt) const; - // Overridden: - public: - // From CMICmdArgValBase - /* dtor */ ~CMICmdArgValNumber() override; - // From CMICmdArgSet::IArg - bool Validate(CMICmdArgContext &vwArgContext) override; + // Overridden: +public: + // From CMICmdArgValBase + /* dtor */ ~CMICmdArgValNumber() override; + // From CMICmdArgSet::IArg + bool Validate(CMICmdArgContext &vwArgContext) override; - // Methods: - private: - bool ExtractNumber(const CMIUtilString &vrTxt); - MIint64 GetNumber() const; + // Methods: +private: + bool ExtractNumber(const CMIUtilString &vrTxt); + MIint64 GetNumber() const; - // Attributes: - private: - MIuint m_nNumberFormatMask; - MIint64 m_nNumber; + // Attributes: +private: + MIuint m_nNumberFormatMask; + MIint64 m_nNumber; }; diff --git a/lldb/tools/lldb-mi/MICmdArgValOptionLong.cpp b/lldb/tools/lldb-mi/MICmdArgValOptionLong.cpp index 3c957894307..cdbcdb9f241 100644 --- a/lldb/tools/lldb-mi/MICmdArgValOptionLong.cpp +++ b/lldb/tools/lldb-mi/MICmdArgValOptionLong.cpp @@ -11,7 +11,8 @@ #include "MICmdArgValOptionLong.h" #include "MICmdArgContext.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValOptionLong constructor. // Type: Method. // Args: None. @@ -19,84 +20,89 @@ // Throws: None. //-- CMICmdArgValOptionLong::CMICmdArgValOptionLong() - : m_nExpectingNOptions(0) - , m_eExpectingOptionType(eArgValType_invalid) -{ -} + : m_nExpectingNOptions(0), m_eExpectingOptionType(eArgValType_invalid) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValOptionLong constructor. // Type: Method. // Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// vbMandatory - (R) True = Yes must be present, false = optional +// argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = +// not handled. // Return: None. // Throws: None. //-- -CMICmdArgValOptionLong::CMICmdArgValOptionLong(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd) - : CMICmdArgValListBase(vrArgName, vbMandatory, vbHandleByCmd) - , m_nExpectingNOptions(0) - , m_eExpectingOptionType(eArgValType_invalid) -{ -} - -//++ ------------------------------------------------------------------------------------ +CMICmdArgValOptionLong::CMICmdArgValOptionLong(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd) + : CMICmdArgValListBase(vrArgName, vbMandatory, vbHandleByCmd), + m_nExpectingNOptions(0), m_eExpectingOptionType(eArgValType_invalid) {} + +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValOptionLong constructor. // Type: Method. // Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// veType - (R) The type of argument to look for and create argument object of a certain type. -// vnExpectingNOptions - (R) The number of options expected to read following *this argument. +// vbMandatory - (R) True = Yes must be present, false = +// optional argument. +// vbHandleByCmd - (R) True = Command processes *this option, +// false = not handled. +// veType - (R) The type of argument to look for and +// create argument object of a certain type. +// vnExpectingNOptions - (R) The number of options expected to read +// following *this argument. // Return: None. // Throws: None. //-- -CMICmdArgValOptionLong::CMICmdArgValOptionLong(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, - const ArgValType_e veType, const MIuint vnExpectingNOptions) - : CMICmdArgValListBase(vrArgName, vbMandatory, vbHandleByCmd) - , m_nExpectingNOptions(vnExpectingNOptions) - , m_eExpectingOptionType(veType) -{ -} - -//++ ------------------------------------------------------------------------------------ +CMICmdArgValOptionLong::CMICmdArgValOptionLong(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd, + const ArgValType_e veType, + const MIuint vnExpectingNOptions) + : CMICmdArgValListBase(vrArgName, vbMandatory, vbHandleByCmd), + m_nExpectingNOptions(vnExpectingNOptions), + m_eExpectingOptionType(veType) {} + +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValOptionLong destructor. // Type: Overridden. // Args: None. // Return: None. // Throws: None. //-- -CMICmdArgValOptionLong::~CMICmdArgValOptionLong() -{ - // Tidy up - Destroy(); +CMICmdArgValOptionLong::~CMICmdArgValOptionLong() { + // Tidy up + Destroy(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Tear down resources used by *this object. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -void -CMICmdArgValOptionLong::Destroy() -{ - // Tidy up - VecArgObjPtr_t::const_iterator it = m_vecArgsExpected.begin(); - while (it != m_vecArgsExpected.end()) - { - CMICmdArgValBase *pOptionObj = *it; - delete pOptionObj; - - // Next - ++it; - } - m_vecArgsExpected.clear(); +void CMICmdArgValOptionLong::Destroy() { + // Tidy up + VecArgObjPtr_t::const_iterator it = m_vecArgsExpected.begin(); + while (it != m_vecArgsExpected.end()) { + CMICmdArgValBase *pOptionObj = *it; + delete pOptionObj; + + // Next + ++it; + } + m_vecArgsExpected.clear(); } -//++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract the long +//++ +//------------------------------------------------------------------------------------ +// Details: Parse the command's argument options string and try to extract the +// long // argument *this argument type is looking for. // Type: Overridden. // Args: vwArgContext - (RW) The command's argument options string. @@ -104,202 +110,198 @@ CMICmdArgValOptionLong::Destroy() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdArgValOptionLong::Validate(CMICmdArgContext &vwArgContext) -{ - if (vwArgContext.IsEmpty()) - return m_bMandatory ? MIstatus::failure : MIstatus::success; - - if (vwArgContext.GetNumberArgsPresent() == 1) - { - const CMIUtilString &rArg(vwArgContext.GetArgsLeftToParse()); - if (IsArgLongOption(rArg) && ArgNameMatch(rArg)) - { - m_bFound = true; - - if (!vwArgContext.RemoveArg(rArg)) - return MIstatus::failure; - - if (m_nExpectingNOptions == 0) - { - m_bValid = true; - return MIstatus::success; - } - - m_bIsMissingOptions = true; - return MIstatus::failure; - } - else - return MIstatus::failure; - } +bool CMICmdArgValOptionLong::Validate(CMICmdArgContext &vwArgContext) { + if (vwArgContext.IsEmpty()) + return m_bMandatory ? MIstatus::failure : MIstatus::success; + + if (vwArgContext.GetNumberArgsPresent() == 1) { + const CMIUtilString &rArg(vwArgContext.GetArgsLeftToParse()); + if (IsArgLongOption(rArg) && ArgNameMatch(rArg)) { + m_bFound = true; + + if (!vwArgContext.RemoveArg(rArg)) + return MIstatus::failure; - // More than one option... - MIuint nArgIndex = 0; - const CMIUtilString::VecString_t vecOptions(vwArgContext.GetArgs()); - CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); - while (it != vecOptions.end()) - { - const CMIUtilString &rArg(*it); - if (IsArgOptionCorrect(rArg) && ArgNameMatch(rArg)) - { - m_bFound = true; - - if (!vwArgContext.RemoveArg(rArg)) - return MIstatus::failure; - - if (m_nExpectingNOptions != 0) - { - if (ExtractExpectedOptions(vwArgContext, nArgIndex)) - { - m_bValid = true; - return MIstatus::success; - } - - m_bIsMissingOptions = true; - return MIstatus::failure; - } - else - { - m_bValid = true; - return MIstatus::success; - } + if (m_nExpectingNOptions == 0) { + m_bValid = true; + return MIstatus::success; + } + + m_bIsMissingOptions = true; + return MIstatus::failure; + } else + return MIstatus::failure; + } + + // More than one option... + MIuint nArgIndex = 0; + const CMIUtilString::VecString_t vecOptions(vwArgContext.GetArgs()); + CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); + while (it != vecOptions.end()) { + const CMIUtilString &rArg(*it); + if (IsArgOptionCorrect(rArg) && ArgNameMatch(rArg)) { + m_bFound = true; + + if (!vwArgContext.RemoveArg(rArg)) + return MIstatus::failure; + + if (m_nExpectingNOptions != 0) { + if (ExtractExpectedOptions(vwArgContext, nArgIndex)) { + m_bValid = true; + return MIstatus::success; } - // Next - ++it; - ++nArgIndex; + m_bIsMissingOptions = true; + return MIstatus::failure; + } else { + m_bValid = true; + return MIstatus::success; + } } - return MIstatus::failure; + // Next + ++it; + ++nArgIndex; + } + + return MIstatus::failure; } -//++ ------------------------------------------------------------------------------------ -// Details: Parse the text following *this argument and extract the options the values of -// CMICmdArgValListBase::m_eArgType forming argument objects for each of those +//++ +//------------------------------------------------------------------------------------ +// Details: Parse the text following *this argument and extract the options the +// values of +// CMICmdArgValListBase::m_eArgType forming argument objects for each +// of those // options extracted. // Type: Method. // Args: vrwTxt - (RW) The command's argument options string. -// nArgIndex - (R) The Nth arg position in argument context from the left. +// nArgIndex - (R) The Nth arg position in argument context from +// the left. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdArgValOptionLong::ExtractExpectedOptions(CMICmdArgContext &vrwTxt, const MIuint nArgIndex) -{ - CMIUtilString::VecString_t vecOptions; - MIuint nOptionsPresent = 0; - if ((m_eExpectingOptionType != eArgValType_StringQuoted) && (m_eExpectingOptionType != eArgValType_StringQuotedNumber) && - (m_eExpectingOptionType != eArgValType_StringQuotedNumberPath)) - nOptionsPresent = vrwTxt.GetArgsLeftToParse().Split(" ", vecOptions); - else - nOptionsPresent = vrwTxt.GetArgsLeftToParse().SplitConsiderQuotes(" ", vecOptions); - if (nOptionsPresent == 0) - return MIstatus::failure; +bool CMICmdArgValOptionLong::ExtractExpectedOptions(CMICmdArgContext &vrwTxt, + const MIuint nArgIndex) { + CMIUtilString::VecString_t vecOptions; + MIuint nOptionsPresent = 0; + if ((m_eExpectingOptionType != eArgValType_StringQuoted) && + (m_eExpectingOptionType != eArgValType_StringQuotedNumber) && + (m_eExpectingOptionType != eArgValType_StringQuotedNumberPath)) + nOptionsPresent = vrwTxt.GetArgsLeftToParse().Split(" ", vecOptions); + else + nOptionsPresent = + vrwTxt.GetArgsLeftToParse().SplitConsiderQuotes(" ", vecOptions); + if (nOptionsPresent == 0) + return MIstatus::failure; - MIuint nArgIndexCnt = 0; - MIuint nTypeCnt = 0; - MIuint nTypeCnt2 = 0; - MIuint nFoundNOptionsCnt = 0; - CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); - while (it != vecOptions.end()) - { - // Move to the Nth argument position from left before do validation/checking - if (nArgIndexCnt++ == nArgIndex) - { - nTypeCnt++; - const CMIUtilString &rOption(*it); - if (IsExpectedCorrectType(rOption, m_eExpectingOptionType)) - { - nTypeCnt2++; - CMICmdArgValBase *pOptionObj = CreationObj(rOption, m_eExpectingOptionType); - if ((pOptionObj != nullptr) && vrwTxt.RemoveArgAtPos(rOption, nArgIndex)) - { - nFoundNOptionsCnt++; - m_vecArgsExpected.push_back(pOptionObj); - } - } - - // Is the sequence 'options' of same type broken. Expecting the same type until the - // next argument. - if (nTypeCnt != nTypeCnt2) - return MIstatus::failure; - - if (nFoundNOptionsCnt == m_nExpectingNOptions) - return MIstatus::success; + MIuint nArgIndexCnt = 0; + MIuint nTypeCnt = 0; + MIuint nTypeCnt2 = 0; + MIuint nFoundNOptionsCnt = 0; + CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); + while (it != vecOptions.end()) { + // Move to the Nth argument position from left before do validation/checking + if (nArgIndexCnt++ == nArgIndex) { + nTypeCnt++; + const CMIUtilString &rOption(*it); + if (IsExpectedCorrectType(rOption, m_eExpectingOptionType)) { + nTypeCnt2++; + CMICmdArgValBase *pOptionObj = + CreationObj(rOption, m_eExpectingOptionType); + if ((pOptionObj != nullptr) && + vrwTxt.RemoveArgAtPos(rOption, nArgIndex)) { + nFoundNOptionsCnt++; + m_vecArgsExpected.push_back(pOptionObj); } + } - // Next - ++it; - } - if (nFoundNOptionsCnt != m_nExpectingNOptions) + // Is the sequence 'options' of same type broken. Expecting the same type + // until the + // next argument. + if (nTypeCnt != nTypeCnt2) return MIstatus::failure; - return MIstatus::success; + if (nFoundNOptionsCnt == m_nExpectingNOptions) + return MIstatus::success; + } + + // Next + ++it; + } + if (nFoundNOptionsCnt != m_nExpectingNOptions) + return MIstatus::failure; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid long type option argument. +//++ +//------------------------------------------------------------------------------------ +// Details: Examine the string and determine if it is a valid long type option +// argument. // Long type argument looks like --someLongOption. // Type: Method. // Args: vrTxt - (R) Some text. // Return: bool - True = yes valid arg, false = no. // Throws: None. //-- -bool -CMICmdArgValOptionLong::IsArgLongOption(const CMIUtilString &vrTxt) const -{ - const bool bHavePosSlash = (vrTxt.find('/') != std::string::npos); - const bool bHaveBckSlash = (vrTxt.find('\\') != std::string::npos); - if (bHavePosSlash || bHaveBckSlash) - return false; - - const size_t nPos = vrTxt.find("--"); - if (nPos != 0) - return false; - - if (vrTxt.length() < 3) - return false; - - const CMIUtilString strArg = vrTxt.substr(2); - if (strArg.IsNumber()) - return false; - - return true; +bool CMICmdArgValOptionLong::IsArgLongOption(const CMIUtilString &vrTxt) const { + const bool bHavePosSlash = (vrTxt.find('/') != std::string::npos); + const bool bHaveBckSlash = (vrTxt.find('\\') != std::string::npos); + if (bHavePosSlash || bHaveBckSlash) + return false; + + const size_t nPos = vrTxt.find("--"); + if (nPos != 0) + return false; + + if (vrTxt.length() < 3) + return false; + + const CMIUtilString strArg = vrTxt.substr(2); + if (strArg.IsNumber()) + return false; + + return true; } -//++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid long type option argument. +//++ +//------------------------------------------------------------------------------------ +// Details: Examine the string and determine if it is a valid long type option +// argument. // Long type argument looks like --someLongOption. // Type: Overideable. // Args: vrTxt - (R) Some text. // Return: bool - True = yes valid arg, false = no. // Throws: None. //-- -bool -CMICmdArgValOptionLong::IsArgOptionCorrect(const CMIUtilString &vrTxt) const -{ - return IsArgLongOption(vrTxt); +bool CMICmdArgValOptionLong::IsArgOptionCorrect( + const CMIUtilString &vrTxt) const { + return IsArgLongOption(vrTxt); } -//++ ------------------------------------------------------------------------------------ -// Details: Does the argument name of the argument being parsed ATM match the name of +//++ +//------------------------------------------------------------------------------------ +// Details: Does the argument name of the argument being parsed ATM match the +// name of // *this argument object. // Type: Method. // Args: vrTxt - (R) Some text. // Return: bool - True = yes arg name matched, false = no. // Throws: None. //-- -bool -CMICmdArgValOptionLong::ArgNameMatch(const CMIUtilString &vrTxt) const -{ - const CMIUtilString strArg = vrTxt.substr(2); - return (strArg == GetName()); +bool CMICmdArgValOptionLong::ArgNameMatch(const CMIUtilString &vrTxt) const { + const CMIUtilString strArg = vrTxt.substr(2); + return (strArg == GetName()); } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the list of CMICmdArgValBase derived option objects found following -// *this long option argument. For example "list-thread-groups [ --recurse 1 ]" +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the list of CMICmdArgValBase derived option objects found +// following +// *this long option argument. For example "list-thread-groups [ +// --recurse 1 ]" // where 1 is the list of expected option to follow. // Type: Method. // Args: None. @@ -307,7 +309,6 @@ CMICmdArgValOptionLong::ArgNameMatch(const CMIUtilString &vrTxt) const // Throws: None. //-- const CMICmdArgValListBase::VecArgObjPtr_t & -CMICmdArgValOptionLong::GetExpectedOptions() const -{ - return m_vecArgsExpected; +CMICmdArgValOptionLong::GetExpectedOptions() const { + return m_vecArgsExpected; } diff --git a/lldb/tools/lldb-mi/MICmdArgValOptionLong.h b/lldb/tools/lldb-mi/MICmdArgValOptionLong.h index 9d074fc0745..cabe3799de8 100644 --- a/lldb/tools/lldb-mi/MICmdArgValOptionLong.h +++ b/lldb/tools/lldb-mi/MICmdArgValOptionLong.h @@ -16,80 +16,91 @@ class CMICmdArgContext; class CMIUtilString; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code class. Command argument class. Arguments object // needing specialization derived from the CMICmdArgValBase class. // An argument knows what type of argument it is and how it is to -// interpret the options (context) string to find and validate a matching +// interpret the options (context) string to find and validate a +// matching // argument and so extract a value from it. -// If *this argument has expected options following it the option objects -// created to hold each of those option's values belong to *this argument +// If *this argument has expected options following it the option +// objects +// created to hold each of those option's values belong to *this +// argument // object and so are deleted when *this object goes out of scope. // Based on the Interpreter pattern. //-- -class CMICmdArgValOptionLong : public CMICmdArgValListBase -{ - // Methods: - public: - /* ctor */ CMICmdArgValOptionLong(); - /* ctor */ CMICmdArgValOptionLong(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd); - /* ctor */ CMICmdArgValOptionLong(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, - const ArgValType_e veType, const MIuint vnExpectingNOptions); - // - bool IsArgLongOption(const CMIUtilString &vrTxt) const; - const VecArgObjPtr_t &GetExpectedOptions() const; - template <class T1, typename T2> bool GetExpectedOption(T2 &vrwValue) const; +class CMICmdArgValOptionLong : public CMICmdArgValListBase { + // Methods: +public: + /* ctor */ CMICmdArgValOptionLong(); + /* ctor */ CMICmdArgValOptionLong(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd); + /* ctor */ CMICmdArgValOptionLong(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd, + const ArgValType_e veType, + const MIuint vnExpectingNOptions); + // + bool IsArgLongOption(const CMIUtilString &vrTxt) const; + const VecArgObjPtr_t &GetExpectedOptions() const; + template <class T1, typename T2> bool GetExpectedOption(T2 &vrwValue) const; - // Overridden: - public: - // From CMICmdArgValBase - /* dtor */ ~CMICmdArgValOptionLong() override; - // From CMICmdArgSet::IArg - bool Validate(CMICmdArgContext &vArgContext) override; + // Overridden: +public: + // From CMICmdArgValBase + /* dtor */ ~CMICmdArgValOptionLong() override; + // From CMICmdArgSet::IArg + bool Validate(CMICmdArgContext &vArgContext) override; - // Methods: - protected: - bool ExtractExpectedOptions(CMICmdArgContext &vrwTxt, const MIuint nArgIndex); + // Methods: +protected: + bool ExtractExpectedOptions(CMICmdArgContext &vrwTxt, const MIuint nArgIndex); - // Overrideable: - protected: - virtual bool IsArgOptionCorrect(const CMIUtilString &vrTxt) const; - virtual bool ArgNameMatch(const CMIUtilString &vrTxt) const; + // Overrideable: +protected: + virtual bool IsArgOptionCorrect(const CMIUtilString &vrTxt) const; + virtual bool ArgNameMatch(const CMIUtilString &vrTxt) const; - // Methods: - private: - void Destroy(); + // Methods: +private: + void Destroy(); - // Attributes: - private: - MIuint m_nExpectingNOptions; // The number of options expected to read following *this argument - VecArgObjPtr_t m_vecArgsExpected; // The option objects holding the value extracted following *this argument - ArgValType_e m_eExpectingOptionType; // The type of options expected to read following *this argument + // Attributes: +private: + MIuint m_nExpectingNOptions; // The number of options expected to read + // following *this argument + VecArgObjPtr_t m_vecArgsExpected; // The option objects holding the value + // extracted following *this argument + ArgValType_e m_eExpectingOptionType; // The type of options expected to read + // following *this argument }; -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the first argument or option value from the list of 1 or more options +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the first argument or option value from the list of 1 or +// more options // parsed from the command's options string. // Type: Template method. // Args: vrwValue - (W) Templated type return value. -// T1 - The argument value's class type of the data hold in the list of options. +// T1 - The argument value's class type of the data hold in +// the list of options. // T2 - The type pf the variable which holds the value wanted. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. List of object was empty. // Throws: None. //-- template <class T1, typename T2> -bool -CMICmdArgValOptionLong::GetExpectedOption(T2 &vrwValue) const -{ - const VecArgObjPtr_t &rVecOptions(GetExpectedOptions()); - VecArgObjPtr_t::const_iterator it2 = rVecOptions.begin(); - if (it2 != rVecOptions.end()) - { - const T1 *pOption = static_cast<T1 *>(*it2); - vrwValue = pOption->GetValue(); - return MIstatus::success; - } +bool CMICmdArgValOptionLong::GetExpectedOption(T2 &vrwValue) const { + const VecArgObjPtr_t &rVecOptions(GetExpectedOptions()); + VecArgObjPtr_t::const_iterator it2 = rVecOptions.begin(); + if (it2 != rVecOptions.end()) { + const T1 *pOption = static_cast<T1 *>(*it2); + vrwValue = pOption->GetValue(); + return MIstatus::success; + } - return MIstatus::failure; + return MIstatus::failure; } diff --git a/lldb/tools/lldb-mi/MICmdArgValOptionShort.cpp b/lldb/tools/lldb-mi/MICmdArgValOptionShort.cpp index d5bdfa0fa2c..cd403aa8fd4 100644 --- a/lldb/tools/lldb-mi/MICmdArgValOptionShort.cpp +++ b/lldb/tools/lldb-mi/MICmdArgValOptionShort.cpp @@ -11,110 +11,119 @@ #include "MICmdArgValOptionShort.h" #include "MICmdArgContext.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValOptionShort constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdArgValOptionShort::CMICmdArgValOptionShort() -{ -} +CMICmdArgValOptionShort::CMICmdArgValOptionShort() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValOptionShort constructor. // Type: Method. // Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// vbMandatory - (R) True = Yes must be present, false = optional +// argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = +// not handled. // Return: None. // Throws: None. //-- -CMICmdArgValOptionShort::CMICmdArgValOptionShort(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd) - : CMICmdArgValOptionLong(vrArgName, vbMandatory, vbHandleByCmd) -{ -} +CMICmdArgValOptionShort::CMICmdArgValOptionShort(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd) + : CMICmdArgValOptionLong(vrArgName, vbMandatory, vbHandleByCmd) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValOptionLong constructor. // Type: Method. // Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// veType - (R) The type of argument to look for and create argument object of a certain type. -// vnExpectingNOptions - (R) The number of options expected to read following *this argument. +// vbMandatory - (R) True = Yes must be present, false = +// optional argument. +// vbHandleByCmd - (R) True = Command processes *this option, +// false = not handled. +// veType - (R) The type of argument to look for and +// create argument object of a certain type. +// vnExpectingNOptions - (R) The number of options expected to read +// following *this argument. // Return: None. // Throws: None. //-- -CMICmdArgValOptionShort::CMICmdArgValOptionShort(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, - const ArgValType_e veType, const MIuint vnExpectingNOptions) - : CMICmdArgValOptionLong(vrArgName, vbMandatory, vbHandleByCmd, veType, vnExpectingNOptions) -{ -} +CMICmdArgValOptionShort::CMICmdArgValOptionShort( + const CMIUtilString &vrArgName, const bool vbMandatory, + const bool vbHandleByCmd, const ArgValType_e veType, + const MIuint vnExpectingNOptions) + : CMICmdArgValOptionLong(vrArgName, vbMandatory, vbHandleByCmd, veType, + vnExpectingNOptions) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValOptionShort destructor. // Type: Overridden. // Args: None. // Return: None. // Throws: None. //-- -CMICmdArgValOptionShort::~CMICmdArgValOptionShort() -{ -} +CMICmdArgValOptionShort::~CMICmdArgValOptionShort() {} -//++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid short type option argument. +//++ +//------------------------------------------------------------------------------------ +// Details: Examine the string and determine if it is a valid short type option +// argument. // Type: Method. // Args: vrTxt - (R) Some text. // Return: bool - True = yes valid arg, false = no. // Throws: None. //-- -bool -CMICmdArgValOptionShort::IsArgShortOption(const CMIUtilString &vrTxt) const -{ - // Look for --someLongOption - MIint nPos = vrTxt.find("--"); - if (nPos == 0) - return false; +bool CMICmdArgValOptionShort::IsArgShortOption( + const CMIUtilString &vrTxt) const { + // Look for --someLongOption + MIint nPos = vrTxt.find("--"); + if (nPos == 0) + return false; - // Look for -f short option - nPos = vrTxt.find('-'); - if (nPos != 0) - return false; + // Look for -f short option + nPos = vrTxt.find('-'); + if (nPos != 0) + return false; - if (vrTxt.length() > 2) - return false; + if (vrTxt.length() > 2) + return false; - return true; + return true; } -//++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid short type option argument. +//++ +//------------------------------------------------------------------------------------ +// Details: Examine the string and determine if it is a valid short type option +// argument. // Long type argument looks like -f some short option. // Type: Overridden. // Args: vrTxt - (R) Some text. // Return: bool - True = yes valid arg, false = no. // Throws: None. //-- -bool -CMICmdArgValOptionShort::IsArgOptionCorrect(const CMIUtilString &vrTxt) const -{ - return IsArgShortOption(vrTxt); +bool CMICmdArgValOptionShort::IsArgOptionCorrect( + const CMIUtilString &vrTxt) const { + return IsArgShortOption(vrTxt); } -//++ ------------------------------------------------------------------------------------ -// Details: Does the argument name of the argument being parsed ATM match the name of +//++ +//------------------------------------------------------------------------------------ +// Details: Does the argument name of the argument being parsed ATM match the +// name of // *this argument object. // Type: Overridden. // Args: vrTxt - (R) Some text. // Return: bool - True = yes arg name matched, false = no. // Throws: None. //-- -bool -CMICmdArgValOptionShort::ArgNameMatch(const CMIUtilString &vrTxt) const -{ - const CMIUtilString strArg = vrTxt.substr(1); - return (strArg == GetName()); +bool CMICmdArgValOptionShort::ArgNameMatch(const CMIUtilString &vrTxt) const { + const CMIUtilString strArg = vrTxt.substr(1); + return (strArg == GetName()); } diff --git a/lldb/tools/lldb-mi/MICmdArgValOptionShort.h b/lldb/tools/lldb-mi/MICmdArgValOptionShort.h index 0f1c2fc12c3..09482899a30 100644 --- a/lldb/tools/lldb-mi/MICmdArgValOptionShort.h +++ b/lldb/tools/lldb-mi/MICmdArgValOptionShort.h @@ -16,36 +16,45 @@ class CMICmdArgContext; class CMIUtilString; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code class. Command argument class. Arguments object -// needing specialization derived from the CMICmdArgValOptionLong class. +// needing specialization derived from the CMICmdArgValOptionLong +// class. // An argument knows what type of argument it is and how it is to -// interpret the options (context) string to find and validate a matching +// interpret the options (context) string to find and validate a +// matching // argument and so extract a value from it. -// If *this argument has expected options following it the option objects -// created to hold each of those option's values belong to *this argument +// If *this argument has expected options following it the option +// objects +// created to hold each of those option's values belong to *this +// argument // object and so are deleted when *this object goes out of scope. // Based on the Interpreter pattern. //-- -class CMICmdArgValOptionShort : public CMICmdArgValOptionLong -{ - // Methods: - public: - /* ctor */ CMICmdArgValOptionShort(); - /* ctor */ CMICmdArgValOptionShort(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd); - /* ctor */ CMICmdArgValOptionShort(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, - const ArgValType_e veType, const MIuint vnExpectingNOptions); - // - bool IsArgShortOption(const CMIUtilString &vrTxt) const; +class CMICmdArgValOptionShort : public CMICmdArgValOptionLong { + // Methods: +public: + /* ctor */ CMICmdArgValOptionShort(); + /* ctor */ CMICmdArgValOptionShort(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd); + /* ctor */ CMICmdArgValOptionShort(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd, + const ArgValType_e veType, + const MIuint vnExpectingNOptions); + // + bool IsArgShortOption(const CMIUtilString &vrTxt) const; - // Overridden: - public: - // From CMICmdArgValBase - /* dtor */ ~CMICmdArgValOptionShort() override; + // Overridden: +public: + // From CMICmdArgValBase + /* dtor */ ~CMICmdArgValOptionShort() override; - // Overridden: - private: - // From CMICmdArgValOptionLong - bool IsArgOptionCorrect(const CMIUtilString &vrTxt) const override; - bool ArgNameMatch(const CMIUtilString &vrTxt) const override; + // Overridden: +private: + // From CMICmdArgValOptionLong + bool IsArgOptionCorrect(const CMIUtilString &vrTxt) const override; + bool ArgNameMatch(const CMIUtilString &vrTxt) const override; }; diff --git a/lldb/tools/lldb-mi/MICmdArgValPrintValues.cpp b/lldb/tools/lldb-mi/MICmdArgValPrintValues.cpp index 3b6eddd315a..722c4c25831 100644 --- a/lldb/tools/lldb-mi/MICmdArgValPrintValues.cpp +++ b/lldb/tools/lldb-mi/MICmdArgValPrintValues.cpp @@ -11,46 +11,48 @@ #include "MICmdArgValPrintValues.h" #include "MICmdArgContext.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValPrintValues constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdArgValPrintValues::CMICmdArgValPrintValues() - : m_nPrintValues(0) -{ -} +CMICmdArgValPrintValues::CMICmdArgValPrintValues() : m_nPrintValues(0) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValPrintValues constructor. // Type: Method. // Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// vbMandatory - (R) True = Yes must be present, false = optional +// argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = +// not handled. // Return: None. // Throws: None. //-- -CMICmdArgValPrintValues::CMICmdArgValPrintValues(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd) - : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd) - , m_nPrintValues(0) -{ -} +CMICmdArgValPrintValues::CMICmdArgValPrintValues(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd) + : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd), + m_nPrintValues(0) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValPrintValues destructor. // Type: Overridden. // Args: None. // Return: None. // Throws: None. //-- -CMICmdArgValPrintValues::~CMICmdArgValPrintValues() -{ -} +CMICmdArgValPrintValues::~CMICmdArgValPrintValues() {} -//++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract the value *this +//++ +//------------------------------------------------------------------------------------ +// Details: Parse the command's argument options string and try to extract the +// value *this // argument is looking for. // Type: Overridden. // Args: vwArgContext - (RW) The command's argument options string. @@ -58,41 +60,43 @@ CMICmdArgValPrintValues::~CMICmdArgValPrintValues() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdArgValPrintValues::Validate(CMICmdArgContext &vwArgContext) -{ - if (vwArgContext.IsEmpty()) - return m_bMandatory ? MIstatus::failure : MIstatus::success; +bool CMICmdArgValPrintValues::Validate(CMICmdArgContext &vwArgContext) { + if (vwArgContext.IsEmpty()) + return m_bMandatory ? MIstatus::failure : MIstatus::success; - const CMIUtilString strArg(vwArgContext.GetArgs()[0]); - if (IsArgPrintValues(strArg) && ExtractPrintValues(strArg)) - { - m_bFound = true; - m_bValid = true; - m_argValue = GetPrintValues(); - vwArgContext.RemoveArg(strArg); - return MIstatus::success; - } + const CMIUtilString strArg(vwArgContext.GetArgs()[0]); + if (IsArgPrintValues(strArg) && ExtractPrintValues(strArg)) { + m_bFound = true; + m_bValid = true; + m_argValue = GetPrintValues(); + vwArgContext.RemoveArg(strArg); + return MIstatus::success; + } - return MIstatus::failure; + return MIstatus::failure; } -//++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid string type argument. +//++ +//------------------------------------------------------------------------------------ +// Details: Examine the string and determine if it is a valid string type +// argument. // Type: Method. // Args: vrTxt - (R) Some text. // Return: bool - True = yes valid arg, false = no. // Throws: None. //-- -bool -CMICmdArgValPrintValues::IsArgPrintValues(const CMIUtilString &vrTxt) const -{ - return (CMIUtilString::Compare(vrTxt, "0") || CMIUtilString::Compare(vrTxt, "--no-values") || - CMIUtilString::Compare(vrTxt, "1") || CMIUtilString::Compare(vrTxt, "--all-values") || - CMIUtilString::Compare(vrTxt, "2") || CMIUtilString::Compare(vrTxt, "--simple-values")); +bool CMICmdArgValPrintValues::IsArgPrintValues( + const CMIUtilString &vrTxt) const { + return (CMIUtilString::Compare(vrTxt, "0") || + CMIUtilString::Compare(vrTxt, "--no-values") || + CMIUtilString::Compare(vrTxt, "1") || + CMIUtilString::Compare(vrTxt, "--all-values") || + CMIUtilString::Compare(vrTxt, "2") || + CMIUtilString::Compare(vrTxt, "--simple-values")); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Extract the print-values from the print-values argument. // Type: Method. // Args: vrTxt - (R) Some text. @@ -100,30 +104,30 @@ CMICmdArgValPrintValues::IsArgPrintValues(const CMIUtilString &vrTxt) const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdArgValPrintValues::ExtractPrintValues(const CMIUtilString &vrTxt) -{ - if (CMIUtilString::Compare(vrTxt, "0") || CMIUtilString::Compare(vrTxt, "--no-values")) - m_nPrintValues = 0; - else if (CMIUtilString::Compare(vrTxt, "1") || CMIUtilString::Compare(vrTxt, "--all-values")) - m_nPrintValues = 1; - else if (CMIUtilString::Compare(vrTxt, "2") || CMIUtilString::Compare(vrTxt, "--simple-values")) - m_nPrintValues = 2; - else - return MIstatus::failure; +bool CMICmdArgValPrintValues::ExtractPrintValues(const CMIUtilString &vrTxt) { + if (CMIUtilString::Compare(vrTxt, "0") || + CMIUtilString::Compare(vrTxt, "--no-values")) + m_nPrintValues = 0; + else if (CMIUtilString::Compare(vrTxt, "1") || + CMIUtilString::Compare(vrTxt, "--all-values")) + m_nPrintValues = 1; + else if (CMIUtilString::Compare(vrTxt, "2") || + CMIUtilString::Compare(vrTxt, "--simple-values")) + m_nPrintValues = 2; + else + return MIstatus::failure; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the print-values found in the argument. // Type: Method. // Args: None. // Return: MIuint - The print-values. // Throws: None. //-- -MIuint -CMICmdArgValPrintValues::GetPrintValues() const -{ - return m_nPrintValues; +MIuint CMICmdArgValPrintValues::GetPrintValues() const { + return m_nPrintValues; } diff --git a/lldb/tools/lldb-mi/MICmdArgValPrintValues.h b/lldb/tools/lldb-mi/MICmdArgValPrintValues.h index fa8ec8a5477..ddfa7c24fcc 100644 --- a/lldb/tools/lldb-mi/MICmdArgValPrintValues.h +++ b/lldb/tools/lldb-mi/MICmdArgValPrintValues.h @@ -15,39 +15,43 @@ // Declarations: class CMICmdArgContext; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code class. Command argument class. Arguments object // needing specialization derived from the CMICmdArgValBase class. // An argument knows what type of argument it is and how it is to -// interpret the options (context) string to find and validate a matching -// argument and so extract a value from it. The print-values looks like: +// interpret the options (context) string to find and validate a +// matching +// argument and so extract a value from it. The print-values looks +// like: // 0 or --no-values // 1 or --all-values // 2 or --simple-values // Based on the Interpreter pattern. //-- -class CMICmdArgValPrintValues : public CMICmdArgValBaseTemplate<MIuint> -{ - // Methods: - public: - /* ctor */ CMICmdArgValPrintValues(); - /* ctor */ CMICmdArgValPrintValues(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd); - // - bool IsArgPrintValues(const CMIUtilString &vrTxt) const; +class CMICmdArgValPrintValues : public CMICmdArgValBaseTemplate<MIuint> { + // Methods: +public: + /* ctor */ CMICmdArgValPrintValues(); + /* ctor */ CMICmdArgValPrintValues(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd); + // + bool IsArgPrintValues(const CMIUtilString &vrTxt) const; - // Overridden: - public: - // From CMICmdArgValBase - /* dtor */ ~CMICmdArgValPrintValues() override; - // From CMICmdArgSet::IArg - bool Validate(CMICmdArgContext &vArgContext) override; + // Overridden: +public: + // From CMICmdArgValBase + /* dtor */ ~CMICmdArgValPrintValues() override; + // From CMICmdArgSet::IArg + bool Validate(CMICmdArgContext &vArgContext) override; - // Methods: - private: - bool ExtractPrintValues(const CMIUtilString &vrTxt); - MIuint GetPrintValues() const; + // Methods: +private: + bool ExtractPrintValues(const CMIUtilString &vrTxt); + MIuint GetPrintValues() const; - // Attributes: - private: - MIuint m_nPrintValues; + // Attributes: +private: + MIuint m_nPrintValues; }; diff --git a/lldb/tools/lldb-mi/MICmdArgValString.cpp b/lldb/tools/lldb-mi/MICmdArgValString.cpp index 78045ae97e6..e872f363058 100644 --- a/lldb/tools/lldb-mi/MICmdArgValString.cpp +++ b/lldb/tools/lldb-mi/MICmdArgValString.cpp @@ -11,7 +11,8 @@ #include "MICmdArgValString.h" #include "MICmdArgContext.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValString constructor. // Type: Method. // Args: None. @@ -19,108 +20,115 @@ // Throws: None. //-- CMICmdArgValString::CMICmdArgValString() - : m_bHandleQuotedString(false) - , m_bAcceptNumbers(false) - , m_bHandleDirPaths(false) - , m_bHandleAnything(false) -{ -} + : m_bHandleQuotedString(false), m_bAcceptNumbers(false), + m_bHandleDirPaths(false), m_bHandleAnything(false) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValString constructor. // Type: Method. -// Args: vbAnything - (R) True = Parse a string and accept anything, false = do not accept anything. +// Args: vbAnything - (R) True = Parse a string and accept anything, false = +// do not accept anything. // Return: None. // Throws: None. //-- CMICmdArgValString::CMICmdArgValString(const bool vbAnything) - : m_bHandleQuotedString(vbAnything ? true : false) - , m_bAcceptNumbers(false) - , m_bHandleDirPaths(false) - , m_bHandleAnything(vbAnything) -{ -} + : m_bHandleQuotedString(vbAnything ? true : false), m_bAcceptNumbers(false), + m_bHandleDirPaths(false), m_bHandleAnything(vbAnything) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValString constructor. // Type: Method. -// Args: vbHandleQuotes - (R) True = Parse a string surrounded by quotes spaces are not delimiters, false = only text up to +// Args: vbHandleQuotes - (R) True = Parse a string surrounded by quotes +// spaces are not delimiters, false = only text up to // next delimiting space character. -// vbAcceptNumbers - (R) True = Parse a string and accept as a number if number, false = numbers not recognised +// vbAcceptNumbers - (R) True = Parse a string and accept as a +// number if number, false = numbers not recognised // as string types. -// vbHandleDirPaths - (R) True = Parse a string and accept as a file path if a path, false = file paths are not +// vbHandleDirPaths - (R) True = Parse a string and accept as a file +// path if a path, false = file paths are not // recognised as string types. // Return: None. // Throws: None. //-- -CMICmdArgValString::CMICmdArgValString(const bool vbHandleQuotes, const bool vbAcceptNumbers, const bool vbHandleDirPaths) - : m_bHandleQuotedString(vbHandleQuotes) - , m_bAcceptNumbers(vbAcceptNumbers) - , m_bHandleDirPaths(vbHandleDirPaths) - , m_bHandleAnything(false) -{ -} - -//++ ------------------------------------------------------------------------------------ +CMICmdArgValString::CMICmdArgValString(const bool vbHandleQuotes, + const bool vbAcceptNumbers, + const bool vbHandleDirPaths) + : m_bHandleQuotedString(vbHandleQuotes), m_bAcceptNumbers(vbAcceptNumbers), + m_bHandleDirPaths(vbHandleDirPaths), m_bHandleAnything(false) {} + +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValString constructor. // Type: Method. // Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// vbHandleQuotes - (R) True = Parse a string surrounded by quotes spaces are not delimiters, false = only text up to +// vbMandatory - (R) True = Yes must be present, false = optional +// argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = +// not handled. +// vbHandleQuotes - (R) True = Parse a string surrounded by quotes +// spaces are not delimiters, false = only text up to // next delimiting space character. (Dflt = false) -// vbAcceptNumbers - (R) True = Parse a string and accept as a number if number, false = numbers not recognised as +// vbAcceptNumbers - (R) True = Parse a string and accept as a number +// if number, false = numbers not recognised as // string types. (Dflt = false) // Return: None. // Throws: None. //-- -CMICmdArgValString::CMICmdArgValString(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, - const bool vbHandleQuotes /* = false */, const bool vbAcceptNumbers /* = false */) - : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd) - , m_bHandleQuotedString(vbHandleQuotes) - , m_bAcceptNumbers(vbAcceptNumbers) - , m_bHandleDirPaths(false) - , m_bHandleAnything(false) -{ -} - -//++ ------------------------------------------------------------------------------------ +CMICmdArgValString::CMICmdArgValString(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd, + const bool vbHandleQuotes /* = false */, + const bool vbAcceptNumbers /* = false */) + : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd), + m_bHandleQuotedString(vbHandleQuotes), m_bAcceptNumbers(vbAcceptNumbers), + m_bHandleDirPaths(false), m_bHandleAnything(false) {} + +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValString constructor. // Type: Method. // Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. -// vbHandleQuotes - (R) True = Parse a string surrounded by quotes spaces are not delimiters, false = only text up to +// vbMandatory - (R) True = Yes must be present, false = optional +// argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = +// not handled. +// vbHandleQuotes - (R) True = Parse a string surrounded by quotes +// spaces are not delimiters, false = only text up to // next delimiting space character. -// vbAcceptNumbers - (R) True = Parse a string and accept as a number if number, false = numbers not recognised as -// vbHandleDirPaths - (R) True = Parse a string and accept as a file path if a path, false = file paths are not +// vbAcceptNumbers - (R) True = Parse a string and accept as a number +// if number, false = numbers not recognised as +// vbHandleDirPaths - (R) True = Parse a string and accept as a file +// path if a path, false = file paths are not // string types. // Return: None. // Throws: None. //-- -CMICmdArgValString::CMICmdArgValString(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, - const bool vbHandleQuotes, const bool vbAcceptNumbers, const bool vbHandleDirPaths) - : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd) - , m_bHandleQuotedString(vbHandleQuotes) - , m_bAcceptNumbers(vbAcceptNumbers) - , m_bHandleDirPaths(vbHandleDirPaths) - , m_bHandleAnything(false) -{ -} - -//++ ------------------------------------------------------------------------------------ +CMICmdArgValString::CMICmdArgValString(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd, + const bool vbHandleQuotes, + const bool vbAcceptNumbers, + const bool vbHandleDirPaths) + : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd), + m_bHandleQuotedString(vbHandleQuotes), m_bAcceptNumbers(vbAcceptNumbers), + m_bHandleDirPaths(vbHandleDirPaths), m_bHandleAnything(false) {} + +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValString destructor. // Type: Overridden. // Args: None. // Return: None. // Throws: None. //-- -CMICmdArgValString::~CMICmdArgValString() -{ -} +CMICmdArgValString::~CMICmdArgValString() {} -//++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract the value *this +//++ +//------------------------------------------------------------------------------------ +// Details: Parse the command's argument options string and try to extract the +// value *this // argument is looking for. // Type: Overridden. // Args: vrwArgContext - (RW) The command's argument options string. @@ -128,20 +136,20 @@ CMICmdArgValString::~CMICmdArgValString() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdArgValString::Validate(CMICmdArgContext &vrwArgContext) -{ - if (vrwArgContext.IsEmpty()) - return m_bMandatory ? MIstatus::failure : MIstatus::success; +bool CMICmdArgValString::Validate(CMICmdArgContext &vrwArgContext) { + if (vrwArgContext.IsEmpty()) + return m_bMandatory ? MIstatus::failure : MIstatus::success; - if (m_bHandleQuotedString) - return ValidateQuotedText(vrwArgContext); + if (m_bHandleQuotedString) + return ValidateQuotedText(vrwArgContext); - return ValidateSingleText(vrwArgContext); + return ValidateSingleText(vrwArgContext); } -//++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract only the next +//++ +//------------------------------------------------------------------------------------ +// Details: Parse the command's argument options string and try to extract only +// the next // word delimited by the next space. // Type: Method. // Args: vrwArgContext - (RW) The command's argument options string. @@ -149,37 +157,33 @@ CMICmdArgValString::Validate(CMICmdArgContext &vrwArgContext) // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdArgValString::ValidateSingleText(CMICmdArgContext &vrwArgContext) -{ - const CMIUtilString::VecString_t vecOptions(vrwArgContext.GetArgs()); - CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); - while (it != vecOptions.end()) - { - const CMIUtilString &rArg(*it); - if (IsStringArg(rArg)) - { - m_bFound = true; - - if (vrwArgContext.RemoveArg(rArg)) - { - m_bValid = true; - m_argValue = rArg.StripSlashes(); - return MIstatus::success; - } - else - return MIstatus::failure; - } - - // Next - ++it; +bool CMICmdArgValString::ValidateSingleText(CMICmdArgContext &vrwArgContext) { + const CMIUtilString::VecString_t vecOptions(vrwArgContext.GetArgs()); + CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); + while (it != vecOptions.end()) { + const CMIUtilString &rArg(*it); + if (IsStringArg(rArg)) { + m_bFound = true; + + if (vrwArgContext.RemoveArg(rArg)) { + m_bValid = true; + m_argValue = rArg.StripSlashes(); + return MIstatus::success; + } else + return MIstatus::failure; } - return MIstatus::failure; + // Next + ++it; + } + + return MIstatus::failure; } -//++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract all the words +//++ +//------------------------------------------------------------------------------------ +// Details: Parse the command's argument options string and try to extract all +// the words // between quotes then delimited by the next space. // Type: Method. // Args: vrwArgContext - (RW) The command's argument options string. @@ -187,197 +191,208 @@ CMICmdArgValString::ValidateSingleText(CMICmdArgContext &vrwArgContext) // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdArgValString::ValidateQuotedText(CMICmdArgContext &vrwArgContext) -{ - const CMIUtilString::VecString_t vecOptions(vrwArgContext.GetArgs()); - if (vecOptions.size() == 0) - return MIstatus::failure; +bool CMICmdArgValString::ValidateQuotedText(CMICmdArgContext &vrwArgContext) { + const CMIUtilString::VecString_t vecOptions(vrwArgContext.GetArgs()); + if (vecOptions.size() == 0) + return MIstatus::failure; - const CMIUtilString &rArg(vecOptions[0]); - if (!IsStringArg(rArg)) - return MIstatus::failure; + const CMIUtilString &rArg(vecOptions[0]); + if (!IsStringArg(rArg)) + return MIstatus::failure; - m_bFound = true; + m_bFound = true; - if (vrwArgContext.RemoveArg(rArg)) - { - m_bValid = true; - const char cQuote = '"'; - m_argValue = rArg.Trim(cQuote).StripSlashes(); - return MIstatus::success; - } + if (vrwArgContext.RemoveArg(rArg)) { + m_bValid = true; + const char cQuote = '"'; + m_argValue = rArg.Trim(cQuote).StripSlashes(); + return MIstatus::success; + } - return MIstatus::failure; + return MIstatus::failure; } -//++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid string type argument. +//++ +//------------------------------------------------------------------------------------ +// Details: Examine the string and determine if it is a valid string type +// argument. // Type: Method. // Args: vrTxt - (R) Some text. // Return: bool - True = yes valid arg, false = no. // Throws: None. //-- -bool -CMICmdArgValString::IsStringArg(const CMIUtilString &vrTxt) const -{ - if (m_bHandleQuotedString) - return (IsStringArgQuotedText(vrTxt) || IsStringArgQuotedTextEmbedded(vrTxt) || IsStringArgQuotedQuotedTextEmbedded(vrTxt) || - IsStringArgSingleText(vrTxt)); // Still test for this as could just be one word still - - return IsStringArgSingleText(vrTxt); +bool CMICmdArgValString::IsStringArg(const CMIUtilString &vrTxt) const { + if (m_bHandleQuotedString) + return (IsStringArgQuotedText(vrTxt) || + IsStringArgQuotedTextEmbedded(vrTxt) || + IsStringArgQuotedQuotedTextEmbedded(vrTxt) || + IsStringArgSingleText( + vrTxt)); // Still test for this as could just be one word still + + return IsStringArgSingleText(vrTxt); } -//++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid string type argument or -// option value. If the string looks like a long option, short option, a thread -// group ID or just a number it is rejected as a string type value. There is an +//++ +//------------------------------------------------------------------------------------ +// Details: Examine the string and determine if it is a valid string type +// argument or +// option value. If the string looks like a long option, short option, +// a thread +// group ID or just a number it is rejected as a string type value. +// There is an // option to allow the string to accept a number as a string type. // Type: Method. // Args: vrTxt - (R) Some text. // Return: bool - True = yes valid argument value, false = something else. // Throws: None. //-- -bool -CMICmdArgValString::IsStringArgSingleText(const CMIUtilString &vrTxt) const -{ - if (!m_bHandleDirPaths) - { - // Look for directory file paths, if found reject - const bool bHavePosSlash = (vrTxt.find('/') != std::string::npos); - const bool bHaveBckSlash = (vrTxt.find('\\') != std::string::npos); - if (bHavePosSlash || bHaveBckSlash) - return false; - } - - // Look for --someLongOption, if found reject - if (0 == vrTxt.find("--")) - return false; +bool CMICmdArgValString::IsStringArgSingleText( + const CMIUtilString &vrTxt) const { + if (!m_bHandleDirPaths) { + // Look for directory file paths, if found reject + const bool bHavePosSlash = (vrTxt.find('/') != std::string::npos); + const bool bHaveBckSlash = (vrTxt.find('\\') != std::string::npos); + if (bHavePosSlash || bHaveBckSlash) + return false; + } + + // Look for --someLongOption, if found reject + if (0 == vrTxt.find("--")) + return false; - // Look for -f type short options, if found reject - if ((0 == vrTxt.find('-')) && (vrTxt.length() == 2)) - return false; + // Look for -f type short options, if found reject + if ((0 == vrTxt.find('-')) && (vrTxt.length() == 2)) + return false; - // Look for thread group i1 i2 i3...., if found reject - if ((vrTxt.find('i') == 0) && ::isdigit(vrTxt[1])) - return false; + // Look for thread group i1 i2 i3...., if found reject + if ((vrTxt.find('i') == 0) && ::isdigit(vrTxt[1])) + return false; - // Look for numbers, if found reject - if (!m_bAcceptNumbers && vrTxt.IsNumber()) - return false; + // Look for numbers, if found reject + if (!m_bAcceptNumbers && vrTxt.IsNumber()) + return false; - return true; + return true; } -//++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid string type argument. -// Take into account quotes surrounding the text. Note this function falls +//++ +//------------------------------------------------------------------------------------ +// Details: Examine the string and determine if it is a valid string type +// argument. +// Take into account quotes surrounding the text. Note this function +// falls // through to IsStringArgSingleText() should the criteria match fail. // Type: Method. // Args: vrTxt - (R) Some text. // Return: bool - True = yes valid arg, false = no. // Throws: None. //-- -bool -CMICmdArgValString::IsStringArgQuotedText(const CMIUtilString &vrTxt) const -{ - // Accept anything as string word - if (m_bHandleAnything) - return true; - - // CODETAG_QUOTEDTEXT_SIMILAR_CODE - const char cQuote = '"'; - const size_t nPos = vrTxt.find(cQuote); - if (nPos == std::string::npos) - return false; - - // Is one and only quote at end of the string - if (nPos == (vrTxt.length() - 1)) - return false; - - // Quote must be the first character in the string or be preceded by a space - // Also check for embedded string formating quote - const char cBckSlash = '\\'; - const char cSpace = ' '; - if ((nPos > 1) && (vrTxt[nPos - 1] == cBckSlash) && (vrTxt[nPos - 2] != cSpace)) - { - return false; - } - if ((nPos > 0) && (vrTxt[nPos - 1] != cSpace)) - return false; +bool CMICmdArgValString::IsStringArgQuotedText( + const CMIUtilString &vrTxt) const { + // Accept anything as string word + if (m_bHandleAnything) + return true; - // Need to find the other quote - const size_t nPos2 = vrTxt.rfind(cQuote); - if (nPos2 == std::string::npos) - return false; + // CODETAG_QUOTEDTEXT_SIMILAR_CODE + const char cQuote = '"'; + const size_t nPos = vrTxt.find(cQuote); + if (nPos == std::string::npos) + return false; - // Make sure not same quote, need two quotes - if (nPos == nPos2) - return MIstatus::failure; + // Is one and only quote at end of the string + if (nPos == (vrTxt.length() - 1)) + return false; - return true; + // Quote must be the first character in the string or be preceded by a space + // Also check for embedded string formating quote + const char cBckSlash = '\\'; + const char cSpace = ' '; + if ((nPos > 1) && (vrTxt[nPos - 1] == cBckSlash) && + (vrTxt[nPos - 2] != cSpace)) { + return false; + } + if ((nPos > 0) && (vrTxt[nPos - 1] != cSpace)) + return false; + + // Need to find the other quote + const size_t nPos2 = vrTxt.rfind(cQuote); + if (nPos2 == std::string::npos) + return false; + + // Make sure not same quote, need two quotes + if (nPos == nPos2) + return MIstatus::failure; + + return true; } -//++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid string type argument. -// Take into account quotes surrounding the text. Take into account string format -// embedded quotes surrounding the text i.e. "\\\"%5d\\\"". Note this function falls +//++ +//------------------------------------------------------------------------------------ +// Details: Examine the string and determine if it is a valid string type +// argument. +// Take into account quotes surrounding the text. Take into account +// string format +// embedded quotes surrounding the text i.e. "\\\"%5d\\\"". Note this +// function falls // through to IsStringArgQuotedText() should the criteria match fail. // Type: Method. // Args: vrTxt - (R) Some text. // Return: bool - True = yes valid arg, false = no. // Throws: None. //-- -bool -CMICmdArgValString::IsStringArgQuotedTextEmbedded(const CMIUtilString &vrTxt) const -{ - // CODETAG_QUOTEDTEXT_SIMILAR_CODE - const char cBckSlash = '\\'; - const size_t nPos = vrTxt.find(cBckSlash); - if (nPos == std::string::npos) - return false; - - // Slash must be the first character in the string or be preceded by a space - const char cSpace = ' '; - if ((nPos > 0) && (vrTxt[nPos - 1] != cSpace)) - return false; - - // Need to find the other matching slash - const size_t nPos2 = vrTxt.rfind(cBckSlash); - if (nPos2 == std::string::npos) - return false; - - // Make sure not same back slash, need two slashes - if (nPos == nPos2) - return MIstatus::failure; +bool CMICmdArgValString::IsStringArgQuotedTextEmbedded( + const CMIUtilString &vrTxt) const { + // CODETAG_QUOTEDTEXT_SIMILAR_CODE + const char cBckSlash = '\\'; + const size_t nPos = vrTxt.find(cBckSlash); + if (nPos == std::string::npos) + return false; + // Slash must be the first character in the string or be preceded by a space + const char cSpace = ' '; + if ((nPos > 0) && (vrTxt[nPos - 1] != cSpace)) return false; + + // Need to find the other matching slash + const size_t nPos2 = vrTxt.rfind(cBckSlash); + if (nPos2 == std::string::npos) + return false; + + // Make sure not same back slash, need two slashes + if (nPos == nPos2) + return MIstatus::failure; + + return false; } -//++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid string type argument. -// Take into account quotes surrounding the text. Take into account string format -// embedded quotes surrounding the text i.e. "\\\"%5d\\\"". Note this function falls -// through to IsStringArgQuotedTextEmbedded() should the criteria match fail. +//++ +//------------------------------------------------------------------------------------ +// Details: Examine the string and determine if it is a valid string type +// argument. +// Take into account quotes surrounding the text. Take into account +// string format +// embedded quotes surrounding the text i.e. "\\\"%5d\\\"". Note this +// function falls +// through to IsStringArgQuotedTextEmbedded() should the criteria match +// fail. // Type: Method. // Args: vrTxt - (R) Some text. // Return: bool - True = yes valid arg, false = no. // Throws: None. //-- -bool -CMICmdArgValString::IsStringArgQuotedQuotedTextEmbedded(const CMIUtilString &vrTxt) const -{ - const size_t nPos = vrTxt.find("\"\\\""); - if (nPos == std::string::npos) - return false; +bool CMICmdArgValString::IsStringArgQuotedQuotedTextEmbedded( + const CMIUtilString &vrTxt) const { + const size_t nPos = vrTxt.find("\"\\\""); + if (nPos == std::string::npos) + return false; - const size_t nPos2 = vrTxt.rfind("\\\"\""); - if (nPos2 == std::string::npos) - return false; + const size_t nPos2 = vrTxt.rfind("\\\"\""); + if (nPos2 == std::string::npos) + return false; - const size_t nLen = vrTxt.length(); - if ((nLen > 5) && ((nPos + 2) == (nPos2 - 2))) - return false; + const size_t nLen = vrTxt.length(); + if ((nLen > 5) && ((nPos + 2) == (nPos2 - 2))) + return false; - return true; + return true; } diff --git a/lldb/tools/lldb-mi/MICmdArgValString.h b/lldb/tools/lldb-mi/MICmdArgValString.h index 1eb680107a2..e5a6107be50 100644 --- a/lldb/tools/lldb-mi/MICmdArgValString.h +++ b/lldb/tools/lldb-mi/MICmdArgValString.h @@ -15,52 +15,69 @@ // Declarations: class CMICmdArgContext; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code class. Command argument class. Arguments object // needing specialization derived from the CMICmdArgValBase class. // An argument knows what type of argument it is and how it is to -// interpret the options (context) string to find and validate a matching +// interpret the options (context) string to find and validate a +// matching // argument and so extract a value from it . // Based on the Interpreter pattern. //-- -class CMICmdArgValString : public CMICmdArgValBaseTemplate<CMIUtilString> -{ - // Methods: - public: - /* ctor */ CMICmdArgValString(); - /* ctor */ CMICmdArgValString(const bool vbAnything); - /* ctor */ CMICmdArgValString(const bool vbHandleQuotes, const bool vbAcceptNumbers, const bool vbHandleDirPaths); - /* ctor */ CMICmdArgValString(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, - const bool vbHandleQuotes = false, const bool vbAcceptNumbers = false); - /* ctor */ CMICmdArgValString(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd, - const bool vbHandleQuotes, const bool vbAcceptNumbers, const bool vbHandleDirPaths); - // - bool IsStringArg(const CMIUtilString &vrTxt) const; +class CMICmdArgValString : public CMICmdArgValBaseTemplate<CMIUtilString> { + // Methods: +public: + /* ctor */ CMICmdArgValString(); + /* ctor */ CMICmdArgValString(const bool vbAnything); + /* ctor */ CMICmdArgValString(const bool vbHandleQuotes, + const bool vbAcceptNumbers, + const bool vbHandleDirPaths); + /* ctor */ CMICmdArgValString(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd, + const bool vbHandleQuotes = false, + const bool vbAcceptNumbers = false); + /* ctor */ CMICmdArgValString(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd, + const bool vbHandleQuotes, + const bool vbAcceptNumbers, + const bool vbHandleDirPaths); + // + bool IsStringArg(const CMIUtilString &vrTxt) const; - // Overridden: - public: - // From CMICmdArgValBase - /* dtor */ ~CMICmdArgValString() override; - // From CMICmdArgSet::IArg - bool Validate(CMICmdArgContext &vrwArgContext) override; + // Overridden: +public: + // From CMICmdArgValBase + /* dtor */ ~CMICmdArgValString() override; + // From CMICmdArgSet::IArg + bool Validate(CMICmdArgContext &vrwArgContext) override; - // Methods: - private: - bool ValidateSingleText(CMICmdArgContext &vrwArgContext); - bool ValidateQuotedText(CMICmdArgContext &vrwArgContext); - bool ValidateQuotedTextEmbedded(CMICmdArgContext &vrwArgContext); - bool ValidateQuotedQuotedTextEmbedded(CMICmdArgContext &vrwArgContext); - bool IsStringArgSingleText(const CMIUtilString &vrTxt) const; - bool IsStringArgQuotedText(const CMIUtilString &vrTxt) const; - bool IsStringArgQuotedTextEmbedded(const CMIUtilString &vrTxt) const; - bool IsStringArgQuotedQuotedTextEmbedded(const CMIUtilString &vrTxt) const; + // Methods: +private: + bool ValidateSingleText(CMICmdArgContext &vrwArgContext); + bool ValidateQuotedText(CMICmdArgContext &vrwArgContext); + bool ValidateQuotedTextEmbedded(CMICmdArgContext &vrwArgContext); + bool ValidateQuotedQuotedTextEmbedded(CMICmdArgContext &vrwArgContext); + bool IsStringArgSingleText(const CMIUtilString &vrTxt) const; + bool IsStringArgQuotedText(const CMIUtilString &vrTxt) const; + bool IsStringArgQuotedTextEmbedded(const CMIUtilString &vrTxt) const; + bool IsStringArgQuotedQuotedTextEmbedded(const CMIUtilString &vrTxt) const; - // Attribute: - private: - bool m_bHandleQuotedString; // True = Parse a string surrounded by quotes spaces are not delimiters, false = only text up to next - // delimiting space character - bool m_bAcceptNumbers; // True = Parse a string and accept as a number if number, false = numbers not recognised as string types - bool m_bHandleDirPaths; // True = Parse a string and accept directory file style string if present, false = directory file path not - // accepted - bool m_bHandleAnything; // True = Parse a string and accept anything if present, false = validate for criteria matches + // Attribute: +private: + bool m_bHandleQuotedString; // True = Parse a string surrounded by quotes + // spaces are not delimiters, false = only text up + // to next + // delimiting space character + bool m_bAcceptNumbers; // True = Parse a string and accept as a number if + // number, false = numbers not recognised as string + // types + bool m_bHandleDirPaths; // True = Parse a string and accept directory file + // style string if present, false = directory file + // path not + // accepted + bool m_bHandleAnything; // True = Parse a string and accept anything if + // present, false = validate for criteria matches }; diff --git a/lldb/tools/lldb-mi/MICmdArgValThreadGrp.cpp b/lldb/tools/lldb-mi/MICmdArgValThreadGrp.cpp index 43e9c724dca..613ad0dcc34 100644 --- a/lldb/tools/lldb-mi/MICmdArgValThreadGrp.cpp +++ b/lldb/tools/lldb-mi/MICmdArgValThreadGrp.cpp @@ -11,46 +11,48 @@ #include "MICmdArgValThreadGrp.h" #include "MICmdArgContext.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValThreadGrp constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdArgValThreadGrp::CMICmdArgValThreadGrp() - : m_nThreadGrp(0) -{ -} +CMICmdArgValThreadGrp::CMICmdArgValThreadGrp() : m_nThreadGrp(0) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValThreadGrp constructor. // Type: Method. // Args: vrArgName - (R) Argument's name to search by. -// vbMandatory - (R) True = Yes must be present, false = optional argument. -// vbHandleByCmd - (R) True = Command processes *this option, false = not handled. +// vbMandatory - (R) True = Yes must be present, false = optional +// argument. +// vbHandleByCmd - (R) True = Command processes *this option, false = +// not handled. // Return: None. // Throws: None. //-- -CMICmdArgValThreadGrp::CMICmdArgValThreadGrp(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd) - : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd) - , m_nThreadGrp(0) -{ -} - -//++ ------------------------------------------------------------------------------------ +CMICmdArgValThreadGrp::CMICmdArgValThreadGrp(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd) + : CMICmdArgValBaseTemplate(vrArgName, vbMandatory, vbHandleByCmd), + m_nThreadGrp(0) {} + +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdArgValThreadGrp destructor. // Type: Overridden. // Args: None. // Return: None. // Throws: None. //-- -CMICmdArgValThreadGrp::~CMICmdArgValThreadGrp() -{ -} +CMICmdArgValThreadGrp::~CMICmdArgValThreadGrp() {} -//++ ------------------------------------------------------------------------------------ -// Details: Parse the command's argument options string and try to extract the value *this +//++ +//------------------------------------------------------------------------------------ +// Details: Parse the command's argument options string and try to extract the +// value *this // argument is looking for. // Type: Overridden. // Args: vwArgContext - (RW) The command's argument options string. @@ -58,77 +60,69 @@ CMICmdArgValThreadGrp::~CMICmdArgValThreadGrp() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdArgValThreadGrp::Validate(CMICmdArgContext &vwArgContext) -{ - if (vwArgContext.IsEmpty()) - return m_bMandatory ? MIstatus::failure : MIstatus::success; - - if (vwArgContext.GetNumberArgsPresent() == 1) - { - const CMIUtilString &rArg(vwArgContext.GetArgsLeftToParse()); - if (IsArgThreadGrp(rArg) && ExtractNumber(rArg)) - { - m_bFound = true; - m_bValid = true; - m_argValue = GetNumber(); - vwArgContext.RemoveArg(rArg); - return MIstatus::success; - } - else - return MIstatus::failure; +bool CMICmdArgValThreadGrp::Validate(CMICmdArgContext &vwArgContext) { + if (vwArgContext.IsEmpty()) + return m_bMandatory ? MIstatus::failure : MIstatus::success; + + if (vwArgContext.GetNumberArgsPresent() == 1) { + const CMIUtilString &rArg(vwArgContext.GetArgsLeftToParse()); + if (IsArgThreadGrp(rArg) && ExtractNumber(rArg)) { + m_bFound = true; + m_bValid = true; + m_argValue = GetNumber(); + vwArgContext.RemoveArg(rArg); + return MIstatus::success; + } else + return MIstatus::failure; + } + + // More than one option... + const CMIUtilString::VecString_t vecOptions(vwArgContext.GetArgs()); + CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); + while (it != vecOptions.end()) { + const CMIUtilString &rArg(*it); + if (IsArgThreadGrp(rArg) && ExtractNumber(rArg)) { + m_bFound = true; + + if (vwArgContext.RemoveArg(rArg)) { + m_bValid = true; + m_argValue = GetNumber(); + return MIstatus::success; + } else + return MIstatus::failure; } - // More than one option... - const CMIUtilString::VecString_t vecOptions(vwArgContext.GetArgs()); - CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); - while (it != vecOptions.end()) - { - const CMIUtilString &rArg(*it); - if (IsArgThreadGrp(rArg) && ExtractNumber(rArg)) - { - m_bFound = true; - - if (vwArgContext.RemoveArg(rArg)) - { - m_bValid = true; - m_argValue = GetNumber(); - return MIstatus::success; - } - else - return MIstatus::failure; - } - - // Next - ++it; - } + // Next + ++it; + } - return MIstatus::failure; + return MIstatus::failure; } -//++ ------------------------------------------------------------------------------------ -// Details: Examine the string and determine if it is a valid string type argument. +//++ +//------------------------------------------------------------------------------------ +// Details: Examine the string and determine if it is a valid string type +// argument. // Type: Method. // Args: vrTxt - (R) Some text. // Return: bool - True = yes valid arg, false = no. // Throws: None. //-- -bool -CMICmdArgValThreadGrp::IsArgThreadGrp(const CMIUtilString &vrTxt) const -{ - // Look for i1 i2 i3.... - const MIint nPos = vrTxt.find('i'); - if (nPos != 0) - return false; - - const CMIUtilString strNum = vrTxt.substr(1); - if (!strNum.IsNumber()) - return false; - - return true; +bool CMICmdArgValThreadGrp::IsArgThreadGrp(const CMIUtilString &vrTxt) const { + // Look for i1 i2 i3.... + const MIint nPos = vrTxt.find('i'); + if (nPos != 0) + return false; + + const CMIUtilString strNum = vrTxt.substr(1); + if (!strNum.IsNumber()) + return false; + + return true; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Extract the thread group number from the thread group argument. // Type: Method. // Args: vrTxt - (R) Some text. @@ -136,29 +130,23 @@ CMICmdArgValThreadGrp::IsArgThreadGrp(const CMIUtilString &vrTxt) const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdArgValThreadGrp::ExtractNumber(const CMIUtilString &vrTxt) -{ - const CMIUtilString strNum = vrTxt.substr(1); - MIint64 nNumber = 0; - bool bOk = strNum.ExtractNumber(nNumber); - if (bOk) - { - m_nThreadGrp = static_cast<MIuint>(nNumber); - } - - return bOk; +bool CMICmdArgValThreadGrp::ExtractNumber(const CMIUtilString &vrTxt) { + const CMIUtilString strNum = vrTxt.substr(1); + MIint64 nNumber = 0; + bool bOk = strNum.ExtractNumber(nNumber); + if (bOk) { + m_nThreadGrp = static_cast<MIuint>(nNumber); + } + + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the thread group ID found in the argument. // Type: Method. // Args: None. // Return: MIuint - Thread group ID. // Throws: None. //-- -MIuint -CMICmdArgValThreadGrp::GetNumber() const -{ - return m_nThreadGrp; -} +MIuint CMICmdArgValThreadGrp::GetNumber() const { return m_nThreadGrp; } diff --git a/lldb/tools/lldb-mi/MICmdArgValThreadGrp.h b/lldb/tools/lldb-mi/MICmdArgValThreadGrp.h index 5c4936c0152..bcdb156a1b1 100644 --- a/lldb/tools/lldb-mi/MICmdArgValThreadGrp.h +++ b/lldb/tools/lldb-mi/MICmdArgValThreadGrp.h @@ -15,37 +15,40 @@ // Declarations: class CMICmdArgContext; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code class. Command argument class. Arguments object // needing specialization derived from the CMICmdArgValBase class. // An argument knows what type of argument it is and how it is to -// interpret the options (context) string to find and validate a matching +// interpret the options (context) string to find and validate a +// matching // argument and so extract a value from it. Thread group looks like // "i1" in the options text. // Based on the Interpreter pattern. //-- -class CMICmdArgValThreadGrp : public CMICmdArgValBaseTemplate<MIuint> -{ - // Methods: - public: - /* ctor */ CMICmdArgValThreadGrp(); - /* ctor */ CMICmdArgValThreadGrp(const CMIUtilString &vrArgName, const bool vbMandatory, const bool vbHandleByCmd); - // - bool IsArgThreadGrp(const CMIUtilString &vrTxt) const; +class CMICmdArgValThreadGrp : public CMICmdArgValBaseTemplate<MIuint> { + // Methods: +public: + /* ctor */ CMICmdArgValThreadGrp(); + /* ctor */ CMICmdArgValThreadGrp(const CMIUtilString &vrArgName, + const bool vbMandatory, + const bool vbHandleByCmd); + // + bool IsArgThreadGrp(const CMIUtilString &vrTxt) const; - // Overridden: - public: - // From CMICmdArgValBase - /* dtor */ ~CMICmdArgValThreadGrp() override; - // From CMICmdArgSet::IArg - bool Validate(CMICmdArgContext &vArgContext) override; + // Overridden: +public: + // From CMICmdArgValBase + /* dtor */ ~CMICmdArgValThreadGrp() override; + // From CMICmdArgSet::IArg + bool Validate(CMICmdArgContext &vArgContext) override; - // Methods: - private: - bool ExtractNumber(const CMIUtilString &vrTxt); - MIuint GetNumber() const; + // Methods: +private: + bool ExtractNumber(const CMIUtilString &vrTxt); + MIuint GetNumber() const; - // Attributes: - private: - MIuint m_nThreadGrp; + // Attributes: +private: + MIuint m_nThreadGrp; }; diff --git a/lldb/tools/lldb-mi/MICmdBase.cpp b/lldb/tools/lldb-mi/MICmdBase.cpp index 2f63205dd9b..c645d84c1e9 100644 --- a/lldb/tools/lldb-mi/MICmdBase.cpp +++ b/lldb/tools/lldb-mi/MICmdBase.cpp @@ -9,12 +9,13 @@ // In-house headers: #include "MICmdBase.h" -#include "MICmnMIValueConst.h" -#include "MICmnLLDBDebugSessionInfo.h" -#include "MICmdArgValOptionLong.h" #include "MICmdArgValConsume.h" +#include "MICmdArgValOptionLong.h" +#include "MICmnLLDBDebugSessionInfo.h" +#include "MICmnMIValueConst.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdBase constructor. // Type: Method. // Args: None. @@ -22,44 +23,35 @@ // Throws: None. //-- CMICmdBase::CMICmdBase() - : m_pSelfCreatorFn(nullptr) - , m_rLLDBDebugSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()) - , m_bHasResultRecordExtra(false) - , m_constStrArgThreadGroup("thread-group") - , m_constStrArgThread("thread") - , m_constStrArgFrame("frame") - , m_constStrArgConsume("--") - , m_ThreadGrpArgMandatory(false) - , m_ThreadArgMandatory(false) - , m_FrameArgMandatory(false) -{ -} + : m_pSelfCreatorFn(nullptr), + m_rLLDBDebugSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()), + m_bHasResultRecordExtra(false), m_constStrArgThreadGroup("thread-group"), + m_constStrArgThread("thread"), m_constStrArgFrame("frame"), + m_constStrArgConsume("--"), m_ThreadGrpArgMandatory(false), + m_ThreadArgMandatory(false), m_FrameArgMandatory(false) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdBase destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdBase::~CMICmdBase() -{ -} +CMICmdBase::~CMICmdBase() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: The invoker requires this function. // Type: Overridden. // Args: None. // Return: SMICmdData & - *this command's present status/data/information. // Throws: None. //-- -const SMICmdData & -CMICmdBase::GetCmdData() const -{ - return m_cmdData; -} +const SMICmdData &CMICmdBase::GetCmdData() const { return m_cmdData; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: The invoker requires this function. // Type: Overridden. // Args: None. @@ -67,169 +59,179 @@ CMICmdBase::GetCmdData() const // Empty string indicates command status ok. // Throws: None. //-- -const CMIUtilString & -CMICmdBase::GetErrorDescription() const -{ - return m_strCurrentErrDescription; +const CMIUtilString &CMICmdBase::GetErrorDescription() const { + return m_strCurrentErrDescription; } -//++ ------------------------------------------------------------------------------------ -// Details: The CMICmdFactory requires this function. Retrieve the command and argument +//++ +//------------------------------------------------------------------------------------ +// Details: The CMICmdFactory requires this function. Retrieve the command and +// argument // options description string. // Type: Overridden. // Args: None. // Return: CMIUtilString & - Command description. // Throws: None. //-- -const CMIUtilString & -CMICmdBase::GetMiCmd() const -{ - return m_strMiCmd; -} +const CMIUtilString &CMICmdBase::GetMiCmd() const { return m_strMiCmd; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Help parse the arguments that are common to all commands. // Args: None. // Return: None // Throws: None. //-- -void -CMICmdBase::AddCommonArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgThreadGroup, m_ThreadGrpArgMandatory, true, CMICmdArgValListBase::eArgValType_ThreadGrp, 1)); - m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgThread, m_ThreadArgMandatory, true, CMICmdArgValListBase::eArgValType_Number, 1)); - m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgFrame, m_FrameArgMandatory, true, CMICmdArgValListBase::eArgValType_Number, 1)); - m_setCmdArgs.Add(new CMICmdArgValConsume(m_constStrArgConsume, false)); +void CMICmdBase::AddCommonArgs() { + m_setCmdArgs.Add(new CMICmdArgValOptionLong( + m_constStrArgThreadGroup, m_ThreadGrpArgMandatory, true, + CMICmdArgValListBase::eArgValType_ThreadGrp, 1)); + m_setCmdArgs.Add(new CMICmdArgValOptionLong( + m_constStrArgThread, m_ThreadArgMandatory, true, + CMICmdArgValListBase::eArgValType_Number, 1)); + m_setCmdArgs.Add( + new CMICmdArgValOptionLong(m_constStrArgFrame, m_FrameArgMandatory, true, + CMICmdArgValListBase::eArgValType_Number, 1)); + m_setCmdArgs.Add(new CMICmdArgValConsume(m_constStrArgConsume, false)); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. A command must be given working data and -// provide data about its status or provide information to other objects. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. A command must be given working +// data and +// provide data about its status or provide information to other +// objects. // Type: Overridden. // Args: None. // Return: None. // Throws: None. //-- -void -CMICmdBase::SetCmdData(const SMICmdData &vCmdData) -{ - m_cmdData = vCmdData; +void CMICmdBase::SetCmdData(const SMICmdData &vCmdData) { + m_cmdData = vCmdData; } -//++ ------------------------------------------------------------------------------------ -// Details: The command factory requires this function. The factory calls this function +//++ +//------------------------------------------------------------------------------------ +// Details: The command factory requires this function. The factory calls this +// function // so it can obtain *this command's creation function. // Type: Overridden. // Args: None. // Return: CMICmdFactory::CmdCreatorFnPtr - Function pointer. // Throws: None. //-- -CMICmdFactory::CmdCreatorFnPtr -CMICmdBase::GetCmdCreatorFn() const -{ - return m_pSelfCreatorFn; +CMICmdFactory::CmdCreatorFnPtr CMICmdBase::GetCmdCreatorFn() const { + return m_pSelfCreatorFn; } -//++ ------------------------------------------------------------------------------------ -// Details: If a command is an event type (has callbacks registered with SBListener) it -// needs to inform the Invoker that it has finished its work so that the -// Invoker can tidy up and call the commands Acknowledge function (yes the -// command itself could call the Acknowledge itself but not doing that way). +//++ +//------------------------------------------------------------------------------------ +// Details: If a command is an event type (has callbacks registered with +// SBListener) it +// needs to inform the Invoker that it has finished its work so that +// the +// Invoker can tidy up and call the commands Acknowledge function (yes +// the +// command itself could call the Acknowledge itself but not doing that +// way). // Type: Overridden. // Args: None. // Return: None. // Throws: None. //-- -void -CMICmdBase::CmdFinishedTellInvoker() const -{ - CMICmdInvoker::Instance().CmdExecuteFinished(const_cast<CMICmdBase &>(*this)); +void CMICmdBase::CmdFinishedTellInvoker() const { + CMICmdInvoker::Instance().CmdExecuteFinished(const_cast<CMICmdBase &>(*this)); } -//++ ------------------------------------------------------------------------------------ -// Details: Returns the final version of the MI result record built up in the command's +//++ +//------------------------------------------------------------------------------------ +// Details: Returns the final version of the MI result record built up in the +// command's // Acknowledge function. The one line text of MI result. // Type: Overridden. // Args: None. // Return: CMIUtilString & - MI text version of the MI result record. // Throws: None. //-- -const CMIUtilString & -CMICmdBase::GetMIResultRecord() const -{ - return m_miResultRecord.GetString(); +const CMIUtilString &CMICmdBase::GetMIResultRecord() const { + return m_miResultRecord.GetString(); } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve from the command additional MI result to its 1 line response. -// Because of using LLDB additional 'fake'/hack output is sometimes required to +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve from the command additional MI result to its 1 line +// response. +// Because of using LLDB additional 'fake'/hack output is sometimes +// required to // help the driver client operate i.e. Eclipse. // Type: Overridden. // Args: None. // Return: CMIUtilString & - MI text version of the MI result record. // Throws: None. //-- -const CMIUtilString & -CMICmdBase::GetMIResultRecordExtra() const -{ - return m_miResultRecordExtra; +const CMIUtilString &CMICmdBase::GetMIResultRecordExtra() const { + return m_miResultRecordExtra; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Hss *this command got additional MI result to its 1 line response. -// Because of using LLDB additional 'fake'/hack output is sometimes required to +// Because of using LLDB additional 'fake'/hack output is sometimes +// required to // help the driver client operate i.e. Eclipse. // Type: Overridden. // Args: None. -// Return: bool - True = Yes have additional MI output, false = no nothing extra. +// Return: bool - True = Yes have additional MI output, false = no nothing +// extra. // Throws: None. //-- -bool -CMICmdBase::HasMIResultRecordExtra() const -{ - return m_bHasResultRecordExtra; +bool CMICmdBase::HasMIResultRecordExtra() const { + return m_bHasResultRecordExtra; } -//++ ------------------------------------------------------------------------------------ -// Details: Short cut function to enter error information into the command's metadata +//++ +//------------------------------------------------------------------------------------ +// Details: Short cut function to enter error information into the command's +// metadata // object and set the command's error status. // Type: Method. // Args: rErrMsg - (R) Error description. // Return: None. // Throws: None. //-- -void -CMICmdBase::SetError(const CMIUtilString &rErrMsg) -{ - m_cmdData.bCmdValid = false; - m_cmdData.strErrorDescription = rErrMsg; - m_cmdData.bCmdExecutedSuccessfully = false; +void CMICmdBase::SetError(const CMIUtilString &rErrMsg) { + m_cmdData.bCmdValid = false; + m_cmdData.strErrorDescription = rErrMsg; + m_cmdData.bCmdExecutedSuccessfully = false; - const CMICmnMIValueResult valueResult("msg", CMICmnMIValueConst(rErrMsg)); - const CMICmnMIResultRecord miResultRecord(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, valueResult); - m_miResultRecord = miResultRecord; - m_cmdData.strMiCmdResultRecord = miResultRecord.GetString(); + const CMICmnMIValueResult valueResult("msg", CMICmnMIValueConst(rErrMsg)); + const CMICmnMIResultRecord miResultRecord( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + valueResult); + m_miResultRecord = miResultRecord; + m_cmdData.strMiCmdResultRecord = miResultRecord.GetString(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Ask a command to provide its unique identifier. // Type: Method. // Args: A unique identifier for this command class. // Return: None. // Throws: None. //-- -MIuint -CMICmdBase::GetGUID() -{ - MIuint64 vptr = reinterpret_cast<MIuint64>(this); - MIuint id = (vptr)&0xFFFFFFFF; - id ^= (vptr >> 32) & 0xFFFFFFFF; +MIuint CMICmdBase::GetGUID() { + MIuint64 vptr = reinterpret_cast<MIuint64>(this); + MIuint id = (vptr)&0xFFFFFFFF; + id ^= (vptr >> 32) & 0xFFFFFFFF; - return id; + return id; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -237,18 +239,20 @@ CMICmdBase::GetGUID() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdBase::ParseArgs() -{ - // Do nothing - override to implement +bool CMICmdBase::ParseArgs() { + // Do nothing - override to implement - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Having previously given CMICmdArgSet m_setCmdArgs all the argument or option -// definitions for the command to handle proceed to parse and validate the -// command's options text for those arguments and extract the values for each if +//++ +//------------------------------------------------------------------------------------ +// Details: Having previously given CMICmdArgSet m_setCmdArgs all the argument +// or option +// definitions for the command to handle proceed to parse and validate +// the +// command's options text for those arguments and extract the values +// for each if // any. // Type: Method. // Args: None. @@ -256,31 +260,33 @@ CMICmdBase::ParseArgs() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdBase::ParseValidateCmdOptions() -{ - CMICmdArgContext argCntxt(m_cmdData.strMiCmdOption); - if (m_setCmdArgs.Validate(m_cmdData.strMiCmd, argCntxt)) - return MIstatus::success; +bool CMICmdBase::ParseValidateCmdOptions() { + CMICmdArgContext argCntxt(m_cmdData.strMiCmdOption); + if (m_setCmdArgs.Validate(m_cmdData.strMiCmd, argCntxt)) + return MIstatus::success; - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_ARGS), m_cmdData.strMiCmd.c_str(), m_setCmdArgs.GetErrorDescription().c_str())); + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_ARGS), + m_cmdData.strMiCmd.c_str(), + m_setCmdArgs.GetErrorDescription().c_str())); - return MIstatus::failure; + return MIstatus::failure; } -//++ ------------------------------------------------------------------------------------ -// Details: If the MI Driver is not operating via a client i.e. Eclipse but say operating -// on a executable passed in as a argument to the drive then what should the driver -// do on a command failing? Either continue operating or exit the application. -// Override this function where a command failure cannot allow the driver to +//++ +//------------------------------------------------------------------------------------ +// Details: If the MI Driver is not operating via a client i.e. Eclipse but say +// operating +// on a executable passed in as a argument to the drive then what +// should the driver +// do on a command failing? Either continue operating or exit the +// application. +// Override this function where a command failure cannot allow the +// driver to // continue operating. // Type: Overrideable. // Args: None. -// Return: bool - True = Fatal if command fails, false = can continue if command fails. +// Return: bool - True = Fatal if command fails, false = can continue if +// command fails. // Throws: None. //-- -bool -CMICmdBase::GetExitAppOnCommandFailure() const -{ - return false; -} +bool CMICmdBase::GetExitAppOnCommandFailure() const { return false; } diff --git a/lldb/tools/lldb-mi/MICmdBase.h b/lldb/tools/lldb-mi/MICmdBase.h index aa567482396..66f9fa6ee5d 100644 --- a/lldb/tools/lldb-mi/MICmdBase.h +++ b/lldb/tools/lldb-mi/MICmdBase.h @@ -13,19 +13,20 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "MIUtilString.h" -#include "MICmnBase.h" -#include "MICmnResources.h" -#include "MICmdInvoker.h" -#include "MICmdFactory.h" +#include "MICmdArgSet.h" #include "MICmdData.h" +#include "MICmdFactory.h" +#include "MICmdInvoker.h" +#include "MICmnBase.h" #include "MICmnMIResultRecord.h" -#include "MICmdArgSet.h" +#include "MICmnResources.h" +#include "MIUtilString.h" // Declarations: class CMICmnLLDBDebugSessionInfo; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command base class. MI commands derive from this base class. // The Command Factory creates command objects and passes them to the // Command Invoker. The Invoker takes ownership of any commands created @@ -39,116 +40,149 @@ class CMICmnLLDBDebugSessionInfo; // function. The other type of command is one that just does some work, // ends, then the Invoker calls the command's Acknowledge function. No // events set up. -// A command's Execute(), Acknowledge() and event callback functions are +// A command's Execute(), Acknowledge() and event callback functions +// are // carried out in the main thread. -// A command may use the argument derived object classes (CMICmdArgValBase) +// A command may use the argument derived object classes +// (CMICmdArgValBase) // to factor handling and parsing of different types of arguments // presented to a command. A command will produce an error should it // be presented with arguments or options it does not understand. //-- -class CMICmdBase : public CMICmnBase, public CMICmdInvoker::ICmd, public CMICmdFactory::ICmd -{ - // Methods: - public: - CMICmdBase(); +class CMICmdBase : public CMICmnBase, + public CMICmdInvoker::ICmd, + public CMICmdFactory::ICmd { + // Methods: +public: + CMICmdBase(); - // Overridden: - // From CMICmdInvoker::ICmd - const SMICmdData &GetCmdData() const override; - const CMIUtilString &GetErrorDescription() const override; - void SetCmdData(const SMICmdData &vCmdData) override; - void CmdFinishedTellInvoker() const override; - const CMIUtilString &GetMIResultRecord() const override; - const CMIUtilString &GetMIResultRecordExtra() const override; - bool HasMIResultRecordExtra() const override; - bool ParseArgs() override; - // From CMICmdFactory::ICmd - const CMIUtilString &GetMiCmd() const override; - CMICmdFactory::CmdCreatorFnPtr GetCmdCreatorFn() const override; + // Overridden: + // From CMICmdInvoker::ICmd + const SMICmdData &GetCmdData() const override; + const CMIUtilString &GetErrorDescription() const override; + void SetCmdData(const SMICmdData &vCmdData) override; + void CmdFinishedTellInvoker() const override; + const CMIUtilString &GetMIResultRecord() const override; + const CMIUtilString &GetMIResultRecordExtra() const override; + bool HasMIResultRecordExtra() const override; + bool ParseArgs() override; + // From CMICmdFactory::ICmd + const CMIUtilString &GetMiCmd() const override; + CMICmdFactory::CmdCreatorFnPtr GetCmdCreatorFn() const override; - virtual MIuint GetGUID(); - void AddCommonArgs(); + virtual MIuint GetGUID(); + void AddCommonArgs(); - // Overrideable: - ~CMICmdBase() override; - virtual bool GetExitAppOnCommandFailure() const; + // Overrideable: + ~CMICmdBase() override; + virtual bool GetExitAppOnCommandFailure() const; - // Methods: - protected: - void SetError(const CMIUtilString &rErrMsg); - template <class T> T *GetOption(const CMIUtilString &vStrOptionName); - bool ParseValidateCmdOptions(); + // Methods: +protected: + void SetError(const CMIUtilString &rErrMsg); + template <class T> T *GetOption(const CMIUtilString &vStrOptionName); + bool ParseValidateCmdOptions(); - // Attributes: - CMICmdFactory::CmdCreatorFnPtr m_pSelfCreatorFn; - CMIUtilString m_strCurrentErrDescription; // Reason for Execute or Acknowledge function failure - SMICmdData m_cmdData; // Holds information/status of *this command. Used by other MI code to report or determine state of a command. - bool m_bWaitForEventFromSBDebugger; // True = yes event type command wait, false = command calls Acknowledge() straight after Execute() - // no waiting - CMIUtilString m_strMiCmd; // The MI text identifying *this command i.e. 'break-insert' - CMICmnMIResultRecord m_miResultRecord; // This is completed in the Acknowledge() function and returned to the Command Invoker to proceed - // stdout output. Each command forms 1 response to its input. - CMIUtilString m_miResultRecordExtra; // This is completed in the Acknowledge() function and returned to the Command Invoker to proceed - // stdout output. Hack command produce more response text to help the client because of using LLDB - CMICmnLLDBDebugSessionInfo & - m_rLLDBDebugSessionInfo; // Access to command sharing information or data across any and all command based derived classes. - bool m_bHasResultRecordExtra; // True = Yes command produced additional MI output to its 1 line response, false = no extra MI output - // formed. - CMICmdArgSet m_setCmdArgs; // The list of arguments *this command needs to parse from the options string to carry out work. - const CMIUtilString m_constStrArgThreadGroup; - const CMIUtilString m_constStrArgThread; - const CMIUtilString m_constStrArgFrame; - const CMIUtilString m_constStrArgConsume; + // Attributes: + CMICmdFactory::CmdCreatorFnPtr m_pSelfCreatorFn; + CMIUtilString m_strCurrentErrDescription; // Reason for Execute or Acknowledge + // function failure + SMICmdData m_cmdData; // Holds information/status of *this command. Used by + // other MI code to report or determine state of a + // command. + bool m_bWaitForEventFromSBDebugger; // True = yes event type command wait, + // false = command calls Acknowledge() + // straight after Execute() + // no waiting + CMIUtilString + m_strMiCmd; // The MI text identifying *this command i.e. 'break-insert' + CMICmnMIResultRecord m_miResultRecord; // This is completed in the + // Acknowledge() function and returned + // to the Command Invoker to proceed + // stdout output. Each command forms 1 response to its input. + CMIUtilString m_miResultRecordExtra; // This is completed in the Acknowledge() + // function and returned to the Command + // Invoker to proceed + // stdout output. Hack command produce more response text to help the client + // because of using LLDB + CMICmnLLDBDebugSessionInfo &m_rLLDBDebugSessionInfo; // Access to command + // sharing information or + // data across any and + // all command based + // derived classes. + bool m_bHasResultRecordExtra; // True = Yes command produced additional MI + // output to its 1 line response, false = no + // extra MI output + // formed. + CMICmdArgSet m_setCmdArgs; // The list of arguments *this command needs to + // parse from the options string to carry out work. + const CMIUtilString m_constStrArgThreadGroup; + const CMIUtilString m_constStrArgThread; + const CMIUtilString m_constStrArgFrame; + const CMIUtilString m_constStrArgConsume; - // These 3 members can be used by the derived classes to make any of - // "thread", "frame" or "thread-group" mandatory. - bool m_ThreadGrpArgMandatory; - bool m_ThreadArgMandatory; - bool m_FrameArgMandatory; + // These 3 members can be used by the derived classes to make any of + // "thread", "frame" or "thread-group" mandatory. + bool m_ThreadGrpArgMandatory; + bool m_ThreadArgMandatory; + bool m_FrameArgMandatory; }; -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the command argument or option object pointer so that it can be -// examined. If the option found and valid get the value (number, string or list -// - see CMICmdArgValBase class) from it to use with the command's decision -// making. If the argument is not found the command's error description is set +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the command argument or option object pointer so that it +// can be +// examined. If the option found and valid get the value (number, +// string or list +// - see CMICmdArgValBase class) from it to use with the command's +// decision +// making. If the argument is not found the command's error description +// is set // describing the error condition. // Type: Template method. -// Args: vStrOptionName - (R) The text name of the argument or option to search for in -// the list of the command's possible arguments or options. +// Args: vStrOptionName - (R) The text name of the argument or option to +// search for in +// the list of the command's possible arguments +// or options. // Return: T * - CMICmdArgValBase derived object. -// - nullptr = function has failed, unable to retrieve the option/arg object. +// - nullptr = function has failed, unable to retrieve the +// option/arg object. // Throws: None. //-- template <class T> -T * -CMICmdBase::GetOption(const CMIUtilString &vStrOptionName) -{ - CMICmdArgValBase *pPtrBase = nullptr; - if (!m_setCmdArgs.GetArg(vStrOptionName, pPtrBase)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), vStrOptionName.c_str())); - return nullptr; - } +T *CMICmdBase::GetOption(const CMIUtilString &vStrOptionName) { + CMICmdArgValBase *pPtrBase = nullptr; + if (!m_setCmdArgs.GetArg(vStrOptionName, pPtrBase)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), + vStrOptionName.c_str())); + return nullptr; + } - return static_cast<T *>(pPtrBase); + return static_cast<T *>(pPtrBase); } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the command argument or option object pointer using template function -// CMICmdBase::GetOption(). Should the argument (by name) not be found the +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the command argument or option object pointer using +// template function +// CMICmdBase::GetOption(). Should the argument (by name) not be found +// the // command will exit with a failure (set in GetOption()). // Type: Preprocessor macro. // Args: a - (R) The actual variable's name. -// b - (R) The type of variable (appended to CMICmdArgVal i.e. CMICmdArgValString). -// c - (R) The text name of the argument or option to search for in the list of +// b - (R) The type of variable (appended to CMICmdArgVal i.e. +// CMICmdArgValString). +// c - (R) The text name of the argument or option to search for in +// the list of // the command's possible arguments or options. // Return: T * - CMICmdArgValBase derived object. -// - nullptr = function has failed, unable to retrieve the option/arg object. +// - nullptr = function has failed, unable to retrieve the +// option/arg object. // Throws: None. //-- -#define CMICMDBASE_GETOPTION(a, b, c) \ - CMICmdArgVal##b *a = CMICmdBase::GetOption<CMICmdArgVal##b>(c); \ - if (a == nullptr) \ - return MIstatus::failure; +#define CMICMDBASE_GETOPTION(a, b, c) \ + CMICmdArgVal##b *a = CMICmdBase::GetOption<CMICmdArgVal##b>(c); \ + if (a == nullptr) \ + return MIstatus::failure; // This comment is to stop compile warning for #define diff --git a/lldb/tools/lldb-mi/MICmdCmd.cpp b/lldb/tools/lldb-mi/MICmdCmd.cpp index c6661112ea3..a784580673f 100644 --- a/lldb/tools/lldb-mi/MICmdCmd.cpp +++ b/lldb/tools/lldb-mi/MICmdCmd.cpp @@ -11,55 +11,56 @@ // CMICmdCmdSource implementation. // - // In-house headers: #include "MICmdCmd.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdEnablePrettyPrinting constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdEnablePrettyPrinting::CMICmdCmdEnablePrettyPrinting() -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "enable-pretty-printing"; +CMICmdCmdEnablePrettyPrinting::CMICmdCmdEnablePrettyPrinting() { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "enable-pretty-printing"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdEnablePrettyPrinting::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdEnablePrettyPrinting::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdEnablePrettyPrinting destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdEnablePrettyPrinting::~CMICmdCmdEnablePrettyPrinting() -{ -} - -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +CMICmdCmdEnablePrettyPrinting::~CMICmdCmdEnablePrettyPrinting() {} + +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdEnablePrettyPrinting::Execute() -{ - // Do nothing - return MIstatus::success; +bool CMICmdCmdEnablePrettyPrinting::Execute() { + // Do nothing + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -67,80 +68,82 @@ CMICmdCmdEnablePrettyPrinting::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdEnablePrettyPrinting::Acknowledge() -{ - const CMICmnMIValueConst miValueConst("0"); - const CMICmnMIValueResult miValueResult("supported", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - - return MIstatus::success; +bool CMICmdCmdEnablePrettyPrinting::Acknowledge() { + const CMICmnMIValueConst miValueConst("0"); + const CMICmnMIValueResult miValueResult("supported", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdEnablePrettyPrinting::CreateSelf() -{ - return new CMICmdCmdEnablePrettyPrinting(); +CMICmdBase *CMICmdCmdEnablePrettyPrinting::CreateSelf() { + return new CMICmdCmdEnablePrettyPrinting(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdSource constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdSource::CMICmdCmdSource() -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "source"; +CMICmdCmdSource::CMICmdCmdSource() { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "source"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdSource::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdSource::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdSource destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdSource::~CMICmdCmdSource() -{ -} - -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +CMICmdCmdSource::~CMICmdCmdSource() {} + +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdSource::Execute() -{ - // Do nothing - return MIstatus::success; +bool CMICmdCmdSource::Execute() { + // Do nothing + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -148,25 +151,22 @@ CMICmdCmdSource::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdSource::Acknowledge() -{ - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); - m_miResultRecord = miRecordResult; +bool CMICmdCmdSource::Acknowledge() { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdSource::CreateSelf() -{ - return new CMICmdCmdSource(); -} +CMICmdBase *CMICmdCmdSource::CreateSelf() { return new CMICmdCmdSource(); } diff --git a/lldb/tools/lldb-mi/MICmdCmd.h b/lldb/tools/lldb-mi/MICmdCmd.h index 6753c3b5390..d3de49c4ded 100644 --- a/lldb/tools/lldb-mi/MICmdCmd.h +++ b/lldb/tools/lldb-mi/MICmdCmd.h @@ -10,13 +10,16 @@ // Overview: CMICmdCmdEnablePrettyPrinting interface. // CMICmdCmdSource interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands derive a new command class from the +// command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// For an introduction to adding a new command see +// CMICmdCmdSupportInfoMiCmdQuery // command class as an example. /* @@ -27,61 +30,62 @@ MI commands implemented are: #pragma once // Third party headers: -#include <vector> #include "lldb/API/SBBreakpoint.h" #include "lldb/API/SBCommandReturnObject.h" +#include <vector> // In-house headers: #include "MICmdBase.h" -#include "MICmnMIValueTuple.h" #include "MICmnMIValueList.h" +#include "MICmnMIValueTuple.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "enable-pretty-printing". // Enables Python base pretty printing. -// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Variable-Objects.html +// Ref: +// http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Variable-Objects.html //-- -class CMICmdCmdEnablePrettyPrinting : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); +class CMICmdCmdEnablePrettyPrinting : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); - // Methods: - public: - /* ctor */ CMICmdCmdEnablePrettyPrinting(); + // Methods: +public: + /* ctor */ CMICmdCmdEnablePrettyPrinting(); - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdEnablePrettyPrinting() override; + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdEnablePrettyPrinting() override; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "source". //-- -class CMICmdCmdSource : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); +class CMICmdCmdSource : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); - // Methods: - public: - /* ctor */ CMICmdCmdSource(); + // Methods: +public: + /* ctor */ CMICmdCmdSource(); - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdSource() override; + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdSource() override; }; diff --git a/lldb/tools/lldb-mi/MICmdCmdBreak.cpp b/lldb/tools/lldb-mi/MICmdCmdBreak.cpp index c58d6b7edb9..020ac982d11 100644 --- a/lldb/tools/lldb-mi/MICmdCmdBreak.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdBreak.cpp @@ -18,22 +18,23 @@ #include "lldb/API/SBBreakpointLocation.h" // In-house headers: -#include "MICmdCmdBreak.h" -#include "MICmnMIResultRecord.h" -#include "MICmnMIValueConst.h" -#include "MICmnMIOutOfBandRecord.h" -#include "MICmnLLDBDebugger.h" -#include "MICmnLLDBDebugSessionInfo.h" #include "MICmdArgValFile.h" +#include "MICmdArgValListOfN.h" #include "MICmdArgValNumber.h" -#include "MICmdArgValString.h" -#include "MICmdArgValThreadGrp.h" #include "MICmdArgValOptionLong.h" #include "MICmdArgValOptionShort.h" -#include "MICmdArgValListOfN.h" +#include "MICmdArgValString.h" +#include "MICmdArgValThreadGrp.h" +#include "MICmdCmdBreak.h" +#include "MICmnLLDBDebugSessionInfo.h" +#include "MICmnLLDBDebugger.h" +#include "MICmnMIOutOfBandRecord.h" +#include "MICmnMIResultRecord.h" +#include "MICmnMIValueConst.h" #include "MICmnStreamStdout.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakInsert constructor. // Type: Method. // Args: None. @@ -41,43 +42,35 @@ // Throws: None. //-- CMICmdCmdBreakInsert::CMICmdCmdBreakInsert() - : m_bBrkPtIsTemp(false) - , m_bBrkPtIsPending(false) - , m_nBrkPtIgnoreCount(0) - , m_bBrkPtEnabled(false) - , m_bBrkPtCondition(false) - , m_bBrkPtThreadId(false) - , m_nBrkPtThreadId(0) - , m_constStrArgNamedTempBrkPt("t") - , m_constStrArgNamedHWBrkPt("h") - , m_constStrArgNamedPendinfBrkPt("f") - , m_constStrArgNamedDisableBrkPt("d") - , m_constStrArgNamedTracePt("a") - , m_constStrArgNamedConditionalBrkPt("c") - , m_constStrArgNamedInoreCnt("i") - , m_constStrArgNamedRestrictBrkPtToThreadId("p") - , m_constStrArgNamedLocation("location") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "break-insert"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdBreakInsert::CreateSelf; + : m_bBrkPtIsTemp(false), m_bBrkPtIsPending(false), m_nBrkPtIgnoreCount(0), + m_bBrkPtEnabled(false), m_bBrkPtCondition(false), m_bBrkPtThreadId(false), + m_nBrkPtThreadId(0), m_constStrArgNamedTempBrkPt("t"), + m_constStrArgNamedHWBrkPt("h"), m_constStrArgNamedPendinfBrkPt("f"), + m_constStrArgNamedDisableBrkPt("d"), m_constStrArgNamedTracePt("a"), + m_constStrArgNamedConditionalBrkPt("c"), m_constStrArgNamedInoreCnt("i"), + m_constStrArgNamedRestrictBrkPtToThreadId("p"), + m_constStrArgNamedLocation("location") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "break-insert"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdBreakInsert::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakInsert destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdBreakInsert::~CMICmdCmdBreakInsert() -{ -} +CMICmdCmdBreakInsert::~CMICmdCmdBreakInsert() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -85,234 +78,241 @@ CMICmdCmdBreakInsert::~CMICmdCmdBreakInsert() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdBreakInsert::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedTempBrkPt, false, true)); - // Not implemented m_setCmdArgs.Add(new CMICmdArgValOptionShort( m_constStrArgNamedHWBrkPt, false, false)); - m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedPendinfBrkPt, false, true, - CMICmdArgValListBase::eArgValType_StringQuotedNumberPath, 1)); - m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedDisableBrkPt, false, false)); - // Not implemented m_setCmdArgs.Add(new CMICmdArgValOptionShort( m_constStrArgNamedTracePt, false, false)); - m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedConditionalBrkPt, false, true, - CMICmdArgValListBase::eArgValType_StringQuoted, 1)); - m_setCmdArgs.Add( - new CMICmdArgValOptionShort(m_constStrArgNamedInoreCnt, false, true, CMICmdArgValListBase::eArgValType_Number, 1)); - m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedRestrictBrkPtToThreadId, false, true, - CMICmdArgValListBase::eArgValType_Number, 1)); - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedLocation, false, true, false, false, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdBreakInsert::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValOptionShort(m_constStrArgNamedTempBrkPt, false, true)); + // Not implemented m_setCmdArgs.Add(new CMICmdArgValOptionShort( + // m_constStrArgNamedHWBrkPt, false, false)); + m_setCmdArgs.Add(new CMICmdArgValOptionShort( + m_constStrArgNamedPendinfBrkPt, false, true, + CMICmdArgValListBase::eArgValType_StringQuotedNumberPath, 1)); + m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedDisableBrkPt, + false, false)); + // Not implemented m_setCmdArgs.Add(new CMICmdArgValOptionShort( + // m_constStrArgNamedTracePt, false, false)); + m_setCmdArgs.Add(new CMICmdArgValOptionShort( + m_constStrArgNamedConditionalBrkPt, false, true, + CMICmdArgValListBase::eArgValType_StringQuoted, 1)); + m_setCmdArgs.Add( + new CMICmdArgValOptionShort(m_constStrArgNamedInoreCnt, false, true, + CMICmdArgValListBase::eArgValType_Number, 1)); + m_setCmdArgs.Add(new CMICmdArgValOptionShort( + m_constStrArgNamedRestrictBrkPtToThreadId, false, true, + CMICmdArgValListBase::eArgValType_Number, 1)); + m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedLocation, false, + true, false, false, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Helper function for CMICmdCmdBreakInsert::Execute(). // // Given a string, return the position of the ':' separator in 'file:func' // or 'file:line', if any. If not found, return npos. For example, return // 5 for 'foo.c:std::string'. //-- -static size_t findFileSeparatorPos(const std::string& x) -{ - // Full paths in windows can have ':' after a drive letter, so we - // search backwards, taking care to skip C++ namespace tokens '::'. - size_t n = x.rfind(':'); - while (n != std::string::npos && n > 1 && x[n-1] == ':') - { - n = x.rfind(':', n - 2); - } - return n; +static size_t findFileSeparatorPos(const std::string &x) { + // Full paths in windows can have ':' after a drive letter, so we + // search backwards, taking care to skip C++ namespace tokens '::'. + size_t n = x.rfind(':'); + while (n != std::string::npos && n > 1 && x[n - 1] == ':') { + n = x.rfind(':', n - 2); + } + return n; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdBreakInsert::Execute() -{ - CMICMDBASE_GETOPTION(pArgTempBrkPt, OptionShort, m_constStrArgNamedTempBrkPt); - CMICMDBASE_GETOPTION(pArgThreadGroup, OptionLong, m_constStrArgThreadGroup); - CMICMDBASE_GETOPTION(pArgLocation, String, m_constStrArgNamedLocation); - CMICMDBASE_GETOPTION(pArgIgnoreCnt, OptionShort, m_constStrArgNamedInoreCnt); - CMICMDBASE_GETOPTION(pArgPendingBrkPt, OptionShort, m_constStrArgNamedPendinfBrkPt); - CMICMDBASE_GETOPTION(pArgDisableBrkPt, OptionShort, m_constStrArgNamedDisableBrkPt); - CMICMDBASE_GETOPTION(pArgConditionalBrkPt, OptionShort, m_constStrArgNamedConditionalBrkPt); - CMICMDBASE_GETOPTION(pArgRestrictBrkPtToThreadId, OptionShort, m_constStrArgNamedRestrictBrkPtToThreadId); - - m_bBrkPtEnabled = !pArgDisableBrkPt->GetFound(); - m_bBrkPtIsTemp = pArgTempBrkPt->GetFound(); - m_bHaveArgOptionThreadGrp = pArgThreadGroup->GetFound(); - if (m_bHaveArgOptionThreadGrp) - { - MIuint nThreadGrp = 0; - pArgThreadGroup->GetExpectedOption<CMICmdArgValThreadGrp, MIuint>(nThreadGrp); - m_strArgOptionThreadGrp = CMIUtilString::Format("i%d", nThreadGrp); - } - m_bBrkPtIsPending = pArgPendingBrkPt->GetFound(); - if (pArgLocation->GetFound()) - m_brkName = pArgLocation->GetValue(); - else if (m_bBrkPtIsPending) - { - pArgPendingBrkPt->GetExpectedOption<CMICmdArgValString, CMIUtilString>(m_brkName); - } - if (pArgIgnoreCnt->GetFound()) - { - pArgIgnoreCnt->GetExpectedOption<CMICmdArgValNumber, MIuint>(m_nBrkPtIgnoreCount); +bool CMICmdCmdBreakInsert::Execute() { + CMICMDBASE_GETOPTION(pArgTempBrkPt, OptionShort, m_constStrArgNamedTempBrkPt); + CMICMDBASE_GETOPTION(pArgThreadGroup, OptionLong, m_constStrArgThreadGroup); + CMICMDBASE_GETOPTION(pArgLocation, String, m_constStrArgNamedLocation); + CMICMDBASE_GETOPTION(pArgIgnoreCnt, OptionShort, m_constStrArgNamedInoreCnt); + CMICMDBASE_GETOPTION(pArgPendingBrkPt, OptionShort, + m_constStrArgNamedPendinfBrkPt); + CMICMDBASE_GETOPTION(pArgDisableBrkPt, OptionShort, + m_constStrArgNamedDisableBrkPt); + CMICMDBASE_GETOPTION(pArgConditionalBrkPt, OptionShort, + m_constStrArgNamedConditionalBrkPt); + CMICMDBASE_GETOPTION(pArgRestrictBrkPtToThreadId, OptionShort, + m_constStrArgNamedRestrictBrkPtToThreadId); + + m_bBrkPtEnabled = !pArgDisableBrkPt->GetFound(); + m_bBrkPtIsTemp = pArgTempBrkPt->GetFound(); + m_bHaveArgOptionThreadGrp = pArgThreadGroup->GetFound(); + if (m_bHaveArgOptionThreadGrp) { + MIuint nThreadGrp = 0; + pArgThreadGroup->GetExpectedOption<CMICmdArgValThreadGrp, MIuint>( + nThreadGrp); + m_strArgOptionThreadGrp = CMIUtilString::Format("i%d", nThreadGrp); + } + m_bBrkPtIsPending = pArgPendingBrkPt->GetFound(); + if (pArgLocation->GetFound()) + m_brkName = pArgLocation->GetValue(); + else if (m_bBrkPtIsPending) { + pArgPendingBrkPt->GetExpectedOption<CMICmdArgValString, CMIUtilString>( + m_brkName); + } + if (pArgIgnoreCnt->GetFound()) { + pArgIgnoreCnt->GetExpectedOption<CMICmdArgValNumber, MIuint>( + m_nBrkPtIgnoreCount); + } + m_bBrkPtCondition = pArgConditionalBrkPt->GetFound(); + if (m_bBrkPtCondition) { + pArgConditionalBrkPt->GetExpectedOption<CMICmdArgValString, CMIUtilString>( + m_brkPtCondition); + } + m_bBrkPtThreadId = pArgRestrictBrkPtToThreadId->GetFound(); + if (m_bBrkPtCondition) { + pArgRestrictBrkPtToThreadId->GetExpectedOption<CMICmdArgValNumber, MIuint>( + m_nBrkPtThreadId); + } + + // Determine if break on a file line or at a function + BreakPoint_e eBrkPtType = eBreakPoint_NotDefineYet; + CMIUtilString fileName; + MIuint nFileLine = 0; + CMIUtilString strFileFn; + CMIUtilString rStrLineOrFn; + // Is the string in the form 'file:func' or 'file:line'? + // If so, find the position of the ':' separator. + const size_t nPosColon = findFileSeparatorPos(m_brkName); + if (nPosColon != std::string::npos) { + // Extract file name and line number from it + fileName = m_brkName.substr(0, nPosColon); + rStrLineOrFn = + m_brkName.substr(nPosColon + 1, m_brkName.size() - nPosColon - 1); + + if (rStrLineOrFn.empty()) + eBrkPtType = eBreakPoint_ByName; + else { + MIint64 nValue = 0; + if (rStrLineOrFn.ExtractNumber(nValue)) { + nFileLine = static_cast<MIuint>(nValue); + eBrkPtType = eBreakPoint_ByFileLine; + } else { + strFileFn = rStrLineOrFn; + eBrkPtType = eBreakPoint_ByFileFn; + } } - m_bBrkPtCondition = pArgConditionalBrkPt->GetFound(); - if (m_bBrkPtCondition) - { - pArgConditionalBrkPt->GetExpectedOption<CMICmdArgValString, CMIUtilString>(m_brkPtCondition); + } + + // Determine if break defined as an address + lldb::addr_t nAddress = 0; + if (eBrkPtType == eBreakPoint_NotDefineYet) { + MIint64 nValue = 0; + if (m_brkName.ExtractNumber(nValue)) { + nAddress = static_cast<lldb::addr_t>(nValue); + eBrkPtType = eBreakPoint_ByAddress; } - m_bBrkPtThreadId = pArgRestrictBrkPtToThreadId->GetFound(); - if (m_bBrkPtCondition) - { - pArgRestrictBrkPtToThreadId->GetExpectedOption<CMICmdArgValNumber, MIuint>(m_nBrkPtThreadId); + } + + // Break defined as an function + if (eBrkPtType == eBreakPoint_NotDefineYet) { + eBrkPtType = eBreakPoint_ByName; + } + + // Ask LLDB to create a breakpoint + bool bOk = MIstatus::success; + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBTarget sbTarget = rSessionInfo.GetTarget(); + switch (eBrkPtType) { + case eBreakPoint_ByAddress: + m_brkPt = sbTarget.BreakpointCreateByAddress(nAddress); + break; + case eBreakPoint_ByFileFn: { + lldb::SBFileSpecList module; // search in all modules + lldb::SBFileSpecList compUnit; + compUnit.Append(lldb::SBFileSpec(fileName.c_str())); + m_brkPt = + sbTarget.BreakpointCreateByName(strFileFn.c_str(), module, compUnit); + break; + } + case eBreakPoint_ByFileLine: + m_brkPt = sbTarget.BreakpointCreateByLocation(fileName.c_str(), nFileLine); + break; + case eBreakPoint_ByName: + m_brkPt = sbTarget.BreakpointCreateByName(m_brkName.c_str(), nullptr); + break; + case eBreakPoint_count: + case eBreakPoint_NotDefineYet: + case eBreakPoint_Invalid: + bOk = MIstatus::failure; + break; + } + + if (bOk) { + if (!m_bBrkPtIsPending && (m_brkPt.GetNumLocations() == 0)) { + sbTarget.BreakpointDelete(m_brkPt.GetID()); + SetError( + CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_LOCATION_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), m_brkName.c_str())); + return MIstatus::failure; } - // Determine if break on a file line or at a function - BreakPoint_e eBrkPtType = eBreakPoint_NotDefineYet; - CMIUtilString fileName; - MIuint nFileLine = 0; - CMIUtilString strFileFn; - CMIUtilString rStrLineOrFn; - // Is the string in the form 'file:func' or 'file:line'? - // If so, find the position of the ':' separator. - const size_t nPosColon = findFileSeparatorPos(m_brkName); - if (nPosColon != std::string::npos) - { - // Extract file name and line number from it - fileName = m_brkName.substr(0, nPosColon); - rStrLineOrFn = m_brkName.substr(nPosColon + 1, m_brkName.size() - nPosColon - 1); - - if (rStrLineOrFn.empty()) - eBrkPtType = eBreakPoint_ByName; - else - { - MIint64 nValue = 0; - if (rStrLineOrFn.ExtractNumber(nValue)) - { - nFileLine = static_cast<MIuint>(nValue); - eBrkPtType = eBreakPoint_ByFileLine; - } - else - { - strFileFn = rStrLineOrFn; - eBrkPtType = eBreakPoint_ByFileFn; - } - } - } - - // Determine if break defined as an address - lldb::addr_t nAddress = 0; - if (eBrkPtType == eBreakPoint_NotDefineYet) - { - MIint64 nValue = 0; - if (m_brkName.ExtractNumber(nValue)) - { - nAddress = static_cast<lldb::addr_t>(nValue); - eBrkPtType = eBreakPoint_ByAddress; - } - } - - // Break defined as an function - if (eBrkPtType == eBreakPoint_NotDefineYet) - { - eBrkPtType = eBreakPoint_ByName; - } - - // Ask LLDB to create a breakpoint - bool bOk = MIstatus::success; - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBTarget sbTarget = rSessionInfo.GetTarget(); - switch (eBrkPtType) - { - case eBreakPoint_ByAddress: - m_brkPt = sbTarget.BreakpointCreateByAddress(nAddress); - break; - case eBreakPoint_ByFileFn: - { - lldb::SBFileSpecList module; // search in all modules - lldb::SBFileSpecList compUnit; - compUnit.Append (lldb::SBFileSpec(fileName.c_str())); - m_brkPt = sbTarget.BreakpointCreateByName(strFileFn.c_str(), module, compUnit); - break; - } - case eBreakPoint_ByFileLine: - m_brkPt = sbTarget.BreakpointCreateByLocation(fileName.c_str(), nFileLine); - break; - case eBreakPoint_ByName: - m_brkPt = sbTarget.BreakpointCreateByName(m_brkName.c_str(), nullptr); - break; - case eBreakPoint_count: - case eBreakPoint_NotDefineYet: - case eBreakPoint_Invalid: - bOk = MIstatus::failure; - break; - } - - if (bOk) - { - if (!m_bBrkPtIsPending && (m_brkPt.GetNumLocations() == 0)) - { - sbTarget.BreakpointDelete(m_brkPt.GetID()); - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_LOCATION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_brkName.c_str())); - return MIstatus::failure; - } - - m_brkPt.SetEnabled(m_bBrkPtEnabled); - m_brkPt.SetIgnoreCount(m_nBrkPtIgnoreCount); - if (m_bBrkPtCondition) - m_brkPt.SetCondition(m_brkPtCondition.c_str()); - if (m_bBrkPtThreadId) - m_brkPt.SetThreadID(m_nBrkPtThreadId); - } - - // CODETAG_LLDB_BREAKPOINT_CREATION - // This is in the main thread - // Record break point information to be by LLDB event handler function - CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; - if (!rSessionInfo.GetBrkPtInfo(m_brkPt, sBrkPtInfo)) - return MIstatus::failure; - sBrkPtInfo.m_id = m_brkPt.GetID(); - sBrkPtInfo.m_bDisp = m_bBrkPtIsTemp; - sBrkPtInfo.m_bEnabled = m_bBrkPtEnabled; - sBrkPtInfo.m_bHaveArgOptionThreadGrp = m_bHaveArgOptionThreadGrp; - sBrkPtInfo.m_strOptThrdGrp = m_strArgOptionThreadGrp; - sBrkPtInfo.m_nTimes = m_brkPt.GetHitCount(); - sBrkPtInfo.m_strOrigLoc = m_brkName; - sBrkPtInfo.m_nIgnore = m_nBrkPtIgnoreCount; - sBrkPtInfo.m_bPending = m_bBrkPtIsPending; - sBrkPtInfo.m_bCondition = m_bBrkPtCondition; - sBrkPtInfo.m_strCondition = m_brkPtCondition; - sBrkPtInfo.m_bBrkPtThreadId = m_bBrkPtThreadId; - sBrkPtInfo.m_nBrkPtThreadId = m_nBrkPtThreadId; - - bOk = bOk && rSessionInfo.RecordBrkPtInfo(m_brkPt.GetID(), sBrkPtInfo); - if (!bOk) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), m_brkName.c_str())); - return MIstatus::failure; - } - - // CODETAG_LLDB_BRKPT_ID_MAX - if (m_brkPt.GetID() > (lldb::break_id_t)rSessionInfo.m_nBrkPointCntMax) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_CNT_EXCEEDED), m_cmdData.strMiCmd.c_str(), rSessionInfo.m_nBrkPointCntMax, - m_brkName.c_str())); - return MIstatus::failure; - } - - return MIstatus::success; + m_brkPt.SetEnabled(m_bBrkPtEnabled); + m_brkPt.SetIgnoreCount(m_nBrkPtIgnoreCount); + if (m_bBrkPtCondition) + m_brkPt.SetCondition(m_brkPtCondition.c_str()); + if (m_bBrkPtThreadId) + m_brkPt.SetThreadID(m_nBrkPtThreadId); + } + + // CODETAG_LLDB_BREAKPOINT_CREATION + // This is in the main thread + // Record break point information to be by LLDB event handler function + CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; + if (!rSessionInfo.GetBrkPtInfo(m_brkPt, sBrkPtInfo)) + return MIstatus::failure; + sBrkPtInfo.m_id = m_brkPt.GetID(); + sBrkPtInfo.m_bDisp = m_bBrkPtIsTemp; + sBrkPtInfo.m_bEnabled = m_bBrkPtEnabled; + sBrkPtInfo.m_bHaveArgOptionThreadGrp = m_bHaveArgOptionThreadGrp; + sBrkPtInfo.m_strOptThrdGrp = m_strArgOptionThreadGrp; + sBrkPtInfo.m_nTimes = m_brkPt.GetHitCount(); + sBrkPtInfo.m_strOrigLoc = m_brkName; + sBrkPtInfo.m_nIgnore = m_nBrkPtIgnoreCount; + sBrkPtInfo.m_bPending = m_bBrkPtIsPending; + sBrkPtInfo.m_bCondition = m_bBrkPtCondition; + sBrkPtInfo.m_strCondition = m_brkPtCondition; + sBrkPtInfo.m_bBrkPtThreadId = m_bBrkPtThreadId; + sBrkPtInfo.m_nBrkPtThreadId = m_nBrkPtThreadId; + + bOk = bOk && rSessionInfo.RecordBrkPtInfo(m_brkPt.GetID(), sBrkPtInfo); + if (!bOk) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), + m_cmdData.strMiCmd.c_str(), + m_brkName.c_str())); + return MIstatus::failure; + } + + // CODETAG_LLDB_BRKPT_ID_MAX + if (m_brkPt.GetID() > (lldb::break_id_t)rSessionInfo.m_nBrkPointCntMax) { + SetError(CMIUtilString::Format( + MIRSRC(IDS_CMD_ERR_BRKPT_CNT_EXCEEDED), m_cmdData.strMiCmd.c_str(), + rSessionInfo.m_nBrkPointCntMax, m_brkName.c_str())); + return MIstatus::failure; + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -320,47 +320,51 @@ CMICmdCmdBreakInsert::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdBreakInsert::Acknowledge() -{ - // Get breakpoint information - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; - if (!rSessionInfo.RecordBrkPtInfoGet(m_brkPt.GetID(), sBrkPtInfo)) - return MIstatus::failure; - - // MI print - // "^done,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" PRIx64 "\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",thread-groups=[\"%s\"],times=\"%d\",original-location=\"%s\"}" - CMICmnMIValueTuple miValueTuple; - if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple)) - return MIstatus::failure; - - const CMICmnMIValueResult miValueResultD("bkpt", miValueTuple); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResultD); - m_miResultRecord = miRecordResult; - - return MIstatus::success; +bool CMICmdCmdBreakInsert::Acknowledge() { + // Get breakpoint information + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; + if (!rSessionInfo.RecordBrkPtInfoGet(m_brkPt.GetID(), sBrkPtInfo)) + return MIstatus::failure; + + // MI print + // "^done,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" + // PRIx64 + // "\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",thread-groups=[\"%s\"],times=\"%d\",original-location=\"%s\"}" + CMICmnMIValueTuple miValueTuple; + if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple)) + return MIstatus::failure; + + const CMICmnMIValueResult miValueResultD("bkpt", miValueTuple); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResultD); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdBreakInsert::CreateSelf() -{ - return new CMICmdCmdBreakInsert(); +CMICmdBase *CMICmdCmdBreakInsert::CreateSelf() { + return new CMICmdCmdBreakInsert(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakDelete constructor. // Type: Method. // Args: None. @@ -368,28 +372,28 @@ CMICmdCmdBreakInsert::CreateSelf() // Throws: None. //-- CMICmdCmdBreakDelete::CMICmdCmdBreakDelete() - : m_constStrArgNamedBrkPt("breakpoint") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "break-delete"; + : m_constStrArgNamedBrkPt("breakpoint") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "break-delete"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdBreakDelete::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdBreakDelete::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakDelete destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdBreakDelete::~CMICmdCmdBreakDelete() -{ -} +CMICmdCmdBreakDelete::~CMICmdCmdBreakDelete() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -397,49 +401,56 @@ CMICmdCmdBreakDelete::~CMICmdCmdBreakDelete() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdBreakDelete::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number)); - return ParseValidateCmdOptions(); +bool CMICmdCmdBreakDelete::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, + CMICmdArgValListBase::eArgValType_Number)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdBreakDelete::Execute() -{ - CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt); - - // ATM we only handle one break point ID - MIuint64 nBrk = UINT64_MAX; - if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgNamedBrkPt.c_str())); - return MIstatus::failure; - } - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - const bool bBrkPt = rSessionInfo.GetTarget().BreakpointDelete(static_cast<lldb::break_id_t>(nBrk)); - if (!bBrkPt) - { - const CMIUtilString strBrkNum(CMIUtilString::Format("%d", nBrk)); - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), strBrkNum.c_str())); - return MIstatus::failure; - } - - return MIstatus::success; +bool CMICmdCmdBreakDelete::Execute() { + CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt); + + // ATM we only handle one break point ID + MIuint64 nBrk = UINT64_MAX; + if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), + m_cmdData.strMiCmd.c_str(), + m_constStrArgNamedBrkPt.c_str())); + return MIstatus::failure; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + const bool bBrkPt = rSessionInfo.GetTarget().BreakpointDelete( + static_cast<lldb::break_id_t>(nBrk)); + if (!bBrkPt) { + const CMIUtilString strBrkNum(CMIUtilString::Format("%d", nBrk)); + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), + m_cmdData.strMiCmd.c_str(), + strBrkNum.c_str())); + return MIstatus::failure; + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -447,34 +458,34 @@ CMICmdCmdBreakDelete::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdBreakDelete::Acknowledge() -{ - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); - m_miResultRecord = miRecordResult; +bool CMICmdCmdBreakDelete::Acknowledge() { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdBreakDelete::CreateSelf() -{ - return new CMICmdCmdBreakDelete(); +CMICmdBase *CMICmdCmdBreakDelete::CreateSelf() { + return new CMICmdCmdBreakDelete(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakDisable constructor. // Type: Method. // Args: None. @@ -482,30 +493,29 @@ CMICmdCmdBreakDelete::CreateSelf() // Throws: None. //-- CMICmdCmdBreakDisable::CMICmdCmdBreakDisable() - : m_constStrArgNamedBrkPt("breakpoint") - , m_bBrkPtDisabledOk(false) - , m_nBrkPtId(0) -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "break-disable"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdBreakDisable::CreateSelf; + : m_constStrArgNamedBrkPt("breakpoint"), m_bBrkPtDisabledOk(false), + m_nBrkPtId(0) { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "break-disable"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdBreakDisable::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakDisable destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdBreakDisable::~CMICmdCmdBreakDisable() -{ -} +CMICmdCmdBreakDisable::~CMICmdCmdBreakDisable() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -513,49 +523,54 @@ CMICmdCmdBreakDisable::~CMICmdCmdBreakDisable() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdBreakDisable::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number)); - return ParseValidateCmdOptions(); +bool CMICmdCmdBreakDisable::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, + CMICmdArgValListBase::eArgValType_Number)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdBreakDisable::Execute() -{ - CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt); - - // ATM we only handle one break point ID - MIuint64 nBrk = UINT64_MAX; - if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgNamedBrkPt.c_str())); - return MIstatus::failure; - } - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(static_cast<lldb::break_id_t>(nBrk)); - if (brkPt.IsValid()) - { - m_bBrkPtDisabledOk = true; - brkPt.SetEnabled(false); - m_nBrkPtId = nBrk; - } - - return MIstatus::success; +bool CMICmdCmdBreakDisable::Execute() { + CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt); + + // ATM we only handle one break point ID + MIuint64 nBrk = UINT64_MAX; + if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), + m_cmdData.strMiCmd.c_str(), + m_constStrArgNamedBrkPt.c_str())); + return MIstatus::failure; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID( + static_cast<lldb::break_id_t>(nBrk)); + if (brkPt.IsValid()) { + m_bBrkPtDisabledOk = true; + brkPt.SetEnabled(false); + m_nBrkPtId = nBrk; + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -563,44 +578,46 @@ CMICmdCmdBreakDisable::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdBreakDisable::Acknowledge() -{ - if (m_bBrkPtDisabledOk) - { - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId)); - const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), strBrkPtId.c_str())); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); +bool CMICmdCmdBreakDisable::Acknowledge() { + if (m_bBrkPtDisabledOk) { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); m_miResultRecord = miRecordResult; - return MIstatus::success; + } + + const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId)); + const CMICmnMIValueConst miValueConst(CMIUtilString::Format( + MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), strBrkPtId.c_str())); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdBreakDisable::CreateSelf() -{ - return new CMICmdCmdBreakDisable(); +CMICmdBase *CMICmdCmdBreakDisable::CreateSelf() { + return new CMICmdCmdBreakDisable(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakEnable constructor. // Type: Method. // Args: None. @@ -608,30 +625,29 @@ CMICmdCmdBreakDisable::CreateSelf() // Throws: None. //-- CMICmdCmdBreakEnable::CMICmdCmdBreakEnable() - : m_constStrArgNamedBrkPt("breakpoint") - , m_bBrkPtEnabledOk(false) - , m_nBrkPtId(0) -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "break-enable"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdBreakEnable::CreateSelf; + : m_constStrArgNamedBrkPt("breakpoint"), m_bBrkPtEnabledOk(false), + m_nBrkPtId(0) { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "break-enable"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdBreakEnable::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakEnable destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdBreakEnable::~CMICmdCmdBreakEnable() -{ -} +CMICmdCmdBreakEnable::~CMICmdCmdBreakEnable() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -639,49 +655,54 @@ CMICmdCmdBreakEnable::~CMICmdCmdBreakEnable() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdBreakEnable::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number)); - return ParseValidateCmdOptions(); +bool CMICmdCmdBreakEnable::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, + CMICmdArgValListBase::eArgValType_Number)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdBreakEnable::Execute() -{ - CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt); - - // ATM we only handle one break point ID - MIuint64 nBrk = UINT64_MAX; - if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgNamedBrkPt.c_str())); - return MIstatus::failure; - } - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(static_cast<lldb::break_id_t>(nBrk)); - if (brkPt.IsValid()) - { - m_bBrkPtEnabledOk = true; - brkPt.SetEnabled(true); - m_nBrkPtId = nBrk; - } - - return MIstatus::success; +bool CMICmdCmdBreakEnable::Execute() { + CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt); + + // ATM we only handle one break point ID + MIuint64 nBrk = UINT64_MAX; + if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), + m_cmdData.strMiCmd.c_str(), + m_constStrArgNamedBrkPt.c_str())); + return MIstatus::failure; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID( + static_cast<lldb::break_id_t>(nBrk)); + if (brkPt.IsValid()) { + m_bBrkPtEnabledOk = true; + brkPt.SetEnabled(true); + m_nBrkPtId = nBrk; + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -689,44 +710,46 @@ CMICmdCmdBreakEnable::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdBreakEnable::Acknowledge() -{ - if (m_bBrkPtEnabledOk) - { - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId)); - const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), strBrkPtId.c_str())); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); +bool CMICmdCmdBreakEnable::Acknowledge() { + if (m_bBrkPtEnabledOk) { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); m_miResultRecord = miRecordResult; - return MIstatus::success; + } + + const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId)); + const CMICmnMIValueConst miValueConst(CMIUtilString::Format( + MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), strBrkPtId.c_str())); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdBreakEnable::CreateSelf() -{ - return new CMICmdCmdBreakEnable(); +CMICmdBase *CMICmdCmdBreakEnable::CreateSelf() { + return new CMICmdCmdBreakEnable(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakAfter constructor. // Type: Method. // Args: None. @@ -734,31 +757,29 @@ CMICmdCmdBreakEnable::CreateSelf() // Throws: None. //-- CMICmdCmdBreakAfter::CMICmdCmdBreakAfter() - : m_constStrArgNamedNumber("number") - , m_constStrArgNamedCount("count") - , m_nBrkPtId(0) - , m_nBrkPtCount(0) -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "break-after"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdBreakAfter::CreateSelf; + : m_constStrArgNamedNumber("number"), m_constStrArgNamedCount("count"), + m_nBrkPtId(0), m_nBrkPtCount(0) { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "break-after"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdBreakAfter::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakAfter destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdBreakAfter::~CMICmdCmdBreakAfter() -{ -} +CMICmdCmdBreakAfter::~CMICmdCmdBreakAfter() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -766,59 +787,63 @@ CMICmdCmdBreakAfter::~CMICmdCmdBreakAfter() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdBreakAfter::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true)); - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNamedCount, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdBreakAfter::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true)); + m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNamedCount, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdBreakAfter::Execute() -{ - CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber); - CMICMDBASE_GETOPTION(pArgCount, Number, m_constStrArgNamedCount); - - m_nBrkPtId = pArgNumber->GetValue(); - m_nBrkPtCount = pArgCount->GetValue(); - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(static_cast<lldb::break_id_t>(m_nBrkPtId)); - if (brkPt.IsValid()) - { - brkPt.SetIgnoreCount(m_nBrkPtCount); - - CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; - if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_nBrkPtId)); - return MIstatus::failure; - } - sBrkPtInfo.m_nIgnore = m_nBrkPtCount; - rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo); - } - else - { - const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId)); - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), strBrkPtId.c_str())); - return MIstatus::failure; +bool CMICmdCmdBreakAfter::Execute() { + CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber); + CMICMDBASE_GETOPTION(pArgCount, Number, m_constStrArgNamedCount); + + m_nBrkPtId = pArgNumber->GetValue(); + m_nBrkPtCount = pArgCount->GetValue(); + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID( + static_cast<lldb::break_id_t>(m_nBrkPtId)); + if (brkPt.IsValid()) { + brkPt.SetIgnoreCount(m_nBrkPtCount); + + CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; + if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) { + SetError( + CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), m_nBrkPtId)); + return MIstatus::failure; } + sBrkPtInfo.m_nIgnore = m_nBrkPtCount; + rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo); + } else { + const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId)); + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), + m_cmdData.strMiCmd.c_str(), + strBrkPtId.c_str())); + return MIstatus::failure; + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -826,34 +851,34 @@ CMICmdCmdBreakAfter::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdBreakAfter::Acknowledge() -{ - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); - m_miResultRecord = miRecordResult; +bool CMICmdCmdBreakAfter::Acknowledge() { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdBreakAfter::CreateSelf() -{ - return new CMICmdCmdBreakAfter(); +CMICmdBase *CMICmdCmdBreakAfter::CreateSelf() { + return new CMICmdCmdBreakAfter(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakCondition constructor. // Type: Method. // Args: None. @@ -861,32 +886,34 @@ CMICmdCmdBreakAfter::CreateSelf() // Throws: None. //-- CMICmdCmdBreakCondition::CMICmdCmdBreakCondition() - : m_constStrArgNamedNumber("number") - , m_constStrArgNamedExpr("expr") - , m_constStrArgNamedExprNoQuotes( - "expression not surround by quotes") // Not specified in MI spec, we need to handle expressions not surrounded by quotes - , m_nBrkPtId(0) -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "break-condition"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdBreakCondition::CreateSelf; + : m_constStrArgNamedNumber("number"), m_constStrArgNamedExpr("expr"), + m_constStrArgNamedExprNoQuotes( + "expression not surround by quotes") // Not specified in MI spec, we + // need to handle expressions not + // surrounded by quotes + , + m_nBrkPtId(0) { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "break-condition"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdBreakCondition::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakCondition destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdBreakCondition::~CMICmdCmdBreakCondition() -{ -} +CMICmdCmdBreakCondition::~CMICmdCmdBreakCondition() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -894,62 +921,68 @@ CMICmdCmdBreakCondition::~CMICmdCmdBreakCondition() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdBreakCondition::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true)); - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedExpr, true, true, true, true)); - m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgNamedExprNoQuotes, false, false, - CMICmdArgValListBase::eArgValType_StringQuotedNumber)); - return ParseValidateCmdOptions(); +bool CMICmdCmdBreakCondition::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true)); + m_setCmdArgs.Add( + new CMICmdArgValString(m_constStrArgNamedExpr, true, true, true, true)); + m_setCmdArgs.Add(new CMICmdArgValListOfN( + m_constStrArgNamedExprNoQuotes, false, false, + CMICmdArgValListBase::eArgValType_StringQuotedNumber)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdBreakCondition::Execute() -{ - CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber); - CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgNamedExpr); - - m_nBrkPtId = pArgNumber->GetValue(); - m_strBrkPtExpr = pArgExpr->GetValue(); - m_strBrkPtExpr += GetRestOfExpressionNotSurroundedInQuotes(); - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID(static_cast<lldb::break_id_t>(m_nBrkPtId)); - if (brkPt.IsValid()) - { - brkPt.SetCondition(m_strBrkPtExpr.c_str()); - - CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; - if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_nBrkPtId)); - return MIstatus::failure; - } - sBrkPtInfo.m_strCondition = m_strBrkPtExpr; - rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo); - } - else - { - const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId)); - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), strBrkPtId.c_str())); - return MIstatus::failure; +bool CMICmdCmdBreakCondition::Execute() { + CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber); + CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgNamedExpr); + + m_nBrkPtId = pArgNumber->GetValue(); + m_strBrkPtExpr = pArgExpr->GetValue(); + m_strBrkPtExpr += GetRestOfExpressionNotSurroundedInQuotes(); + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID( + static_cast<lldb::break_id_t>(m_nBrkPtId)); + if (brkPt.IsValid()) { + brkPt.SetCondition(m_strBrkPtExpr.c_str()); + + CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; + if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) { + SetError( + CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), m_nBrkPtId)); + return MIstatus::failure; } + sBrkPtInfo.m_strCondition = m_strBrkPtExpr; + rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo); + } else { + const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId)); + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), + m_cmdData.strMiCmd.c_str(), + strBrkPtId.c_str())); + return MIstatus::failure; + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -957,39 +990,43 @@ CMICmdCmdBreakCondition::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdBreakCondition::Acknowledge() -{ - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); - m_miResultRecord = miRecordResult; +bool CMICmdCmdBreakCondition::Acknowledge() { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdBreakCondition::CreateSelf() -{ - return new CMICmdCmdBreakCondition(); +CMICmdBase *CMICmdCmdBreakCondition::CreateSelf() { + return new CMICmdCmdBreakCondition(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: A breakpoint expression can be passed to *this command as: // a single string i.e. '2' -> ok. // a quoted string i.e. "a > 100" -> ok // a non quoted string i.e. 'a > 100' -> not ok -// CMICmdArgValString only extracts the first space separated string, the "a". -// This function using the optional argument type CMICmdArgValListOfN collects -// the rest of the expression so that is may be added to the 'a' part to form a +// CMICmdArgValString only extracts the first space separated string, +// the "a". +// This function using the optional argument type CMICmdArgValListOfN +// collects +// the rest of the expression so that is may be added to the 'a' part +// to form a // complete expression string i.e. "a > 100". -// If the expression value was guaranteed to be surrounded by quotes them this +// If the expression value was guaranteed to be surrounded by quotes +// them this // function would not be necessary. // Type: Method. // Args: None. @@ -997,30 +1034,31 @@ CMICmdCmdBreakCondition::CreateSelf() // Throws: None. //-- CMIUtilString -CMICmdCmdBreakCondition::GetRestOfExpressionNotSurroundedInQuotes() -{ - CMIUtilString strExpression; - - CMICmdArgValListOfN *pArgExprNoQuotes = CMICmdBase::GetOption<CMICmdArgValListOfN>(m_constStrArgNamedExprNoQuotes); - if (pArgExprNoQuotes != nullptr) - { - const CMICmdArgValListBase::VecArgObjPtr_t &rVecExprParts(pArgExprNoQuotes->GetExpectedOptions()); - if (!rVecExprParts.empty()) - { - CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecExprParts.begin(); - while (it != rVecExprParts.end()) - { - const CMICmdArgValString *pPartExpr = static_cast<CMICmdArgValString *>(*it); - const CMIUtilString &rPartExpr = pPartExpr->GetValue(); - strExpression += " "; - strExpression += rPartExpr; - - // Next - ++it; - } - strExpression = strExpression.Trim(); - } +CMICmdCmdBreakCondition::GetRestOfExpressionNotSurroundedInQuotes() { + CMIUtilString strExpression; + + CMICmdArgValListOfN *pArgExprNoQuotes = + CMICmdBase::GetOption<CMICmdArgValListOfN>( + m_constStrArgNamedExprNoQuotes); + if (pArgExprNoQuotes != nullptr) { + const CMICmdArgValListBase::VecArgObjPtr_t &rVecExprParts( + pArgExprNoQuotes->GetExpectedOptions()); + if (!rVecExprParts.empty()) { + CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = + rVecExprParts.begin(); + while (it != rVecExprParts.end()) { + const CMICmdArgValString *pPartExpr = + static_cast<CMICmdArgValString *>(*it); + const CMIUtilString &rPartExpr = pPartExpr->GetValue(); + strExpression += " "; + strExpression += rPartExpr; + + // Next + ++it; + } + strExpression = strExpression.Trim(); } + } - return strExpression; + return strExpression; } diff --git a/lldb/tools/lldb-mi/MICmdCmdBreak.h b/lldb/tools/lldb-mi/MICmdCmdBreak.h index b8c4240a8a5..7640e50a2bb 100644 --- a/lldb/tools/lldb-mi/MICmdCmdBreak.h +++ b/lldb/tools/lldb-mi/MICmdCmdBreak.h @@ -14,13 +14,16 @@ // CMICmdCmdBreakAfter interface. // CMICmdCmdBreakCondition interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands derive a new command class from the +// command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// For an introduction to adding a new command see +// CMICmdCmdSupportInfoMiCmdQuery // command class as an example. #pragma once @@ -31,228 +34,230 @@ // In-house headers: #include "MICmdBase.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "break-insert". // This command does not follow the MI documentation exactly. //-- -class CMICmdCmdBreakInsert : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); +class CMICmdCmdBreakInsert : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); - // Methods: - public: - /* ctor */ CMICmdCmdBreakInsert(); + // Methods: +public: + /* ctor */ CMICmdCmdBreakInsert(); - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdBreakInsert() override; + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdBreakInsert() override; - // Enumerations: - private: - //++ =================================================================== - // Details: The type of break point give in the MI command text. - //-- - enum BreakPoint_e - { - eBreakPoint_Invalid = 0, - eBreakPoint_ByFileLine, - eBreakPoint_ByFileFn, - eBreakPoint_ByName, - eBreakPoint_ByAddress, - eBreakPoint_count, - eBreakPoint_NotDefineYet - }; + // Enumerations: +private: + //++ =================================================================== + // Details: The type of break point give in the MI command text. + //-- + enum BreakPoint_e { + eBreakPoint_Invalid = 0, + eBreakPoint_ByFileLine, + eBreakPoint_ByFileFn, + eBreakPoint_ByName, + eBreakPoint_ByAddress, + eBreakPoint_count, + eBreakPoint_NotDefineYet + }; - // Attributes: - private: - bool m_bBrkPtIsTemp; - bool m_bHaveArgOptionThreadGrp; - CMIUtilString m_brkName; - CMIUtilString m_strArgOptionThreadGrp; - lldb::SBBreakpoint m_brkPt; - bool m_bBrkPtIsPending; - MIuint m_nBrkPtIgnoreCount; - bool m_bBrkPtEnabled; - bool m_bBrkPtCondition; - CMIUtilString m_brkPtCondition; - bool m_bBrkPtThreadId; - MIuint m_nBrkPtThreadId; - const CMIUtilString m_constStrArgNamedTempBrkPt; - const CMIUtilString m_constStrArgNamedHWBrkPt; // Not handled by *this command - const CMIUtilString m_constStrArgNamedPendinfBrkPt; - const CMIUtilString m_constStrArgNamedDisableBrkPt; - const CMIUtilString m_constStrArgNamedTracePt; // Not handled by *this command - const CMIUtilString m_constStrArgNamedConditionalBrkPt; - const CMIUtilString m_constStrArgNamedInoreCnt; - const CMIUtilString m_constStrArgNamedRestrictBrkPtToThreadId; - const CMIUtilString m_constStrArgNamedLocation; + // Attributes: +private: + bool m_bBrkPtIsTemp; + bool m_bHaveArgOptionThreadGrp; + CMIUtilString m_brkName; + CMIUtilString m_strArgOptionThreadGrp; + lldb::SBBreakpoint m_brkPt; + bool m_bBrkPtIsPending; + MIuint m_nBrkPtIgnoreCount; + bool m_bBrkPtEnabled; + bool m_bBrkPtCondition; + CMIUtilString m_brkPtCondition; + bool m_bBrkPtThreadId; + MIuint m_nBrkPtThreadId; + const CMIUtilString m_constStrArgNamedTempBrkPt; + const CMIUtilString m_constStrArgNamedHWBrkPt; // Not handled by *this command + const CMIUtilString m_constStrArgNamedPendinfBrkPt; + const CMIUtilString m_constStrArgNamedDisableBrkPt; + const CMIUtilString m_constStrArgNamedTracePt; // Not handled by *this command + const CMIUtilString m_constStrArgNamedConditionalBrkPt; + const CMIUtilString m_constStrArgNamedInoreCnt; + const CMIUtilString m_constStrArgNamedRestrictBrkPtToThreadId; + const CMIUtilString m_constStrArgNamedLocation; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "break-delete". //-- -class CMICmdCmdBreakDelete : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); +class CMICmdCmdBreakDelete : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); - // Methods: - public: - /* ctor */ CMICmdCmdBreakDelete(); + // Methods: +public: + /* ctor */ CMICmdCmdBreakDelete(); - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdBreakDelete() override; + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdBreakDelete() override; - // Attributes: - private: - const CMIUtilString m_constStrArgNamedBrkPt; + // Attributes: +private: + const CMIUtilString m_constStrArgNamedBrkPt; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "break-disable". //-- -class CMICmdCmdBreakDisable : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); +class CMICmdCmdBreakDisable : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); - // Methods: - public: - /* ctor */ CMICmdCmdBreakDisable(); + // Methods: +public: + /* ctor */ CMICmdCmdBreakDisable(); - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdBreakDisable() override; + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdBreakDisable() override; - // Attributes: - private: - const CMIUtilString m_constStrArgNamedBrkPt; - bool m_bBrkPtDisabledOk; - MIuint m_nBrkPtId; + // Attributes: +private: + const CMIUtilString m_constStrArgNamedBrkPt; + bool m_bBrkPtDisabledOk; + MIuint m_nBrkPtId; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "break-enable". //-- -class CMICmdCmdBreakEnable : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); +class CMICmdCmdBreakEnable : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); - // Methods: - public: - /* ctor */ CMICmdCmdBreakEnable(); + // Methods: +public: + /* ctor */ CMICmdCmdBreakEnable(); - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdBreakEnable() override; + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdBreakEnable() override; - // Attributes: - private: - const CMIUtilString m_constStrArgNamedBrkPt; - bool m_bBrkPtEnabledOk; - MIuint m_nBrkPtId; + // Attributes: +private: + const CMIUtilString m_constStrArgNamedBrkPt; + bool m_bBrkPtEnabledOk; + MIuint m_nBrkPtId; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "break-after". //-- -class CMICmdCmdBreakAfter : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); +class CMICmdCmdBreakAfter : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); - // Methods: - public: - /* ctor */ CMICmdCmdBreakAfter(); + // Methods: +public: + /* ctor */ CMICmdCmdBreakAfter(); - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdBreakAfter() override; + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdBreakAfter() override; - // Attributes: - private: - const CMIUtilString m_constStrArgNamedNumber; - const CMIUtilString m_constStrArgNamedCount; - MIuint m_nBrkPtId; - MIuint m_nBrkPtCount; + // Attributes: +private: + const CMIUtilString m_constStrArgNamedNumber; + const CMIUtilString m_constStrArgNamedCount; + MIuint m_nBrkPtId; + MIuint m_nBrkPtCount; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "break-condition". //-- -class CMICmdCmdBreakCondition : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); +class CMICmdCmdBreakCondition : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); - // Methods: - public: - /* ctor */ CMICmdCmdBreakCondition(); + // Methods: +public: + /* ctor */ CMICmdCmdBreakCondition(); - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdBreakCondition() override; + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdBreakCondition() override; - // Methods: - private: - CMIUtilString GetRestOfExpressionNotSurroundedInQuotes(); + // Methods: +private: + CMIUtilString GetRestOfExpressionNotSurroundedInQuotes(); - // Attributes: - private: - const CMIUtilString m_constStrArgNamedNumber; - const CMIUtilString m_constStrArgNamedExpr; - const CMIUtilString m_constStrArgNamedExprNoQuotes; // Not specified in MI spec, we need to handle expressions not surrounded by quotes - MIuint m_nBrkPtId; - CMIUtilString m_strBrkPtExpr; + // Attributes: +private: + const CMIUtilString m_constStrArgNamedNumber; + const CMIUtilString m_constStrArgNamedExpr; + const CMIUtilString m_constStrArgNamedExprNoQuotes; // Not specified in MI + // spec, we need to handle + // expressions not + // surrounded by quotes + MIuint m_nBrkPtId; + CMIUtilString m_strBrkPtExpr; }; diff --git a/lldb/tools/lldb-mi/MICmdCmdData.cpp b/lldb/tools/lldb-mi/MICmdCmdData.cpp index 7f4c2e8fd1f..729ab3970cf 100644 --- a/lldb/tools/lldb-mi/MICmdCmdData.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdData.cpp @@ -19,34 +19,35 @@ // CMICmdCmdDataInfoLine implementation. // Third Party Headers: -#include <inttypes.h> // For PRIx64 #include "lldb/API/SBCommandInterpreter.h" -#include "lldb/API/SBThread.h" #include "lldb/API/SBInstruction.h" #include "lldb/API/SBInstructionList.h" #include "lldb/API/SBStream.h" +#include "lldb/API/SBThread.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Regex.h" +#include <inttypes.h> // For PRIx64 // In-house headers: -#include "MICmdCmdData.h" -#include "MICmnMIResultRecord.h" -#include "MICmnMIValueConst.h" -#include "MICmnLLDBDebugger.h" -#include "MICmnLLDBDebugSessionInfo.h" -#include "MICmnLLDBProxySBValue.h" +#include "MICmdArgValConsume.h" +#include "MICmdArgValListOfN.h" #include "MICmdArgValNumber.h" -#include "MICmdArgValString.h" -#include "MICmdArgValThreadGrp.h" #include "MICmdArgValOptionLong.h" #include "MICmdArgValOptionShort.h" -#include "MICmdArgValListOfN.h" -#include "MICmdArgValConsume.h" +#include "MICmdArgValString.h" +#include "MICmdArgValThreadGrp.h" +#include "MICmdCmdData.h" +#include "MICmnLLDBDebugSessionInfo.h" #include "MICmnLLDBDebugSessionInfoVarObj.h" +#include "MICmnLLDBDebugger.h" +#include "MICmnLLDBProxySBValue.h" #include "MICmnLLDBUtilSBValue.h" +#include "MICmnMIResultRecord.h" +#include "MICmnMIValueConst.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataEvaluateExpression constructor. // Type: Method. // Args: None. @@ -54,33 +55,30 @@ // Throws: None. //-- CMICmdCmdDataEvaluateExpression::CMICmdCmdDataEvaluateExpression() - : m_bExpressionValid(true) - , m_bEvaluatedExpression(true) - , m_strValue("??") - , m_bFoundInvalidChar(false) - , m_cExpressionInvalidChar(0x00) - , m_constStrArgExpr("expr") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "data-evaluate-expression"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdDataEvaluateExpression::CreateSelf; + : m_bExpressionValid(true), m_bEvaluatedExpression(true), m_strValue("??"), + m_bFoundInvalidChar(false), m_cExpressionInvalidChar(0x00), + m_constStrArgExpr("expr") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "data-evaluate-expression"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdDataEvaluateExpression::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataEvaluateExpression destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdDataEvaluateExpression::~CMICmdCmdDataEvaluateExpression() -{ -} +CMICmdCmdDataEvaluateExpression::~CMICmdCmdDataEvaluateExpression() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -88,68 +86,68 @@ CMICmdCmdDataEvaluateExpression::~CMICmdCmdDataEvaluateExpression() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataEvaluateExpression::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgExpr, true, true, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdDataEvaluateExpression::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValString(m_constStrArgExpr, true, true, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataEvaluateExpression::Execute() -{ - CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgExpr); - - const CMIUtilString &rExpression(pArgExpr->GetValue()); - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); - lldb::SBThread thread = sbProcess.GetSelectedThread(); - m_bExpressionValid = (thread.GetNumFrames() > 0); - if (!m_bExpressionValid) - return MIstatus::success; +bool CMICmdCmdDataEvaluateExpression::Execute() { + CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgExpr); + + const CMIUtilString &rExpression(pArgExpr->GetValue()); + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + lldb::SBThread thread = sbProcess.GetSelectedThread(); + m_bExpressionValid = (thread.GetNumFrames() > 0); + if (!m_bExpressionValid) + return MIstatus::success; - lldb::SBFrame frame = thread.GetSelectedFrame(); - lldb::SBValue value = frame.EvaluateExpression(rExpression.c_str()); - m_Error = value.GetError(); - if (!value.IsValid() || m_Error.Fail()) - value = frame.FindVariable(rExpression.c_str()); - const CMICmnLLDBUtilSBValue utilValue(value, true); - if (!utilValue.IsValid() || utilValue.IsValueUnknown()) - { - m_bEvaluatedExpression = false; - return MIstatus::success; + lldb::SBFrame frame = thread.GetSelectedFrame(); + lldb::SBValue value = frame.EvaluateExpression(rExpression.c_str()); + m_Error = value.GetError(); + if (!value.IsValid() || m_Error.Fail()) + value = frame.FindVariable(rExpression.c_str()); + const CMICmnLLDBUtilSBValue utilValue(value, true); + if (!utilValue.IsValid() || utilValue.IsValueUnknown()) { + m_bEvaluatedExpression = false; + return MIstatus::success; + } + if (!utilValue.HasName()) { + if (HaveInvalidCharacterInExpression(rExpression, + m_cExpressionInvalidChar)) { + m_bFoundInvalidChar = true; + return MIstatus::success; } - if (!utilValue.HasName()) - { - if (HaveInvalidCharacterInExpression(rExpression, m_cExpressionInvalidChar)) - { - m_bFoundInvalidChar = true; - return MIstatus::success; - } - m_strValue = rExpression; - return MIstatus::success; - } - if (rExpression.IsQuoted()) - { - m_strValue = rExpression.Trim('\"'); - return MIstatus::success; - } - m_strValue = utilValue.GetValue(true).Escape().AddSlashes(); + m_strValue = rExpression; return MIstatus::success; + } + if (rExpression.IsQuoted()) { + m_strValue = rExpression.Trim('\"'); + return MIstatus::success; + } + m_strValue = utilValue.GetValue(true).Escape().AddSlashes(); + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -157,84 +155,93 @@ CMICmdCmdDataEvaluateExpression::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataEvaluateExpression::Acknowledge() -{ - if (m_bExpressionValid) - { - if (m_bEvaluatedExpression) - { - if (m_bFoundInvalidChar) - { - const CMICmnMIValueConst miValueConst( - CMIUtilString::Format("Invalid character '%c' in expression", m_cExpressionInvalidChar)); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - const CMICmnMIValueConst miValueConst(m_strValue); - const CMICmnMIValueResult miValueResult("value", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - CMIUtilString mi_error_msg = "Could not evaluate expression"; - if (const char* err_msg = m_Error.GetCString()) - mi_error_msg = err_msg; - const CMICmnMIValueConst miValueConst(mi_error_msg.Escape(true)); +bool CMICmdCmdDataEvaluateExpression::Acknowledge() { + if (m_bExpressionValid) { + if (m_bEvaluatedExpression) { + if (m_bFoundInvalidChar) { + const CMICmnMIValueConst miValueConst(CMIUtilString::Format( + "Invalid character '%c' in expression", m_cExpressionInvalidChar)); const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); m_miResultRecord = miRecordResult; return MIstatus::success; + } + + const CMICmnMIValueConst miValueConst(m_strValue); + const CMICmnMIValueResult miValueResult("value", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; } - - const CMICmnMIValueConst miValueConst("Invalid expression"); + CMIUtilString mi_error_msg = "Could not evaluate expression"; + if (const char *err_msg = m_Error.GetCString()) + mi_error_msg = err_msg; + const CMICmnMIValueConst miValueConst(mi_error_msg.Escape(true)); const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); m_miResultRecord = miRecordResult; - return MIstatus::success; + } + + const CMICmnMIValueConst miValueConst("Invalid expression"); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdDataEvaluateExpression::CreateSelf() -{ - return new CMICmdCmdDataEvaluateExpression(); +CMICmdBase *CMICmdCmdDataEvaluateExpression::CreateSelf() { + return new CMICmdCmdDataEvaluateExpression(); } -//++ ------------------------------------------------------------------------------------ -// Details: Examine the expression string to see if it contains invalid characters. +//++ +//------------------------------------------------------------------------------------ +// Details: Examine the expression string to see if it contains invalid +// characters. // Type: Method. // Args: vrExpr - (R) Expression string given to *this command. -// vrwInvalidChar - (W) True = Invalid character found, false = nothing found. +// vrwInvalidChar - (W) True = Invalid character found, false = +// nothing found. // Return: bool - True = Invalid character found, false = nothing found. // Throws: None. //-- -bool -CMICmdCmdDataEvaluateExpression::HaveInvalidCharacterInExpression(const CMIUtilString &vrExpr, char &vrwInvalidChar) -{ - static const std::string strInvalidCharacters(";#\\"); - const size_t nInvalidCharacterOffset = vrExpr.find_first_of(strInvalidCharacters); - const bool bFoundInvalidCharInExpression = (nInvalidCharacterOffset != CMIUtilString::npos); - vrwInvalidChar = bFoundInvalidCharInExpression ? vrExpr[nInvalidCharacterOffset] : 0x00; - return bFoundInvalidCharInExpression; +bool CMICmdCmdDataEvaluateExpression::HaveInvalidCharacterInExpression( + const CMIUtilString &vrExpr, char &vrwInvalidChar) { + static const std::string strInvalidCharacters(";#\\"); + const size_t nInvalidCharacterOffset = + vrExpr.find_first_of(strInvalidCharacters); + const bool bFoundInvalidCharInExpression = + (nInvalidCharacterOffset != CMIUtilString::npos); + vrwInvalidChar = + bFoundInvalidCharInExpression ? vrExpr[nInvalidCharacterOffset] : 0x00; + return bFoundInvalidCharInExpression; } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataDisassemble constructor. // Type: Method. // Args: None. @@ -242,31 +249,29 @@ CMICmdCmdDataEvaluateExpression::HaveInvalidCharacterInExpression(const CMIUtilS // Throws: None. //-- CMICmdCmdDataDisassemble::CMICmdCmdDataDisassemble() - : m_constStrArgAddrStart("s") - , m_constStrArgAddrEnd("e") - , m_constStrArgMode("mode") - , m_miValueList(true) -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "data-disassemble"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdDataDisassemble::CreateSelf; + : m_constStrArgAddrStart("s"), m_constStrArgAddrEnd("e"), + m_constStrArgMode("mode"), m_miValueList(true) { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "data-disassemble"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdDataDisassemble::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataDisassemble destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdDataDisassemble::~CMICmdCmdDataDisassemble() -{ -} +CMICmdCmdDataDisassemble::~CMICmdCmdDataDisassemble() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -274,149 +279,164 @@ CMICmdCmdDataDisassemble::~CMICmdCmdDataDisassemble() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataDisassemble::ParseArgs() -{ - m_setCmdArgs.Add( - new CMICmdArgValOptionShort(m_constStrArgAddrStart, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1)); - m_setCmdArgs.Add( - new CMICmdArgValOptionShort(m_constStrArgAddrEnd, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1)); - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgMode, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdDataDisassemble::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValOptionShort( + m_constStrArgAddrStart, true, true, + CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1)); + m_setCmdArgs.Add(new CMICmdArgValOptionShort( + m_constStrArgAddrEnd, true, true, + CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1)); + m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgMode, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataDisassemble::Execute() -{ - CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); - CMICMDBASE_GETOPTION(pArgAddrStart, OptionShort, m_constStrArgAddrStart); - CMICMDBASE_GETOPTION(pArgAddrEnd, OptionShort, m_constStrArgAddrEnd); - CMICMDBASE_GETOPTION(pArgMode, Number, m_constStrArgMode); - - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); - return MIstatus::failure; - } - CMIUtilString strAddrStart; - if (!pArgAddrStart->GetExpectedOption<CMICmdArgValString, CMIUtilString>(strAddrStart)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID), m_cmdData.strMiCmd.c_str(), - m_constStrArgAddrStart.c_str())); - return MIstatus::failure; - } - MIint64 nAddrStart = 0; - if (!strAddrStart.ExtractNumber(nAddrStart)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID), m_cmdData.strMiCmd.c_str(), - m_constStrArgAddrStart.c_str())); - return MIstatus::failure; - } - - CMIUtilString strAddrEnd; - if (!pArgAddrEnd->GetExpectedOption<CMICmdArgValString, CMIUtilString>(strAddrEnd)) - { - SetError( - CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrEnd.c_str())); - return MIstatus::failure; - } - MIint64 nAddrEnd = 0; - if (!strAddrEnd.ExtractNumber(nAddrEnd)) - { - SetError( - CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrEnd.c_str())); - return MIstatus::failure; - } - const MIuint nDisasmMode = pArgMode->GetValue(); - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBTarget sbTarget = rSessionInfo.GetTarget(); - lldb::addr_t lldbStartAddr = static_cast<lldb::addr_t>(nAddrStart); - lldb::SBInstructionList instructions = sbTarget.ReadInstructions(lldb::SBAddress(lldbStartAddr, sbTarget), nAddrEnd - nAddrStart); - const MIuint nInstructions = instructions.GetSize(); - // Calculate the offset of first instruction so that we can generate offset starting at 0 - lldb::addr_t start_offset = 0; - if(nInstructions > 0) - start_offset = instructions.GetInstructionAtIndex(0).GetAddress().GetOffset(); - - for (size_t i = 0; i < nInstructions; i++) - { - const char *pUnknown = "??"; - lldb::SBInstruction instrt = instructions.GetInstructionAtIndex(i); - const char *pStrMnemonic = instrt.GetMnemonic(sbTarget); - pStrMnemonic = (pStrMnemonic != nullptr) ? pStrMnemonic : pUnknown; - const char *pStrComment = instrt.GetComment(sbTarget); - CMIUtilString strComment; - if (pStrComment != nullptr && *pStrComment != '\0') - strComment = CMIUtilString::Format("; %s", pStrComment); - lldb::SBAddress address = instrt.GetAddress(); - lldb::addr_t addr = address.GetLoadAddress(sbTarget); - const char *pFnName = address.GetFunction().GetName(); - pFnName = (pFnName != nullptr) ? pFnName : pUnknown; - lldb::addr_t addrOffSet = address.GetOffset() - start_offset; - const char *pStrOperands = instrt.GetOperands(sbTarget); - pStrOperands = (pStrOperands != nullptr) ? pStrOperands : pUnknown; - const size_t instrtSize = instrt.GetByteSize(); - - // MI "{address=\"0x%016" PRIx64 "\",func-name=\"%s\",offset=\"%lld\",inst=\"%s %s\"}" - const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%016" PRIx64, addr)); - const CMICmnMIValueResult miValueResult("address", miValueConst); - CMICmnMIValueTuple miValueTuple(miValueResult); - const CMICmnMIValueConst miValueConst2(pFnName); - const CMICmnMIValueResult miValueResult2("func-name", miValueConst2); - miValueTuple.Add(miValueResult2); - const CMICmnMIValueConst miValueConst3(CMIUtilString::Format("%lld", addrOffSet)); - const CMICmnMIValueResult miValueResult3("offset", miValueConst3); - miValueTuple.Add(miValueResult3); - const CMICmnMIValueConst miValueConst4(CMIUtilString::Format("%d", instrtSize)); - const CMICmnMIValueResult miValueResult4("size", miValueConst4); - miValueTuple.Add(miValueResult4); - const CMICmnMIValueConst miValueConst5(CMIUtilString::Format("%s %s%s", pStrMnemonic, pStrOperands, strComment.Escape(true).c_str())); - const CMICmnMIValueResult miValueResult5("inst", miValueConst5); - miValueTuple.Add(miValueResult5); - - if (nDisasmMode == 1) - { - lldb::SBLineEntry lineEntry = address.GetLineEntry(); - const MIuint nLine = lineEntry.GetLine(); - const char *pFileName = lineEntry.GetFileSpec().GetFilename(); - pFileName = (pFileName != nullptr) ? pFileName : pUnknown; - - // MI "src_and_asm_line={line=\"%u\",file=\"%s\",line_asm_insn=[ ]}" - const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%u", nLine)); - const CMICmnMIValueResult miValueResult("line", miValueConst); - CMICmnMIValueTuple miValueTuple2(miValueResult); - const CMICmnMIValueConst miValueConst2(pFileName); - const CMICmnMIValueResult miValueResult2("file", miValueConst2); - miValueTuple2.Add(miValueResult2); - const CMICmnMIValueList miValueList(miValueTuple); - const CMICmnMIValueResult miValueResult3("line_asm_insn", miValueList); - miValueTuple2.Add(miValueResult3); - const CMICmnMIValueResult miValueResult4("src_and_asm_line", miValueTuple2); - m_miValueList.Add(miValueResult4); - } - else - { - m_miValueList.Add(miValueTuple); - } +bool CMICmdCmdDataDisassemble::Execute() { + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + CMICMDBASE_GETOPTION(pArgAddrStart, OptionShort, m_constStrArgAddrStart); + CMICMDBASE_GETOPTION(pArgAddrEnd, OptionShort, m_constStrArgAddrEnd); + CMICMDBASE_GETOPTION(pArgMode, Number, m_constStrArgMode); + + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (pArgThread->GetFound() && + !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), + m_cmdData.strMiCmd.c_str(), + m_constStrArgThread.c_str())); + return MIstatus::failure; + } + CMIUtilString strAddrStart; + if (!pArgAddrStart->GetExpectedOption<CMICmdArgValString, CMIUtilString>( + strAddrStart)) { + SetError(CMIUtilString::Format( + MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID), + m_cmdData.strMiCmd.c_str(), m_constStrArgAddrStart.c_str())); + return MIstatus::failure; + } + MIint64 nAddrStart = 0; + if (!strAddrStart.ExtractNumber(nAddrStart)) { + SetError(CMIUtilString::Format( + MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID), + m_cmdData.strMiCmd.c_str(), m_constStrArgAddrStart.c_str())); + return MIstatus::failure; + } + + CMIUtilString strAddrEnd; + if (!pArgAddrEnd->GetExpectedOption<CMICmdArgValString, CMIUtilString>( + strAddrEnd)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID), + m_cmdData.strMiCmd.c_str(), + m_constStrArgAddrEnd.c_str())); + return MIstatus::failure; + } + MIint64 nAddrEnd = 0; + if (!strAddrEnd.ExtractNumber(nAddrEnd)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID), + m_cmdData.strMiCmd.c_str(), + m_constStrArgAddrEnd.c_str())); + return MIstatus::failure; + } + const MIuint nDisasmMode = pArgMode->GetValue(); + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBTarget sbTarget = rSessionInfo.GetTarget(); + lldb::addr_t lldbStartAddr = static_cast<lldb::addr_t>(nAddrStart); + lldb::SBInstructionList instructions = sbTarget.ReadInstructions( + lldb::SBAddress(lldbStartAddr, sbTarget), nAddrEnd - nAddrStart); + const MIuint nInstructions = instructions.GetSize(); + // Calculate the offset of first instruction so that we can generate offset + // starting at 0 + lldb::addr_t start_offset = 0; + if (nInstructions > 0) + start_offset = + instructions.GetInstructionAtIndex(0).GetAddress().GetOffset(); + + for (size_t i = 0; i < nInstructions; i++) { + const char *pUnknown = "??"; + lldb::SBInstruction instrt = instructions.GetInstructionAtIndex(i); + const char *pStrMnemonic = instrt.GetMnemonic(sbTarget); + pStrMnemonic = (pStrMnemonic != nullptr) ? pStrMnemonic : pUnknown; + const char *pStrComment = instrt.GetComment(sbTarget); + CMIUtilString strComment; + if (pStrComment != nullptr && *pStrComment != '\0') + strComment = CMIUtilString::Format("; %s", pStrComment); + lldb::SBAddress address = instrt.GetAddress(); + lldb::addr_t addr = address.GetLoadAddress(sbTarget); + const char *pFnName = address.GetFunction().GetName(); + pFnName = (pFnName != nullptr) ? pFnName : pUnknown; + lldb::addr_t addrOffSet = address.GetOffset() - start_offset; + const char *pStrOperands = instrt.GetOperands(sbTarget); + pStrOperands = (pStrOperands != nullptr) ? pStrOperands : pUnknown; + const size_t instrtSize = instrt.GetByteSize(); + + // MI "{address=\"0x%016" PRIx64 + // "\",func-name=\"%s\",offset=\"%lld\",inst=\"%s %s\"}" + const CMICmnMIValueConst miValueConst( + CMIUtilString::Format("0x%016" PRIx64, addr)); + const CMICmnMIValueResult miValueResult("address", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const CMICmnMIValueConst miValueConst2(pFnName); + const CMICmnMIValueResult miValueResult2("func-name", miValueConst2); + miValueTuple.Add(miValueResult2); + const CMICmnMIValueConst miValueConst3( + CMIUtilString::Format("%lld", addrOffSet)); + const CMICmnMIValueResult miValueResult3("offset", miValueConst3); + miValueTuple.Add(miValueResult3); + const CMICmnMIValueConst miValueConst4( + CMIUtilString::Format("%d", instrtSize)); + const CMICmnMIValueResult miValueResult4("size", miValueConst4); + miValueTuple.Add(miValueResult4); + const CMICmnMIValueConst miValueConst5( + CMIUtilString::Format("%s %s%s", pStrMnemonic, pStrOperands, + strComment.Escape(true).c_str())); + const CMICmnMIValueResult miValueResult5("inst", miValueConst5); + miValueTuple.Add(miValueResult5); + + if (nDisasmMode == 1) { + lldb::SBLineEntry lineEntry = address.GetLineEntry(); + const MIuint nLine = lineEntry.GetLine(); + const char *pFileName = lineEntry.GetFileSpec().GetFilename(); + pFileName = (pFileName != nullptr) ? pFileName : pUnknown; + + // MI "src_and_asm_line={line=\"%u\",file=\"%s\",line_asm_insn=[ ]}" + const CMICmnMIValueConst miValueConst( + CMIUtilString::Format("0x%u", nLine)); + const CMICmnMIValueResult miValueResult("line", miValueConst); + CMICmnMIValueTuple miValueTuple2(miValueResult); + const CMICmnMIValueConst miValueConst2(pFileName); + const CMICmnMIValueResult miValueResult2("file", miValueConst2); + miValueTuple2.Add(miValueResult2); + const CMICmnMIValueList miValueList(miValueTuple); + const CMICmnMIValueResult miValueResult3("line_asm_insn", miValueList); + miValueTuple2.Add(miValueResult3); + const CMICmnMIValueResult miValueResult4("src_and_asm_line", + miValueTuple2); + m_miValueList.Add(miValueResult4); + } else { + m_miValueList.Add(miValueTuple); } + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -424,35 +444,36 @@ CMICmdCmdDataDisassemble::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataDisassemble::Acknowledge() -{ - const CMICmnMIValueResult miValueResult("asm_insns", m_miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - - return MIstatus::success; +bool CMICmdCmdDataDisassemble::Acknowledge() { + const CMICmnMIValueResult miValueResult("asm_insns", m_miValueList); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdDataDisassemble::CreateSelf() -{ - return new CMICmdCmdDataDisassemble(); +CMICmdBase *CMICmdCmdDataDisassemble::CreateSelf() { + return new CMICmdCmdDataDisassemble(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataReadMemoryBytes constructor. // Type: Method. // Args: None. @@ -460,38 +481,35 @@ CMICmdCmdDataDisassemble::CreateSelf() // Throws: None. //-- CMICmdCmdDataReadMemoryBytes::CMICmdCmdDataReadMemoryBytes() - : m_constStrArgByteOffset("o") - , m_constStrArgAddrExpr("address") - , m_constStrArgNumBytes("count") - , m_pBufferMemory(nullptr) - , m_nAddrStart(0) - , m_nAddrNumBytesToRead(0) -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "data-read-memory-bytes"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdDataReadMemoryBytes::CreateSelf; + : m_constStrArgByteOffset("o"), m_constStrArgAddrExpr("address"), + m_constStrArgNumBytes("count"), m_pBufferMemory(nullptr), m_nAddrStart(0), + m_nAddrNumBytesToRead(0) { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "data-read-memory-bytes"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdDataReadMemoryBytes::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataReadMemoryBytes destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdDataReadMemoryBytes::~CMICmdCmdDataReadMemoryBytes() -{ - if (m_pBufferMemory != nullptr) - { - delete[] m_pBufferMemory; - m_pBufferMemory = nullptr; - } +CMICmdCmdDataReadMemoryBytes::~CMICmdCmdDataReadMemoryBytes() { + if (m_pBufferMemory != nullptr) { + delete[] m_pBufferMemory; + m_pBufferMemory = nullptr; + } } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -499,140 +517,150 @@ CMICmdCmdDataReadMemoryBytes::~CMICmdCmdDataReadMemoryBytes() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataReadMemoryBytes::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgByteOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1)); - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgAddrExpr, true, true, true, true)); - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumBytes, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdDataReadMemoryBytes::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValOptionShort(m_constStrArgByteOffset, false, true, + CMICmdArgValListBase::eArgValType_Number, 1)); + m_setCmdArgs.Add( + new CMICmdArgValString(m_constStrArgAddrExpr, true, true, true, true)); + m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumBytes, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdDataReadMemoryBytes::Execute() -{ - CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); - CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame); - CMICMDBASE_GETOPTION(pArgAddrOffset, OptionShort, m_constStrArgByteOffset); - CMICMDBASE_GETOPTION(pArgAddrExpr, String, m_constStrArgAddrExpr); - CMICMDBASE_GETOPTION(pArgNumBytes, Number, m_constStrArgNumBytes); - - // get the --thread option value - MIuint64 nThreadId = UINT64_MAX; - if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), - m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); - return MIstatus::failure; - } - - // get the --frame option value - MIuint64 nFrame = UINT64_MAX; - if (pArgFrame->GetFound() && !pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), - m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str())); - return MIstatus::failure; - } - - // get the -o option value - MIuint64 nAddrOffset = 0; - if (pArgAddrOffset->GetFound() && !pArgAddrOffset->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nAddrOffset)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), - m_cmdData.strMiCmd.c_str(), m_constStrArgByteOffset.c_str())); - return MIstatus::failure; - } - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); - if (!sbProcess.IsValid()) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str())); - return MIstatus::failure; - } - - lldb::SBThread thread = (nThreadId != UINT64_MAX) ? - sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.GetSelectedThread(); - if (!thread.IsValid()) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str())); - return MIstatus::failure; - } - - lldb::SBFrame frame = (nFrame != UINT64_MAX) ? - thread.GetFrameAtIndex(nFrame) : thread.GetSelectedFrame(); - if (!frame.IsValid()) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FRAME_INVALID), m_cmdData.strMiCmd.c_str())); - return MIstatus::failure; - } - - const CMIUtilString &rAddrExpr = pArgAddrExpr->GetValue(); - lldb::SBValue addrExprValue = frame.EvaluateExpression(rAddrExpr.c_str()); - lldb::SBError error = addrExprValue.GetError(); - if (error.Fail()) - { - SetError(error.GetCString()); - return MIstatus::failure; - } - else if (!addrExprValue.IsValid()) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID), rAddrExpr.c_str())); - return MIstatus::failure; - } - - MIuint64 nAddrStart = 0; - if (!CMICmnLLDBProxySBValue::GetValueAsUnsigned(addrExprValue, nAddrStart)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID), rAddrExpr.c_str())); - return MIstatus::failure; - } - - nAddrStart += nAddrOffset; - const MIuint64 nAddrNumBytes = pArgNumBytes->GetValue(); - - m_pBufferMemory = new unsigned char[nAddrNumBytes]; - if (m_pBufferMemory == nullptr) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE), m_cmdData.strMiCmd.c_str(), nAddrNumBytes)); - return MIstatus::failure; - } - - const MIuint64 nReadBytes = sbProcess.ReadMemory(static_cast<lldb::addr_t>(nAddrStart), (void *)m_pBufferMemory, nAddrNumBytes, error); - if (nReadBytes != nAddrNumBytes) - { - SetError( - CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK), m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart)); - return MIstatus::failure; - } - if (error.Fail()) - { - lldb::SBStream err; - const bool bOk = error.GetDescription(err); - MIunused(bOk); - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES), m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart, - err.GetData())); - return MIstatus::failure; - } - - m_nAddrStart = nAddrStart; - m_nAddrNumBytesToRead = nAddrNumBytes; - - return MIstatus::success; +bool CMICmdCmdDataReadMemoryBytes::Execute() { + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame); + CMICMDBASE_GETOPTION(pArgAddrOffset, OptionShort, m_constStrArgByteOffset); + CMICMDBASE_GETOPTION(pArgAddrExpr, String, m_constStrArgAddrExpr); + CMICMDBASE_GETOPTION(pArgNumBytes, Number, m_constStrArgNumBytes); + + // get the --thread option value + MIuint64 nThreadId = UINT64_MAX; + if (pArgThread->GetFound() && + !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), + m_constStrArgThread.c_str())); + return MIstatus::failure; + } + + // get the --frame option value + MIuint64 nFrame = UINT64_MAX; + if (pArgFrame->GetFound() && + !pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), + m_constStrArgFrame.c_str())); + return MIstatus::failure; + } + + // get the -o option value + MIuint64 nAddrOffset = 0; + if (pArgAddrOffset->GetFound() && + !pArgAddrOffset->GetExpectedOption<CMICmdArgValNumber, MIuint64>( + nAddrOffset)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), + m_constStrArgByteOffset.c_str())); + return MIstatus::failure; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + if (!sbProcess.IsValid()) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), + m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + + lldb::SBThread thread = (nThreadId != UINT64_MAX) + ? sbProcess.GetThreadByIndexID(nThreadId) + : sbProcess.GetSelectedThread(); + if (!thread.IsValid()) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), + m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + + lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex(nFrame) + : thread.GetSelectedFrame(); + if (!frame.IsValid()) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FRAME_INVALID), + m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + + const CMIUtilString &rAddrExpr = pArgAddrExpr->GetValue(); + lldb::SBValue addrExprValue = frame.EvaluateExpression(rAddrExpr.c_str()); + lldb::SBError error = addrExprValue.GetError(); + if (error.Fail()) { + SetError(error.GetCString()); + return MIstatus::failure; + } else if (!addrExprValue.IsValid()) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID), + rAddrExpr.c_str())); + return MIstatus::failure; + } + + MIuint64 nAddrStart = 0; + if (!CMICmnLLDBProxySBValue::GetValueAsUnsigned(addrExprValue, nAddrStart)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID), + rAddrExpr.c_str())); + return MIstatus::failure; + } + + nAddrStart += nAddrOffset; + const MIuint64 nAddrNumBytes = pArgNumBytes->GetValue(); + + m_pBufferMemory = new unsigned char[nAddrNumBytes]; + if (m_pBufferMemory == nullptr) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE), + m_cmdData.strMiCmd.c_str(), nAddrNumBytes)); + return MIstatus::failure; + } + + const MIuint64 nReadBytes = + sbProcess.ReadMemory(static_cast<lldb::addr_t>(nAddrStart), + (void *)m_pBufferMemory, nAddrNumBytes, error); + if (nReadBytes != nAddrNumBytes) { + SetError(CMIUtilString::Format( + MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK), + m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart)); + return MIstatus::failure; + } + if (error.Fail()) { + lldb::SBStream err; + const bool bOk = error.GetDescription(err); + MIunused(bOk); + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES), + m_cmdData.strMiCmd.c_str(), nAddrNumBytes, + nAddrStart, err.GetData())); + return MIstatus::failure; + } + + m_nAddrStart = nAddrStart; + m_nAddrNumBytesToRead = nAddrNumBytes; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -640,103 +668,108 @@ CMICmdCmdDataReadMemoryBytes::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataReadMemoryBytes::Acknowledge() -{ - // MI: memory=[{begin=\"0x%016" PRIx64 "\",offset=\"0x%016" PRIx64" \",end=\"0x%016" PRIx64 "\",contents=\" \" }]" - const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%016" PRIx64, m_nAddrStart)); - const CMICmnMIValueResult miValueResult("begin", miValueConst); - CMICmnMIValueTuple miValueTuple(miValueResult); - const MIuint64 nAddrOffset = 0; - const CMICmnMIValueConst miValueConst2(CMIUtilString::Format("0x%016" PRIx64, nAddrOffset)); - const CMICmnMIValueResult miValueResult2("offset", miValueConst2); - miValueTuple.Add(miValueResult2); - const CMICmnMIValueConst miValueConst3(CMIUtilString::Format("0x%016" PRIx64, m_nAddrStart + m_nAddrNumBytesToRead)); - const CMICmnMIValueResult miValueResult3("end", miValueConst3); - miValueTuple.Add(miValueResult3); - - // MI: contents=\" \" - CMIUtilString strContent; - strContent.reserve((m_nAddrNumBytesToRead << 1) + 1); - for (MIuint64 i = 0; i < m_nAddrNumBytesToRead; i++) - { - strContent += CMIUtilString::Format("%02hhx", m_pBufferMemory[i]); - } - const CMICmnMIValueConst miValueConst4(strContent); - const CMICmnMIValueResult miValueResult4("contents", miValueConst4); - miValueTuple.Add(miValueResult4); - const CMICmnMIValueList miValueList(miValueTuple); - const CMICmnMIValueResult miValueResult5("memory", miValueList); - - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult5); - m_miResultRecord = miRecordResult; - - return MIstatus::success; +bool CMICmdCmdDataReadMemoryBytes::Acknowledge() { + // MI: memory=[{begin=\"0x%016" PRIx64 "\",offset=\"0x%016" PRIx64" + // \",end=\"0x%016" PRIx64 "\",contents=\" \" }]" + const CMICmnMIValueConst miValueConst( + CMIUtilString::Format("0x%016" PRIx64, m_nAddrStart)); + const CMICmnMIValueResult miValueResult("begin", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const MIuint64 nAddrOffset = 0; + const CMICmnMIValueConst miValueConst2( + CMIUtilString::Format("0x%016" PRIx64, nAddrOffset)); + const CMICmnMIValueResult miValueResult2("offset", miValueConst2); + miValueTuple.Add(miValueResult2); + const CMICmnMIValueConst miValueConst3(CMIUtilString::Format( + "0x%016" PRIx64, m_nAddrStart + m_nAddrNumBytesToRead)); + const CMICmnMIValueResult miValueResult3("end", miValueConst3); + miValueTuple.Add(miValueResult3); + + // MI: contents=\" \" + CMIUtilString strContent; + strContent.reserve((m_nAddrNumBytesToRead << 1) + 1); + for (MIuint64 i = 0; i < m_nAddrNumBytesToRead; i++) { + strContent += CMIUtilString::Format("%02hhx", m_pBufferMemory[i]); + } + const CMICmnMIValueConst miValueConst4(strContent); + const CMICmnMIValueResult miValueResult4("contents", miValueConst4); + miValueTuple.Add(miValueResult4); + const CMICmnMIValueList miValueList(miValueTuple); + const CMICmnMIValueResult miValueResult5("memory", miValueList); + + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult5); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdDataReadMemoryBytes::CreateSelf() -{ - return new CMICmdCmdDataReadMemoryBytes(); +CMICmdBase *CMICmdCmdDataReadMemoryBytes::CreateSelf() { + return new CMICmdCmdDataReadMemoryBytes(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataReadMemory constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdDataReadMemory::CMICmdCmdDataReadMemory() -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "data-read-memory"; +CMICmdCmdDataReadMemory::CMICmdCmdDataReadMemory() { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "data-read-memory"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdDataReadMemory::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdDataReadMemory::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataReadMemory destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdDataReadMemory::~CMICmdCmdDataReadMemory() -{ -} - -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +CMICmdCmdDataReadMemory::~CMICmdCmdDataReadMemory() {} + +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataReadMemory::Execute() -{ - // Do nothing - command deprecated use "data-read-memory-bytes" command - return MIstatus::success; +bool CMICmdCmdDataReadMemory::Execute() { + // Do nothing - command deprecated use "data-read-memory-bytes" command + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -744,37 +777,40 @@ CMICmdCmdDataReadMemory::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataReadMemory::Acknowledge() -{ - // Command CMICmdCmdSupportListFeatures sends "data-read-memory-bytes" which causes this command not to be called - const CMICmnMIValueConst miValueConst(MIRSRC(IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED)); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; - - return MIstatus::success; +bool CMICmdCmdDataReadMemory::Acknowledge() { + // Command CMICmdCmdSupportListFeatures sends "data-read-memory-bytes" which + // causes this command not to be called + const CMICmnMIValueConst miValueConst( + MIRSRC(IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED)); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdDataReadMemory::CreateSelf() -{ - return new CMICmdCmdDataReadMemory(); +CMICmdBase *CMICmdCmdDataReadMemory::CreateSelf() { + return new CMICmdCmdDataReadMemory(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataListRegisterNames constructor. // Type: Method. // Args: None. @@ -782,29 +818,28 @@ CMICmdCmdDataReadMemory::CreateSelf() // Throws: None. //-- CMICmdCmdDataListRegisterNames::CMICmdCmdDataListRegisterNames() - : m_constStrArgRegNo("regno") - , m_miValueList(true) -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "data-list-register-names"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdDataListRegisterNames::CreateSelf; + : m_constStrArgRegNo("regno"), m_miValueList(true) { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "data-list-register-names"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdDataListRegisterNames::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataReadMemoryBytes destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdDataListRegisterNames::~CMICmdCmdDataListRegisterNames() -{ -} +CMICmdCmdDataListRegisterNames::~CMICmdCmdDataListRegisterNames() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -812,83 +847,82 @@ CMICmdCmdDataListRegisterNames::~CMICmdCmdDataListRegisterNames() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataListRegisterNames::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgRegNo, false, false, CMICmdArgValListBase::eArgValType_Number)); - return ParseValidateCmdOptions(); +bool CMICmdCmdDataListRegisterNames::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValListOfN(m_constStrArgRegNo, false, false, + CMICmdArgValListBase::eArgValType_Number)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataListRegisterNames::Execute() -{ - CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo); - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); - if (!sbProcess.IsValid()) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str())); - return MIstatus::failure; - } - - const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo(pArgRegNo->GetExpectedOptions()); - if (!rVecRegNo.empty()) - { - // List of required registers - CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin(); - while (it != rVecRegNo.end()) - { - const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it); - const MIuint nRegIndex = pRegNo->GetValue(); - lldb::SBValue regValue = GetRegister(nRegIndex); - if (regValue.IsValid()) - { - const CMICmnMIValueConst miValueConst(CMICmnLLDBUtilSBValue(regValue).GetName()); - m_miValueList.Add(miValueConst); - } - - // Next - ++it; - } +bool CMICmdCmdDataListRegisterNames::Execute() { + CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo); + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + if (!sbProcess.IsValid()) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), + m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + + const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo( + pArgRegNo->GetExpectedOptions()); + if (!rVecRegNo.empty()) { + // List of required registers + CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin(); + while (it != rVecRegNo.end()) { + const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it); + const MIuint nRegIndex = pRegNo->GetValue(); + lldb::SBValue regValue = GetRegister(nRegIndex); + if (regValue.IsValid()) { + const CMICmnMIValueConst miValueConst( + CMICmnLLDBUtilSBValue(regValue).GetName()); + m_miValueList.Add(miValueConst); + } + + // Next + ++it; } - else - { - // List of all registers - lldb::SBThread thread = sbProcess.GetSelectedThread(); - lldb::SBFrame frame = thread.GetSelectedFrame(); - lldb::SBValueList registers = frame.GetRegisters(); - const MIuint nRegisters = registers.GetSize(); - for (MIuint i = 0; i < nRegisters; i++) - { - lldb::SBValue value = registers.GetValueAtIndex(i); - const MIuint nRegChildren = value.GetNumChildren(); - for (MIuint j = 0; j < nRegChildren; j++) - { - lldb::SBValue regValue = value.GetChildAtIndex(j); - if (regValue.IsValid()) - { - const CMICmnMIValueConst miValueConst(CMICmnLLDBUtilSBValue(regValue).GetName()); - m_miValueList.Add(miValueConst); - } - } + } else { + // List of all registers + lldb::SBThread thread = sbProcess.GetSelectedThread(); + lldb::SBFrame frame = thread.GetSelectedFrame(); + lldb::SBValueList registers = frame.GetRegisters(); + const MIuint nRegisters = registers.GetSize(); + for (MIuint i = 0; i < nRegisters; i++) { + lldb::SBValue value = registers.GetValueAtIndex(i); + const MIuint nRegChildren = value.GetNumChildren(); + for (MIuint j = 0; j < nRegChildren; j++) { + lldb::SBValue regValue = value.GetChildAtIndex(j); + if (regValue.IsValid()) { + const CMICmnMIValueConst miValueConst( + CMICmnLLDBUtilSBValue(regValue).GetName()); + m_miValueList.Add(miValueConst); } + } } + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -896,32 +930,34 @@ CMICmdCmdDataListRegisterNames::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataListRegisterNames::Acknowledge() -{ - const CMICmnMIValueResult miValueResult("register-names", m_miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - - return MIstatus::success; +bool CMICmdCmdDataListRegisterNames::Acknowledge() { + const CMICmnMIValueResult miValueResult("register-names", m_miValueList); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdDataListRegisterNames::CreateSelf() -{ - return new CMICmdCmdDataListRegisterNames(); +CMICmdBase *CMICmdCmdDataListRegisterNames::CreateSelf() { + return new CMICmdCmdDataListRegisterNames(); } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Method. // Args: None. @@ -929,38 +965,36 @@ CMICmdCmdDataListRegisterNames::CreateSelf() // Throws: None. //-- lldb::SBValue -CMICmdCmdDataListRegisterNames::GetRegister(const MIuint vRegisterIndex) const -{ - lldb::SBThread thread = CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetSelectedThread(); - lldb::SBFrame frame = thread.GetSelectedFrame(); - lldb::SBValueList registers = frame.GetRegisters(); - const MIuint nRegisters = registers.GetSize(); - MIuint nRegisterIndex(vRegisterIndex); - for (MIuint i = 0; i < nRegisters; i++) - { - lldb::SBValue value = registers.GetValueAtIndex(i); - const MIuint nRegChildren = value.GetNumChildren(); - if (nRegisterIndex >= nRegChildren) - { - nRegisterIndex -= nRegChildren; - continue; - } +CMICmdCmdDataListRegisterNames::GetRegister(const MIuint vRegisterIndex) const { + lldb::SBThread thread = + CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetSelectedThread(); + lldb::SBFrame frame = thread.GetSelectedFrame(); + lldb::SBValueList registers = frame.GetRegisters(); + const MIuint nRegisters = registers.GetSize(); + MIuint nRegisterIndex(vRegisterIndex); + for (MIuint i = 0; i < nRegisters; i++) { + lldb::SBValue value = registers.GetValueAtIndex(i); + const MIuint nRegChildren = value.GetNumChildren(); + if (nRegisterIndex >= nRegChildren) { + nRegisterIndex -= nRegChildren; + continue; + } - lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex); - if (value2.IsValid()) - { - return value2; - } + lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex); + if (value2.IsValid()) { + return value2; } + } - return lldb::SBValue(); + return lldb::SBValue(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataListRegisterValues constructor. // Type: Method. // Args: None. @@ -968,31 +1002,29 @@ CMICmdCmdDataListRegisterNames::GetRegister(const MIuint vRegisterIndex) const // Throws: None. //-- CMICmdCmdDataListRegisterValues::CMICmdCmdDataListRegisterValues() - : m_constStrArgSkip("skip-unavailable") - , m_constStrArgFormat("fmt") - , m_constStrArgRegNo("regno") - , m_miValueList(true) -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "data-list-register-values"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdDataListRegisterValues::CreateSelf; + : m_constStrArgSkip("skip-unavailable"), m_constStrArgFormat("fmt"), + m_constStrArgRegNo("regno"), m_miValueList(true) { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "data-list-register-values"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdDataListRegisterValues::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataListRegisterValues destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdDataListRegisterValues::~CMICmdCmdDataListRegisterValues() -{ -} +CMICmdCmdDataListRegisterValues::~CMICmdCmdDataListRegisterValues() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -1000,102 +1032,104 @@ CMICmdCmdDataListRegisterValues::~CMICmdCmdDataListRegisterValues() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataListRegisterValues::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1)); - m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgSkip, false, false)); - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgFormat, true, true)); - m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgRegNo, false, true, CMICmdArgValListBase::eArgValType_Number)); - return ParseValidateCmdOptions(); +bool CMICmdCmdDataListRegisterValues::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValOptionLong(m_constStrArgThread, false, false, + CMICmdArgValListBase::eArgValType_Number, 1)); + m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgSkip, false, false)); + m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgFormat, true, true)); + m_setCmdArgs.Add( + new CMICmdArgValListOfN(m_constStrArgRegNo, false, true, + CMICmdArgValListBase::eArgValType_Number)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataListRegisterValues::Execute() -{ - CMICMDBASE_GETOPTION(pArgFormat, String, m_constStrArgFormat); - CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo); - - const CMIUtilString &rStrFormat(pArgFormat->GetValue()); - if (rStrFormat.length() != 1) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE), m_cmdData.strMiCmd.c_str(), rStrFormat.c_str())); - return MIstatus::failure; - } - const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e eFormat = CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar(rStrFormat[0]); - if (eFormat == CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE), m_cmdData.strMiCmd.c_str(), rStrFormat.c_str())); - return MIstatus::failure; - } - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); - if (!sbProcess.IsValid()) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str())); - return MIstatus::failure; - } - - const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo(pArgRegNo->GetExpectedOptions()); - if (!rVecRegNo.empty()) - { - // List of required registers - CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin(); - while (it != rVecRegNo.end()) - { - const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it); - const MIuint nRegIndex = pRegNo->GetValue(); - lldb::SBValue regValue = GetRegister(nRegIndex); - if (regValue.IsValid()) - { - AddToOutput(nRegIndex, regValue, eFormat); - } - - // Next - ++it; - } +bool CMICmdCmdDataListRegisterValues::Execute() { + CMICMDBASE_GETOPTION(pArgFormat, String, m_constStrArgFormat); + CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo); + + const CMIUtilString &rStrFormat(pArgFormat->GetValue()); + if (rStrFormat.length() != 1) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE), + m_cmdData.strMiCmd.c_str(), + rStrFormat.c_str())); + return MIstatus::failure; + } + const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e eFormat = + CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar(rStrFormat[0]); + if (eFormat == CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE), + m_cmdData.strMiCmd.c_str(), + rStrFormat.c_str())); + return MIstatus::failure; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + if (!sbProcess.IsValid()) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), + m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + + const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo( + pArgRegNo->GetExpectedOptions()); + if (!rVecRegNo.empty()) { + // List of required registers + CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin(); + while (it != rVecRegNo.end()) { + const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it); + const MIuint nRegIndex = pRegNo->GetValue(); + lldb::SBValue regValue = GetRegister(nRegIndex); + if (regValue.IsValid()) { + AddToOutput(nRegIndex, regValue, eFormat); + } + + // Next + ++it; } - else - { - // No register numbers are provided. Output all registers. - lldb::SBThread thread = sbProcess.GetSelectedThread(); - lldb::SBFrame frame = thread.GetSelectedFrame(); - lldb::SBValueList registers = frame.GetRegisters(); - const MIuint nRegisters = registers.GetSize(); - MIuint nRegIndex = 0; - for (MIuint i = 0; i < nRegisters; i++) - { - lldb::SBValue value = registers.GetValueAtIndex(i); - const MIuint nRegChildren = value.GetNumChildren(); - for (MIuint j = 0; j < nRegChildren; j++) - { - lldb::SBValue regValue = value.GetChildAtIndex(j); - if (regValue.IsValid()) - { - AddToOutput(nRegIndex, regValue, eFormat); - } - - // Next - ++nRegIndex; - } + } else { + // No register numbers are provided. Output all registers. + lldb::SBThread thread = sbProcess.GetSelectedThread(); + lldb::SBFrame frame = thread.GetSelectedFrame(); + lldb::SBValueList registers = frame.GetRegisters(); + const MIuint nRegisters = registers.GetSize(); + MIuint nRegIndex = 0; + for (MIuint i = 0; i < nRegisters; i++) { + lldb::SBValue value = registers.GetValueAtIndex(i); + const MIuint nRegChildren = value.GetNumChildren(); + for (MIuint j = 0; j < nRegChildren; j++) { + lldb::SBValue regValue = value.GetChildAtIndex(j); + if (regValue.IsValid()) { + AddToOutput(nRegIndex, regValue, eFormat); } + + // Next + ++nRegIndex; + } } + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -1103,137 +1137,140 @@ CMICmdCmdDataListRegisterValues::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataListRegisterValues::Acknowledge() -{ - const CMICmnMIValueResult miValueResult("register-values", m_miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - - return MIstatus::success; +bool CMICmdCmdDataListRegisterValues::Acknowledge() { + const CMICmnMIValueResult miValueResult("register-values", m_miValueList); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdDataListRegisterValues::CreateSelf() -{ - return new CMICmdCmdDataListRegisterValues(); +CMICmdBase *CMICmdCmdDataListRegisterValues::CreateSelf() { + return new CMICmdCmdDataListRegisterValues(); } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Method. // Args: None. // Return: lldb::SBValue - LLDB SBValue object. // Throws: None. //-- -lldb::SBValue -CMICmdCmdDataListRegisterValues::GetRegister(const MIuint vRegisterIndex) const -{ - lldb::SBThread thread = CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetSelectedThread(); - lldb::SBFrame frame = thread.GetSelectedFrame(); - lldb::SBValueList registers = frame.GetRegisters(); - const MIuint nRegisters = registers.GetSize(); - MIuint nRegisterIndex(vRegisterIndex); - for (MIuint i = 0; i < nRegisters; i++) - { - lldb::SBValue value = registers.GetValueAtIndex(i); - const MIuint nRegChildren = value.GetNumChildren(); - if (nRegisterIndex >= nRegChildren) - { - nRegisterIndex -= nRegChildren; - continue; - } +lldb::SBValue CMICmdCmdDataListRegisterValues::GetRegister( + const MIuint vRegisterIndex) const { + lldb::SBThread thread = + CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetSelectedThread(); + lldb::SBFrame frame = thread.GetSelectedFrame(); + lldb::SBValueList registers = frame.GetRegisters(); + const MIuint nRegisters = registers.GetSize(); + MIuint nRegisterIndex(vRegisterIndex); + for (MIuint i = 0; i < nRegisters; i++) { + lldb::SBValue value = registers.GetValueAtIndex(i); + const MIuint nRegChildren = value.GetNumChildren(); + if (nRegisterIndex >= nRegChildren) { + nRegisterIndex -= nRegChildren; + continue; + } - lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex); - if (value2.IsValid()) - { - return value2; - } + lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex); + if (value2.IsValid()) { + return value2; } + } - return lldb::SBValue(); + return lldb::SBValue(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Adds the register value to the output list. // Type: Method. // Args: Value of the register, its index and output format. // Return: None // Throws: None. //-- -void -CMICmdCmdDataListRegisterValues::AddToOutput(const MIuint vnIndex, const lldb::SBValue &vrValue, - CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat) -{ - const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%u", vnIndex)); - const CMICmnMIValueResult miValueResult("number", miValueConst); - CMICmnMIValueTuple miValueTuple(miValueResult); - const CMIUtilString strRegValue(CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(vrValue, veVarFormat)); - const CMICmnMIValueConst miValueConst2(strRegValue); - const CMICmnMIValueResult miValueResult2("value", miValueConst2); - miValueTuple.Add(miValueResult2); - m_miValueList.Add(miValueTuple); +void CMICmdCmdDataListRegisterValues::AddToOutput( + const MIuint vnIndex, const lldb::SBValue &vrValue, + CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat) { + const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%u", vnIndex)); + const CMICmnMIValueResult miValueResult("number", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const CMIUtilString strRegValue( + CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(vrValue, + veVarFormat)); + const CMICmnMIValueConst miValueConst2(strRegValue); + const CMICmnMIValueResult miValueResult2("value", miValueConst2); + miValueTuple.Add(miValueResult2); + m_miValueList.Add(miValueTuple); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataListRegisterChanged constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdDataListRegisterChanged::CMICmdCmdDataListRegisterChanged() -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "data-list-changed-registers"; +CMICmdCmdDataListRegisterChanged::CMICmdCmdDataListRegisterChanged() { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "data-list-changed-registers"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdDataListRegisterChanged::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdDataListRegisterChanged::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataListRegisterChanged destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdDataListRegisterChanged::~CMICmdCmdDataListRegisterChanged() -{ -} - -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +CMICmdCmdDataListRegisterChanged::~CMICmdCmdDataListRegisterChanged() {} + +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataListRegisterChanged::Execute() -{ - // Do nothing +bool CMICmdCmdDataListRegisterChanged::Execute() { + // Do nothing - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -1241,36 +1278,37 @@ CMICmdCmdDataListRegisterChanged::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataListRegisterChanged::Acknowledge() -{ - const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED)); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; - - return MIstatus::success; +bool CMICmdCmdDataListRegisterChanged::Acknowledge() { + const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED)); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdDataListRegisterChanged::CreateSelf() -{ - return new CMICmdCmdDataListRegisterChanged(); +CMICmdBase *CMICmdCmdDataListRegisterChanged::CreateSelf() { + return new CMICmdCmdDataListRegisterChanged(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataWriteMemoryBytes constructor. // Type: Method. // Args: None. @@ -1278,30 +1316,29 @@ CMICmdCmdDataListRegisterChanged::CreateSelf() // Throws: None. //-- CMICmdCmdDataWriteMemoryBytes::CMICmdCmdDataWriteMemoryBytes() - : m_constStrArgAddr("address") - , m_constStrArgContents("contents") - , m_constStrArgCount("count") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "data-write-memory-bytes"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdDataWriteMemoryBytes::CreateSelf; + : m_constStrArgAddr("address"), m_constStrArgContents("contents"), + m_constStrArgCount("count") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "data-write-memory-bytes"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdDataWriteMemoryBytes::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataWriteMemoryBytes destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdDataWriteMemoryBytes::~CMICmdCmdDataWriteMemoryBytes() -{ -} +CMICmdCmdDataWriteMemoryBytes::~CMICmdCmdDataWriteMemoryBytes() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -1309,41 +1346,45 @@ CMICmdCmdDataWriteMemoryBytes::~CMICmdCmdDataWriteMemoryBytes() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataWriteMemoryBytes::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgAddr, true, true, false, true)); - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgContents, true, true, true, true)); - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgCount, false, true, false, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdDataWriteMemoryBytes::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValString(m_constStrArgAddr, true, true, false, true)); + m_setCmdArgs.Add( + new CMICmdArgValString(m_constStrArgContents, true, true, true, true)); + m_setCmdArgs.Add( + new CMICmdArgValString(m_constStrArgCount, false, true, false, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataWriteMemoryBytes::Execute() -{ - // Do nothing - not reproduceable (yet) in Eclipse - // CMICMDBASE_GETOPTION( pArgOffset, OptionShort, m_constStrArgOffset ); - // CMICMDBASE_GETOPTION( pArgAddr, String, m_constStrArgAddr ); - // CMICMDBASE_GETOPTION( pArgNumber, String, m_constStrArgNumber ); - // CMICMDBASE_GETOPTION( pArgContents, String, m_constStrArgContents ); - // - // Numbers extracts as string types as they could be hex numbers - // '&' is not recognised and so has to be removed - - return MIstatus::success; +bool CMICmdCmdDataWriteMemoryBytes::Execute() { + // Do nothing - not reproduceable (yet) in Eclipse + // CMICMDBASE_GETOPTION( pArgOffset, OptionShort, m_constStrArgOffset ); + // CMICMDBASE_GETOPTION( pArgAddr, String, m_constStrArgAddr ); + // CMICMDBASE_GETOPTION( pArgNumber, String, m_constStrArgNumber ); + // CMICMDBASE_GETOPTION( pArgContents, String, m_constStrArgContents ); + // + // Numbers extracts as string types as they could be hex numbers + // '&' is not recognised and so has to be removed + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -1351,36 +1392,37 @@ CMICmdCmdDataWriteMemoryBytes::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataWriteMemoryBytes::Acknowledge() -{ - const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED)); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; - - return MIstatus::success; +bool CMICmdCmdDataWriteMemoryBytes::Acknowledge() { + const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED)); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdDataWriteMemoryBytes::CreateSelf() -{ - return new CMICmdCmdDataWriteMemoryBytes(); +CMICmdBase *CMICmdCmdDataWriteMemoryBytes::CreateSelf() { + return new CMICmdCmdDataWriteMemoryBytes(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataWriteMemory constructor. // Type: Method. // Args: None. @@ -1388,40 +1430,36 @@ CMICmdCmdDataWriteMemoryBytes::CreateSelf() // Throws: None. //-- CMICmdCmdDataWriteMemory::CMICmdCmdDataWriteMemory() - : m_constStrArgOffset("o") - , m_constStrArgAddr("address") - , m_constStrArgD("d") - , m_constStrArgNumber("a number") - , m_constStrArgContents("contents") - , m_nAddr(0) - , m_nCount(0) - , m_pBufferMemory(nullptr) -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "data-write-memory"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdDataWriteMemory::CreateSelf; + : m_constStrArgOffset("o"), m_constStrArgAddr("address"), + m_constStrArgD("d"), m_constStrArgNumber("a number"), + m_constStrArgContents("contents"), m_nAddr(0), m_nCount(0), + m_pBufferMemory(nullptr) { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "data-write-memory"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdDataWriteMemory::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataWriteMemory destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdDataWriteMemory::~CMICmdCmdDataWriteMemory() -{ - if (m_pBufferMemory != nullptr) - { - delete[] m_pBufferMemory; - m_pBufferMemory = nullptr; - } +CMICmdCmdDataWriteMemory::~CMICmdCmdDataWriteMemory() { + if (m_pBufferMemory != nullptr) { + delete[] m_pBufferMemory; + m_pBufferMemory = nullptr; + } } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -1429,77 +1467,85 @@ CMICmdCmdDataWriteMemory::~CMICmdCmdDataWriteMemory() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataWriteMemory::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1)); - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgAddr, true, true)); - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgD, true, true)); - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, true, true)); - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgContents, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdDataWriteMemory::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValOptionShort(m_constStrArgOffset, false, true, + CMICmdArgValListBase::eArgValType_Number, 1)); + m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgAddr, true, true)); + m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgD, true, true)); + m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, true, true)); + m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgContents, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataWriteMemory::Execute() -{ - CMICMDBASE_GETOPTION(pArgOffset, OptionShort, m_constStrArgOffset); - CMICMDBASE_GETOPTION(pArgAddr, Number, m_constStrArgAddr); - CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNumber); - CMICMDBASE_GETOPTION(pArgContents, Number, m_constStrArgContents); - - MIuint nAddrOffset = 0; - if (pArgOffset->GetFound() && !pArgOffset->GetExpectedOption<CMICmdArgValNumber, MIuint>(nAddrOffset)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgAddr.c_str())); - return MIstatus::failure; - } - m_nAddr = pArgAddr->GetValue(); - m_nCount = pArgNumber->GetValue(); - const MIuint64 nValue = pArgContents->GetValue(); - - m_pBufferMemory = new unsigned char[m_nCount]; - if (m_pBufferMemory == nullptr) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE), m_cmdData.strMiCmd.c_str(), m_nCount)); - return MIstatus::failure; - } - *m_pBufferMemory = static_cast<char>(nValue); - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); - lldb::SBError error; - lldb::addr_t addr = static_cast<lldb::addr_t>(m_nAddr + nAddrOffset); - const size_t nBytesWritten = sbProcess.WriteMemory(addr, (const void *)m_pBufferMemory, (size_t)m_nCount, error); - if (nBytesWritten != static_cast<size_t>(m_nCount)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK), m_cmdData.strMiCmd.c_str(), m_nCount, addr)); - return MIstatus::failure; - } - if (error.Fail()) - { - lldb::SBStream err; - const bool bOk = error.GetDescription(err); - MIunused(bOk); - SetError( - CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES), m_cmdData.strMiCmd.c_str(), m_nCount, addr, err.GetData())); - return MIstatus::failure; - } - - return MIstatus::success; +bool CMICmdCmdDataWriteMemory::Execute() { + CMICMDBASE_GETOPTION(pArgOffset, OptionShort, m_constStrArgOffset); + CMICMDBASE_GETOPTION(pArgAddr, Number, m_constStrArgAddr); + CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNumber); + CMICMDBASE_GETOPTION(pArgContents, Number, m_constStrArgContents); + + MIuint nAddrOffset = 0; + if (pArgOffset->GetFound() && + !pArgOffset->GetExpectedOption<CMICmdArgValNumber, MIuint>(nAddrOffset)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_INVALID), + m_cmdData.strMiCmd.c_str(), + m_constStrArgAddr.c_str())); + return MIstatus::failure; + } + m_nAddr = pArgAddr->GetValue(); + m_nCount = pArgNumber->GetValue(); + const MIuint64 nValue = pArgContents->GetValue(); + + m_pBufferMemory = new unsigned char[m_nCount]; + if (m_pBufferMemory == nullptr) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE), + m_cmdData.strMiCmd.c_str(), m_nCount)); + return MIstatus::failure; + } + *m_pBufferMemory = static_cast<char>(nValue); + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + lldb::SBError error; + lldb::addr_t addr = static_cast<lldb::addr_t>(m_nAddr + nAddrOffset); + const size_t nBytesWritten = sbProcess.WriteMemory( + addr, (const void *)m_pBufferMemory, (size_t)m_nCount, error); + if (nBytesWritten != static_cast<size_t>(m_nCount)) { + SetError( + CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK), + m_cmdData.strMiCmd.c_str(), m_nCount, addr)); + return MIstatus::failure; + } + if (error.Fail()) { + lldb::SBStream err; + const bool bOk = error.GetDescription(err); + MIunused(bOk); + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES), + m_cmdData.strMiCmd.c_str(), m_nCount, addr, + err.GetData())); + return MIstatus::failure; + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -1507,34 +1553,34 @@ CMICmdCmdDataWriteMemory::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataWriteMemory::Acknowledge() -{ - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); - m_miResultRecord = miRecordResult; +bool CMICmdCmdDataWriteMemory::Acknowledge() { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdDataWriteMemory::CreateSelf() -{ - return new CMICmdCmdDataWriteMemory(); +CMICmdBase *CMICmdCmdDataWriteMemory::CreateSelf() { + return new CMICmdCmdDataWriteMemory(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataInfoLine constructor. // Type: Method. // Args: None. @@ -1542,28 +1588,28 @@ CMICmdCmdDataWriteMemory::CreateSelf() // Throws: None. //-- CMICmdCmdDataInfoLine::CMICmdCmdDataInfoLine() - : m_constStrArgLocation("location") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "data-info-line"; + : m_constStrArgLocation("location") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "data-info-line"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdDataInfoLine::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdDataInfoLine::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdDataInfoLine destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdDataInfoLine::~CMICmdCmdDataInfoLine() -{ -} +CMICmdCmdDataInfoLine::~CMICmdCmdDataInfoLine() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -1571,112 +1617,124 @@ CMICmdCmdDataInfoLine::~CMICmdCmdDataInfoLine() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataInfoLine::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgLocation, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdDataInfoLine::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgLocation, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataInfoLine::Execute() -{ - CMICMDBASE_GETOPTION(pArgLocation, String, m_constStrArgLocation); - - const CMIUtilString &strLocation(pArgLocation->GetValue()); - CMIUtilString strCmdOptionsLocation; - if (strLocation.at(0) == '*') - { - // Parse argument: - // *0x12345 - // ^^^^^^^ -- address - const CMIUtilString strAddress(strLocation.substr(1)); - strCmdOptionsLocation = CMIUtilString::Format("--address %s", strAddress.c_str()); - } - else - { - const size_t nLineStartPos = strLocation.rfind(':'); - if ((nLineStartPos == std::string::npos) || (nLineStartPos == 0) || (nLineStartPos == strLocation.length() - 1)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_LOCATION_FORMAT), m_cmdData.strMiCmd.c_str(), strLocation.c_str()) - .c_str()); - return MIstatus::failure; - } - // Parse argument: - // hello.cpp:5 - // ^^^^^^^^^ -- file - // ^ -- line - const CMIUtilString strFile(strLocation.substr(0, nLineStartPos)); - const CMIUtilString strLine(strLocation.substr(nLineStartPos + 1)); - strCmdOptionsLocation = CMIUtilString::Format("--file \"%s\" --line %s", strFile.AddSlashes().c_str(), strLine.c_str()); +bool CMICmdCmdDataInfoLine::Execute() { + CMICMDBASE_GETOPTION(pArgLocation, String, m_constStrArgLocation); + + const CMIUtilString &strLocation(pArgLocation->GetValue()); + CMIUtilString strCmdOptionsLocation; + if (strLocation.at(0) == '*') { + // Parse argument: + // *0x12345 + // ^^^^^^^ -- address + const CMIUtilString strAddress(strLocation.substr(1)); + strCmdOptionsLocation = + CMIUtilString::Format("--address %s", strAddress.c_str()); + } else { + const size_t nLineStartPos = strLocation.rfind(':'); + if ((nLineStartPos == std::string::npos) || (nLineStartPos == 0) || + (nLineStartPos == strLocation.length() - 1)) { + SetError( + CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_LOCATION_FORMAT), + m_cmdData.strMiCmd.c_str(), strLocation.c_str()) + .c_str()); + return MIstatus::failure; } - const CMIUtilString strCmd(CMIUtilString::Format("target modules lookup -v %s", strCmdOptionsLocation.c_str())); - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - const lldb::ReturnStatus rtn = rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult); - MIunused(rtn); - - return MIstatus::success; + // Parse argument: + // hello.cpp:5 + // ^^^^^^^^^ -- file + // ^ -- line + const CMIUtilString strFile(strLocation.substr(0, nLineStartPos)); + const CMIUtilString strLine(strLocation.substr(nLineStartPos + 1)); + strCmdOptionsLocation = + CMIUtilString::Format("--file \"%s\" --line %s", + strFile.AddSlashes().c_str(), strLine.c_str()); + } + const CMIUtilString strCmd(CMIUtilString::Format( + "target modules lookup -v %s", strCmdOptionsLocation.c_str())); + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + const lldb::ReturnStatus rtn = + rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand( + strCmd.c_str(), m_lldbResult); + MIunused(rtn); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Helper function for parsing a line entry returned from lldb for the command: +//++ +//------------------------------------------------------------------------------------ +// Details: Helper function for parsing a line entry returned from lldb for the +// command: // target modules lookup -v <location> // where the line entry is of the format: -// LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/file:3[:1] -// start end file line column(opt) +// LineEntry: \[0x0000000100000f37-0x0000000100000f45\): +// /path/file:3[:1] +// start end file +// line column(opt) // Args: input - (R) Input string to parse. // start - (W) String representing the start address. // end - (W) String representing the end address. // file - (W) String representing the file. // line - (W) String representing the line. -// Return: bool - True = input was parsed successfully, false = input could not be parsed. +// Return: bool - True = input was parsed successfully, false = input could not +// be parsed. // Throws: None. //-- -static bool -ParseLLDBLineEntry(const char *input, CMIUtilString &start, CMIUtilString &end, - CMIUtilString &file, CMIUtilString &line) -{ - // Note: Ambiguities arise because the column is optional, and - // because : can appear in filenames or as a byte in a multibyte - // UTF8 character. We keep those cases to a minimum by using regex - // to work on the string from both the left and right, so that what - // is remains is assumed to be the filename. - - // Match LineEntry using regex. - static llvm::Regex g_lineentry_nocol_regex( - llvm::StringRef("^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+)$")); - static llvm::Regex g_lineentry_col_regex( - llvm::StringRef("^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+):[0-9]+$")); - // ^1=start ^2=end ^3=f ^4=line ^5=:col(opt) - - llvm::SmallVector<llvm::StringRef, 6> match; - - // First try matching the LineEntry with the column, - // then try without the column. - const bool ok = g_lineentry_col_regex.match(input, &match) || - g_lineentry_nocol_regex.match(input, &match); - if (ok) - { - start = match[1]; - end = match[2]; - file = match[3]; - line = match[4]; - } - return ok; +static bool ParseLLDBLineEntry(const char *input, CMIUtilString &start, + CMIUtilString &end, CMIUtilString &file, + CMIUtilString &line) { + // Note: Ambiguities arise because the column is optional, and + // because : can appear in filenames or as a byte in a multibyte + // UTF8 character. We keep those cases to a minimum by using regex + // to work on the string from both the left and right, so that what + // is remains is assumed to be the filename. + + // Match LineEntry using regex. + static llvm::Regex g_lineentry_nocol_regex(llvm::StringRef( + "^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+)$")); + static llvm::Regex g_lineentry_col_regex( + llvm::StringRef("^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): " + "(.+):([0-9]+):[0-9]+$")); + // ^1=start ^2=end ^3=f + // ^4=line ^5=:col(opt) + + llvm::SmallVector<llvm::StringRef, 6> match; + + // First try matching the LineEntry with the column, + // then try without the column. + const bool ok = g_lineentry_col_regex.match(input, &match) || + g_lineentry_nocol_regex.match(input, &match); + if (ok) { + start = match[1]; + end = match[2]; + file = match[3]; + line = match[4]; + } + return ok; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -1684,77 +1742,80 @@ ParseLLDBLineEntry(const char *input, CMIUtilString &start, CMIUtilString &end, // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdDataInfoLine::Acknowledge() -{ - if (m_lldbResult.GetErrorSize() > 0) - { - const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - else if (m_lldbResult.GetOutputSize() > 0) - { - CMIUtilString::VecString_t vecLines; - const CMIUtilString strLldbMsg(m_lldbResult.GetOutput()); - const MIuint nLines(strLldbMsg.SplitLines(vecLines)); - - for (MIuint i = 0; i < nLines; ++i) - { - // String looks like: - // LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/to/file:3[:1] - const CMIUtilString &rLine(vecLines[i]); - CMIUtilString strStart; - CMIUtilString strEnd; - CMIUtilString strFile; - CMIUtilString strLine; - - if (!ParseLLDBLineEntry(rLine.c_str(), strStart, strEnd, strFile, strLine)) - continue; - - const CMICmnMIValueConst miValueConst(strStart); - const CMICmnMIValueResult miValueResult("start", miValueConst); - CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, - CMICmnMIResultRecord::eResultClass_Done, - miValueResult); - const CMICmnMIValueConst miValueConst2(strEnd); - const CMICmnMIValueResult miValueResult2("end", miValueConst2); - miRecordResult.Add(miValueResult2); - const CMICmnMIValueConst miValueConst3(strFile); - const CMICmnMIValueResult miValueResult3("file", miValueConst3); - miRecordResult.Add(miValueResult3); - const CMICmnMIValueConst miValueConst4(strLine); - const CMICmnMIValueResult miValueResult4("line", miValueConst4); - miRecordResult.Add(miValueResult4); - - // MI print "%s^done,start=\"%d\",end=\"%d\"",file=\"%s\",line=\"%d\" - m_miResultRecord = miRecordResult; - - return MIstatus::success; - } - } - - // MI print "%s^error,msg=\"Command '-data-info-line'. Error: The LineEntry is absent or has an unknown format.\"" - const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SOME_ERROR), m_cmdData.strMiCmd.c_str(), "The LineEntry is absent or has an unknown format.")); +bool CMICmdCmdDataInfoLine::Acknowledge() { + if (m_lldbResult.GetErrorSize() > 0) { + const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); m_miResultRecord = miRecordResult; - return MIstatus::success; + } else if (m_lldbResult.GetOutputSize() > 0) { + CMIUtilString::VecString_t vecLines; + const CMIUtilString strLldbMsg(m_lldbResult.GetOutput()); + const MIuint nLines(strLldbMsg.SplitLines(vecLines)); + + for (MIuint i = 0; i < nLines; ++i) { + // String looks like: + // LineEntry: \[0x0000000100000f37-0x0000000100000f45\): + // /path/to/file:3[:1] + const CMIUtilString &rLine(vecLines[i]); + CMIUtilString strStart; + CMIUtilString strEnd; + CMIUtilString strFile; + CMIUtilString strLine; + + if (!ParseLLDBLineEntry(rLine.c_str(), strStart, strEnd, strFile, + strLine)) + continue; + + const CMICmnMIValueConst miValueConst(strStart); + const CMICmnMIValueResult miValueResult("start", miValueConst); + CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + const CMICmnMIValueConst miValueConst2(strEnd); + const CMICmnMIValueResult miValueResult2("end", miValueConst2); + miRecordResult.Add(miValueResult2); + const CMICmnMIValueConst miValueConst3(strFile); + const CMICmnMIValueResult miValueResult3("file", miValueConst3); + miRecordResult.Add(miValueResult3); + const CMICmnMIValueConst miValueConst4(strLine); + const CMICmnMIValueResult miValueResult4("line", miValueConst4); + miRecordResult.Add(miValueResult4); + + // MI print "%s^done,start=\"%d\",end=\"%d\"",file=\"%s\",line=\"%d\" + m_miResultRecord = miRecordResult; + + return MIstatus::success; + } + } + + // MI print "%s^error,msg=\"Command '-data-info-line'. Error: The LineEntry is + // absent or has an unknown format.\"" + const CMICmnMIValueConst miValueConst(CMIUtilString::Format( + MIRSRC(IDS_CMD_ERR_SOME_ERROR), m_cmdData.strMiCmd.c_str(), + "The LineEntry is absent or has an unknown format.")); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdDataInfoLine::CreateSelf() -{ - return new CMICmdCmdDataInfoLine(); +CMICmdBase *CMICmdCmdDataInfoLine::CreateSelf() { + return new CMICmdCmdDataInfoLine(); } diff --git a/lldb/tools/lldb-mi/MICmdCmdData.h b/lldb/tools/lldb-mi/MICmdCmdData.h index a67fd6beaf7..683e41022af 100644 --- a/lldb/tools/lldb-mi/MICmdCmdData.h +++ b/lldb/tools/lldb-mi/MICmdCmdData.h @@ -18,13 +18,16 @@ // CMICmdCmdDataWriteMemory interface. // CMICmdCmdDataInfoLine interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands derive a new command class from the +// command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// For an introduction to adding a new command see +// CMICmdCmdSupportInfoMiCmdQuery // command class as an example. // @@ -36,332 +39,344 @@ // In-house headers: #include "MICmdBase.h" -#include "MICmnMIValueTuple.h" -#include "MICmnMIValueList.h" #include "MICmnLLDBDebugSessionInfoVarObj.h" +#include "MICmnMIValueList.h" +#include "MICmnMIValueTuple.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "data-evaluate-expression". //-- -class CMICmdCmdDataEvaluateExpression : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdDataEvaluateExpression(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdDataEvaluateExpression() override; - - // Methods: - private: - bool HaveInvalidCharacterInExpression(const CMIUtilString &vrExpr, char &vrwInvalidChar); - - // Attributes: - private: - bool m_bExpressionValid; // True = yes is valid, false = not valid - bool m_bEvaluatedExpression; // True = yes is expression evaluated, false = failed - lldb::SBError m_Error; // Error object, which is examined when m_bEvaluatedExpression is false - CMIUtilString m_strValue; - CMICmnMIValueTuple m_miValueTuple; - bool m_bFoundInvalidChar; // True = yes found unexpected character in the expression, false = all ok - char m_cExpressionInvalidChar; - const CMIUtilString m_constStrArgExpr; +class CMICmdCmdDataEvaluateExpression : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdDataEvaluateExpression(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdDataEvaluateExpression() override; + + // Methods: +private: + bool HaveInvalidCharacterInExpression(const CMIUtilString &vrExpr, + char &vrwInvalidChar); + + // Attributes: +private: + bool m_bExpressionValid; // True = yes is valid, false = not valid + bool m_bEvaluatedExpression; // True = yes is expression evaluated, false = + // failed + lldb::SBError m_Error; // Error object, which is examined when + // m_bEvaluatedExpression is false + CMIUtilString m_strValue; + CMICmnMIValueTuple m_miValueTuple; + bool m_bFoundInvalidChar; // True = yes found unexpected character in the + // expression, false = all ok + char m_cExpressionInvalidChar; + const CMIUtilString m_constStrArgExpr; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "data-disassemble". //-- -class CMICmdCmdDataDisassemble : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdDataDisassemble(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdDataDisassemble() override; - - // Attributes: - private: - const CMIUtilString m_constStrArgAddrStart; // MI spec non mandatory, *this command mandatory - const CMIUtilString m_constStrArgAddrEnd; // MI spec non mandatory, *this command mandatory - const CMIUtilString m_constStrArgMode; - CMICmnMIValueList m_miValueList; +class CMICmdCmdDataDisassemble : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdDataDisassemble(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdDataDisassemble() override; + + // Attributes: +private: + const CMIUtilString + m_constStrArgAddrStart; // MI spec non mandatory, *this command mandatory + const CMIUtilString + m_constStrArgAddrEnd; // MI spec non mandatory, *this command mandatory + const CMIUtilString m_constStrArgMode; + CMICmnMIValueList m_miValueList; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "data-read-memory-bytes". //-- -class CMICmdCmdDataReadMemoryBytes : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdDataReadMemoryBytes(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdDataReadMemoryBytes() override; - - // Attributes: - private: - const CMIUtilString m_constStrArgByteOffset; - const CMIUtilString m_constStrArgAddrExpr; - const CMIUtilString m_constStrArgNumBytes; - unsigned char *m_pBufferMemory; - MIuint64 m_nAddrStart; - MIuint64 m_nAddrNumBytesToRead; +class CMICmdCmdDataReadMemoryBytes : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdDataReadMemoryBytes(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdDataReadMemoryBytes() override; + + // Attributes: +private: + const CMIUtilString m_constStrArgByteOffset; + const CMIUtilString m_constStrArgAddrExpr; + const CMIUtilString m_constStrArgNumBytes; + unsigned char *m_pBufferMemory; + MIuint64 m_nAddrStart; + MIuint64 m_nAddrNumBytesToRead; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "data-read-memory". //-- -class CMICmdCmdDataReadMemory : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdDataReadMemory(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdDataReadMemory() override; +class CMICmdCmdDataReadMemory : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdDataReadMemory(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdDataReadMemory() override; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "data-list-register-names". //-- -class CMICmdCmdDataListRegisterNames : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdDataListRegisterNames(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdDataListRegisterNames() override; - - // Methods: - private: - lldb::SBValue GetRegister(const MIuint vRegisterIndex) const; - - // Attributes: - private: - const CMIUtilString m_constStrArgRegNo; // Not handled by *this command - CMICmnMIValueList m_miValueList; +class CMICmdCmdDataListRegisterNames : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdDataListRegisterNames(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdDataListRegisterNames() override; + + // Methods: +private: + lldb::SBValue GetRegister(const MIuint vRegisterIndex) const; + + // Attributes: +private: + const CMIUtilString m_constStrArgRegNo; // Not handled by *this command + CMICmnMIValueList m_miValueList; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "data-list-register-values". //-- -class CMICmdCmdDataListRegisterValues : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdDataListRegisterValues(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdDataListRegisterValues() override; - - // Methods: - private: - lldb::SBValue GetRegister(const MIuint vRegisterIndex) const; - void AddToOutput(const MIuint vnIndex, const lldb::SBValue &vrValue, CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat); - - // Attributes: - private: - const CMIUtilString m_constStrArgSkip; // Not handled by *this command - const CMIUtilString m_constStrArgFormat; - const CMIUtilString m_constStrArgRegNo; - CMICmnMIValueList m_miValueList; +class CMICmdCmdDataListRegisterValues : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdDataListRegisterValues(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdDataListRegisterValues() override; + + // Methods: +private: + lldb::SBValue GetRegister(const MIuint vRegisterIndex) const; + void AddToOutput(const MIuint vnIndex, const lldb::SBValue &vrValue, + CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat); + + // Attributes: +private: + const CMIUtilString m_constStrArgSkip; // Not handled by *this command + const CMIUtilString m_constStrArgFormat; + const CMIUtilString m_constStrArgRegNo; + CMICmnMIValueList m_miValueList; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "data-list-changed-registers". //-- -class CMICmdCmdDataListRegisterChanged : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdDataListRegisterChanged(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdDataListRegisterChanged() override; +class CMICmdCmdDataListRegisterChanged : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdDataListRegisterChanged(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdDataListRegisterChanged() override; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "data-read-memory-bytes". //-- -class CMICmdCmdDataWriteMemoryBytes : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdDataWriteMemoryBytes(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdDataWriteMemoryBytes() override; - - // Attributes: - private: - const CMIUtilString m_constStrArgAddr; - const CMIUtilString m_constStrArgContents; - const CMIUtilString m_constStrArgCount; - CMIUtilString m_strContents; +class CMICmdCmdDataWriteMemoryBytes : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdDataWriteMemoryBytes(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdDataWriteMemoryBytes() override; + + // Attributes: +private: + const CMIUtilString m_constStrArgAddr; + const CMIUtilString m_constStrArgContents; + const CMIUtilString m_constStrArgCount; + CMIUtilString m_strContents; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "data-read-memory". // Not specified in MI spec but Eclipse gives *this command. //-- -class CMICmdCmdDataWriteMemory : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdDataWriteMemory(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdDataWriteMemory() override; - - // Attributes: - private: - const CMIUtilString m_constStrArgOffset; // Not specified in MI spec but Eclipse gives this option. - const CMIUtilString m_constStrArgAddr; // Not specified in MI spec but Eclipse gives this option. - const CMIUtilString m_constStrArgD; // Not specified in MI spec but Eclipse gives this option. - const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option. - const CMIUtilString m_constStrArgContents; // Not specified in MI spec but Eclipse gives this option. - MIuint64 m_nAddr; - CMIUtilString m_strContents; - MIuint64 m_nCount; - unsigned char *m_pBufferMemory; +class CMICmdCmdDataWriteMemory : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdDataWriteMemory(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdDataWriteMemory() override; + + // Attributes: +private: + const CMIUtilString m_constStrArgOffset; // Not specified in MI spec but + // Eclipse gives this option. + const CMIUtilString m_constStrArgAddr; // Not specified in MI spec but Eclipse + // gives this option. + const CMIUtilString + m_constStrArgD; // Not specified in MI spec but Eclipse gives this option. + const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but + // Eclipse gives this option. + const CMIUtilString m_constStrArgContents; // Not specified in MI spec but + // Eclipse gives this option. + MIuint64 m_nAddr; + CMIUtilString m_strContents; + MIuint64 m_nCount; + unsigned char *m_pBufferMemory; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "data-info-line". // See MIExtensions.txt for details. //-- -class CMICmdCmdDataInfoLine : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdDataInfoLine(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdDataInfoLine() override; - - // Attributes: - private: - lldb::SBCommandReturnObject m_lldbResult; - const CMIUtilString m_constStrArgLocation; +class CMICmdCmdDataInfoLine : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdDataInfoLine(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdDataInfoLine() override; + + // Attributes: +private: + lldb::SBCommandReturnObject m_lldbResult; + const CMIUtilString m_constStrArgLocation; }; diff --git a/lldb/tools/lldb-mi/MICmdCmdEnviro.cpp b/lldb/tools/lldb-mi/MICmdCmdEnviro.cpp index adacc2a5780..808e8f6c49c 100644 --- a/lldb/tools/lldb-mi/MICmdCmdEnviro.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdEnviro.cpp @@ -11,13 +11,14 @@ // In-house headers: #include "MICmdCmdEnviro.h" +#include "MICmdArgValFile.h" +#include "MICmnLLDBDebugSessionInfo.h" +#include "MICmnLLDBDebugger.h" #include "MICmnMIResultRecord.h" #include "MICmnMIValueConst.h" -#include "MICmnLLDBDebugger.h" -#include "MICmnLLDBDebugSessionInfo.h" -#include "MICmdArgValFile.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdEnvironmentCd constructor. // Type: Method. // Args: None. @@ -25,28 +26,28 @@ // Throws: None. //-- CMICmdCmdEnvironmentCd::CMICmdCmdEnvironmentCd() - : m_constStrArgNamePathDir("pathdir") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "environment-cd"; + : m_constStrArgNamePathDir("pathdir") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "environment-cd"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdEnvironmentCd::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdEnvironmentCd::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdEnvironmentCd destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdEnvironmentCd::~CMICmdCmdEnvironmentCd() -{ -} +CMICmdCmdEnvironmentCd::~CMICmdCmdEnvironmentCd() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -54,48 +55,52 @@ CMICmdCmdEnvironmentCd::~CMICmdCmdEnvironmentCd() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdEnvironmentCd::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValFile(m_constStrArgNamePathDir, true, true)); - CMICmdArgContext argCntxt(m_cmdData.strMiCmdOption); - return ParseValidateCmdOptions(); +bool CMICmdCmdEnvironmentCd::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValFile(m_constStrArgNamePathDir, true, true)); + CMICmdArgContext argCntxt(m_cmdData.strMiCmdOption); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdEnvironmentCd::Execute() -{ - CMICMDBASE_GETOPTION(pArgPathDir, File, m_constStrArgNamePathDir); - const CMIUtilString &strWkDir(pArgPathDir->GetValue()); - CMICmnLLDBDebugger &rDbg(CMICmnLLDBDebugger::Instance()); - lldb::SBDebugger &rLldbDbg = rDbg.GetTheDebugger(); - bool bOk = rLldbDbg.SetCurrentPlatformSDKRoot(strWkDir.c_str()); - if (bOk) - { - const CMIUtilString &rStrKeyWkDir(m_rLLDBDebugSessionInfo.m_constStrSharedDataKeyWkDir); - if (!m_rLLDBDebugSessionInfo.SharedDataAdd<CMIUtilString>(rStrKeyWkDir, strWkDir)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD), m_cmdData.strMiCmd.c_str(), rStrKeyWkDir.c_str())); - bOk = MIstatus::failure; - } +bool CMICmdCmdEnvironmentCd::Execute() { + CMICMDBASE_GETOPTION(pArgPathDir, File, m_constStrArgNamePathDir); + const CMIUtilString &strWkDir(pArgPathDir->GetValue()); + CMICmnLLDBDebugger &rDbg(CMICmnLLDBDebugger::Instance()); + lldb::SBDebugger &rLldbDbg = rDbg.GetTheDebugger(); + bool bOk = rLldbDbg.SetCurrentPlatformSDKRoot(strWkDir.c_str()); + if (bOk) { + const CMIUtilString &rStrKeyWkDir( + m_rLLDBDebugSessionInfo.m_constStrSharedDataKeyWkDir); + if (!m_rLLDBDebugSessionInfo.SharedDataAdd<CMIUtilString>(rStrKeyWkDir, + strWkDir)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD), + m_cmdData.strMiCmd.c_str(), + rStrKeyWkDir.c_str())); + bOk = MIstatus::failure; } - else - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FNFAILED), m_cmdData.strMiCmd.c_str(), "SetCurrentPlatformSDKRoot()")); + } else + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FNFAILED), + m_cmdData.strMiCmd.c_str(), + "SetCurrentPlatformSDKRoot()")); - return bOk; + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -103,35 +108,38 @@ CMICmdCmdEnvironmentCd::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdEnvironmentCd::Acknowledge() -{ - const CMIUtilString &rStrKeyWkDir(m_rLLDBDebugSessionInfo.m_constStrSharedDataKeyWkDir); - CMIUtilString strWkDir; - const bool bOk = m_rLLDBDebugSessionInfo.SharedDataRetrieve<CMIUtilString>(rStrKeyWkDir, strWkDir); - if (bOk) - { - const CMICmnMIValueConst miValueConst(strWkDir); - const CMICmnMIValueResult miValueResult("path", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } +bool CMICmdCmdEnvironmentCd::Acknowledge() { + const CMIUtilString &rStrKeyWkDir( + m_rLLDBDebugSessionInfo.m_constStrSharedDataKeyWkDir); + CMIUtilString strWkDir; + const bool bOk = m_rLLDBDebugSessionInfo.SharedDataRetrieve<CMIUtilString>( + rStrKeyWkDir, strWkDir); + if (bOk) { + const CMICmnMIValueConst miValueConst(strWkDir); + const CMICmnMIValueResult miValueResult("path", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SHARED_DATA_NOT_FOUND), m_cmdData.strMiCmd.c_str(), rStrKeyWkDir.c_str())); - return MIstatus::failure; + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SHARED_DATA_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), + rStrKeyWkDir.c_str())); + return MIstatus::failure; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdEnvironmentCd::CreateSelf() -{ - return new CMICmdCmdEnvironmentCd(); +CMICmdBase *CMICmdCmdEnvironmentCd::CreateSelf() { + return new CMICmdCmdEnvironmentCd(); } diff --git a/lldb/tools/lldb-mi/MICmdCmdEnviro.h b/lldb/tools/lldb-mi/MICmdCmdEnviro.h index 6f06cb69c7e..5c663203143 100644 --- a/lldb/tools/lldb-mi/MICmdCmdEnviro.h +++ b/lldb/tools/lldb-mi/MICmdCmdEnviro.h @@ -9,47 +9,50 @@ // Overview: CMICmdCmdEnvironmentCd interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands derive a new command class from the +// command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// For an introduction to adding a new command see +// CMICmdCmdSupportInfoMiCmdQuery // command class as an example. #pragma once // In-house headers: #include "MICmdBase.h" -#include "MICmnMIValueTuple.h" #include "MICmnMIValueList.h" +#include "MICmnMIValueTuple.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "environment-cd". //-- -class CMICmdCmdEnvironmentCd : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); +class CMICmdCmdEnvironmentCd : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); - // Methods: - public: - /* ctor */ CMICmdCmdEnvironmentCd(); + // Methods: +public: + /* ctor */ CMICmdCmdEnvironmentCd(); - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdEnvironmentCd() override; + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdEnvironmentCd() override; - // Attributes: - private: - const CMIUtilString m_constStrArgNamePathDir; + // Attributes: +private: + const CMIUtilString m_constStrArgNamePathDir; }; diff --git a/lldb/tools/lldb-mi/MICmdCmdExec.cpp b/lldb/tools/lldb-mi/MICmdCmdExec.cpp index dccfe129b2c..8fa63f4d98e 100644 --- a/lldb/tools/lldb-mi/MICmdCmdExec.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdExec.cpp @@ -25,51 +25,51 @@ #include "lldb/lldb-enumerations.h" // In-house headers: -#include "MICmdCmdExec.h" -#include "MICmnMIResultRecord.h" -#include "MICmnMIValueConst.h" -#include "MICmnLLDBDebugger.h" -#include "MICmnLLDBDebugSessionInfo.h" -#include "MIDriver.h" +#include "MICmdArgValListOfN.h" #include "MICmdArgValNumber.h" -#include "MICmdArgValString.h" -#include "MICmdArgValThreadGrp.h" #include "MICmdArgValOptionLong.h" #include "MICmdArgValOptionShort.h" -#include "MICmdArgValListOfN.h" -#include "MICmnStreamStdout.h" +#include "MICmdArgValString.h" +#include "MICmdArgValThreadGrp.h" +#include "MICmdCmdExec.h" +#include "MICmnLLDBDebugSessionInfo.h" +#include "MICmnLLDBDebugger.h" #include "MICmnMIOutOfBandRecord.h" +#include "MICmnMIResultRecord.h" +#include "MICmnMIValueConst.h" +#include "MICmnStreamStdout.h" +#include "MIDriver.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecRun constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdExecRun::CMICmdCmdExecRun() - : m_constStrArgStart("start") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "exec-run"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdExecRun::CreateSelf; +CMICmdCmdExecRun::CMICmdCmdExecRun() : m_constStrArgStart("start") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "exec-run"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdExecRun::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecRun destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdExecRun::~CMICmdCmdExecRun() -{ -} +CMICmdCmdExecRun::~CMICmdCmdExecRun() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. It parses the command line options' +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. It parses the command line +// options' // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -77,57 +77,62 @@ CMICmdCmdExecRun::~CMICmdCmdExecRun() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecRun::ParseArgs() -{ - m_setCmdArgs.Add( - new CMICmdArgValOptionLong(m_constStrArgStart, false, true, CMICmdArgValListBase::eArgValType_OptionLong, 0)); - return ParseValidateCmdOptions(); +bool CMICmdCmdExecRun::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValOptionLong( + m_constStrArgStart, false, true, + CMICmdArgValListBase::eArgValType_OptionLong, 0)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecRun::Execute() -{ - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBError error; - lldb::SBStream errMsg; - lldb::SBLaunchInfo launchInfo = rSessionInfo.GetTarget().GetLaunchInfo(); - launchInfo.SetListener(rSessionInfo.GetListener()); - - // Run to first instruction or main() requested? - CMICMDBASE_GETOPTION(pArgStart, OptionLong, m_constStrArgStart); - if (pArgStart->GetFound()) - { - launchInfo.SetLaunchFlags(launchInfo.GetLaunchFlags() | lldb::eLaunchFlagStopAtEntry); - } - - lldb::SBProcess process = rSessionInfo.GetTarget().Launch(launchInfo, error); - if ((!process.IsValid()) || (error.Fail())) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str(), errMsg.GetData())); - return MIstatus::failure; - } - - if (!CMIDriver::Instance().SetDriverStateRunningDebugging()) - { - const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE), m_cmdData.strMiCmd.c_str(), rErrMsg.c_str())); - return MIstatus::failure; - } - return MIstatus::success; +bool CMICmdCmdExecRun::Execute() { + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBError error; + lldb::SBStream errMsg; + lldb::SBLaunchInfo launchInfo = rSessionInfo.GetTarget().GetLaunchInfo(); + launchInfo.SetListener(rSessionInfo.GetListener()); + + // Run to first instruction or main() requested? + CMICMDBASE_GETOPTION(pArgStart, OptionLong, m_constStrArgStart); + if (pArgStart->GetFound()) { + launchInfo.SetLaunchFlags(launchInfo.GetLaunchFlags() | + lldb::eLaunchFlagStopAtEntry); + } + + lldb::SBProcess process = rSessionInfo.GetTarget().Launch(launchInfo, error); + if ((!process.IsValid()) || (error.Fail())) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), + m_cmdData.strMiCmd.c_str(), + errMsg.GetData())); + return MIstatus::failure; + } + + if (!CMIDriver::Instance().SetDriverStateRunningDebugging()) { + const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE), + m_cmdData.strMiCmd.c_str(), + rErrMsg.c_str())); + return MIstatus::failure; + } + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Called only if Execute() set status as successful on completion. // Type: Overridden. @@ -136,117 +141,119 @@ CMICmdCmdExecRun::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecRun::Acknowledge() -{ - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); - m_miResultRecord = miRecordResult; - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID(); - // Give the client '=thread-group-started,id="i1" pid="xyz"' - m_bHasResultRecordExtra = true; - const CMICmnMIValueConst miValueConst2("i1"); - const CMICmnMIValueResult miValueResult2("id", miValueConst2); - const CMIUtilString strPid(CMIUtilString::Format("%lld", pid)); - const CMICmnMIValueConst miValueConst(strPid); - const CMICmnMIValueResult miValueResult("pid", miValueConst); - CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2); - miOutOfBand.Add(miValueResult); - m_miResultRecordExtra = miOutOfBand.GetString(); - - return MIstatus::success; +bool CMICmdCmdExecRun::Acknowledge() { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); + m_miResultRecord = miRecordResult; + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID(); + // Give the client '=thread-group-started,id="i1" pid="xyz"' + m_bHasResultRecordExtra = true; + const CMICmnMIValueConst miValueConst2("i1"); + const CMICmnMIValueResult miValueResult2("id", miValueConst2); + const CMIUtilString strPid(CMIUtilString::Format("%lld", pid)); + const CMICmnMIValueConst miValueConst(strPid); + const CMICmnMIValueResult miValueResult("pid", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBand( + CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2); + miOutOfBand.Add(miValueResult); + m_miResultRecordExtra = miOutOfBand.GetString(); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdExecRun::CreateSelf() -{ - return new CMICmdCmdExecRun(); -} +CMICmdBase *CMICmdCmdExecRun::CreateSelf() { return new CMICmdCmdExecRun(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecContinue constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdExecContinue::CMICmdCmdExecContinue() -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "exec-continue"; +CMICmdCmdExecContinue::CMICmdCmdExecContinue() { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "exec-continue"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdExecContinue::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdExecContinue::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecContinue destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdExecContinue::~CMICmdCmdExecContinue() -{ -} - -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +CMICmdCmdExecContinue::~CMICmdCmdExecContinue() {} + +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecContinue::Execute() -{ - const char *pCmd = "continue"; - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - const lldb::ReturnStatus rtn = rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(pCmd, m_lldbResult); - MIunused(rtn); - - if (m_lldbResult.GetErrorSize() == 0) - { - // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM - if (!CMIDriver::Instance().SetDriverStateRunningDebugging()) - { - const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE), m_cmdData.strMiCmd.c_str(), rErrMsg.c_str())); - return MIstatus::failure; - } +bool CMICmdCmdExecContinue::Execute() { + const char *pCmd = "continue"; + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + const lldb::ReturnStatus rtn = + rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand( + pCmd, m_lldbResult); + MIunused(rtn); + + if (m_lldbResult.GetErrorSize() == 0) { + // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM + if (!CMIDriver::Instance().SetDriverStateRunningDebugging()) { + const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE), + m_cmdData.strMiCmd.c_str(), + rErrMsg.c_str())); + return MIstatus::failure; } - else - { - // ToDo: Re-evaluate if this is required when application near finished as this is parsing LLDB error message - // which seems a hack and is code brittle - const char *pLldbErr = m_lldbResult.GetError(); - const CMIUtilString strLldbMsg(CMIUtilString(pLldbErr).StripCREndOfLine()); - if (strLldbMsg == "error: Process must be launched.") - { - CMIDriver::Instance().SetExitApplicationFlag(true); - } + } else { + // ToDo: Re-evaluate if this is required when application near finished as + // this is parsing LLDB error message + // which seems a hack and is code brittle + const char *pLldbErr = m_lldbResult.GetError(); + const CMIUtilString strLldbMsg(CMIUtilString(pLldbErr).StripCREndOfLine()); + if (strLldbMsg == "error: Process must be launched.") { + CMIDriver::Instance().SetExitApplicationFlag(true); } + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -254,73 +261,71 @@ CMICmdCmdExecContinue::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecContinue::Acknowledge() -{ - if (m_lldbResult.GetErrorSize() > 0) - { - const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); - const CMICmnMIValueResult miValueResult("message", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; - } - else - { - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); - m_miResultRecord = miRecordResult; - } +bool CMICmdCmdExecContinue::Acknowledge() { + if (m_lldbResult.GetErrorSize() > 0) { + const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); + const CMICmnMIValueResult miValueResult("message", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + } else { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); + m_miResultRecord = miRecordResult; + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdExecContinue::CreateSelf() -{ - return new CMICmdCmdExecContinue(); +CMICmdBase *CMICmdCmdExecContinue::CreateSelf() { + return new CMICmdCmdExecContinue(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecNext constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdExecNext::CMICmdCmdExecNext() - : m_constStrArgNumber("number") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "exec-next"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdExecNext::CreateSelf; +CMICmdCmdExecNext::CMICmdCmdExecNext() : m_constStrArgNumber("number") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "exec-next"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdExecNext::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecNext destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdExecNext::~CMICmdCmdExecNext() -{ -} +CMICmdCmdExecNext::~CMICmdCmdExecNext() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -328,47 +333,52 @@ CMICmdCmdExecNext::~CMICmdCmdExecNext() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecNext::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, false, false)); - return ParseValidateCmdOptions(); +bool CMICmdCmdExecNext::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, false, false)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecNext::Execute() -{ - CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); - - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); - return MIstatus::failure; - } - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); - CMIUtilString strCmd("thread step-over"); - if (nThreadId != UINT64_MAX) - strCmd += CMIUtilString::Format(" %llu", nThreadId); - rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, false); - - return MIstatus::success; +bool CMICmdCmdExecNext::Execute() { + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (pArgThread->GetFound() && + !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), + m_cmdData.strMiCmd.c_str(), + m_constStrArgThread.c_str())); + return MIstatus::failure; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); + CMIUtilString strCmd("thread step-over"); + if (nThreadId != UINT64_MAX) + strCmd += CMIUtilString::Format(" %llu", nThreadId); + rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, + false); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -376,75 +386,71 @@ CMICmdCmdExecNext::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecNext::Acknowledge() -{ - if (m_lldbResult.GetErrorSize() > 0) - { - const char *pLldbErr = m_lldbResult.GetError(); - MIunused(pLldbErr); - const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); - const CMICmnMIValueResult miValueResult("message", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; - } - else - { - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); - m_miResultRecord = miRecordResult; - } +bool CMICmdCmdExecNext::Acknowledge() { + if (m_lldbResult.GetErrorSize() > 0) { + const char *pLldbErr = m_lldbResult.GetError(); + MIunused(pLldbErr); + const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); + const CMICmnMIValueResult miValueResult("message", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + } else { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); + m_miResultRecord = miRecordResult; + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdExecNext::CreateSelf() -{ - return new CMICmdCmdExecNext(); -} +CMICmdBase *CMICmdCmdExecNext::CreateSelf() { return new CMICmdCmdExecNext(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecStep constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdExecStep::CMICmdCmdExecStep() - : m_constStrArgNumber("number") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "exec-step"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdExecStep::CreateSelf; +CMICmdCmdExecStep::CMICmdCmdExecStep() : m_constStrArgNumber("number") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "exec-step"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdExecStep::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecStep destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdExecStep::~CMICmdCmdExecStep() -{ -} +CMICmdCmdExecStep::~CMICmdCmdExecStep() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -452,47 +458,52 @@ CMICmdCmdExecStep::~CMICmdCmdExecStep() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecStep::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, false, false)); - return ParseValidateCmdOptions(); +bool CMICmdCmdExecStep::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, false, false)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecStep::Execute() -{ - CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); - - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); - return MIstatus::failure; - } - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); - CMIUtilString strCmd("thread step-in"); - if (nThreadId != UINT64_MAX) - strCmd += CMIUtilString::Format(" %llu", nThreadId); - rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, false); - - return MIstatus::success; +bool CMICmdCmdExecStep::Execute() { + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (pArgThread->GetFound() && + !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), + m_constStrArgThread.c_str())); + return MIstatus::failure; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); + CMIUtilString strCmd("thread step-in"); + if (nThreadId != UINT64_MAX) + strCmd += CMIUtilString::Format(" %llu", nThreadId); + rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, + false); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -500,46 +511,43 @@ CMICmdCmdExecStep::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecStep::Acknowledge() -{ - if (m_lldbResult.GetErrorSize() > 0) - { - const char *pLldbErr = m_lldbResult.GetError(); - MIunused(pLldbErr); - const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); - const CMICmnMIValueResult miValueResult("message", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; - } - else - { - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); - m_miResultRecord = miRecordResult; - } +bool CMICmdCmdExecStep::Acknowledge() { + if (m_lldbResult.GetErrorSize() > 0) { + const char *pLldbErr = m_lldbResult.GetError(); + MIunused(pLldbErr); + const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); + const CMICmnMIValueResult miValueResult("message", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + } else { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); + m_miResultRecord = miRecordResult; + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdExecStep::CreateSelf() -{ - return new CMICmdCmdExecStep(); -} +CMICmdBase *CMICmdCmdExecStep::CreateSelf() { return new CMICmdCmdExecStep(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecNextInstruction constructor. // Type: Method. // Args: None. @@ -547,28 +555,28 @@ CMICmdCmdExecStep::CreateSelf() // Throws: None. //-- CMICmdCmdExecNextInstruction::CMICmdCmdExecNextInstruction() - : m_constStrArgNumber("number") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "exec-next-instruction"; + : m_constStrArgNumber("number") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "exec-next-instruction"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdExecNextInstruction::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdExecNextInstruction::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecNextInstruction destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdExecNextInstruction::~CMICmdCmdExecNextInstruction() -{ -} +CMICmdCmdExecNextInstruction::~CMICmdCmdExecNextInstruction() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -576,47 +584,52 @@ CMICmdCmdExecNextInstruction::~CMICmdCmdExecNextInstruction() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecNextInstruction::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, false, false)); - return ParseValidateCmdOptions(); +bool CMICmdCmdExecNextInstruction::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, false, false)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecNextInstruction::Execute() -{ - CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); - - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); - return MIstatus::failure; - } - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); - CMIUtilString strCmd("thread step-inst-over"); - if (nThreadId != UINT64_MAX) - strCmd += CMIUtilString::Format(" %llu", nThreadId); - rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, false); - - return MIstatus::success; +bool CMICmdCmdExecNextInstruction::Execute() { + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (pArgThread->GetFound() && + !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), + m_constStrArgThread.c_str())); + return MIstatus::failure; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); + CMIUtilString strCmd("thread step-inst-over"); + if (nThreadId != UINT64_MAX) + strCmd += CMIUtilString::Format(" %llu", nThreadId); + rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, + false); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -624,46 +637,45 @@ CMICmdCmdExecNextInstruction::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecNextInstruction::Acknowledge() -{ - if (m_lldbResult.GetErrorSize() > 0) - { - const char *pLldbErr = m_lldbResult.GetError(); - MIunused(pLldbErr); - const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); - const CMICmnMIValueResult miValueResult("message", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; - } - else - { - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); - m_miResultRecord = miRecordResult; - } +bool CMICmdCmdExecNextInstruction::Acknowledge() { + if (m_lldbResult.GetErrorSize() > 0) { + const char *pLldbErr = m_lldbResult.GetError(); + MIunused(pLldbErr); + const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); + const CMICmnMIValueResult miValueResult("message", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + } else { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); + m_miResultRecord = miRecordResult; + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdExecNextInstruction::CreateSelf() -{ - return new CMICmdCmdExecNextInstruction(); +CMICmdBase *CMICmdCmdExecNextInstruction::CreateSelf() { + return new CMICmdCmdExecNextInstruction(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecStepInstruction constructor. // Type: Method. // Args: None. @@ -671,28 +683,28 @@ CMICmdCmdExecNextInstruction::CreateSelf() // Throws: None. //-- CMICmdCmdExecStepInstruction::CMICmdCmdExecStepInstruction() - : m_constStrArgNumber("number") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "exec-step-instruction"; + : m_constStrArgNumber("number") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "exec-step-instruction"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdExecStepInstruction::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdExecStepInstruction::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecStepInstruction destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdExecStepInstruction::~CMICmdCmdExecStepInstruction() -{ -} +CMICmdCmdExecStepInstruction::~CMICmdCmdExecStepInstruction() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -700,47 +712,52 @@ CMICmdCmdExecStepInstruction::~CMICmdCmdExecStepInstruction() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecStepInstruction::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, false, false)); - return ParseValidateCmdOptions(); +bool CMICmdCmdExecStepInstruction::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, false, false)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecStepInstruction::Execute() -{ - CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); - - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); - return MIstatus::failure; - } - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); - CMIUtilString strCmd("thread step-inst"); - if (nThreadId != UINT64_MAX) - strCmd += CMIUtilString::Format(" %llu", nThreadId); - rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, false); - - return MIstatus::success; +bool CMICmdCmdExecStepInstruction::Execute() { + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (pArgThread->GetFound() && + !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), + m_constStrArgThread.c_str())); + return MIstatus::failure; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); + CMIUtilString strCmd("thread step-inst"); + if (nThreadId != UINT64_MAX) + strCmd += CMIUtilString::Format(" %llu", nThreadId); + rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, + false); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -748,74 +765,73 @@ CMICmdCmdExecStepInstruction::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecStepInstruction::Acknowledge() -{ - if (m_lldbResult.GetErrorSize() > 0) - { - const char *pLldbErr = m_lldbResult.GetError(); - MIunused(pLldbErr); - const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); - const CMICmnMIValueResult miValueResult("message", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; - } - else - { - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); - m_miResultRecord = miRecordResult; - } +bool CMICmdCmdExecStepInstruction::Acknowledge() { + if (m_lldbResult.GetErrorSize() > 0) { + const char *pLldbErr = m_lldbResult.GetError(); + MIunused(pLldbErr); + const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); + const CMICmnMIValueResult miValueResult("message", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + } else { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); + m_miResultRecord = miRecordResult; + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdExecStepInstruction::CreateSelf() -{ - return new CMICmdCmdExecStepInstruction(); +CMICmdBase *CMICmdCmdExecStepInstruction::CreateSelf() { + return new CMICmdCmdExecStepInstruction(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecFinish constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdExecFinish::CMICmdCmdExecFinish() -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "exec-finish"; +CMICmdCmdExecFinish::CMICmdCmdExecFinish() { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "exec-finish"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdExecFinish::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdExecFinish::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecFinish destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdExecFinish::~CMICmdCmdExecFinish() -{ -} +CMICmdCmdExecFinish::~CMICmdCmdExecFinish() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -823,46 +839,49 @@ CMICmdCmdExecFinish::~CMICmdCmdExecFinish() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecFinish::ParseArgs() -{ - return ParseValidateCmdOptions(); -} - -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +bool CMICmdCmdExecFinish::ParseArgs() { return ParseValidateCmdOptions(); } + +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecFinish::Execute() -{ - CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); - - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); - return MIstatus::failure; - } - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); - CMIUtilString strCmd("thread step-out"); - if (nThreadId != UINT64_MAX) - strCmd += CMIUtilString::Format(" %llu", nThreadId); - rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, false); - - return MIstatus::success; +bool CMICmdCmdExecFinish::Execute() { + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (pArgThread->GetFound() && + !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), + m_constStrArgThread.c_str())); + return MIstatus::failure; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); + CMIUtilString strCmd("thread step-out"); + if (nThreadId != UINT64_MAX) + strCmd += CMIUtilString::Format(" %llu", nThreadId); + rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, + false); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -870,103 +889,107 @@ CMICmdCmdExecFinish::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecFinish::Acknowledge() -{ - if (m_lldbResult.GetErrorSize() > 0) - { - const char *pLldbErr = m_lldbResult.GetError(); - MIunused(pLldbErr); - const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); - const CMICmnMIValueResult miValueResult("message", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; - } - else - { - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); - m_miResultRecord = miRecordResult; - } +bool CMICmdCmdExecFinish::Acknowledge() { + if (m_lldbResult.GetErrorSize() > 0) { + const char *pLldbErr = m_lldbResult.GetError(); + MIunused(pLldbErr); + const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); + const CMICmnMIValueResult miValueResult("message", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + } else { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); + m_miResultRecord = miRecordResult; + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdExecFinish::CreateSelf() -{ - return new CMICmdCmdExecFinish(); +CMICmdBase *CMICmdCmdExecFinish::CreateSelf() { + return new CMICmdCmdExecFinish(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecInterrupt constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdExecInterrupt::CMICmdCmdExecInterrupt() -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "exec-interrupt"; +CMICmdCmdExecInterrupt::CMICmdCmdExecInterrupt() { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "exec-interrupt"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdExecInterrupt::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdExecInterrupt::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecInterrupt destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdExecInterrupt::~CMICmdCmdExecInterrupt() -{ -} - -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +CMICmdCmdExecInterrupt::~CMICmdCmdExecInterrupt() {} + +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecInterrupt::Execute() -{ - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); - CMIUtilString strCmd("process interrupt"); - const lldb::ReturnStatus status = rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, false); - MIunused(status); - - // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM - if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging()) - { - const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE), strCmd.c_str(), rErrMsg.c_str())); - return MIstatus::failure; - } - - return MIstatus::success; +bool CMICmdCmdExecInterrupt::Execute() { + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); + CMIUtilString strCmd("process interrupt"); + const lldb::ReturnStatus status = + rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), + m_lldbResult, false); + MIunused(status); + + // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM + if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging()) { + const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE), + strCmd.c_str(), rErrMsg.c_str())); + return MIstatus::failure; + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -974,44 +997,43 @@ CMICmdCmdExecInterrupt::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdExecInterrupt::Acknowledge() -{ - if (m_lldbResult.GetErrorSize() > 0) - { - const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); - const CMICmnMIValueResult miValueResult("message", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; - } - else - { - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); - m_miResultRecord = miRecordResult; - } +bool CMICmdCmdExecInterrupt::Acknowledge() { + if (m_lldbResult.GetErrorSize() > 0) { + const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); + const CMICmnMIValueResult miValueResult("message", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + } else { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdExecInterrupt::CreateSelf() -{ - return new CMICmdCmdExecInterrupt(); +CMICmdBase *CMICmdCmdExecInterrupt::CreateSelf() { + return new CMICmdCmdExecInterrupt(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecArguments constructor. // Type: Method. // Args: None. @@ -1019,28 +1041,28 @@ CMICmdCmdExecInterrupt::CreateSelf() // Throws: None. //-- CMICmdCmdExecArguments::CMICmdCmdExecArguments() - : m_constStrArgArguments("arguments") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "exec-arguments"; + : m_constStrArgArguments("arguments") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "exec-arguments"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdExecArguments::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdExecArguments::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecArguments destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdExecArguments::~CMICmdCmdExecArguments() -{ -} +CMICmdCmdExecArguments::~CMICmdCmdExecArguments() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -1048,55 +1070,58 @@ CMICmdCmdExecArguments::~CMICmdCmdExecArguments() // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdExecArguments::ParseArgs() -{ - m_setCmdArgs.Add( - new CMICmdArgValListOfN(m_constStrArgArguments, false, true, CMICmdArgValListBase::eArgValType_StringAnything)); - return ParseValidateCmdOptions(); +bool CMICmdCmdExecArguments::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValListOfN( + m_constStrArgArguments, false, true, + CMICmdArgValListBase::eArgValType_StringAnything)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdExecArguments::Execute() -{ - CMICMDBASE_GETOPTION(pArgArguments, ListOfN, m_constStrArgArguments); - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBTarget sbTarget = rSessionInfo.GetTarget(); - if (!sbTarget.IsValid()) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT), m_cmdData.strMiCmd.c_str())); - return MIstatus::failure; - } - - lldb::SBLaunchInfo sbLaunchInfo = sbTarget.GetLaunchInfo(); - sbLaunchInfo.SetArguments(NULL, false); - - CMIUtilString strArg; - size_t nArgIndex = 0; - while (pArgArguments->GetExpectedOption<CMICmdArgValString, CMIUtilString>(strArg, nArgIndex)) - { - const char *argv[2] = { strArg.c_str(), NULL }; - sbLaunchInfo.SetArguments(argv, true); - ++nArgIndex; - } - - sbTarget.SetLaunchInfo(sbLaunchInfo); - - return MIstatus::success; +bool CMICmdCmdExecArguments::Execute() { + CMICMDBASE_GETOPTION(pArgArguments, ListOfN, m_constStrArgArguments); + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBTarget sbTarget = rSessionInfo.GetTarget(); + if (!sbTarget.IsValid()) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT), + m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + + lldb::SBLaunchInfo sbLaunchInfo = sbTarget.GetLaunchInfo(); + sbLaunchInfo.SetArguments(NULL, false); + + CMIUtilString strArg; + size_t nArgIndex = 0; + while (pArgArguments->GetExpectedOption<CMICmdArgValString, CMIUtilString>( + strArg, nArgIndex)) { + const char *argv[2] = {strArg.c_str(), NULL}; + sbLaunchInfo.SetArguments(argv, true); + ++nArgIndex; + } + + sbTarget.SetLaunchInfo(sbLaunchInfo); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -1104,92 +1129,95 @@ CMICmdCmdExecArguments::Execute() // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdExecArguments::Acknowledge() -{ - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); - m_miResultRecord = miRecordResult; +bool CMICmdCmdExecArguments::Acknowledge() { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdExecArguments::CreateSelf() -{ - return new CMICmdCmdExecArguments(); +CMICmdBase *CMICmdCmdExecArguments::CreateSelf() { + return new CMICmdCmdExecArguments(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecAbort constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdExecAbort::CMICmdCmdExecAbort() -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "exec-abort"; +CMICmdCmdExecAbort::CMICmdCmdExecAbort() { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "exec-abort"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdExecAbort::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdExecAbort::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdExecAbort destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdExecAbort::~CMICmdCmdExecAbort() -{ -} - -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +CMICmdCmdExecAbort::~CMICmdCmdExecAbort() {} + +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdExecAbort::Execute() -{ - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); - if (!sbProcess.IsValid()) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str())); - return MIstatus::failure; - } - - lldb::SBError sbError = sbProcess.Destroy(); - if (sbError.Fail()) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDBPROCESS_DESTROY), m_cmdData.strMiCmd.c_str(), sbError.GetCString())); - return MIstatus::failure; - } - - return MIstatus::success; +bool CMICmdCmdExecAbort::Execute() { + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + if (!sbProcess.IsValid()) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), + m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + + lldb::SBError sbError = sbProcess.Destroy(); + if (sbError.Fail()) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDBPROCESS_DESTROY), + m_cmdData.strMiCmd.c_str(), + sbError.GetCString())); + return MIstatus::failure; + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -1197,24 +1225,23 @@ CMICmdCmdExecAbort::Execute() // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdExecAbort::Acknowledge() -{ - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); - m_miResultRecord = miRecordResult; - return MIstatus::success; +bool CMICmdCmdExecAbort::Acknowledge() { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdExecAbort::CreateSelf() -{ - return new CMICmdCmdExecAbort(); +CMICmdBase *CMICmdCmdExecAbort::CreateSelf() { + return new CMICmdCmdExecAbort(); } diff --git a/lldb/tools/lldb-mi/MICmdCmdExec.h b/lldb/tools/lldb-mi/MICmdCmdExec.h index c131132870b..46e7783c91e 100644 --- a/lldb/tools/lldb-mi/MICmdCmdExec.h +++ b/lldb/tools/lldb-mi/MICmdCmdExec.h @@ -18,13 +18,16 @@ // CMICmdCmdExecArguments interface. // CMICmdCmdExecAbort interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands derive a new command class from the +// command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// For an introduction to adding a new command see +// CMICmdCmdSupportInfoMiCmdQuery // command class as an example. #pragma once @@ -35,293 +38,299 @@ // In-house headers: #include "MICmdBase.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "exec-run". //-- -class CMICmdCmdExecRun : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdExecRun(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdExecRun() override; - - // Attributes: - private: - const CMIUtilString m_constStrArgStart; // StopAtEntry - run to first instruction or main() if specified - lldb::SBCommandReturnObject m_lldbResult; +class CMICmdCmdExecRun : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdExecRun(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdExecRun() override; + + // Attributes: +private: + const CMIUtilString m_constStrArgStart; // StopAtEntry - run to first + // instruction or main() if specified + lldb::SBCommandReturnObject m_lldbResult; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "exec-continue". //-- -class CMICmdCmdExecContinue : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdExecContinue(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdExecContinue() override; - - // Attributes: - private: - lldb::SBCommandReturnObject m_lldbResult; +class CMICmdCmdExecContinue : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdExecContinue(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdExecContinue() override; + + // Attributes: +private: + lldb::SBCommandReturnObject m_lldbResult; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "exec-next". //-- -class CMICmdCmdExecNext : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdExecNext(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdExecNext() override; - - // Attributes: - private: - lldb::SBCommandReturnObject m_lldbResult; - const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option +class CMICmdCmdExecNext : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdExecNext(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdExecNext() override; + + // Attributes: +private: + lldb::SBCommandReturnObject m_lldbResult; + const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but + // Eclipse gives this option }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "exec-step". //-- -class CMICmdCmdExecStep : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdExecStep(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdExecStep() override; - - // Attributes: - private: - lldb::SBCommandReturnObject m_lldbResult; - const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option +class CMICmdCmdExecStep : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdExecStep(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdExecStep() override; + + // Attributes: +private: + lldb::SBCommandReturnObject m_lldbResult; + const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but + // Eclipse gives this option }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "exec-next-instruction". //-- -class CMICmdCmdExecNextInstruction : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdExecNextInstruction(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdExecNextInstruction() override; - - // Attributes: - private: - lldb::SBCommandReturnObject m_lldbResult; - const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option +class CMICmdCmdExecNextInstruction : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdExecNextInstruction(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdExecNextInstruction() override; + + // Attributes: +private: + lldb::SBCommandReturnObject m_lldbResult; + const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but + // Eclipse gives this option }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "exec-step-instruction". //-- -class CMICmdCmdExecStepInstruction : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdExecStepInstruction(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdExecStepInstruction() override; - - // Attributes: - private: - lldb::SBCommandReturnObject m_lldbResult; - const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but Eclipse gives this option +class CMICmdCmdExecStepInstruction : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdExecStepInstruction(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdExecStepInstruction() override; + + // Attributes: +private: + lldb::SBCommandReturnObject m_lldbResult; + const CMIUtilString m_constStrArgNumber; // Not specified in MI spec but + // Eclipse gives this option }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "exec-finish". //-- -class CMICmdCmdExecFinish : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdExecFinish(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdExecFinish() override; - - // Attributes: - private: - lldb::SBCommandReturnObject m_lldbResult; +class CMICmdCmdExecFinish : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdExecFinish(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdExecFinish() override; + + // Attributes: +private: + lldb::SBCommandReturnObject m_lldbResult; }; // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "exec-interrupt". -// Gotchas: Using Eclipse this command is injected into the command system when a +// Gotchas: Using Eclipse this command is injected into the command system when +// a // SIGINT signal is received while running an inferior program. //-- -class CMICmdCmdExecInterrupt : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdExecInterrupt(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdExecInterrupt() override; - - // Attributes: - private: - lldb::SBCommandReturnObject m_lldbResult; +class CMICmdCmdExecInterrupt : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdExecInterrupt(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdExecInterrupt() override; + + // Attributes: +private: + lldb::SBCommandReturnObject m_lldbResult; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "exec-arguments". //-- -class CMICmdCmdExecArguments : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdExecArguments(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdExecArguments() override; - - // Attributes: - private: - const CMIUtilString m_constStrArgArguments; +class CMICmdCmdExecArguments : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdExecArguments(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdExecArguments() override; + + // Attributes: +private: + const CMIUtilString m_constStrArgArguments; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "exec-abort". //-- -class CMICmdCmdExecAbort : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdExecAbort(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdExecAbort() override; +class CMICmdCmdExecAbort : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdExecAbort(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdExecAbort() override; }; diff --git a/lldb/tools/lldb-mi/MICmdCmdFile.cpp b/lldb/tools/lldb-mi/MICmdCmdFile.cpp index 3316c8eccaf..9e3ea273b07 100644 --- a/lldb/tools/lldb-mi/MICmdCmdFile.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdFile.cpp @@ -13,17 +13,18 @@ #include "lldb/API/SBStream.h" // In-house headers: -#include "MICmdCmdFile.h" -#include "MICmnMIResultRecord.h" -#include "MICmnLLDBDebugger.h" -#include "MICmnLLDBDebugSessionInfo.h" -#include "MIUtilFileStd.h" #include "MICmdArgValFile.h" -#include "MICmdArgValString.h" #include "MICmdArgValOptionLong.h" #include "MICmdArgValOptionShort.h" +#include "MICmdArgValString.h" +#include "MICmdCmdFile.h" +#include "MICmnLLDBDebugSessionInfo.h" +#include "MICmnLLDBDebugger.h" +#include "MICmnMIResultRecord.h" +#include "MIUtilFileStd.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdFileExecAndSymbols constructor. // Type: Method. // Args: None. @@ -31,30 +32,29 @@ // Throws: None. //-- CMICmdCmdFileExecAndSymbols::CMICmdCmdFileExecAndSymbols() - : m_constStrArgNameFile("file") - , m_constStrArgNamedPlatformName("p") - , m_constStrArgNamedRemotePath("r") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "file-exec-and-symbols"; + : m_constStrArgNameFile("file"), m_constStrArgNamedPlatformName("p"), + m_constStrArgNamedRemotePath("r") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "file-exec-and-symbols"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdFileExecAndSymbols::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdFileExecAndSymbols::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdFileExecAndSymbols destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdFileExecAndSymbols::~CMICmdCmdFileExecAndSymbols() -{ -} +CMICmdCmdFileExecAndSymbols::~CMICmdCmdFileExecAndSymbols() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -62,99 +62,107 @@ CMICmdCmdFileExecAndSymbols::~CMICmdCmdFileExecAndSymbols() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdFileExecAndSymbols::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValFile(m_constStrArgNameFile, true, true)); - m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedPlatformName, false, true, - CMICmdArgValListBase::eArgValType_String, 1)); - m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedRemotePath, false, true, - CMICmdArgValListBase::eArgValType_StringQuotedNumberPath, 1)); - return ParseValidateCmdOptions(); +bool CMICmdCmdFileExecAndSymbols::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValFile(m_constStrArgNameFile, true, true)); + m_setCmdArgs.Add( + new CMICmdArgValOptionShort(m_constStrArgNamedPlatformName, false, true, + CMICmdArgValListBase::eArgValType_String, 1)); + m_setCmdArgs.Add(new CMICmdArgValOptionShort( + m_constStrArgNamedRemotePath, false, true, + CMICmdArgValListBase::eArgValType_StringQuotedNumberPath, 1)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Synopsis: -file-exec-and-symbols file -// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-File-Commands.html#GDB_002fMI-File-Commands +// Ref: +// http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-File-Commands.html#GDB_002fMI-File-Commands // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdFileExecAndSymbols::Execute() -{ - CMICMDBASE_GETOPTION(pArgNamedFile, File, m_constStrArgNameFile); - CMICMDBASE_GETOPTION(pArgPlatformName, OptionShort, m_constStrArgNamedPlatformName); - CMICMDBASE_GETOPTION(pArgRemotePath, OptionShort, m_constStrArgNamedRemotePath); - CMICmdArgValFile *pArgFile = static_cast<CMICmdArgValFile *>(pArgNamedFile); - const CMIUtilString &strExeFilePath(pArgFile->GetValue()); - bool bPlatformName = pArgPlatformName->GetFound(); - CMIUtilString platformName; - if (bPlatformName) - { - pArgPlatformName->GetExpectedOption<CMICmdArgValString, CMIUtilString>(platformName); - } - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBDebugger &rDbgr = rSessionInfo.GetDebugger(); - lldb::SBError error; - const char *pTargetTriple = nullptr; // Let LLDB discover the triple required - const char *pTargetPlatformName = platformName.c_str(); - const bool bAddDepModules = false; - lldb::SBTarget target = rDbgr.CreateTarget(strExeFilePath.c_str(), pTargetTriple, pTargetPlatformName, bAddDepModules, error); - CMIUtilString strWkDir; - const CMIUtilString &rStrKeyWkDir(rSessionInfo.m_constStrSharedDataKeyWkDir); - if (!rSessionInfo.SharedDataRetrieve<CMIUtilString>(rStrKeyWkDir, strWkDir)) - { - strWkDir = CMIUtilFileStd::StripOffFileName(strExeFilePath); - if (!rSessionInfo.SharedDataAdd<CMIUtilString>(rStrKeyWkDir, strWkDir)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD), m_cmdData.strMiCmd.c_str(), rStrKeyWkDir.c_str())); - return MIstatus::failure; - } +bool CMICmdCmdFileExecAndSymbols::Execute() { + CMICMDBASE_GETOPTION(pArgNamedFile, File, m_constStrArgNameFile); + CMICMDBASE_GETOPTION(pArgPlatformName, OptionShort, + m_constStrArgNamedPlatformName); + CMICMDBASE_GETOPTION(pArgRemotePath, OptionShort, + m_constStrArgNamedRemotePath); + CMICmdArgValFile *pArgFile = static_cast<CMICmdArgValFile *>(pArgNamedFile); + const CMIUtilString &strExeFilePath(pArgFile->GetValue()); + bool bPlatformName = pArgPlatformName->GetFound(); + CMIUtilString platformName; + if (bPlatformName) { + pArgPlatformName->GetExpectedOption<CMICmdArgValString, CMIUtilString>( + platformName); + } + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBDebugger &rDbgr = rSessionInfo.GetDebugger(); + lldb::SBError error; + const char *pTargetTriple = nullptr; // Let LLDB discover the triple required + const char *pTargetPlatformName = platformName.c_str(); + const bool bAddDepModules = false; + lldb::SBTarget target = + rDbgr.CreateTarget(strExeFilePath.c_str(), pTargetTriple, + pTargetPlatformName, bAddDepModules, error); + CMIUtilString strWkDir; + const CMIUtilString &rStrKeyWkDir(rSessionInfo.m_constStrSharedDataKeyWkDir); + if (!rSessionInfo.SharedDataRetrieve<CMIUtilString>(rStrKeyWkDir, strWkDir)) { + strWkDir = CMIUtilFileStd::StripOffFileName(strExeFilePath); + if (!rSessionInfo.SharedDataAdd<CMIUtilString>(rStrKeyWkDir, strWkDir)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD), + m_cmdData.strMiCmd.c_str(), + rStrKeyWkDir.c_str())); + return MIstatus::failure; } - if (!rDbgr.SetCurrentPlatformSDKRoot(strWkDir.c_str())) - { + } + if (!rDbgr.SetCurrentPlatformSDKRoot(strWkDir.c_str())) { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FNFAILED), m_cmdData.strMiCmd.c_str(), "SetCurrentPlatformSDKRoot()")); - return MIstatus::failure; - } - if (pArgRemotePath->GetFound()) - { - CMIUtilString remotePath; - pArgRemotePath->GetExpectedOption<CMICmdArgValString, CMIUtilString>(remotePath); - lldb::SBModule module = target.FindModule(target.GetExecutable()); - if (module.IsValid()) - { - module.SetPlatformFileSpec(lldb::SBFileSpec(remotePath.c_str())); - } - } - lldb::SBStream err; - if (error.Fail()) - { - const bool bOk = error.GetDescription(err); - MIunused(bOk); - } - if (!target.IsValid()) - { - SetError( - CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET), m_cmdData.strMiCmd.c_str(), strExeFilePath.c_str(), err.GetData())); - return MIstatus::failure; - } - if (error.Fail()) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_CREATE_TARGET), m_cmdData.strMiCmd.c_str(), err.GetData())); - return MIstatus::failure; + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FNFAILED), + m_cmdData.strMiCmd.c_str(), + "SetCurrentPlatformSDKRoot()")); + return MIstatus::failure; + } + if (pArgRemotePath->GetFound()) { + CMIUtilString remotePath; + pArgRemotePath->GetExpectedOption<CMICmdArgValString, CMIUtilString>( + remotePath); + lldb::SBModule module = target.FindModule(target.GetExecutable()); + if (module.IsValid()) { + module.SetPlatformFileSpec(lldb::SBFileSpec(remotePath.c_str())); } + } + lldb::SBStream err; + if (error.Fail()) { + const bool bOk = error.GetDescription(err); + MIunused(bOk); + } + if (!target.IsValid()) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET), + m_cmdData.strMiCmd.c_str(), + strExeFilePath.c_str(), err.GetData())); + return MIstatus::failure; + } + if (error.Fail()) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_CREATE_TARGET), + m_cmdData.strMiCmd.c_str(), err.GetData())); + return MIstatus::failure; + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -162,42 +170,45 @@ CMICmdCmdFileExecAndSymbols::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdFileExecAndSymbols::Acknowledge() -{ - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); - m_miResultRecord = miRecordResult; +bool CMICmdCmdFileExecAndSymbols::Acknowledge() { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdFileExecAndSymbols::CreateSelf() -{ - return new CMICmdCmdFileExecAndSymbols(); +CMICmdBase *CMICmdCmdFileExecAndSymbols::CreateSelf() { + return new CMICmdCmdFileExecAndSymbols(); } -//++ ------------------------------------------------------------------------------------ -// Details: If the MI Driver is not operating via a client i.e. Eclipse but say operating -// on a executable passed in as a argument to the drive then what should the driver -// do on a command failing? Either continue operating or exit the application. -// Override this function where a command failure cannot allow the driver to +//++ +//------------------------------------------------------------------------------------ +// Details: If the MI Driver is not operating via a client i.e. Eclipse but say +// operating +// on a executable passed in as a argument to the drive then what +// should the driver +// do on a command failing? Either continue operating or exit the +// application. +// Override this function where a command failure cannot allow the +// driver to // continue operating. // Type: Overridden. // Args: None. -// Return: bool - True = Fatal if command fails, false = can continue if command fails. +// Return: bool - True = Fatal if command fails, false = can continue if +// command fails. // Throws: None. //-- -bool -CMICmdCmdFileExecAndSymbols::GetExitAppOnCommandFailure() const -{ - return true; +bool CMICmdCmdFileExecAndSymbols::GetExitAppOnCommandFailure() const { + return true; } diff --git a/lldb/tools/lldb-mi/MICmdCmdFile.h b/lldb/tools/lldb-mi/MICmdCmdFile.h index b6bf5e5ccc6..0a25200cda8 100644 --- a/lldb/tools/lldb-mi/MICmdCmdFile.h +++ b/lldb/tools/lldb-mi/MICmdCmdFile.h @@ -9,53 +9,59 @@ // Overview: CMICmdCmdFileExecAndSymbols interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands derive a new command class from the +// command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// For an introduction to adding a new command see +// CMICmdCmdSupportInfoMiCmdQuery // command class as an example. #pragma once // In-house headers: #include "MICmdBase.h" -#include "MICmnMIValueTuple.h" #include "MICmnMIValueList.h" +#include "MICmnMIValueTuple.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "file-exec-and-symbols". // This command does not follow the MI documentation exactly. // Gotchas: This command has additional flags that were not available in GDB MI. // See MIextensions.txt for details. //-- -class CMICmdCmdFileExecAndSymbols : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); +class CMICmdCmdFileExecAndSymbols : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); - // Methods: - public: - /* ctor */ CMICmdCmdFileExecAndSymbols(); + // Methods: +public: + /* ctor */ CMICmdCmdFileExecAndSymbols(); - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdFileExecAndSymbols() override; - bool GetExitAppOnCommandFailure() const override; + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdFileExecAndSymbols() override; + bool GetExitAppOnCommandFailure() const override; - // Attributes: - private: - const CMIUtilString m_constStrArgNameFile; - const CMIUtilString m_constStrArgNamedPlatformName; // Added to support iOS platform selection - const CMIUtilString m_constStrArgNamedRemotePath; // Added to support iOS device remote file location + // Attributes: +private: + const CMIUtilString m_constStrArgNameFile; + const CMIUtilString + m_constStrArgNamedPlatformName; // Added to support iOS platform selection + const CMIUtilString m_constStrArgNamedRemotePath; // Added to support iOS + // device remote file + // location }; diff --git a/lldb/tools/lldb-mi/MICmdCmdGdbInfo.cpp b/lldb/tools/lldb-mi/MICmdCmdGdbInfo.cpp index c57c4ac6f02..c6f629d87f6 100644 --- a/lldb/tools/lldb-mi/MICmdCmdGdbInfo.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdGdbInfo.cpp @@ -10,22 +10,24 @@ // Overview: CMICmdCmdGdbInfo implementation. // Third party headers: -#include <inttypes.h> // For PRIx64 #include "lldb/API/SBCommandReturnObject.h" +#include <inttypes.h> // For PRIx64 // In-house headers: +#include "MICmdArgValString.h" #include "MICmdCmdGdbInfo.h" +#include "MICmnLLDBDebugSessionInfo.h" #include "MICmnMIResultRecord.h" #include "MICmnMIValueConst.h" -#include "MICmdArgValString.h" #include "MICmnStreamStdout.h" -#include "MICmnLLDBDebugSessionInfo.h" // Instantiations: -const CMICmdCmdGdbInfo::MapPrintFnNameToPrintFn_t CMICmdCmdGdbInfo::ms_mapPrintFnNameToPrintFn = { - {"sharedlibrary", &CMICmdCmdGdbInfo::PrintFnSharedLibrary}}; +const CMICmdCmdGdbInfo::MapPrintFnNameToPrintFn_t + CMICmdCmdGdbInfo::ms_mapPrintFnNameToPrintFn = { + {"sharedlibrary", &CMICmdCmdGdbInfo::PrintFnSharedLibrary}}; -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdGdbInfo constructor. // Type: Method. // Args: None. @@ -33,31 +35,30 @@ const CMICmdCmdGdbInfo::MapPrintFnNameToPrintFn_t CMICmdCmdGdbInfo::ms_mapPrintF // Throws: None. //-- CMICmdCmdGdbInfo::CMICmdCmdGdbInfo() - : m_constStrArgNamedPrint("print") - , m_bPrintFnRecognised(true) - , m_bPrintFnSuccessful(false) - , m_strPrintFnError(MIRSRC(IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS)) -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "info"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdGdbInfo::CreateSelf; + : m_constStrArgNamedPrint("print"), m_bPrintFnRecognised(true), + m_bPrintFnSuccessful(false), + m_strPrintFnError(MIRSRC(IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS)) { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "info"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdGdbInfo::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdGdbInfo destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdGdbInfo::~CMICmdCmdGdbInfo() -{ -} +CMICmdCmdGdbInfo::~CMICmdCmdGdbInfo() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -65,43 +66,43 @@ CMICmdCmdGdbInfo::~CMICmdCmdGdbInfo() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdGdbInfo::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedPrint, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdGdbInfo::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedPrint, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdGdbInfo::Execute() -{ - CMICMDBASE_GETOPTION(pArgPrint, String, m_constStrArgNamedPrint); - const CMIUtilString &rPrintRequest(pArgPrint->GetValue()); - - FnPrintPtr pPrintRequestFn = nullptr; - if (!GetPrintFn(rPrintRequest, pPrintRequestFn)) - { - m_strPrintFnName = rPrintRequest; - m_bPrintFnRecognised = false; - return MIstatus::success; - } +bool CMICmdCmdGdbInfo::Execute() { + CMICMDBASE_GETOPTION(pArgPrint, String, m_constStrArgNamedPrint); + const CMIUtilString &rPrintRequest(pArgPrint->GetValue()); + + FnPrintPtr pPrintRequestFn = nullptr; + if (!GetPrintFn(rPrintRequest, pPrintRequestFn)) { + m_strPrintFnName = rPrintRequest; + m_bPrintFnRecognised = false; + return MIstatus::success; + } - m_bPrintFnSuccessful = (this->*(pPrintRequestFn))(); + m_bPrintFnSuccessful = (this->*(pPrintRequestFn))(); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -109,72 +110,77 @@ CMICmdCmdGdbInfo::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdGdbInfo::Acknowledge() -{ - if (!m_bPrintFnRecognised) - { - const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND), m_strPrintFnName.c_str())); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - if (m_bPrintFnSuccessful) - { - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_FAILED), m_strPrintFnError.c_str())); +bool CMICmdCmdGdbInfo::Acknowledge() { + if (!m_bPrintFnRecognised) { + const CMICmnMIValueConst miValueConst(CMIUtilString::Format( + MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND), m_strPrintFnName.c_str())); const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); m_miResultRecord = miRecordResult; + return MIstatus::success; + } + if (m_bPrintFnSuccessful) { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; return MIstatus::success; + } + + const CMICmnMIValueConst miValueConst(CMIUtilString::Format( + MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_FAILED), m_strPrintFnError.c_str())); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdGdbInfo::CreateSelf() -{ - return new CMICmdCmdGdbInfo(); -} +CMICmdBase *CMICmdCmdGdbInfo::CreateSelf() { return new CMICmdCmdGdbInfo(); } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the print function's pointer for the matching print request. +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the print function's pointer for the matching print +// request. // Type: Method. // Args: vrPrintFnName - (R) The info requested. -// vrwpFn - (W) The print function's pointer of the function to carry out +// vrwpFn - (W) The print function's pointer of the function +// to carry out // Return: bool - True = Print request is implemented, false = not found. // Throws: None. //-- -bool -CMICmdCmdGdbInfo::GetPrintFn(const CMIUtilString &vrPrintFnName, FnPrintPtr &vrwpFn) const -{ - vrwpFn = nullptr; - - const MapPrintFnNameToPrintFn_t::const_iterator it = ms_mapPrintFnNameToPrintFn.find(vrPrintFnName); - if (it != ms_mapPrintFnNameToPrintFn.end()) - { - vrwpFn = (*it).second; - return true; - } - - return false; +bool CMICmdCmdGdbInfo::GetPrintFn(const CMIUtilString &vrPrintFnName, + FnPrintPtr &vrwpFn) const { + vrwpFn = nullptr; + + const MapPrintFnNameToPrintFn_t::const_iterator it = + ms_mapPrintFnNameToPrintFn.find(vrPrintFnName); + if (it != ms_mapPrintFnNameToPrintFn.end()) { + vrwpFn = (*it).second; + return true; + } + + return false; } -//++ ------------------------------------------------------------------------------------ -// Details: Carry out work to complete the request to prepare and send back information +//++ +//------------------------------------------------------------------------------------ +// Details: Carry out work to complete the request to prepare and send back +// information // asked for. // Type: Method. // Args: None. @@ -182,48 +188,48 @@ CMICmdCmdGdbInfo::GetPrintFn(const CMIUtilString &vrPrintFnName, FnPrintPtr &vrw // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdGdbInfo::PrintFnSharedLibrary() -{ - CMICmnStreamStdout &rStdout = CMICmnStreamStdout::Instance(); - bool bOk = rStdout.TextToStdout("~\"From To Syms Read Shared Object Library\""); - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBTarget sbTarget = rSessionInfo.GetTarget(); - const MIuint nModules = sbTarget.GetNumModules(); - for (MIuint i = 0; bOk && (i < nModules); i++) - { - lldb::SBModule module = sbTarget.GetModuleAtIndex(i); - if (module.IsValid()) - { - const CMIUtilString strModuleFilePath(module.GetFileSpec().GetDirectory()); - const CMIUtilString strModuleFileName(module.GetFileSpec().GetFilename()); - const CMIUtilString strModuleFullPath(CMIUtilString::Format("%s/%s", strModuleFilePath.c_str(), strModuleFileName.c_str())); - const CMIUtilString strHasSymbols = (module.GetNumSymbols() > 0) ? "Yes" : "No"; - lldb::addr_t addrLoadS = 0xffffffffffffffff; - lldb::addr_t addrLoadSize = 0; - bool bHaveAddrLoad = false; - const MIuint nSections = module.GetNumSections(); - for (MIuint j = 0; j < nSections; j++) - { - lldb::SBSection section = module.GetSectionAtIndex(j); - lldb::addr_t addrLoad = section.GetLoadAddress(sbTarget); - if (addrLoad != (lldb::addr_t) - 1) - { - if (!bHaveAddrLoad) - { - bHaveAddrLoad = true; - addrLoadS = addrLoad; - } - - addrLoadSize += section.GetByteSize(); - } - } - bOk = bOk && - rStdout.TextToStdout(CMIUtilString::Format("~\"0x%016" PRIx64 "\t0x%016" PRIx64 "\t%s\t\t%s\"", addrLoadS, addrLoadS + addrLoadSize, - strHasSymbols.c_str(), strModuleFullPath.c_str())); +bool CMICmdCmdGdbInfo::PrintFnSharedLibrary() { + CMICmnStreamStdout &rStdout = CMICmnStreamStdout::Instance(); + bool bOk = rStdout.TextToStdout( + "~\"From To Syms Read Shared Object Library\""); + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBTarget sbTarget = rSessionInfo.GetTarget(); + const MIuint nModules = sbTarget.GetNumModules(); + for (MIuint i = 0; bOk && (i < nModules); i++) { + lldb::SBModule module = sbTarget.GetModuleAtIndex(i); + if (module.IsValid()) { + const CMIUtilString strModuleFilePath( + module.GetFileSpec().GetDirectory()); + const CMIUtilString strModuleFileName(module.GetFileSpec().GetFilename()); + const CMIUtilString strModuleFullPath(CMIUtilString::Format( + "%s/%s", strModuleFilePath.c_str(), strModuleFileName.c_str())); + const CMIUtilString strHasSymbols = + (module.GetNumSymbols() > 0) ? "Yes" : "No"; + lldb::addr_t addrLoadS = 0xffffffffffffffff; + lldb::addr_t addrLoadSize = 0; + bool bHaveAddrLoad = false; + const MIuint nSections = module.GetNumSections(); + for (MIuint j = 0; j < nSections; j++) { + lldb::SBSection section = module.GetSectionAtIndex(j); + lldb::addr_t addrLoad = section.GetLoadAddress(sbTarget); + if (addrLoad != (lldb::addr_t)-1) { + if (!bHaveAddrLoad) { + bHaveAddrLoad = true; + addrLoadS = addrLoad; + } + + addrLoadSize += section.GetByteSize(); } + } + bOk = bOk && + rStdout.TextToStdout(CMIUtilString::Format( + "~\"0x%016" PRIx64 "\t0x%016" PRIx64 "\t%s\t\t%s\"", addrLoadS, + addrLoadS + addrLoadSize, strHasSymbols.c_str(), + strModuleFullPath.c_str())); } + } - return bOk; + return bOk; } diff --git a/lldb/tools/lldb-mi/MICmdCmdGdbInfo.h b/lldb/tools/lldb-mi/MICmdCmdGdbInfo.h index 6a7a2137ff4..43daf8e8275 100644 --- a/lldb/tools/lldb-mi/MICmdCmdGdbInfo.h +++ b/lldb/tools/lldb-mi/MICmdCmdGdbInfo.h @@ -9,13 +9,16 @@ // Overview: CMICmdCmdGdbInfo interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands derive a new command class from the +// command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// For an introduction to adding a new command see +// CMICmdCmdSupportInfoMiCmdQuery // command class as an example. #pragma once @@ -26,55 +29,60 @@ // In-house headers: #include "MICmdBase.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements GDB command "info". // The design of matching the info request to a request action (or // command) is very simple. The request function which carries out // the task of information gathering and printing to stdout is part of -// *this class. Should the request function become more complicated then +// *this class. Should the request function become more complicated +// then // that request should really reside in a command type class. Then this -// class instantiates a request info command for a matching request. The +// class instantiates a request info command for a matching request. +// The // design/code of *this class then does not then become bloated. Use a // lightweight version of the current MI command system. //-- -class CMICmdCmdGdbInfo : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); +class CMICmdCmdGdbInfo : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); - // Methods: - public: - /* ctor */ CMICmdCmdGdbInfo(); + // Methods: +public: + /* ctor */ CMICmdCmdGdbInfo(); - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdGdbInfo() override; + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdGdbInfo() override; - // Typedefs: - private: - typedef bool (CMICmdCmdGdbInfo::*FnPrintPtr)(); - typedef std::map<CMIUtilString, FnPrintPtr> MapPrintFnNameToPrintFn_t; + // Typedefs: +private: + typedef bool (CMICmdCmdGdbInfo::*FnPrintPtr)(); + typedef std::map<CMIUtilString, FnPrintPtr> MapPrintFnNameToPrintFn_t; - // Methods: - private: - bool GetPrintFn(const CMIUtilString &vrPrintFnName, FnPrintPtr &vrwpFn) const; - bool PrintFnSharedLibrary(); + // Methods: +private: + bool GetPrintFn(const CMIUtilString &vrPrintFnName, FnPrintPtr &vrwpFn) const; + bool PrintFnSharedLibrary(); - // Attributes: - private: - const static MapPrintFnNameToPrintFn_t ms_mapPrintFnNameToPrintFn; - // - const CMIUtilString m_constStrArgNamedPrint; - bool m_bPrintFnRecognised; // True = This command has a function with a name that matches the Print argument, false = not found - bool m_bPrintFnSuccessful; // True = The print function completed its task ok, false = function failed for some reason - CMIUtilString m_strPrintFnName; - CMIUtilString m_strPrintFnError; + // Attributes: +private: + const static MapPrintFnNameToPrintFn_t ms_mapPrintFnNameToPrintFn; + // + const CMIUtilString m_constStrArgNamedPrint; + bool m_bPrintFnRecognised; // True = This command has a function with a name + // that matches the Print argument, false = not + // found + bool m_bPrintFnSuccessful; // True = The print function completed its task ok, + // false = function failed for some reason + CMIUtilString m_strPrintFnName; + CMIUtilString m_strPrintFnError; }; diff --git a/lldb/tools/lldb-mi/MICmdCmdGdbSet.cpp b/lldb/tools/lldb-mi/MICmdCmdGdbSet.cpp index 1d68b0b5e27..38b81facc43 100644 --- a/lldb/tools/lldb-mi/MICmdCmdGdbSet.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdGdbSet.cpp @@ -11,23 +11,26 @@ // In-house headers: #include "MICmdCmdGdbSet.h" -#include "MICmnMIResultRecord.h" -#include "MICmnMIValueConst.h" -#include "MICmdArgValString.h" #include "MICmdArgValListOfN.h" #include "MICmdArgValOptionLong.h" +#include "MICmdArgValString.h" #include "MICmnLLDBDebugSessionInfo.h" +#include "MICmnMIResultRecord.h" +#include "MICmnMIValueConst.h" // Instantiations: -const CMICmdCmdGdbSet::MapGdbOptionNameToFnGdbOptionPtr_t CMICmdCmdGdbSet::ms_mapGdbOptionNameToFnGdbOptionPtr = { - {"target-async", &CMICmdCmdGdbSet::OptionFnTargetAsync}, - {"print", &CMICmdCmdGdbSet::OptionFnPrint}, - // { "auto-solib-add", &CMICmdCmdGdbSet::OptionFnAutoSolibAdd }, // Example code if need to implement GDB set other options - {"output-radix", &CMICmdCmdGdbSet::OptionFnOutputRadix}, - {"solib-search-path", &CMICmdCmdGdbSet::OptionFnSolibSearchPath}, - {"fallback", &CMICmdCmdGdbSet::OptionFnFallback}}; - -//++ ------------------------------------------------------------------------------------ +const CMICmdCmdGdbSet::MapGdbOptionNameToFnGdbOptionPtr_t + CMICmdCmdGdbSet::ms_mapGdbOptionNameToFnGdbOptionPtr = { + {"target-async", &CMICmdCmdGdbSet::OptionFnTargetAsync}, + {"print", &CMICmdCmdGdbSet::OptionFnPrint}, + // { "auto-solib-add", &CMICmdCmdGdbSet::OptionFnAutoSolibAdd }, // + // Example code if need to implement GDB set other options + {"output-radix", &CMICmdCmdGdbSet::OptionFnOutputRadix}, + {"solib-search-path", &CMICmdCmdGdbSet::OptionFnSolibSearchPath}, + {"fallback", &CMICmdCmdGdbSet::OptionFnFallback}}; + +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdGdbSet constructor. // Type: Method. // Args: None. @@ -35,32 +38,30 @@ const CMICmdCmdGdbSet::MapGdbOptionNameToFnGdbOptionPtr_t CMICmdCmdGdbSet::ms_ma // Throws: None. //-- CMICmdCmdGdbSet::CMICmdCmdGdbSet() - : m_constStrArgNamedGdbOption("option") - , m_bGdbOptionRecognised(true) - , m_bGdbOptionFnSuccessful(false) - , m_bGbbOptionFnHasError(false) - , m_strGdbOptionFnError(MIRSRC(IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS)) -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "gdb-set"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdGdbSet::CreateSelf; + : m_constStrArgNamedGdbOption("option"), m_bGdbOptionRecognised(true), + m_bGdbOptionFnSuccessful(false), m_bGbbOptionFnHasError(false), + m_strGdbOptionFnError(MIRSRC(IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS)) { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "gdb-set"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdGdbSet::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdGdbSet destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdGdbSet::~CMICmdCmdGdbSet() -{ -} +CMICmdCmdGdbSet::~CMICmdCmdGdbSet() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -68,69 +69,71 @@ CMICmdCmdGdbSet::~CMICmdCmdGdbSet() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdGdbSet::ParseArgs() -{ - m_setCmdArgs.Add( - new CMICmdArgValListOfN(m_constStrArgNamedGdbOption, true, true, CMICmdArgValListBase::eArgValType_StringAnything)); - return ParseValidateCmdOptions(); +bool CMICmdCmdGdbSet::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValListOfN( + m_constStrArgNamedGdbOption, true, true, + CMICmdArgValListBase::eArgValType_StringAnything)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command is executed in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command is executed in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdGdbSet::Execute() -{ - CMICMDBASE_GETOPTION(pArgGdbOption, ListOfN, m_constStrArgNamedGdbOption); - const CMICmdArgValListBase::VecArgObjPtr_t &rVecWords(pArgGdbOption->GetExpectedOptions()); - - // Get the gdb-set option to carry out. This option will be used as an action - // which should be done. Further arguments will be used as parameters for it. - CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecWords.begin(); - const CMICmdArgValString *pOption = static_cast<const CMICmdArgValString *>(*it); - const CMIUtilString strOption(pOption->GetValue()); +bool CMICmdCmdGdbSet::Execute() { + CMICMDBASE_GETOPTION(pArgGdbOption, ListOfN, m_constStrArgNamedGdbOption); + const CMICmdArgValListBase::VecArgObjPtr_t &rVecWords( + pArgGdbOption->GetExpectedOptions()); + + // Get the gdb-set option to carry out. This option will be used as an action + // which should be done. Further arguments will be used as parameters for it. + CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecWords.begin(); + const CMICmdArgValString *pOption = + static_cast<const CMICmdArgValString *>(*it); + const CMIUtilString strOption(pOption->GetValue()); + ++it; + + // Retrieve the parameter(s) for the option + CMIUtilString::VecString_t vecWords; + while (it != rVecWords.end()) { + const CMICmdArgValString *pWord = + static_cast<const CMICmdArgValString *>(*it); + vecWords.push_back(pWord->GetValue()); + + // Next ++it; - - // Retrieve the parameter(s) for the option - CMIUtilString::VecString_t vecWords; - while (it != rVecWords.end()) - { - const CMICmdArgValString *pWord = static_cast<const CMICmdArgValString *>(*it); - vecWords.push_back(pWord->GetValue()); - - // Next - ++it; - } - - FnGdbOptionPtr pPrintRequestFn = nullptr; - if (!GetOptionFn(strOption, pPrintRequestFn)) - { - // For unimplemented option handlers, fallback on a generic handler - // ToDo: Remove this when ALL options have been implemented - if (!GetOptionFn("fallback", pPrintRequestFn)) - { - m_bGdbOptionRecognised = false; - m_strGdbOptionName = "fallback"; // This would be the strOption name - return MIstatus::success; - } + } + + FnGdbOptionPtr pPrintRequestFn = nullptr; + if (!GetOptionFn(strOption, pPrintRequestFn)) { + // For unimplemented option handlers, fallback on a generic handler + // ToDo: Remove this when ALL options have been implemented + if (!GetOptionFn("fallback", pPrintRequestFn)) { + m_bGdbOptionRecognised = false; + m_strGdbOptionName = "fallback"; // This would be the strOption name + return MIstatus::success; } + } - m_bGdbOptionFnSuccessful = (this->*(pPrintRequestFn))(vecWords); - if (!m_bGdbOptionFnSuccessful && !m_bGbbOptionFnHasError) - return MIstatus::failure; + m_bGdbOptionFnSuccessful = (this->*(pPrintRequestFn))(vecWords); + if (!m_bGdbOptionFnSuccessful && !m_bGbbOptionFnHasError) + return MIstatus::failure; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute() method. // Type: Overridden. // Args: None. @@ -138,78 +141,83 @@ CMICmdCmdGdbSet::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdGdbSet::Acknowledge() -{ - // Print error if option isn't recognized: - // ^error,msg="The request '%s' was not recognized, not implemented" - if (!m_bGdbOptionRecognised) - { - const CMICmnMIValueConst miValueConst( - CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND), m_strGdbOptionName.c_str())); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - // ^done,value="%s" - if (m_bGdbOptionFnSuccessful) - { - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - // Print error if request failed: - // ^error,msg="The request '%s' failed. - const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_FAILED), m_strGdbOptionFnError.c_str())); +bool CMICmdCmdGdbSet::Acknowledge() { + // Print error if option isn't recognized: + // ^error,msg="The request '%s' was not recognized, not implemented" + if (!m_bGdbOptionRecognised) { + const CMICmnMIValueConst miValueConst( + CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND), + m_strGdbOptionName.c_str())); const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); m_miResultRecord = miRecordResult; + return MIstatus::success; + } + // ^done,value="%s" + if (m_bGdbOptionFnSuccessful) { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; return MIstatus::success; + } + + // Print error if request failed: + // ^error,msg="The request '%s' failed. + const CMICmnMIValueConst miValueConst(CMIUtilString::Format( + MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_FAILED), m_strGdbOptionFnError.c_str())); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdGdbSet::CreateSelf() -{ - return new CMICmdCmdGdbSet(); -} +CMICmdBase *CMICmdCmdGdbSet::CreateSelf() { return new CMICmdCmdGdbSet(); } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the print function's pointer for the matching print request. +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the print function's pointer for the matching print +// request. // Type: Method. // Args: vrPrintFnName - (R) The info requested. -// vrwpFn - (W) The print function's pointer of the function to carry out +// vrwpFn - (W) The print function's pointer of the function +// to carry out // Return: bool - True = Print request is implemented, false = not found. // Throws: None. //-- -bool -CMICmdCmdGdbSet::GetOptionFn(const CMIUtilString &vrPrintFnName, FnGdbOptionPtr &vrwpFn) const -{ - vrwpFn = nullptr; - - const MapGdbOptionNameToFnGdbOptionPtr_t::const_iterator it = ms_mapGdbOptionNameToFnGdbOptionPtr.find(vrPrintFnName); - if (it != ms_mapGdbOptionNameToFnGdbOptionPtr.end()) - { - vrwpFn = (*it).second; - return true; - } - - return false; +bool CMICmdCmdGdbSet::GetOptionFn(const CMIUtilString &vrPrintFnName, + FnGdbOptionPtr &vrwpFn) const { + vrwpFn = nullptr; + + const MapGdbOptionNameToFnGdbOptionPtr_t::const_iterator it = + ms_mapGdbOptionNameToFnGdbOptionPtr.find(vrPrintFnName); + if (it != ms_mapGdbOptionNameToFnGdbOptionPtr.end()) { + vrwpFn = (*it).second; + return true; + } + + return false; } -//++ ------------------------------------------------------------------------------------ -// Details: Carry out work to complete the GDB set option 'target-async' to prepare +//++ +//------------------------------------------------------------------------------------ +// Details: Carry out work to complete the GDB set option 'target-async' to +// prepare // and send back information asked for. // Type: Method. // Args: vrWords - (R) List of additional parameters used by this option. @@ -217,43 +225,44 @@ CMICmdCmdGdbSet::GetOptionFn(const CMIUtilString &vrPrintFnName, FnGdbOptionPtr // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdGdbSet::OptionFnTargetAsync(const CMIUtilString::VecString_t &vrWords) -{ - bool bAsyncMode = false; - bool bOk = true; - - if (vrWords.size() > 1) - // Too many arguments. - bOk = false; - else if (vrWords.size() == 0) - // If no arguments, default is "on". - bAsyncMode = true; - else if (CMIUtilString::Compare(vrWords[0], "on")) - bAsyncMode = true; - else if (CMIUtilString::Compare(vrWords[0], "off")) - bAsyncMode = false; - else - // Unrecognized argument. - bOk = false; - - if (!bOk) - { - // Report error. - m_bGbbOptionFnHasError = true; - m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_TARGETASYNC); - return MIstatus::failure; - } - - // Turn async mode on/off. - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - rSessionInfo.GetDebugger().SetAsync(bAsyncMode); - - return MIstatus::success; +bool CMICmdCmdGdbSet::OptionFnTargetAsync( + const CMIUtilString::VecString_t &vrWords) { + bool bAsyncMode = false; + bool bOk = true; + + if (vrWords.size() > 1) + // Too many arguments. + bOk = false; + else if (vrWords.size() == 0) + // If no arguments, default is "on". + bAsyncMode = true; + else if (CMIUtilString::Compare(vrWords[0], "on")) + bAsyncMode = true; + else if (CMIUtilString::Compare(vrWords[0], "off")) + bAsyncMode = false; + else + // Unrecognized argument. + bOk = false; + + if (!bOk) { + // Report error. + m_bGbbOptionFnHasError = true; + m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_TARGETASYNC); + return MIstatus::failure; + } + + // Turn async mode on/off. + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + rSessionInfo.GetDebugger().SetAsync(bAsyncMode); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Carry out work to complete the GDB set option 'print-char-array-as-string' to +//++ +//------------------------------------------------------------------------------------ +// Details: Carry out work to complete the GDB set option +// 'print-char-array-as-string' to // prepare and send back information asked for. // Type: Method. // Args: vrWords - (R) List of additional parameters used by this option. @@ -261,47 +270,50 @@ CMICmdCmdGdbSet::OptionFnTargetAsync(const CMIUtilString::VecString_t &vrWords) // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdGdbSet::OptionFnPrint(const CMIUtilString::VecString_t &vrWords) -{ - const bool bAllArgs(vrWords.size() == 2); - const bool bArgOn(bAllArgs && (CMIUtilString::Compare(vrWords[1], "on") || CMIUtilString::Compare(vrWords[1], "1"))); - const bool bArgOff(bAllArgs && (CMIUtilString::Compare(vrWords[1], "off") || CMIUtilString::Compare(vrWords[1], "0"))); - if (!bAllArgs || (!bArgOn && !bArgOff)) - { - m_bGbbOptionFnHasError = true; - m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_PRINT_BAD_ARGS); - return MIstatus::failure; - } - - const CMIUtilString strOption(vrWords[0]); - CMIUtilString strOptionKey; - if (CMIUtilString::Compare(strOption, "char-array-as-string")) - strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintCharArrayAsString; - else if (CMIUtilString::Compare(strOption, "expand-aggregates")) - strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintExpandAggregates; - else if (CMIUtilString::Compare(strOption, "aggregate-field-names")) - strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintAggregateFieldNames; - else - { - m_bGbbOptionFnHasError = true; - m_strGdbOptionFnError = CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_GDBSET_OPT_PRINT_UNKNOWN_OPTION), strOption.c_str()); - return MIstatus::failure; - } - - const bool bOptionValue(bArgOn); - if (!m_rLLDBDebugSessionInfo.SharedDataAdd<bool>(strOptionKey, bOptionValue)) - { - m_bGbbOptionFnHasError = false; - SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD), m_cmdData.strMiCmd.c_str(), strOptionKey.c_str())); - return MIstatus::failure; - } - - return MIstatus::success; +bool CMICmdCmdGdbSet::OptionFnPrint(const CMIUtilString::VecString_t &vrWords) { + const bool bAllArgs(vrWords.size() == 2); + const bool bArgOn(bAllArgs && (CMIUtilString::Compare(vrWords[1], "on") || + CMIUtilString::Compare(vrWords[1], "1"))); + const bool bArgOff(bAllArgs && (CMIUtilString::Compare(vrWords[1], "off") || + CMIUtilString::Compare(vrWords[1], "0"))); + if (!bAllArgs || (!bArgOn && !bArgOff)) { + m_bGbbOptionFnHasError = true; + m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_PRINT_BAD_ARGS); + return MIstatus::failure; + } + + const CMIUtilString strOption(vrWords[0]); + CMIUtilString strOptionKey; + if (CMIUtilString::Compare(strOption, "char-array-as-string")) + strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintCharArrayAsString; + else if (CMIUtilString::Compare(strOption, "expand-aggregates")) + strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintExpandAggregates; + else if (CMIUtilString::Compare(strOption, "aggregate-field-names")) + strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintAggregateFieldNames; + else { + m_bGbbOptionFnHasError = true; + m_strGdbOptionFnError = CMIUtilString::Format( + MIRSRC(IDS_CMD_ERR_GDBSET_OPT_PRINT_UNKNOWN_OPTION), strOption.c_str()); + return MIstatus::failure; + } + + const bool bOptionValue(bArgOn); + if (!m_rLLDBDebugSessionInfo.SharedDataAdd<bool>(strOptionKey, + bOptionValue)) { + m_bGbbOptionFnHasError = false; + SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD), + m_cmdData.strMiCmd.c_str(), + strOptionKey.c_str())); + return MIstatus::failure; + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Carry out work to complete the GDB set option 'solib-search-path' to prepare +//++ +//------------------------------------------------------------------------------------ +// Details: Carry out work to complete the GDB set option 'solib-search-path' to +// prepare // and send back information asked for. // Type: Method. // Args: vrWords - (R) List of additional parameters used by this option. @@ -309,32 +321,35 @@ CMICmdCmdGdbSet::OptionFnPrint(const CMIUtilString::VecString_t &vrWords) // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdGdbSet::OptionFnSolibSearchPath(const CMIUtilString::VecString_t &vrWords) -{ - // Check we have at least one argument - if (vrWords.size() < 1) - { - m_bGbbOptionFnHasError = true; - m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH); - return MIstatus::failure; - } - const CMIUtilString &rStrValSolibPath(vrWords[0]); - - // Add 'solib-search-path' to the shared data list - const CMIUtilString &rStrKeySolibPath(m_rLLDBDebugSessionInfo.m_constStrSharedDataSolibPath); - if (!m_rLLDBDebugSessionInfo.SharedDataAdd<CMIUtilString>(rStrKeySolibPath, rStrValSolibPath)) - { - m_bGbbOptionFnHasError = false; - SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD), m_cmdData.strMiCmd.c_str(), rStrKeySolibPath.c_str())); - return MIstatus::failure; - } - - return MIstatus::success; +bool CMICmdCmdGdbSet::OptionFnSolibSearchPath( + const CMIUtilString::VecString_t &vrWords) { + // Check we have at least one argument + if (vrWords.size() < 1) { + m_bGbbOptionFnHasError = true; + m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH); + return MIstatus::failure; + } + const CMIUtilString &rStrValSolibPath(vrWords[0]); + + // Add 'solib-search-path' to the shared data list + const CMIUtilString &rStrKeySolibPath( + m_rLLDBDebugSessionInfo.m_constStrSharedDataSolibPath); + if (!m_rLLDBDebugSessionInfo.SharedDataAdd<CMIUtilString>(rStrKeySolibPath, + rStrValSolibPath)) { + m_bGbbOptionFnHasError = false; + SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD), + m_cmdData.strMiCmd.c_str(), + rStrKeySolibPath.c_str())); + return MIstatus::failure; + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Carry out work to complete the GDB set option 'output-radix' to prepare +//++ +//------------------------------------------------------------------------------------ +// Details: Carry out work to complete the GDB set option 'output-radix' to +// prepare // and send back information asked for. // Type: Method. // Args: vrWords - (R) List of additional parameters used by this option. @@ -342,51 +357,50 @@ CMICmdCmdGdbSet::OptionFnSolibSearchPath(const CMIUtilString::VecString_t &vrWor // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdGdbSet::OptionFnOutputRadix(const CMIUtilString::VecString_t &vrWords) -{ - // Check we have at least one argument - if (vrWords.size() < 1) - { - m_bGbbOptionFnHasError = true; - m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH); - return MIstatus::failure; - } - const CMIUtilString &rStrValOutputRadix(vrWords[0]); - - CMICmnLLDBDebugSessionInfoVarObj::varFormat_e format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid; - MIint64 radix; - if (rStrValOutputRadix.ExtractNumber(radix)) - { - switch (radix) - { - case 8: - format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Octal; - break; - case 10: - format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural; - break; - case 16: - format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Hex; - break; - default: - format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid; - break; - } - } - if (format == CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid) - { - m_bGbbOptionFnHasError = false; - SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD), m_cmdData.strMiCmd.c_str(), "Output Radix")); - return MIstatus::failure; +bool CMICmdCmdGdbSet::OptionFnOutputRadix( + const CMIUtilString::VecString_t &vrWords) { + // Check we have at least one argument + if (vrWords.size() < 1) { + m_bGbbOptionFnHasError = true; + m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH); + return MIstatus::failure; + } + const CMIUtilString &rStrValOutputRadix(vrWords[0]); + + CMICmnLLDBDebugSessionInfoVarObj::varFormat_e format = + CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid; + MIint64 radix; + if (rStrValOutputRadix.ExtractNumber(radix)) { + switch (radix) { + case 8: + format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Octal; + break; + case 10: + format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural; + break; + case 16: + format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Hex; + break; + default: + format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid; + break; } - CMICmnLLDBDebugSessionInfoVarObj::VarObjSetFormat(format); - - return MIstatus::success; + } + if (format == CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid) { + m_bGbbOptionFnHasError = false; + SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD), + m_cmdData.strMiCmd.c_str(), "Output Radix")); + return MIstatus::failure; + } + CMICmnLLDBDebugSessionInfoVarObj::VarObjSetFormat(format); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Carry out work to complete the GDB set option to prepare and send back the +//++ +//------------------------------------------------------------------------------------ +// Details: Carry out work to complete the GDB set option to prepare and send +// back the // requested information. // Type: Method. // Args: None. @@ -394,14 +408,14 @@ CMICmdCmdGdbSet::OptionFnOutputRadix(const CMIUtilString::VecString_t &vrWords) // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdGdbSet::OptionFnFallback(const CMIUtilString::VecString_t &vrWords) -{ - MIunused(vrWords); +bool CMICmdCmdGdbSet::OptionFnFallback( + const CMIUtilString::VecString_t &vrWords) { + MIunused(vrWords); - // Do nothing - intentional. This is a fallback function to do nothing. - // This allows the search for gdb-set options to always succeed when the option is not - // found (implemented). + // Do nothing - intentional. This is a fallback function to do nothing. + // This allows the search for gdb-set options to always succeed when the + // option is not + // found (implemented). - return MIstatus::success; + return MIstatus::success; } diff --git a/lldb/tools/lldb-mi/MICmdCmdGdbSet.h b/lldb/tools/lldb-mi/MICmdCmdGdbSet.h index db33f6580a2..98017baf2b9 100644 --- a/lldb/tools/lldb-mi/MICmdCmdGdbSet.h +++ b/lldb/tools/lldb-mi/MICmdCmdGdbSet.h @@ -9,13 +9,16 @@ // Overview: CMICmdCmdGdbSet interface. // -// To implement new MI commands, derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands, derive a new command class from +// the command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// For an introduction to adding a new command see +// CMICmdCmdSupportInfoMiCmdQuery // command class as an example. #pragma once @@ -23,63 +26,75 @@ // In-house headers: #include "MICmdBase.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "gdb-set". -// This command does not follow the MI documentation exactly. While *this +// This command does not follow the MI documentation exactly. While +// *this // command is implemented it does not do anything with the gdb-set // variable past in. // The design of matching the info request to a request action (or // command) is very simple. The request function which carries out // the task of information gathering and printing to stdout is part of -// *this class. Should the request function become more complicated then +// *this class. Should the request function become more complicated +// then // that request should really reside in a command type class. Then this -// class instantiates a request info command for a matching request. The +// class instantiates a request info command for a matching request. +// The // design/code of *this class then does not then become bloated. Use a // lightweight version of the current MI command system. //-- -class CMICmdCmdGdbSet : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); +class CMICmdCmdGdbSet : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); - // Methods: - public: - /* ctor */ CMICmdCmdGdbSet(); + // Methods: +public: + /* ctor */ CMICmdCmdGdbSet(); - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdGdbSet() override; + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdGdbSet() override; - // Typedefs: - private: - typedef bool (CMICmdCmdGdbSet::*FnGdbOptionPtr)(const CMIUtilString::VecString_t &vrWords); - typedef std::map<CMIUtilString, FnGdbOptionPtr> MapGdbOptionNameToFnGdbOptionPtr_t; + // Typedefs: +private: + typedef bool (CMICmdCmdGdbSet::*FnGdbOptionPtr)( + const CMIUtilString::VecString_t &vrWords); + typedef std::map<CMIUtilString, FnGdbOptionPtr> + MapGdbOptionNameToFnGdbOptionPtr_t; - // Methods: - private: - bool GetOptionFn(const CMIUtilString &vrGdbOptionName, FnGdbOptionPtr &vrwpFn) const; - bool OptionFnTargetAsync(const CMIUtilString::VecString_t &vrWords); - bool OptionFnPrint(const CMIUtilString::VecString_t &vrWords); - bool OptionFnSolibSearchPath(const CMIUtilString::VecString_t &vrWords); - bool OptionFnOutputRadix(const CMIUtilString::VecString_t &vrWords); - bool OptionFnFallback(const CMIUtilString::VecString_t &vrWords); + // Methods: +private: + bool GetOptionFn(const CMIUtilString &vrGdbOptionName, + FnGdbOptionPtr &vrwpFn) const; + bool OptionFnTargetAsync(const CMIUtilString::VecString_t &vrWords); + bool OptionFnPrint(const CMIUtilString::VecString_t &vrWords); + bool OptionFnSolibSearchPath(const CMIUtilString::VecString_t &vrWords); + bool OptionFnOutputRadix(const CMIUtilString::VecString_t &vrWords); + bool OptionFnFallback(const CMIUtilString::VecString_t &vrWords); - // Attributes: - private: - const static MapGdbOptionNameToFnGdbOptionPtr_t ms_mapGdbOptionNameToFnGdbOptionPtr; - // - const CMIUtilString m_constStrArgNamedGdbOption; - bool m_bGdbOptionRecognised; // True = This command has a function with a name that matches the Print argument, false = not found - bool m_bGdbOptionFnSuccessful; // True = The print function completed its task ok, false = function failed for some reason - bool m_bGbbOptionFnHasError; // True = The option function has an error condition (not the command!), false = option function ok. - CMIUtilString m_strGdbOptionName; - CMIUtilString m_strGdbOptionFnError; + // Attributes: +private: + const static MapGdbOptionNameToFnGdbOptionPtr_t + ms_mapGdbOptionNameToFnGdbOptionPtr; + // + const CMIUtilString m_constStrArgNamedGdbOption; + bool m_bGdbOptionRecognised; // True = This command has a function with a name + // that matches the Print argument, false = not + // found + bool m_bGdbOptionFnSuccessful; // True = The print function completed its task + // ok, false = function failed for some reason + bool m_bGbbOptionFnHasError; // True = The option function has an error + // condition (not the command!), false = option + // function ok. + CMIUtilString m_strGdbOptionName; + CMIUtilString m_strGdbOptionFnError; }; diff --git a/lldb/tools/lldb-mi/MICmdCmdGdbShow.cpp b/lldb/tools/lldb-mi/MICmdCmdGdbShow.cpp index 147e76798bf..591d80bb9d0 100644 --- a/lldb/tools/lldb-mi/MICmdCmdGdbShow.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdGdbShow.cpp @@ -16,22 +16,24 @@ #include "lldb/API/SBThread.h" // In-house headers: -#include "MICmdCmdGdbShow.h" -#include "MICmnMIResultRecord.h" -#include "MICmnMIValueConst.h" -#include "MICmdArgValString.h" #include "MICmdArgValListOfN.h" #include "MICmdArgValOptionLong.h" +#include "MICmdArgValString.h" +#include "MICmdCmdGdbShow.h" #include "MICmnLLDBDebugSessionInfo.h" +#include "MICmnMIResultRecord.h" +#include "MICmnMIValueConst.h" // Instantiations: -const CMICmdCmdGdbShow::MapGdbOptionNameToFnGdbOptionPtr_t CMICmdCmdGdbShow::ms_mapGdbOptionNameToFnGdbOptionPtr = { - {"target-async", &CMICmdCmdGdbShow::OptionFnTargetAsync}, - {"print", &CMICmdCmdGdbShow::OptionFnPrint}, - {"language", &CMICmdCmdGdbShow::OptionFnLanguage}, - {"fallback", &CMICmdCmdGdbShow::OptionFnFallback}}; - -//++ ------------------------------------------------------------------------------------ +const CMICmdCmdGdbShow::MapGdbOptionNameToFnGdbOptionPtr_t + CMICmdCmdGdbShow::ms_mapGdbOptionNameToFnGdbOptionPtr = { + {"target-async", &CMICmdCmdGdbShow::OptionFnTargetAsync}, + {"print", &CMICmdCmdGdbShow::OptionFnPrint}, + {"language", &CMICmdCmdGdbShow::OptionFnLanguage}, + {"fallback", &CMICmdCmdGdbShow::OptionFnFallback}}; + +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdGdbShow constructor. // Type: Method. // Args: None. @@ -39,32 +41,30 @@ const CMICmdCmdGdbShow::MapGdbOptionNameToFnGdbOptionPtr_t CMICmdCmdGdbShow::ms_ // Throws: None. //-- CMICmdCmdGdbShow::CMICmdCmdGdbShow() - : m_constStrArgNamedGdbOption("option") - , m_bGdbOptionRecognised(true) - , m_bGdbOptionFnSuccessful(false) - , m_bGbbOptionFnHasError(false) - , m_strGdbOptionFnError(MIRSRC(IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS)) -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "gdb-show"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdGdbShow::CreateSelf; + : m_constStrArgNamedGdbOption("option"), m_bGdbOptionRecognised(true), + m_bGdbOptionFnSuccessful(false), m_bGbbOptionFnHasError(false), + m_strGdbOptionFnError(MIRSRC(IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS)) { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "gdb-show"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdGdbShow::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdGdbShow destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdGdbShow::~CMICmdCmdGdbShow() -{ -} +CMICmdCmdGdbShow::~CMICmdCmdGdbShow() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -72,68 +72,69 @@ CMICmdCmdGdbShow::~CMICmdCmdGdbShow() // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdGdbShow::ParseArgs() -{ - m_setCmdArgs.Add( - new CMICmdArgValListOfN(m_constStrArgNamedGdbOption, true, true, CMICmdArgValListBase::eArgValType_StringAnything)); - return ParseValidateCmdOptions(); +bool CMICmdCmdGdbShow::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValListOfN( + m_constStrArgNamedGdbOption, true, true, + CMICmdArgValListBase::eArgValType_StringAnything)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command is executed in this function. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command is executed in this +// function. // Type: Overridden. // Args: None. // Return: MIstatus::success - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdGdbShow::Execute() -{ - CMICMDBASE_GETOPTION(pArgGdbOption, ListOfN, m_constStrArgNamedGdbOption); - const CMICmdArgValListBase::VecArgObjPtr_t &rVecWords(pArgGdbOption->GetExpectedOptions()); - - // Get the gdb-show option to carry out. This option will be used as an action - // which should be done. Further arguments will be used as parameters for it. - CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecWords.begin(); - const CMICmdArgValString *pOption = static_cast<const CMICmdArgValString *>(*it); - const CMIUtilString strOption(pOption->GetValue()); +bool CMICmdCmdGdbShow::Execute() { + CMICMDBASE_GETOPTION(pArgGdbOption, ListOfN, m_constStrArgNamedGdbOption); + const CMICmdArgValListBase::VecArgObjPtr_t &rVecWords( + pArgGdbOption->GetExpectedOptions()); + + // Get the gdb-show option to carry out. This option will be used as an action + // which should be done. Further arguments will be used as parameters for it. + CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecWords.begin(); + const CMICmdArgValString *pOption = + static_cast<const CMICmdArgValString *>(*it); + const CMIUtilString strOption(pOption->GetValue()); + ++it; + + // Retrieve the parameter(s) for the option + CMIUtilString::VecString_t vecWords; + while (it != rVecWords.end()) { + const CMICmdArgValString *pWord = + static_cast<const CMICmdArgValString *>(*it); + vecWords.push_back(pWord->GetValue()); + + // Next ++it; - - // Retrieve the parameter(s) for the option - CMIUtilString::VecString_t vecWords; - while (it != rVecWords.end()) - { - const CMICmdArgValString *pWord = static_cast<const CMICmdArgValString *>(*it); - vecWords.push_back(pWord->GetValue()); - - // Next - ++it; + } + + FnGdbOptionPtr pPrintRequestFn = nullptr; + if (!GetOptionFn(strOption, pPrintRequestFn)) { + // For unimplemented option handlers, fallback to a generic handler + // ToDo: Remove this when ALL options have been implemented + if (!GetOptionFn("fallback", pPrintRequestFn)) { + m_bGdbOptionRecognised = false; + m_strGdbOptionName = "fallback"; // This would be the strOption name + return MIstatus::success; } + } - FnGdbOptionPtr pPrintRequestFn = nullptr; - if (!GetOptionFn(strOption, pPrintRequestFn)) - { - // For unimplemented option handlers, fallback to a generic handler - // ToDo: Remove this when ALL options have been implemented - if (!GetOptionFn("fallback", pPrintRequestFn)) - { - m_bGdbOptionRecognised = false; - m_strGdbOptionName = "fallback"; // This would be the strOption name - return MIstatus::success; - } - } + m_bGdbOptionFnSuccessful = (this->*(pPrintRequestFn))(vecWords); + if (!m_bGdbOptionFnSuccessful && !m_bGbbOptionFnHasError) + return MIstatus::failure; - m_bGdbOptionFnSuccessful = (this->*(pPrintRequestFn))(vecWords); - if (!m_bGdbOptionFnSuccessful && !m_bGbbOptionFnHasError) - return MIstatus::failure; - - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute() method. // Type: Overridden. // Args: None. @@ -141,87 +142,92 @@ CMICmdCmdGdbShow::Execute() // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdGdbShow::Acknowledge() -{ - // Print error if option isn't recognized: - // ^error,msg="The request '%s' was not recognized, not implemented" - if (!m_bGdbOptionRecognised) - { - const CMICmnMIValueConst miValueConst( - CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND), m_strGdbOptionName.c_str())); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - // ^done,value="%s" - if (m_bGdbOptionFnSuccessful && !m_strValue.empty()) - { - const CMICmnMIValueConst miValueConst(m_strValue); - const CMICmnMIValueResult miValueResult("value", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - else if (m_bGdbOptionFnSuccessful) - { - // Ignore empty value (for fallback) - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - // Print error if request failed: - // ^error,msg="The request '%s' failed. - const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_FAILED), m_strGdbOptionFnError.c_str())); +bool CMICmdCmdGdbShow::Acknowledge() { + // Print error if option isn't recognized: + // ^error,msg="The request '%s' was not recognized, not implemented" + if (!m_bGdbOptionRecognised) { + const CMICmnMIValueConst miValueConst( + CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND), + m_strGdbOptionName.c_str())); const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + + // ^done,value="%s" + if (m_bGdbOptionFnSuccessful && !m_strValue.empty()) { + const CMICmnMIValueConst miValueConst(m_strValue); + const CMICmnMIValueResult miValueResult("value", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } else if (m_bGdbOptionFnSuccessful) { + // Ignore empty value (for fallback) + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); m_miResultRecord = miRecordResult; - return MIstatus::success; + } + + // Print error if request failed: + // ^error,msg="The request '%s' failed. + const CMICmnMIValueConst miValueConst(CMIUtilString::Format( + MIRSRC(IDS_CMD_ERR_INFO_PRINTFN_FAILED), m_strGdbOptionFnError.c_str())); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdGdbShow::CreateSelf() -{ - return new CMICmdCmdGdbShow(); -} +CMICmdBase *CMICmdCmdGdbShow::CreateSelf() { return new CMICmdCmdGdbShow(); } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the print function's pointer for the matching print request. +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the print function's pointer for the matching print +// request. // Type: Method. // Args: vrPrintFnName - (R) The info requested. -// vrwpFn - (W) The print function's pointer of the function to carry out +// vrwpFn - (W) The print function's pointer of the function +// to carry out // Return: bool - True = Print request is implemented, false = not found. // Throws: None. //-- -bool -CMICmdCmdGdbShow::GetOptionFn(const CMIUtilString &vrPrintFnName, FnGdbOptionPtr &vrwpFn) const -{ - vrwpFn = nullptr; - - const MapGdbOptionNameToFnGdbOptionPtr_t::const_iterator it = ms_mapGdbOptionNameToFnGdbOptionPtr.find(vrPrintFnName); - if (it != ms_mapGdbOptionNameToFnGdbOptionPtr.end()) - { - vrwpFn = (*it).second; - return true; - } - - return false; +bool CMICmdCmdGdbShow::GetOptionFn(const CMIUtilString &vrPrintFnName, + FnGdbOptionPtr &vrwpFn) const { + vrwpFn = nullptr; + + const MapGdbOptionNameToFnGdbOptionPtr_t::const_iterator it = + ms_mapGdbOptionNameToFnGdbOptionPtr.find(vrPrintFnName); + if (it != ms_mapGdbOptionNameToFnGdbOptionPtr.end()) { + vrwpFn = (*it).second; + return true; + } + + return false; } -//++ ------------------------------------------------------------------------------------ -// Details: Carry out work to complete the GDB show option 'target-async' to prepare +//++ +//------------------------------------------------------------------------------------ +// Details: Carry out work to complete the GDB show option 'target-async' to +// prepare // and send back the requested information. // Type: Method. // Args: vrWords - (R) List of additional parameters used by this option. @@ -229,21 +235,23 @@ CMICmdCmdGdbShow::GetOptionFn(const CMIUtilString &vrPrintFnName, FnGdbOptionPtr // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdGdbShow::OptionFnTargetAsync(const CMIUtilString::VecString_t &vrWords) -{ - MIunused(vrWords); +bool CMICmdCmdGdbShow::OptionFnTargetAsync( + const CMIUtilString::VecString_t &vrWords) { + MIunused(vrWords); - // Get async mode - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - const bool bAsyncMode = rSessionInfo.GetDebugger().GetAsync(); + // Get async mode + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + const bool bAsyncMode = rSessionInfo.GetDebugger().GetAsync(); - m_strValue = bAsyncMode ? "on" : "off"; - return MIstatus::success; + m_strValue = bAsyncMode ? "on" : "off"; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Carry out work to complete the GDB show option 'print' to prepare and send +//++ +//------------------------------------------------------------------------------------ +// Details: Carry out work to complete the GDB show option 'print' to prepare +// and send // back the requested information. // Type: Method. // Args: vrWords - (R) List of additional parameters used by this option. @@ -251,45 +259,48 @@ CMICmdCmdGdbShow::OptionFnTargetAsync(const CMIUtilString::VecString_t &vrWords) // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdGdbShow::OptionFnPrint(const CMIUtilString::VecString_t &vrWords) -{ - const bool bAllArgs(vrWords.size() == 1); - if (!bAllArgs) - { - m_bGbbOptionFnHasError = true; - m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSHOW_OPT_PRINT_BAD_ARGS); - return MIstatus::failure; - } - - const CMIUtilString strOption(vrWords[0]); - CMIUtilString strOptionKey; - bool bOptionValueDefault = false; - if (CMIUtilString::Compare(strOption, "char-array-as-string")) - strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintCharArrayAsString; - else if (CMIUtilString::Compare(strOption, "expand-aggregates")) - strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintExpandAggregates; - else if (CMIUtilString::Compare(strOption, "aggregate-field-names")) - { - strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintAggregateFieldNames; - bOptionValueDefault = true; - } - else - { - m_bGbbOptionFnHasError = true; - m_strGdbOptionFnError = CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_GDBSHOW_OPT_PRINT_UNKNOWN_OPTION), strOption.c_str()); - return MIstatus::failure; - } - - bool bOptionValue = false; - bOptionValue = bOptionValueDefault ? !m_rLLDBDebugSessionInfo.SharedDataRetrieve<bool>(strOptionKey, bOptionValue) || bOptionValue - : m_rLLDBDebugSessionInfo.SharedDataRetrieve<bool>(strOptionKey, bOptionValue) && bOptionValue; - - m_strValue = bOptionValue ? "on" : "off"; - return MIstatus::success; +bool CMICmdCmdGdbShow::OptionFnPrint( + const CMIUtilString::VecString_t &vrWords) { + const bool bAllArgs(vrWords.size() == 1); + if (!bAllArgs) { + m_bGbbOptionFnHasError = true; + m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSHOW_OPT_PRINT_BAD_ARGS); + return MIstatus::failure; + } + + const CMIUtilString strOption(vrWords[0]); + CMIUtilString strOptionKey; + bool bOptionValueDefault = false; + if (CMIUtilString::Compare(strOption, "char-array-as-string")) + strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintCharArrayAsString; + else if (CMIUtilString::Compare(strOption, "expand-aggregates")) + strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintExpandAggregates; + else if (CMIUtilString::Compare(strOption, "aggregate-field-names")) { + strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintAggregateFieldNames; + bOptionValueDefault = true; + } else { + m_bGbbOptionFnHasError = true; + m_strGdbOptionFnError = CMIUtilString::Format( + MIRSRC(IDS_CMD_ERR_GDBSHOW_OPT_PRINT_UNKNOWN_OPTION), + strOption.c_str()); + return MIstatus::failure; + } + + bool bOptionValue = false; + bOptionValue = bOptionValueDefault + ? !m_rLLDBDebugSessionInfo.SharedDataRetrieve<bool>( + strOptionKey, bOptionValue) || + bOptionValue + : m_rLLDBDebugSessionInfo.SharedDataRetrieve<bool>( + strOptionKey, bOptionValue) && + bOptionValue; + + m_strValue = bOptionValue ? "on" : "off"; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Carry out work to complete the GDB show option 'language' to prepare // and send back the requested information. // Type: Method. @@ -298,24 +309,26 @@ CMICmdCmdGdbShow::OptionFnPrint(const CMIUtilString::VecString_t &vrWords) // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdGdbShow::OptionFnLanguage(const CMIUtilString::VecString_t &vrWords) -{ - MIunused(vrWords); - - // Get current language - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBThread sbThread = rSessionInfo.GetProcess().GetSelectedThread(); - const lldb::SBFrame sbFrame = sbThread.GetSelectedFrame(); - lldb::SBCompileUnit sbCompileUnit = sbFrame.GetCompileUnit(); - const lldb::LanguageType eLanguageType = sbCompileUnit.GetLanguage(); - - m_strValue = lldb::SBLanguageRuntime::GetNameForLanguageType(eLanguageType); - return MIstatus::success; +bool CMICmdCmdGdbShow::OptionFnLanguage( + const CMIUtilString::VecString_t &vrWords) { + MIunused(vrWords); + + // Get current language + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBThread sbThread = rSessionInfo.GetProcess().GetSelectedThread(); + const lldb::SBFrame sbFrame = sbThread.GetSelectedFrame(); + lldb::SBCompileUnit sbCompileUnit = sbFrame.GetCompileUnit(); + const lldb::LanguageType eLanguageType = sbCompileUnit.GetLanguage(); + + m_strValue = lldb::SBLanguageRuntime::GetNameForLanguageType(eLanguageType); + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Carry out work to complete the GDB show option to prepare and send back the +//++ +//------------------------------------------------------------------------------------ +// Details: Carry out work to complete the GDB show option to prepare and send +// back the // requested information. // Type: Method. // Args: None. @@ -323,14 +336,14 @@ CMICmdCmdGdbShow::OptionFnLanguage(const CMIUtilString::VecString_t &vrWords) // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdGdbShow::OptionFnFallback(const CMIUtilString::VecString_t &vrWords) -{ - MIunused(vrWords); +bool CMICmdCmdGdbShow::OptionFnFallback( + const CMIUtilString::VecString_t &vrWords) { + MIunused(vrWords); - // Do nothing - intentional. This is a fallback function to do nothing. - // This allows the search for gdb-show options to always succeed when the option is not - // found (implemented). + // Do nothing - intentional. This is a fallback function to do nothing. + // This allows the search for gdb-show options to always succeed when the + // option is not + // found (implemented). - return MIstatus::success; + return MIstatus::success; } diff --git a/lldb/tools/lldb-mi/MICmdCmdGdbShow.h b/lldb/tools/lldb-mi/MICmdCmdGdbShow.h index 934105312da..9873e87c812 100644 --- a/lldb/tools/lldb-mi/MICmdCmdGdbShow.h +++ b/lldb/tools/lldb-mi/MICmdCmdGdbShow.h @@ -9,13 +9,16 @@ // Overview: CMICmdCmdGdbShow interface. // -// To implement new MI commands, derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands, derive a new command class from +// the command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// For an introduction to adding a new command see +// CMICmdCmdSupportInfoMiCmdQuery // command class as an example. #pragma once @@ -23,63 +26,75 @@ // In-house headers: #include "MICmdBase.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "gdb-show". -// This command does not follow the MI documentation exactly. While *this +// This command does not follow the MI documentation exactly. While +// *this // command is implemented it does not do anything with the gdb-set // variable past in. // The design of matching the info request to a request action (or // command) is very simple. The request function which carries out // the task of information gathering and printing to stdout is part of -// *this class. Should the request function become more complicated then +// *this class. Should the request function become more complicated +// then // that request should really reside in a command type class. Then this -// class instantiates a request info command for a matching request. The +// class instantiates a request info command for a matching request. +// The // design/code of *this class then does not then become bloated. Use a // lightweight version of the current MI command system. //-- -class CMICmdCmdGdbShow : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); +class CMICmdCmdGdbShow : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); - // Methods: - public: - /* ctor */ CMICmdCmdGdbShow(); + // Methods: +public: + /* ctor */ CMICmdCmdGdbShow(); - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdGdbShow() override; + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdGdbShow() override; - // Typedefs: - private: - typedef bool (CMICmdCmdGdbShow::*FnGdbOptionPtr)(const CMIUtilString::VecString_t &vrWords); - typedef std::map<CMIUtilString, FnGdbOptionPtr> MapGdbOptionNameToFnGdbOptionPtr_t; + // Typedefs: +private: + typedef bool (CMICmdCmdGdbShow::*FnGdbOptionPtr)( + const CMIUtilString::VecString_t &vrWords); + typedef std::map<CMIUtilString, FnGdbOptionPtr> + MapGdbOptionNameToFnGdbOptionPtr_t; - // Methods: - private: - bool GetOptionFn(const CMIUtilString &vrGdbOptionName, FnGdbOptionPtr &vrwpFn) const; - bool OptionFnTargetAsync(const CMIUtilString::VecString_t &vrWords); - bool OptionFnPrint(const CMIUtilString::VecString_t &vrWords); - bool OptionFnLanguage(const CMIUtilString::VecString_t &vrWords); - bool OptionFnFallback(const CMIUtilString::VecString_t &vrWords); + // Methods: +private: + bool GetOptionFn(const CMIUtilString &vrGdbOptionName, + FnGdbOptionPtr &vrwpFn) const; + bool OptionFnTargetAsync(const CMIUtilString::VecString_t &vrWords); + bool OptionFnPrint(const CMIUtilString::VecString_t &vrWords); + bool OptionFnLanguage(const CMIUtilString::VecString_t &vrWords); + bool OptionFnFallback(const CMIUtilString::VecString_t &vrWords); - // Attributes: - private: - const static MapGdbOptionNameToFnGdbOptionPtr_t ms_mapGdbOptionNameToFnGdbOptionPtr; + // Attributes: +private: + const static MapGdbOptionNameToFnGdbOptionPtr_t + ms_mapGdbOptionNameToFnGdbOptionPtr; - const CMIUtilString m_constStrArgNamedGdbOption; - bool m_bGdbOptionRecognised; // True = This command has a function with a name that matches the Print argument, false = not found - bool m_bGdbOptionFnSuccessful; // True = The print function completed its task ok, false = function failed for some reason - bool m_bGbbOptionFnHasError; // True = The option function has an error condition (not the command!), false = option function ok. - CMIUtilString m_strGdbOptionName; - CMIUtilString m_strGdbOptionFnError; - CMIUtilString m_strValue; + const CMIUtilString m_constStrArgNamedGdbOption; + bool m_bGdbOptionRecognised; // True = This command has a function with a name + // that matches the Print argument, false = not + // found + bool m_bGdbOptionFnSuccessful; // True = The print function completed its task + // ok, false = function failed for some reason + bool m_bGbbOptionFnHasError; // True = The option function has an error + // condition (not the command!), false = option + // function ok. + CMIUtilString m_strGdbOptionName; + CMIUtilString m_strGdbOptionFnError; + CMIUtilString m_strValue; }; diff --git a/lldb/tools/lldb-mi/MICmdCmdGdbThread.cpp b/lldb/tools/lldb-mi/MICmdCmdGdbThread.cpp index 5f71b054760..06dc0c84109 100644 --- a/lldb/tools/lldb-mi/MICmdCmdGdbThread.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdGdbThread.cpp @@ -14,52 +14,54 @@ #include "MICmnMIResultRecord.h" #include "MICmnMIValueConst.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdGdbThread constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdGdbThread::CMICmdCmdGdbThread() -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "thread"; +CMICmdCmdGdbThread::CMICmdCmdGdbThread() { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "thread"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdGdbThread::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdGdbThread::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdThread destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdGdbThread::~CMICmdCmdGdbThread() -{ -} +CMICmdCmdGdbThread::~CMICmdCmdGdbThread() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdGdbThread::Execute() -{ - // Do nothing +bool CMICmdCmdGdbThread::Execute() { + // Do nothing - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -67,27 +69,27 @@ CMICmdCmdGdbThread::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdGdbThread::Acknowledge() -{ - const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED)); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; +bool CMICmdCmdGdbThread::Acknowledge() { + const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED)); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdGdbThread::CreateSelf() -{ - return new CMICmdCmdGdbThread(); +CMICmdBase *CMICmdCmdGdbThread::CreateSelf() { + return new CMICmdCmdGdbThread(); } diff --git a/lldb/tools/lldb-mi/MICmdCmdGdbThread.h b/lldb/tools/lldb-mi/MICmdCmdGdbThread.h index 40d8b783789..2f8b0bc0ad5 100644 --- a/lldb/tools/lldb-mi/MICmdCmdGdbThread.h +++ b/lldb/tools/lldb-mi/MICmdCmdGdbThread.h @@ -9,13 +9,16 @@ // Overview: CMICmdCmdGdbThread interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands derive a new command class from the +// command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// For an introduction to adding a new command see +// CMICmdCmdSupportInfoMiCmdQuery // command class as an example. #pragma once @@ -23,26 +26,26 @@ // In-house headers: #include "MICmdBase.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements GDB command "thread". //-- -class CMICmdCmdGdbThread : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); +class CMICmdCmdGdbThread : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); - // Methods: - public: - /* ctor */ CMICmdCmdGdbThread(); + // Methods: +public: + /* ctor */ CMICmdCmdGdbThread(); - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdGdbThread() override; + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdGdbThread() override; }; diff --git a/lldb/tools/lldb-mi/MICmdCmdMiscellanous.cpp b/lldb/tools/lldb-mi/MICmdCmdMiscellanous.cpp index d534a6fafa0..f2aecbc32ed 100644 --- a/lldb/tools/lldb-mi/MICmdCmdMiscellanous.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdMiscellanous.cpp @@ -17,71 +17,73 @@ #include "lldb/API/SBThread.h" // In-house headers: -#include "MICmdCmdMiscellanous.h" -#include "MICmnMIResultRecord.h" -#include "MICmnMIValueConst.h" -#include "MICmnMIOutOfBandRecord.h" -#include "MICmnLLDBDebugger.h" -#include "MICmnLLDBDebugSessionInfo.h" -#include "MIDriverBase.h" #include "MICmdArgValFile.h" +#include "MICmdArgValListOfN.h" #include "MICmdArgValNumber.h" -#include "MICmdArgValString.h" -#include "MICmdArgValThreadGrp.h" #include "MICmdArgValOptionLong.h" #include "MICmdArgValOptionShort.h" -#include "MICmdArgValListOfN.h" -#include "MICmnStreamStdout.h" +#include "MICmdArgValString.h" +#include "MICmdArgValThreadGrp.h" +#include "MICmdCmdMiscellanous.h" +#include "MICmnLLDBDebugSessionInfo.h" +#include "MICmnLLDBDebugger.h" +#include "MICmnMIOutOfBandRecord.h" +#include "MICmnMIResultRecord.h" +#include "MICmnMIValueConst.h" #include "MICmnStreamStderr.h" +#include "MICmnStreamStdout.h" +#include "MIDriverBase.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdGdbExit constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdGdbExit::CMICmdCmdGdbExit() -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "gdb-exit"; +CMICmdCmdGdbExit::CMICmdCmdGdbExit() { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "gdb-exit"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdGdbExit::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdGdbExit::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdGdbExit destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdGdbExit::~CMICmdCmdGdbExit() -{ -} - -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +CMICmdCmdGdbExit::~CMICmdCmdGdbExit() {} + +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdGdbExit::Execute() -{ - CMICmnLLDBDebugger::Instance().GetDriver().SetExitApplicationFlag(true); - const lldb::SBError sbErr = m_rLLDBDebugSessionInfo.GetProcess().Destroy(); - // Do not check for sbErr.Fail() here, m_lldbProcess is likely !IsValid() +bool CMICmdCmdGdbExit::Execute() { + CMICmnLLDBDebugger::Instance().GetDriver().SetExitApplicationFlag(true); + const lldb::SBError sbErr = m_rLLDBDebugSessionInfo.GetProcess().Destroy(); + // Do not check for sbErr.Fail() here, m_lldbProcess is likely !IsValid() - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -89,42 +91,42 @@ CMICmdCmdGdbExit::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdGdbExit::Acknowledge() -{ - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Exit); - m_miResultRecord = miRecordResult; - - // Prod the client i.e. Eclipse with out-of-band results to help it 'continue' because it is using LLDB debugger - // Give the client '=thread-group-exited,id="i1"' - m_bHasResultRecordExtra = true; - const CMICmnMIValueConst miValueConst2("i1"); - const CMICmnMIValueResult miValueResult2("id", miValueConst2); - const CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult2); - m_miResultRecordExtra = miOutOfBand.GetString(); - - return MIstatus::success; +bool CMICmdCmdGdbExit::Acknowledge() { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Exit); + m_miResultRecord = miRecordResult; + + // Prod the client i.e. Eclipse with out-of-band results to help it 'continue' + // because it is using LLDB debugger + // Give the client '=thread-group-exited,id="i1"' + m_bHasResultRecordExtra = true; + const CMICmnMIValueConst miValueConst2("i1"); + const CMICmnMIValueResult miValueResult2("id", miValueConst2); + const CMICmnMIOutOfBandRecord miOutOfBand( + CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult2); + m_miResultRecordExtra = miOutOfBand.GetString(); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdGdbExit::CreateSelf() -{ - return new CMICmdCmdGdbExit(); -} +CMICmdBase *CMICmdCmdGdbExit::CreateSelf() { return new CMICmdCmdGdbExit(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdListThreadGroups constructor. // Type: Method. // Args: None. @@ -132,35 +134,33 @@ CMICmdCmdGdbExit::CreateSelf() // Throws: None. //-- CMICmdCmdListThreadGroups::CMICmdCmdListThreadGroups() - : m_bIsI1(false) - , m_bHaveArgOption(false) - , m_bHaveArgRecurse(false) - , m_constStrArgNamedAvailable("available") - , m_constStrArgNamedRecurse("recurse") - , m_constStrArgNamedGroup("group") - , m_constStrArgNamedThreadGroup("i1") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "list-thread-groups"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdListThreadGroups::CreateSelf; + : m_bIsI1(false), m_bHaveArgOption(false), m_bHaveArgRecurse(false), + m_constStrArgNamedAvailable("available"), + m_constStrArgNamedRecurse("recurse"), m_constStrArgNamedGroup("group"), + m_constStrArgNamedThreadGroup("i1") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "list-thread-groups"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdListThreadGroups::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdListThreadGroups destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdListThreadGroups::~CMICmdCmdListThreadGroups() -{ - m_vecMIValueTuple.clear(); +CMICmdCmdListThreadGroups::~CMICmdCmdListThreadGroups() { + m_vecMIValueTuple.clear(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -168,22 +168,30 @@ CMICmdCmdListThreadGroups::~CMICmdCmdListThreadGroups() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdListThreadGroups::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgNamedAvailable, false, true)); - m_setCmdArgs.Add( - new CMICmdArgValOptionLong(m_constStrArgNamedRecurse, false, true, CMICmdArgValListBase::eArgValType_Number, 1)); - m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgNamedGroup, false, true, CMICmdArgValListBase::eArgValType_Number)); - m_setCmdArgs.Add(new CMICmdArgValThreadGrp(m_constStrArgNamedThreadGroup, false, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdListThreadGroups::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValOptionLong(m_constStrArgNamedAvailable, false, true)); + m_setCmdArgs.Add( + new CMICmdArgValOptionLong(m_constStrArgNamedRecurse, false, true, + CMICmdArgValListBase::eArgValType_Number, 1)); + m_setCmdArgs.Add( + new CMICmdArgValListOfN(m_constStrArgNamedGroup, false, true, + CMICmdArgValListBase::eArgValType_Number)); + m_setCmdArgs.Add( + new CMICmdArgValThreadGrp(m_constStrArgNamedThreadGroup, false, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. -// Synopsis: -list-thread-groups [ --available ] [ --recurse 1 ] [ group ... ] -// This command does not follow the MI documentation exactly. Has an extra +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. +// Synopsis: -list-thread-groups [ --available ] [ --recurse 1 ] [ +// group ... ] +// This command does not follow the MI documentation exactly. Has an +// extra // argument "i1" to handle. // Ref: // http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Miscellaneous-Commands.html#GDB_002fMI-Miscellaneous-Commands @@ -193,62 +201,62 @@ CMICmdCmdListThreadGroups::ParseArgs() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdListThreadGroups::Execute() -{ - if (m_setCmdArgs.IsArgContextEmpty()) - // No options so "top level thread groups" - return MIstatus::success; - - CMICMDBASE_GETOPTION(pArgAvailable, OptionLong, m_constStrArgNamedAvailable); - CMICMDBASE_GETOPTION(pArgRecurse, OptionLong, m_constStrArgNamedRecurse); - CMICMDBASE_GETOPTION(pArgThreadGroup, ThreadGrp, m_constStrArgNamedThreadGroup); - - // Got some options so "threads" - if (pArgAvailable->GetFound()) - { - if (pArgRecurse->GetFound()) - { - m_bHaveArgRecurse = true; - return MIstatus::success; - } - - m_bHaveArgOption = true; - return MIstatus::success; - } - // "i1" as first argument (pos 0 of possible arg) - if (!pArgThreadGroup->GetFound()) - return MIstatus::success; - m_bIsI1 = true; - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); - - // Note do not check for sbProcess is IsValid(), continue - - m_vecMIValueTuple.clear(); - const MIuint nThreads = sbProcess.GetNumThreads(); - for (MIuint i = 0; i < nThreads; i++) - { - // GetThreadAtIndex() uses a base 0 index - // GetThreadByIndexID() uses a base 1 index - lldb::SBThread thread = sbProcess.GetThreadAtIndex(i); - - if (thread.IsValid()) - { - CMICmnMIValueTuple miTuple; - if (!rSessionInfo.MIResponseFormThreadInfo(m_cmdData, thread, CMICmnLLDBDebugSessionInfo::eThreadInfoFormat_NoFrames, miTuple)) - return MIstatus::failure; - - m_vecMIValueTuple.push_back(miTuple); - } +bool CMICmdCmdListThreadGroups::Execute() { + if (m_setCmdArgs.IsArgContextEmpty()) + // No options so "top level thread groups" + return MIstatus::success; + + CMICMDBASE_GETOPTION(pArgAvailable, OptionLong, m_constStrArgNamedAvailable); + CMICMDBASE_GETOPTION(pArgRecurse, OptionLong, m_constStrArgNamedRecurse); + CMICMDBASE_GETOPTION(pArgThreadGroup, ThreadGrp, + m_constStrArgNamedThreadGroup); + + // Got some options so "threads" + if (pArgAvailable->GetFound()) { + if (pArgRecurse->GetFound()) { + m_bHaveArgRecurse = true; + return MIstatus::success; } + m_bHaveArgOption = true; return MIstatus::success; + } + // "i1" as first argument (pos 0 of possible arg) + if (!pArgThreadGroup->GetFound()) + return MIstatus::success; + m_bIsI1 = true; + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + + // Note do not check for sbProcess is IsValid(), continue + + m_vecMIValueTuple.clear(); + const MIuint nThreads = sbProcess.GetNumThreads(); + for (MIuint i = 0; i < nThreads; i++) { + // GetThreadAtIndex() uses a base 0 index + // GetThreadByIndexID() uses a base 1 index + lldb::SBThread thread = sbProcess.GetThreadAtIndex(i); + + if (thread.IsValid()) { + CMICmnMIValueTuple miTuple; + if (!rSessionInfo.MIResponseFormThreadInfo( + m_cmdData, thread, + CMICmnLLDBDebugSessionInfo::eThreadInfoFormat_NoFrames, miTuple)) + return MIstatus::failure; + + m_vecMIValueTuple.push_back(miTuple); + } + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -256,140 +264,147 @@ CMICmdCmdListThreadGroups::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdListThreadGroups::Acknowledge() -{ - if (m_bHaveArgOption) - { - if (m_bHaveArgRecurse) - { - const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED_BRKTS)); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; - - return MIstatus::success; - } - - const CMICmnMIValueConst miValueConst1("i1"); - const CMICmnMIValueResult miValueResult1("id", miValueConst1); - CMICmnMIValueTuple miTuple(miValueResult1); - - const CMICmnMIValueConst miValueConst2("process"); - const CMICmnMIValueResult miValueResult2("type", miValueConst2); - miTuple.Add(miValueResult2); - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - if (rSessionInfo.GetProcess().IsValid()) - { - const lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID(); - const CMIUtilString strPid(CMIUtilString::Format("%lld", pid)); - const CMICmnMIValueConst miValueConst3(strPid); - const CMICmnMIValueResult miValueResult3("pid", miValueConst3); - miTuple.Add(miValueResult3); - } - - const CMICmnMIValueConst miValueConst4(MIRSRC(IDS_WORD_NOT_IMPLEMENTED_BRKTS)); - const CMICmnMIValueResult miValueResult4("num_children", miValueConst4); - miTuple.Add(miValueResult4); - - const CMICmnMIValueConst miValueConst5(MIRSRC(IDS_WORD_NOT_IMPLEMENTED_BRKTS)); - const CMICmnMIValueResult miValueResult5("cores", miValueConst5); - miTuple.Add(miValueResult5); - - const CMICmnMIValueList miValueList(miTuple); - const CMICmnMIValueResult miValueResult6("groups", miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6); - m_miResultRecord = miRecordResult; - - return MIstatus::success; +bool CMICmdCmdListThreadGroups::Acknowledge() { + if (m_bHaveArgOption) { + if (m_bHaveArgRecurse) { + const CMICmnMIValueConst miValueConst( + MIRSRC(IDS_WORD_NOT_IMPLEMENTED_BRKTS)); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } - if (!m_bIsI1) - { - const CMICmnMIValueConst miValueConst1("i1"); - const CMICmnMIValueResult miValueResult1("id", miValueConst1); - CMICmnMIValueTuple miTuple(miValueResult1); - - const CMICmnMIValueConst miValueConst2("process"); - const CMICmnMIValueResult miValueResult2("type", miValueConst2); - miTuple.Add(miValueResult2); - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - if (rSessionInfo.GetProcess().IsValid()) - { - const lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID(); - const CMIUtilString strPid(CMIUtilString::Format("%lld", pid)); - const CMICmnMIValueConst miValueConst3(strPid); - const CMICmnMIValueResult miValueResult3("pid", miValueConst3); - miTuple.Add(miValueResult3); - } - - if (rSessionInfo.GetTarget().IsValid()) - { - lldb::SBTarget sbTrgt = rSessionInfo.GetTarget(); - const char *pDir = sbTrgt.GetExecutable().GetDirectory(); - const char *pFileName = sbTrgt.GetExecutable().GetFilename(); - const CMIUtilString strFile(CMIUtilString::Format("%s/%s", pDir, pFileName)); - const CMICmnMIValueConst miValueConst4(strFile); - const CMICmnMIValueResult miValueResult4("executable", miValueConst4); - miTuple.Add(miValueResult4); - } - - const CMICmnMIValueList miValueList(miTuple); - const CMICmnMIValueResult miValueResult5("groups", miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult5); - m_miResultRecord = miRecordResult; - return MIstatus::success; + const CMICmnMIValueConst miValueConst1("i1"); + const CMICmnMIValueResult miValueResult1("id", miValueConst1); + CMICmnMIValueTuple miTuple(miValueResult1); + + const CMICmnMIValueConst miValueConst2("process"); + const CMICmnMIValueResult miValueResult2("type", miValueConst2); + miTuple.Add(miValueResult2); + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + if (rSessionInfo.GetProcess().IsValid()) { + const lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID(); + const CMIUtilString strPid(CMIUtilString::Format("%lld", pid)); + const CMICmnMIValueConst miValueConst3(strPid); + const CMICmnMIValueResult miValueResult3("pid", miValueConst3); + miTuple.Add(miValueResult3); } - // Build up a list of thread information from tuples - VecMIValueTuple_t::const_iterator it = m_vecMIValueTuple.begin(); - if (it == m_vecMIValueTuple.end()) - { - const CMICmnMIValueConst miValueConst("[]"); - const CMICmnMIValueResult miValueResult("threads", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - return MIstatus::success; + const CMICmnMIValueConst miValueConst4( + MIRSRC(IDS_WORD_NOT_IMPLEMENTED_BRKTS)); + const CMICmnMIValueResult miValueResult4("num_children", miValueConst4); + miTuple.Add(miValueResult4); + + const CMICmnMIValueConst miValueConst5( + MIRSRC(IDS_WORD_NOT_IMPLEMENTED_BRKTS)); + const CMICmnMIValueResult miValueResult5("cores", miValueConst5); + miTuple.Add(miValueResult5); + + const CMICmnMIValueList miValueList(miTuple); + const CMICmnMIValueResult miValueResult6("groups", miValueList); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult6); + m_miResultRecord = miRecordResult; + + return MIstatus::success; + } + + if (!m_bIsI1) { + const CMICmnMIValueConst miValueConst1("i1"); + const CMICmnMIValueResult miValueResult1("id", miValueConst1); + CMICmnMIValueTuple miTuple(miValueResult1); + + const CMICmnMIValueConst miValueConst2("process"); + const CMICmnMIValueResult miValueResult2("type", miValueConst2); + miTuple.Add(miValueResult2); + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + if (rSessionInfo.GetProcess().IsValid()) { + const lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID(); + const CMIUtilString strPid(CMIUtilString::Format("%lld", pid)); + const CMICmnMIValueConst miValueConst3(strPid); + const CMICmnMIValueResult miValueResult3("pid", miValueConst3); + miTuple.Add(miValueResult3); } - CMICmnMIValueList miValueList(*it); - ++it; - while (it != m_vecMIValueTuple.end()) - { - const CMICmnMIValueTuple &rTuple(*it); - miValueList.Add(rTuple); - // Next - ++it; + if (rSessionInfo.GetTarget().IsValid()) { + lldb::SBTarget sbTrgt = rSessionInfo.GetTarget(); + const char *pDir = sbTrgt.GetExecutable().GetDirectory(); + const char *pFileName = sbTrgt.GetExecutable().GetFilename(); + const CMIUtilString strFile( + CMIUtilString::Format("%s/%s", pDir, pFileName)); + const CMICmnMIValueConst miValueConst4(strFile); + const CMICmnMIValueResult miValueResult4("executable", miValueConst4); + miTuple.Add(miValueResult4); } - const CMICmnMIValueResult miValueResult("threads", miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + const CMICmnMIValueList miValueList(miTuple); + const CMICmnMIValueResult miValueResult5("groups", miValueList); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult5); m_miResultRecord = miRecordResult; - return MIstatus::success; + } + + // Build up a list of thread information from tuples + VecMIValueTuple_t::const_iterator it = m_vecMIValueTuple.begin(); + if (it == m_vecMIValueTuple.end()) { + const CMICmnMIValueConst miValueConst("[]"); + const CMICmnMIValueResult miValueResult("threads", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + CMICmnMIValueList miValueList(*it); + ++it; + while (it != m_vecMIValueTuple.end()) { + const CMICmnMIValueTuple &rTuple(*it); + miValueList.Add(rTuple); + + // Next + ++it; + } + + const CMICmnMIValueResult miValueResult("threads", miValueList); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdListThreadGroups::CreateSelf() -{ - return new CMICmdCmdListThreadGroups(); +CMICmdBase *CMICmdCmdListThreadGroups::CreateSelf() { + return new CMICmdCmdListThreadGroups(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdInterpreterExec constructor. // Type: Method. // Args: None. @@ -397,29 +412,29 @@ CMICmdCmdListThreadGroups::CreateSelf() // Throws: None. //-- CMICmdCmdInterpreterExec::CMICmdCmdInterpreterExec() - : m_constStrArgNamedInterpreter("interpreter") - , m_constStrArgNamedCommand("command") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "interpreter-exec"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdInterpreterExec::CreateSelf; + : m_constStrArgNamedInterpreter("interpreter"), + m_constStrArgNamedCommand("command") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "interpreter-exec"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdInterpreterExec::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdInterpreterExec destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdInterpreterExec::~CMICmdCmdInterpreterExec() -{ -} +CMICmdCmdInterpreterExec::~CMICmdCmdInterpreterExec() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -427,45 +442,51 @@ CMICmdCmdInterpreterExec::~CMICmdCmdInterpreterExec() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdInterpreterExec::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedInterpreter, true, true)); - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedCommand, true, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdInterpreterExec::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValString(m_constStrArgNamedInterpreter, true, true)); + m_setCmdArgs.Add( + new CMICmdArgValString(m_constStrArgNamedCommand, true, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdInterpreterExec::Execute() -{ - CMICMDBASE_GETOPTION(pArgInterpreter, String, m_constStrArgNamedInterpreter); - CMICMDBASE_GETOPTION(pArgCommand, String, m_constStrArgNamedCommand); - - // Handle the interpreter parameter by do nothing on purpose (set to 'handled' in - // the arg definition above) - const CMIUtilString &rStrInterpreter(pArgInterpreter->GetValue()); - MIunused(rStrInterpreter); - - const CMIUtilString &rStrCommand(pArgCommand->GetValue()); - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - const lldb::ReturnStatus rtn = - rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(rStrCommand.c_str(), m_lldbResult, true); - MIunused(rtn); - - return MIstatus::success; +bool CMICmdCmdInterpreterExec::Execute() { + CMICMDBASE_GETOPTION(pArgInterpreter, String, m_constStrArgNamedInterpreter); + CMICMDBASE_GETOPTION(pArgCommand, String, m_constStrArgNamedCommand); + + // Handle the interpreter parameter by do nothing on purpose (set to 'handled' + // in + // the arg definition above) + const CMIUtilString &rStrInterpreter(pArgInterpreter->GetValue()); + MIunused(rStrInterpreter); + + const CMIUtilString &rStrCommand(pArgCommand->GetValue()); + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + const lldb::ReturnStatus rtn = + rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand( + rStrCommand.c_str(), m_lldbResult, true); + MIunused(rtn); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -473,92 +494,91 @@ CMICmdCmdInterpreterExec::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdInterpreterExec::Acknowledge() -{ - if (m_lldbResult.GetOutputSize() > 0) - { - CMIUtilString strMsg(m_lldbResult.GetOutput()); - strMsg = strMsg.StripCREndOfLine(); - CMICmnStreamStdout::TextToStdout(strMsg); - } - if (m_lldbResult.GetErrorSize() > 0) - { - CMIUtilString strMsg(m_lldbResult.GetError()); - strMsg = strMsg.StripCREndOfLine(); - CMICmnStreamStderr::LLDBMsgToConsole(strMsg); - } - - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); - m_miResultRecord = miRecordResult; - - return MIstatus::success; +bool CMICmdCmdInterpreterExec::Acknowledge() { + if (m_lldbResult.GetOutputSize() > 0) { + CMIUtilString strMsg(m_lldbResult.GetOutput()); + strMsg = strMsg.StripCREndOfLine(); + CMICmnStreamStdout::TextToStdout(strMsg); + } + if (m_lldbResult.GetErrorSize() > 0) { + CMIUtilString strMsg(m_lldbResult.GetError()); + strMsg = strMsg.StripCREndOfLine(); + CMICmnStreamStderr::LLDBMsgToConsole(strMsg); + } + + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdInterpreterExec::CreateSelf() -{ - return new CMICmdCmdInterpreterExec(); +CMICmdBase *CMICmdCmdInterpreterExec::CreateSelf() { + return new CMICmdCmdInterpreterExec(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdInferiorTtySet constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdInferiorTtySet::CMICmdCmdInferiorTtySet() -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "inferior-tty-set"; +CMICmdCmdInferiorTtySet::CMICmdCmdInferiorTtySet() { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "inferior-tty-set"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdInferiorTtySet::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdInferiorTtySet::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdInferiorTtySet destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdInferiorTtySet::~CMICmdCmdInferiorTtySet() -{ -} - -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +CMICmdCmdInferiorTtySet::~CMICmdCmdInferiorTtySet() {} + +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdInferiorTtySet::Execute() -{ - // Do nothing +bool CMICmdCmdInferiorTtySet::Execute() { + // Do nothing - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -566,25 +586,24 @@ CMICmdCmdInferiorTtySet::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdInferiorTtySet::Acknowledge() -{ - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error); - m_miResultRecord = miRecordResult; +bool CMICmdCmdInferiorTtySet::Acknowledge() { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdInferiorTtySet::CreateSelf() -{ - return new CMICmdCmdInferiorTtySet(); +CMICmdBase *CMICmdCmdInferiorTtySet::CreateSelf() { + return new CMICmdCmdInferiorTtySet(); } diff --git a/lldb/tools/lldb-mi/MICmdCmdMiscellanous.h b/lldb/tools/lldb-mi/MICmdCmdMiscellanous.h index 9f82195c998..af75c19b4df 100644 --- a/lldb/tools/lldb-mi/MICmdCmdMiscellanous.h +++ b/lldb/tools/lldb-mi/MICmdCmdMiscellanous.h @@ -12,13 +12,16 @@ // CMICmdCmdInterpreterExec interface. // CMICmdCmdInferiorTtySet interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands derive a new command class from the +// command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// For an introduction to adding a new command see +// CMICmdCmdSupportInfoMiCmdQuery // command class as an example. #pragma once @@ -28,126 +31,127 @@ // In-house headers: #include "MICmdBase.h" -#include "MICmnMIValueTuple.h" #include "MICmnMIValueList.h" +#include "MICmnMIValueTuple.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "gdb-exit". //-- -class CMICmdCmdGdbExit : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdGdbExit(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdGdbExit() override; +class CMICmdCmdGdbExit : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdGdbExit(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdGdbExit() override; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "list-thread-groups". // This command does not follow the MI documentation exactly. // http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Miscellaneous-Commands.html#GDB_002fMI-Miscellaneous-Commands //-- -class CMICmdCmdListThreadGroups : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdListThreadGroups(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdListThreadGroups() override; - - // Typedefs: - private: - typedef std::vector<CMICmnMIValueTuple> VecMIValueTuple_t; - - // Attributes: - private: - bool m_bIsI1; // True = Yes command argument equal "i1", false = no match - bool m_bHaveArgOption; // True = Yes "--available" present, false = not found - bool m_bHaveArgRecurse; // True = Yes command argument "--recurse", false = no found - VecMIValueTuple_t m_vecMIValueTuple; - const CMIUtilString m_constStrArgNamedAvailable; - const CMIUtilString m_constStrArgNamedRecurse; - const CMIUtilString m_constStrArgNamedGroup; - const CMIUtilString m_constStrArgNamedThreadGroup; +class CMICmdCmdListThreadGroups : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdListThreadGroups(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdListThreadGroups() override; + + // Typedefs: +private: + typedef std::vector<CMICmnMIValueTuple> VecMIValueTuple_t; + + // Attributes: +private: + bool m_bIsI1; // True = Yes command argument equal "i1", false = no match + bool m_bHaveArgOption; // True = Yes "--available" present, false = not found + bool m_bHaveArgRecurse; // True = Yes command argument "--recurse", false = no + // found + VecMIValueTuple_t m_vecMIValueTuple; + const CMIUtilString m_constStrArgNamedAvailable; + const CMIUtilString m_constStrArgNamedRecurse; + const CMIUtilString m_constStrArgNamedGroup; + const CMIUtilString m_constStrArgNamedThreadGroup; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "interpreter-exec". //-- -class CMICmdCmdInterpreterExec : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdInterpreterExec(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdInterpreterExec() override; - - // Attributes: - private: - const CMIUtilString m_constStrArgNamedInterpreter; - const CMIUtilString m_constStrArgNamedCommand; - lldb::SBCommandReturnObject m_lldbResult; +class CMICmdCmdInterpreterExec : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdInterpreterExec(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdInterpreterExec() override; + + // Attributes: +private: + const CMIUtilString m_constStrArgNamedInterpreter; + const CMIUtilString m_constStrArgNamedCommand; + lldb::SBCommandReturnObject m_lldbResult; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "inferior-tty-set". //-- -class CMICmdCmdInferiorTtySet : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdInferiorTtySet(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdInferiorTtySet() override; +class CMICmdCmdInferiorTtySet : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdInferiorTtySet(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdInferiorTtySet() override; }; diff --git a/lldb/tools/lldb-mi/MICmdCmdStack.cpp b/lldb/tools/lldb-mi/MICmdCmdStack.cpp index bc3483313f3..9160c401094 100644 --- a/lldb/tools/lldb-mi/MICmdCmdStack.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdStack.cpp @@ -18,21 +18,22 @@ #include "lldb/API/SBThread.h" // In-house headers: -#include "MICmdCmdStack.h" -#include "MICmnMIResultRecord.h" -#include "MICmnMIValueConst.h" -#include "MICmnMIOutOfBandRecord.h" -#include "MICmnLLDBDebugger.h" -#include "MICmnLLDBDebugSessionInfo.h" +#include "MICmdArgValListOfN.h" #include "MICmdArgValNumber.h" -#include "MICmdArgValString.h" -#include "MICmdArgValThreadGrp.h" #include "MICmdArgValOptionLong.h" #include "MICmdArgValOptionShort.h" #include "MICmdArgValPrintValues.h" -#include "MICmdArgValListOfN.h" +#include "MICmdArgValString.h" +#include "MICmdArgValThreadGrp.h" +#include "MICmdCmdStack.h" +#include "MICmnLLDBDebugSessionInfo.h" +#include "MICmnLLDBDebugger.h" +#include "MICmnMIOutOfBandRecord.h" +#include "MICmnMIResultRecord.h" +#include "MICmnMIValueConst.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdStackInfoDepth constructor. // Type: Method. // Args: None. @@ -40,29 +41,28 @@ // Throws: None. //-- CMICmdCmdStackInfoDepth::CMICmdCmdStackInfoDepth() - : m_nThreadFrames(0) - , m_constStrArgMaxDepth("max-depth") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "stack-info-depth"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdStackInfoDepth::CreateSelf; + : m_nThreadFrames(0), m_constStrArgMaxDepth("max-depth") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "stack-info-depth"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdStackInfoDepth::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdStackInfoDepth destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdStackInfoDepth::~CMICmdCmdStackInfoDepth() -{ -} +CMICmdCmdStackInfoDepth::~CMICmdCmdStackInfoDepth() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -70,46 +70,52 @@ CMICmdCmdStackInfoDepth::~CMICmdCmdStackInfoDepth() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdStackInfoDepth::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgMaxDepth, false, false)); - return ParseValidateCmdOptions(); +bool CMICmdCmdStackInfoDepth::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgMaxDepth, false, false)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdStackInfoDepth::Execute() -{ - CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); - CMICMDBASE_GETOPTION(pArgMaxDepth, Number, m_constStrArgMaxDepth); - - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); - return MIstatus::failure; - } - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); - lldb::SBThread thread = (nThreadId != UINT64_MAX) ? sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.GetSelectedThread(); - m_nThreadFrames = thread.GetNumFrames(); - - return MIstatus::success; +bool CMICmdCmdStackInfoDepth::Execute() { + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + CMICMDBASE_GETOPTION(pArgMaxDepth, Number, m_constStrArgMaxDepth); + + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (pArgThread->GetFound() && + !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), + m_constStrArgThread.c_str())); + return MIstatus::failure; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + lldb::SBThread thread = (nThreadId != UINT64_MAX) + ? sbProcess.GetThreadByIndexID(nThreadId) + : sbProcess.GetSelectedThread(); + m_nThreadFrames = thread.GetNumFrames(); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -117,65 +123,66 @@ CMICmdCmdStackInfoDepth::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdStackInfoDepth::Acknowledge() -{ - const CMIUtilString strDepth(CMIUtilString::Format("%d", m_nThreadFrames)); - const CMICmnMIValueConst miValueConst(strDepth); - const CMICmnMIValueResult miValueResult("depth", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - - return MIstatus::success; +bool CMICmdCmdStackInfoDepth::Acknowledge() { + const CMIUtilString strDepth(CMIUtilString::Format("%d", m_nThreadFrames)); + const CMICmnMIValueConst miValueConst(strDepth); + const CMICmnMIValueResult miValueResult("depth", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdStackInfoDepth::CreateSelf() -{ - return new CMICmdCmdStackInfoDepth(); +CMICmdBase *CMICmdCmdStackInfoDepth::CreateSelf() { + return new CMICmdCmdStackInfoDepth(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdStackInfoFrame constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdStackInfoFrame::CMICmdCmdStackInfoFrame() -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "stack-info-frame"; +CMICmdCmdStackInfoFrame::CMICmdCmdStackInfoFrame() { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "stack-info-frame"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdStackInfoFrame::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdStackInfoFrame::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdStackInfoFrame destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdStackInfoFrame::~CMICmdCmdStackInfoFrame() -{ -} +CMICmdCmdStackInfoFrame::~CMICmdCmdStackInfoFrame() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -183,42 +190,45 @@ CMICmdCmdStackInfoFrame::~CMICmdCmdStackInfoFrame() // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdStackInfoFrame::ParseArgs() -{ - return ParseValidateCmdOptions(); -} - -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +bool CMICmdCmdStackInfoFrame::ParseArgs() { return ParseValidateCmdOptions(); } + +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdStackInfoFrame::Execute() -{ - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); - if (!sbProcess.IsValid()) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str())); - return MIstatus::failure; - } - - lldb::SBThread sbThread = sbProcess.GetSelectedThread(); - MIuint nFrameId = sbThread.GetSelectedFrame().GetFrameID(); - if (!rSessionInfo.MIResponseFormFrameInfo(sbThread, nFrameId, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_NoArguments, m_miValueTuple)) - return MIstatus::failure; - - return MIstatus::success; +bool CMICmdCmdStackInfoFrame::Execute() { + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + if (!sbProcess.IsValid()) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), + m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + + lldb::SBThread sbThread = sbProcess.GetSelectedThread(); + MIuint nFrameId = sbThread.GetSelectedFrame().GetFrameID(); + if (!rSessionInfo.MIResponseFormFrameInfo( + sbThread, nFrameId, + CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_NoArguments, + m_miValueTuple)) + return MIstatus::failure; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -226,35 +236,36 @@ CMICmdCmdStackInfoFrame::Execute() // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdStackInfoFrame::Acknowledge() -{ - const CMICmnMIValueResult miValueResult("frame", m_miValueTuple); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - - return MIstatus::success; +bool CMICmdCmdStackInfoFrame::Acknowledge() { + const CMICmnMIValueResult miValueResult("frame", m_miValueTuple); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdStackInfoFrame::CreateSelf() -{ - return new CMICmdCmdStackInfoFrame(); +CMICmdBase *CMICmdCmdStackInfoFrame::CreateSelf() { + return new CMICmdCmdStackInfoFrame(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdStackListFrames constructor. // Type: Method. // Args: None. @@ -262,31 +273,31 @@ CMICmdCmdStackInfoFrame::CreateSelf() // Throws: None. //-- CMICmdCmdStackListFrames::CMICmdCmdStackListFrames() - : m_nThreadFrames(0) - , m_constStrArgFrameLow("low-frame") - , m_constStrArgFrameHigh("high-frame") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "stack-list-frames"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdStackListFrames::CreateSelf; + : m_nThreadFrames(0), m_constStrArgFrameLow("low-frame"), + m_constStrArgFrameHigh("high-frame") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "stack-list-frames"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdStackListFrames::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdStackListFrames destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdStackListFrames::~CMICmdCmdStackListFrames() -{ - m_vecMIValueResult.clear(); +CMICmdCmdStackListFrames::~CMICmdCmdStackListFrames() { + m_vecMIValueResult.clear(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -294,75 +305,85 @@ CMICmdCmdStackListFrames::~CMICmdCmdStackListFrames() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdStackListFrames::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameLow, false, true)); - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameHigh, false, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdStackListFrames::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameLow, false, true)); + m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameHigh, false, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdStackListFrames::Execute() -{ - CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); - CMICMDBASE_GETOPTION(pArgFrameLow, Number, m_constStrArgFrameLow); - CMICMDBASE_GETOPTION(pArgFrameHigh, Number, m_constStrArgFrameHigh); - - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); - return MIstatus::failure; - } - - // Frame low and high options are not mandatory - MIuint nFrameHigh = pArgFrameHigh->GetFound() ? pArgFrameHigh->GetValue() : UINT32_MAX; - const MIuint nFrameLow = pArgFrameLow->GetFound() ? pArgFrameLow->GetValue() : 0; - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); - lldb::SBThread thread = (nThreadId != UINT64_MAX) ? sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.GetSelectedThread(); - MIuint nThreadFrames = thread.GetNumFrames(); - - // Adjust nThreadFrames for the nFrameHigh argument as we use nFrameHigh+1 in the min calc as the arg - // is not an index, but a frame id value. - if (nFrameHigh < UINT32_MAX) - { - nFrameHigh++; - nThreadFrames = (nFrameHigh < nThreadFrames) ? nFrameHigh : nThreadFrames; - } - - m_nThreadFrames = nThreadFrames; - if (nThreadFrames == 0) - return MIstatus::success; +bool CMICmdCmdStackListFrames::Execute() { + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + CMICMDBASE_GETOPTION(pArgFrameLow, Number, m_constStrArgFrameLow); + CMICMDBASE_GETOPTION(pArgFrameHigh, Number, m_constStrArgFrameHigh); + + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (pArgThread->GetFound() && + !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), + m_constStrArgThread.c_str())); + return MIstatus::failure; + } + + // Frame low and high options are not mandatory + MIuint nFrameHigh = + pArgFrameHigh->GetFound() ? pArgFrameHigh->GetValue() : UINT32_MAX; + const MIuint nFrameLow = + pArgFrameLow->GetFound() ? pArgFrameLow->GetValue() : 0; + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + lldb::SBThread thread = (nThreadId != UINT64_MAX) + ? sbProcess.GetThreadByIndexID(nThreadId) + : sbProcess.GetSelectedThread(); + MIuint nThreadFrames = thread.GetNumFrames(); + + // Adjust nThreadFrames for the nFrameHigh argument as we use nFrameHigh+1 in + // the min calc as the arg + // is not an index, but a frame id value. + if (nFrameHigh < UINT32_MAX) { + nFrameHigh++; + nThreadFrames = (nFrameHigh < nThreadFrames) ? nFrameHigh : nThreadFrames; + } + + m_nThreadFrames = nThreadFrames; + if (nThreadFrames == 0) + return MIstatus::success; - m_vecMIValueResult.clear(); - for (MIuint nLevel = nFrameLow; nLevel < nThreadFrames; nLevel++) - { - CMICmnMIValueTuple miValueTuple; - if (!rSessionInfo.MIResponseFormFrameInfo(thread, nLevel, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_NoArguments, miValueTuple)) - return MIstatus::failure; + m_vecMIValueResult.clear(); + for (MIuint nLevel = nFrameLow; nLevel < nThreadFrames; nLevel++) { + CMICmnMIValueTuple miValueTuple; + if (!rSessionInfo.MIResponseFormFrameInfo( + thread, nLevel, + CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_NoArguments, + miValueTuple)) + return MIstatus::failure; - const CMICmnMIValueResult miValueResult8("frame", miValueTuple); - m_vecMIValueResult.push_back(miValueResult8); - } + const CMICmnMIValueResult miValueResult8("frame", miValueTuple); + m_vecMIValueResult.push_back(miValueResult8); + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -370,69 +391,71 @@ CMICmdCmdStackListFrames::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdStackListFrames::Acknowledge() -{ - if (m_nThreadFrames == 0) - { - // MI print "3^done,stack=[{}]" - const CMICmnMIValueTuple miValueTuple; - const CMICmnMIValueList miValueList(miValueTuple); - const CMICmnMIValueResult miValueResult("stack", miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - - return MIstatus::success; - } - - // Build up a list of thread information from tuples - VecMIValueResult_t::const_iterator it = m_vecMIValueResult.begin(); - if (it == m_vecMIValueResult.end()) - { - // MI print "3^done,stack=[{}]" - const CMICmnMIValueTuple miValueTuple; - const CMICmnMIValueList miValueList(miValueTuple); - const CMICmnMIValueResult miValueResult("stack", miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - CMICmnMIValueList miValueList(*it); - ++it; - while (it != m_vecMIValueResult.end()) - { - const CMICmnMIValueResult &rTuple(*it); - miValueList.Add(rTuple); - - // Next - ++it; - } +bool CMICmdCmdStackListFrames::Acknowledge() { + if (m_nThreadFrames == 0) { + // MI print "3^done,stack=[{}]" + const CMICmnMIValueTuple miValueTuple; + const CMICmnMIValueList miValueList(miValueTuple); const CMICmnMIValueResult miValueResult("stack", miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); m_miResultRecord = miRecordResult; return MIstatus::success; + } + + // Build up a list of thread information from tuples + VecMIValueResult_t::const_iterator it = m_vecMIValueResult.begin(); + if (it == m_vecMIValueResult.end()) { + // MI print "3^done,stack=[{}]" + const CMICmnMIValueTuple miValueTuple; + const CMICmnMIValueList miValueList(miValueTuple); + const CMICmnMIValueResult miValueResult("stack", miValueList); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + CMICmnMIValueList miValueList(*it); + ++it; + while (it != m_vecMIValueResult.end()) { + const CMICmnMIValueResult &rTuple(*it); + miValueList.Add(rTuple); + + // Next + ++it; + } + const CMICmnMIValueResult miValueResult("stack", miValueList); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdStackListFrames::CreateSelf() -{ - return new CMICmdCmdStackListFrames(); +CMICmdBase *CMICmdCmdStackListFrames::CreateSelf() { + return new CMICmdCmdStackListFrames(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdStackListArguments constructor. // Type: Method. // Args: None. @@ -440,32 +463,30 @@ CMICmdCmdStackListFrames::CreateSelf() // Throws: None. //-- CMICmdCmdStackListArguments::CMICmdCmdStackListArguments() - : m_bThreadInvalid(false) - , m_miValueList(true) - , m_constStrArgPrintValues("print-values") - , m_constStrArgFrameLow("low-frame") - , m_constStrArgFrameHigh("high-frame") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "stack-list-arguments"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdStackListArguments::CreateSelf; + : m_bThreadInvalid(false), m_miValueList(true), + m_constStrArgPrintValues("print-values"), + m_constStrArgFrameLow("low-frame"), m_constStrArgFrameHigh("high-frame") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "stack-list-arguments"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdStackListArguments::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdStackListArguments destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdStackListArguments::~CMICmdCmdStackListArguments() -{ -} +CMICmdCmdStackListArguments::~CMICmdCmdStackListArguments() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -473,103 +494,112 @@ CMICmdCmdStackListArguments::~CMICmdCmdStackListArguments() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdStackListArguments::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValPrintValues(m_constStrArgPrintValues, true, true)); - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameLow, false, true)); - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameHigh, false, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdStackListArguments::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValPrintValues(m_constStrArgPrintValues, true, true)); + m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameLow, false, true)); + m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameHigh, false, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdStackListArguments::Execute() -{ - CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); - CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues); - CMICMDBASE_GETOPTION(pArgFrameLow, Number, m_constStrArgFrameLow); - CMICMDBASE_GETOPTION(pArgFrameHigh, Number, m_constStrArgFrameHigh); - - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if (pArgThread->GetFound()) - { - if (!pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); - return MIstatus::failure; - } - } - - const CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat = static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>(pArgPrintValues->GetValue()); - - MIuint nFrameLow = 0; - MIuint nFrameHigh = UINT32_MAX; - if (pArgFrameLow->GetFound() && pArgFrameHigh->GetFound()) - { - nFrameLow = pArgFrameLow->GetValue(); - nFrameHigh = pArgFrameHigh->GetValue() + 1; - } - else if (pArgFrameLow->GetFound() || pArgFrameHigh->GetFound()) - { - // Only low-frame or high-frame was specified but both are required - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID), m_cmdData.strMiCmd.c_str())); - return MIstatus::failure; - } - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); - lldb::SBThread thread = (nThreadId != UINT64_MAX) ? sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.GetSelectedThread(); - m_bThreadInvalid = !thread.IsValid(); - if (m_bThreadInvalid) - return MIstatus::success; - - const lldb::StopReason eStopReason = thread.GetStopReason(); - if ((eStopReason == lldb::eStopReasonNone) || (eStopReason == lldb::eStopReasonInvalid)) - { - m_bThreadInvalid = true; - return MIstatus::success; - } - - const MIuint nFrames = thread.GetNumFrames(); - if (nFrameLow >= nFrames) - { - // The low-frame is larger than the actual number of frames - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID), m_cmdData.strMiCmd.c_str())); - return MIstatus::failure; - } - - nFrameHigh = std::min(nFrameHigh, nFrames); - for (MIuint i = nFrameLow; i < nFrameHigh; i++) - { - lldb::SBFrame frame = thread.GetFrameAtIndex(i); - CMICmnMIValueList miValueList(true); - const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments; - if (!rSessionInfo.MIResponseFormVariableInfo(frame, maskVarTypes, eVarInfoFormat, miValueList)) - return MIstatus::failure; - const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", i)); - const CMICmnMIValueResult miValueResult("level", miValueConst); - CMICmnMIValueTuple miValueTuple(miValueResult); - const CMICmnMIValueResult miValueResult2("args", miValueList); - miValueTuple.Add(miValueResult2); - const CMICmnMIValueResult miValueResult3("frame", miValueTuple); - m_miValueList.Add(miValueResult3); +bool CMICmdCmdStackListArguments::Execute() { + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues); + CMICMDBASE_GETOPTION(pArgFrameLow, Number, m_constStrArgFrameLow); + CMICMDBASE_GETOPTION(pArgFrameHigh, Number, m_constStrArgFrameHigh); + + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (pArgThread->GetFound()) { + if (!pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>( + nThreadId)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), + m_constStrArgThread.c_str())); + return MIstatus::failure; } + } + + const CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat = + static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>( + pArgPrintValues->GetValue()); + + MIuint nFrameLow = 0; + MIuint nFrameHigh = UINT32_MAX; + if (pArgFrameLow->GetFound() && pArgFrameHigh->GetFound()) { + nFrameLow = pArgFrameLow->GetValue(); + nFrameHigh = pArgFrameHigh->GetValue() + 1; + } else if (pArgFrameLow->GetFound() || pArgFrameHigh->GetFound()) { + // Only low-frame or high-frame was specified but both are required + SetError( + CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID), + m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + lldb::SBThread thread = (nThreadId != UINT64_MAX) + ? sbProcess.GetThreadByIndexID(nThreadId) + : sbProcess.GetSelectedThread(); + m_bThreadInvalid = !thread.IsValid(); + if (m_bThreadInvalid) + return MIstatus::success; + const lldb::StopReason eStopReason = thread.GetStopReason(); + if ((eStopReason == lldb::eStopReasonNone) || + (eStopReason == lldb::eStopReasonInvalid)) { + m_bThreadInvalid = true; return MIstatus::success; + } + + const MIuint nFrames = thread.GetNumFrames(); + if (nFrameLow >= nFrames) { + // The low-frame is larger than the actual number of frames + SetError( + CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID), + m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + + nFrameHigh = std::min(nFrameHigh, nFrames); + for (MIuint i = nFrameLow; i < nFrameHigh; i++) { + lldb::SBFrame frame = thread.GetFrameAtIndex(i); + CMICmnMIValueList miValueList(true); + const MIuint maskVarTypes = + CMICmnLLDBDebugSessionInfo::eVariableType_Arguments; + if (!rSessionInfo.MIResponseFormVariableInfo(frame, maskVarTypes, + eVarInfoFormat, miValueList)) + return MIstatus::failure; + const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", i)); + const CMICmnMIValueResult miValueResult("level", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const CMICmnMIValueResult miValueResult2("args", miValueList); + miValueTuple.Add(miValueResult2); + const CMICmnMIValueResult miValueResult3("frame", miValueTuple); + m_miValueList.Add(miValueResult3); + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -577,46 +607,49 @@ CMICmdCmdStackListArguments::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdStackListArguments::Acknowledge() -{ - if (m_bThreadInvalid) - { - // MI print "%s^done,stack-args=[]" - const CMICmnMIValueList miValueList(true); - const CMICmnMIValueResult miValueResult("stack-args", miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - // MI print "%s^done,stack-args=[frame={level=\"0\",args=[%s]},frame={level=\"1\",args=[%s]}]" - const CMICmnMIValueResult miValueResult4("stack-args", m_miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult4); +bool CMICmdCmdStackListArguments::Acknowledge() { + if (m_bThreadInvalid) { + // MI print "%s^done,stack-args=[]" + const CMICmnMIValueList miValueList(true); + const CMICmnMIValueResult miValueResult("stack-args", miValueList); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); m_miResultRecord = miRecordResult; - return MIstatus::success; + } + + // MI print + // "%s^done,stack-args=[frame={level=\"0\",args=[%s]},frame={level=\"1\",args=[%s]}]" + const CMICmnMIValueResult miValueResult4("stack-args", m_miValueList); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult4); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdStackListArguments::CreateSelf() -{ - return new CMICmdCmdStackListArguments(); +CMICmdBase *CMICmdCmdStackListArguments::CreateSelf() { + return new CMICmdCmdStackListArguments(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdStackListLocals constructor. // Type: Method. // Args: None. @@ -624,30 +657,29 @@ CMICmdCmdStackListArguments::CreateSelf() // Throws: None. //-- CMICmdCmdStackListLocals::CMICmdCmdStackListLocals() - : m_bThreadInvalid(false) - , m_miValueList(true) - , m_constStrArgPrintValues("print-values") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "stack-list-locals"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdStackListLocals::CreateSelf; + : m_bThreadInvalid(false), m_miValueList(true), + m_constStrArgPrintValues("print-values") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "stack-list-locals"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdStackListLocals::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdStackListLocals destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdStackListLocals::~CMICmdCmdStackListLocals() -{ -} +CMICmdCmdStackListLocals::~CMICmdCmdStackListLocals() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -655,80 +687,90 @@ CMICmdCmdStackListLocals::~CMICmdCmdStackListLocals() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdStackListLocals::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValPrintValues(m_constStrArgPrintValues, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdStackListLocals::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValPrintValues(m_constStrArgPrintValues, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdStackListLocals::Execute() -{ - CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); - CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame); - CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues); - - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if (pArgThread->GetFound()) - { - if (!pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); - return MIstatus::failure; - } +bool CMICmdCmdStackListLocals::Execute() { + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame); + CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues); + + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (pArgThread->GetFound()) { + if (!pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>( + nThreadId)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), + m_constStrArgThread.c_str())); + return MIstatus::failure; } - - MIuint64 nFrame = UINT64_MAX; - if (pArgFrame->GetFound()) - { - if (!pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str())); - return MIstatus::failure; - } + } + + MIuint64 nFrame = UINT64_MAX; + if (pArgFrame->GetFound()) { + if (!pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), + m_constStrArgFrame.c_str())); + return MIstatus::failure; } + } + + const CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat = + static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>( + pArgPrintValues->GetValue()); + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + lldb::SBThread thread = (nThreadId != UINT64_MAX) + ? sbProcess.GetThreadByIndexID(nThreadId) + : sbProcess.GetSelectedThread(); + m_bThreadInvalid = !thread.IsValid(); + if (m_bThreadInvalid) + return MIstatus::success; - const CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat = static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>(pArgPrintValues->GetValue()); - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); - lldb::SBThread thread = (nThreadId != UINT64_MAX) ? sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.GetSelectedThread(); - m_bThreadInvalid = !thread.IsValid(); - if (m_bThreadInvalid) - return MIstatus::success; - - const lldb::StopReason eStopReason = thread.GetStopReason(); - if ((eStopReason == lldb::eStopReasonNone) || (eStopReason == lldb::eStopReasonInvalid)) - { - m_bThreadInvalid = true; - return MIstatus::success; - } + const lldb::StopReason eStopReason = thread.GetStopReason(); + if ((eStopReason == lldb::eStopReasonNone) || + (eStopReason == lldb::eStopReasonInvalid)) { + m_bThreadInvalid = true; + return MIstatus::success; + } - lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex(nFrame) : thread.GetSelectedFrame(); + lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex(nFrame) + : thread.GetSelectedFrame(); - CMICmnMIValueList miValueList(true); - const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Locals; - if (!rSessionInfo.MIResponseFormVariableInfo(frame, maskVarTypes, eVarInfoFormat, miValueList)) - return MIstatus::failure; + CMICmnMIValueList miValueList(true); + const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Locals; + if (!rSessionInfo.MIResponseFormVariableInfo(frame, maskVarTypes, + eVarInfoFormat, miValueList)) + return MIstatus::failure; - m_miValueList = miValueList; + m_miValueList = miValueList; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -736,46 +778,48 @@ CMICmdCmdStackListLocals::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdStackListLocals::Acknowledge() -{ - if (m_bThreadInvalid) - { - // MI print "%s^done,locals=[]" - const CMICmnMIValueList miValueList(true); - const CMICmnMIValueResult miValueResult("locals", miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - // MI print "%s^done,locals=[%s]" - const CMICmnMIValueResult miValueResult("locals", m_miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); +bool CMICmdCmdStackListLocals::Acknowledge() { + if (m_bThreadInvalid) { + // MI print "%s^done,locals=[]" + const CMICmnMIValueList miValueList(true); + const CMICmnMIValueResult miValueResult("locals", miValueList); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); m_miResultRecord = miRecordResult; - return MIstatus::success; + } + + // MI print "%s^done,locals=[%s]" + const CMICmnMIValueResult miValueResult("locals", m_miValueList); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdStackListLocals::CreateSelf() -{ - return new CMICmdCmdStackListLocals(); +CMICmdBase *CMICmdCmdStackListLocals::CreateSelf() { + return new CMICmdCmdStackListLocals(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdStackListVariables constructor. // Type: Method. // Args: None. @@ -783,30 +827,29 @@ CMICmdCmdStackListLocals::CreateSelf() // Throws: None. //-- CMICmdCmdStackListVariables::CMICmdCmdStackListVariables() - : m_bThreadInvalid(false) - , m_miValueList(true) - , m_constStrArgPrintValues("print-values") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "stack-list-variables"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdStackListVariables::CreateSelf; + : m_bThreadInvalid(false), m_miValueList(true), + m_constStrArgPrintValues("print-values") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "stack-list-variables"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdStackListVariables::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdStackListVariables destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdStackListVariables::~CMICmdCmdStackListVariables() -{ -} +CMICmdCmdStackListVariables::~CMICmdCmdStackListVariables() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -814,79 +857,91 @@ CMICmdCmdStackListVariables::~CMICmdCmdStackListVariables() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdStackListVariables::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValPrintValues(m_constStrArgPrintValues, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdStackListVariables::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValPrintValues(m_constStrArgPrintValues, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdStackListVariables::Execute() -{ - CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); - CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame); - CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues); - - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if (pArgThread->GetFound()) - { - if (!pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); - return MIstatus::failure; - } +bool CMICmdCmdStackListVariables::Execute() { + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame); + CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues); + + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (pArgThread->GetFound()) { + if (!pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>( + nThreadId)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), + m_constStrArgThread.c_str())); + return MIstatus::failure; } - - MIuint64 nFrame = UINT64_MAX; - if (pArgFrame->GetFound()) - { - if (!pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str())); - return MIstatus::failure; - } + } + + MIuint64 nFrame = UINT64_MAX; + if (pArgFrame->GetFound()) { + if (!pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), + m_constStrArgFrame.c_str())); + return MIstatus::failure; } - - const CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat = static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>(pArgPrintValues->GetValue()); - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); - lldb::SBThread thread = (nThreadId != UINT64_MAX) ? sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.GetSelectedThread(); - m_bThreadInvalid = !thread.IsValid(); - if (m_bThreadInvalid) - return MIstatus::success; - - const lldb::StopReason eStopReason = thread.GetStopReason(); - if ((eStopReason == lldb::eStopReasonNone) || (eStopReason == lldb::eStopReasonInvalid)) - { - m_bThreadInvalid = true; - return MIstatus::success; - } - - lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex(nFrame) : thread.GetSelectedFrame(); - - CMICmnMIValueList miValueList(true); - const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments | CMICmnLLDBDebugSessionInfo::eVariableType_Locals; - if (!rSessionInfo.MIResponseFormVariableInfo(frame, maskVarTypes, eVarInfoFormat, miValueList, 10, true)) - return MIstatus::failure; - m_miValueList = miValueList; - + } + + const CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat = + static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>( + pArgPrintValues->GetValue()); + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + lldb::SBThread thread = (nThreadId != UINT64_MAX) + ? sbProcess.GetThreadByIndexID(nThreadId) + : sbProcess.GetSelectedThread(); + m_bThreadInvalid = !thread.IsValid(); + if (m_bThreadInvalid) + return MIstatus::success; + + const lldb::StopReason eStopReason = thread.GetStopReason(); + if ((eStopReason == lldb::eStopReasonNone) || + (eStopReason == lldb::eStopReasonInvalid)) { + m_bThreadInvalid = true; return MIstatus::success; + } + + lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex(nFrame) + : thread.GetSelectedFrame(); + + CMICmnMIValueList miValueList(true); + const MIuint maskVarTypes = + CMICmnLLDBDebugSessionInfo::eVariableType_Arguments | + CMICmnLLDBDebugSessionInfo::eVariableType_Locals; + if (!rSessionInfo.MIResponseFormVariableInfo( + frame, maskVarTypes, eVarInfoFormat, miValueList, 10, true)) + return MIstatus::failure; + m_miValueList = miValueList; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -894,46 +949,48 @@ CMICmdCmdStackListVariables::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdStackListVariables::Acknowledge() -{ - if (m_bThreadInvalid) - { - // MI print "%s^done,variables=[]" - const CMICmnMIValueList miValueList(true); - const CMICmnMIValueResult miValueResult("variables", miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - // MI print "%s^done,variables=[%s]" - const CMICmnMIValueResult miValueResult("variables", m_miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); +bool CMICmdCmdStackListVariables::Acknowledge() { + if (m_bThreadInvalid) { + // MI print "%s^done,variables=[]" + const CMICmnMIValueList miValueList(true); + const CMICmnMIValueResult miValueResult("variables", miValueList); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); m_miResultRecord = miRecordResult; - return MIstatus::success; + } + + // MI print "%s^done,variables=[%s]" + const CMICmnMIValueResult miValueResult("variables", m_miValueList); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdStackListVariables::CreateSelf() -{ - return new CMICmdCmdStackListVariables(); +CMICmdBase *CMICmdCmdStackListVariables::CreateSelf() { + return new CMICmdCmdStackListVariables(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdStackSelectFrame constructor. // Type: Method. // Args: None. @@ -941,29 +998,28 @@ CMICmdCmdStackListVariables::CreateSelf() // Throws: None. //-- CMICmdCmdStackSelectFrame::CMICmdCmdStackSelectFrame() - : m_bFrameInvalid(false) - , m_constStrArgFrameId("frame_id") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "stack-select-frame"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdStackSelectFrame::CreateSelf; + : m_bFrameInvalid(false), m_constStrArgFrameId("frame_id") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "stack-select-frame"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdStackSelectFrame::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdStackSelectFrame destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdStackSelectFrame::~CMICmdCmdStackSelectFrame() -{ -} +CMICmdCmdStackSelectFrame::~CMICmdCmdStackSelectFrame() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -971,43 +1027,45 @@ CMICmdCmdStackSelectFrame::~CMICmdCmdStackSelectFrame() // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdStackSelectFrame::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameId, true, false)); - return ParseValidateCmdOptions(); +bool CMICmdCmdStackSelectFrame::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrameId, true, false)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdStackSelectFrame::Execute() -{ - CMICMDBASE_GETOPTION(pArgFrame, Number, m_constStrArgFrameId); +bool CMICmdCmdStackSelectFrame::Execute() { + CMICMDBASE_GETOPTION(pArgFrame, Number, m_constStrArgFrameId); - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBThread sbThread = rSessionInfo.GetProcess().GetSelectedThread(); + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBThread sbThread = rSessionInfo.GetProcess().GetSelectedThread(); - const MIuint nFrameId = pArgFrame->GetValue(); - m_bFrameInvalid = (nFrameId >= sbThread.GetNumFrames()); - if (m_bFrameInvalid) - return MIstatus::success; + const MIuint nFrameId = pArgFrame->GetValue(); + m_bFrameInvalid = (nFrameId >= sbThread.GetNumFrames()); + if (m_bFrameInvalid) + return MIstatus::success; - lldb::SBFrame sbFrame = sbThread.SetSelectedFrame(nFrameId); - m_bFrameInvalid = !sbFrame.IsValid(); + lldb::SBFrame sbFrame = sbThread.SetSelectedFrame(nFrameId); + m_bFrameInvalid = !sbFrame.IsValid(); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -1015,37 +1073,38 @@ CMICmdCmdStackSelectFrame::Execute() // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmdCmdStackSelectFrame::Acknowledge() -{ - if (m_bFrameInvalid) - { - // MI print "%s^error,msg=\"Command '-stack-select-frame'. Frame ID invalid\"" - const CMICmnMIValueConst miValueConst( - CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FRAME_INVALID), m_cmdData.strMiCmd.c_str())); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; - - return MIstatus::success; - } - - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); +bool CMICmdCmdStackSelectFrame::Acknowledge() { + if (m_bFrameInvalid) { + // MI print "%s^error,msg=\"Command '-stack-select-frame'. Frame ID + // invalid\"" + const CMICmnMIValueConst miValueConst(CMIUtilString::Format( + MIRSRC(IDS_CMD_ERR_FRAME_INVALID), m_cmdData.strMiCmd.c_str())); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); m_miResultRecord = miRecordResult; return MIstatus::success; + } + + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdStackSelectFrame::CreateSelf() -{ - return new CMICmdCmdStackSelectFrame(); +CMICmdBase *CMICmdCmdStackSelectFrame::CreateSelf() { + return new CMICmdCmdStackSelectFrame(); } diff --git a/lldb/tools/lldb-mi/MICmdCmdStack.h b/lldb/tools/lldb-mi/MICmdCmdStack.h index e22a703545b..481186f5ddc 100644 --- a/lldb/tools/lldb-mi/MICmdCmdStack.h +++ b/lldb/tools/lldb-mi/MICmdCmdStack.h @@ -14,13 +14,16 @@ // CMICmdCmdStackListLocals interface. // CMICmdCmdStackSelectFrame interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands derive a new command class from the +// command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// For an introduction to adding a new command see +// CMICmdCmdSupportInfoMiCmdQuery // command class as an example. #pragma once @@ -30,222 +33,225 @@ #include "MICmnMIValueList.h" #include "MICmnMIValueTuple.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "stack-info-depth". //-- -class CMICmdCmdStackInfoDepth : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdStackInfoDepth(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdStackInfoDepth() override; - - // Attributes: - private: - MIuint m_nThreadFrames; - const CMIUtilString m_constStrArgMaxDepth; // Not handled by *this command +class CMICmdCmdStackInfoDepth : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdStackInfoDepth(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdStackInfoDepth() override; + + // Attributes: +private: + MIuint m_nThreadFrames; + const CMIUtilString m_constStrArgMaxDepth; // Not handled by *this command }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "stack-info-frame". //-- -class CMICmdCmdStackInfoFrame : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdStackInfoFrame(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdStackInfoFrame() override; - - // Attributes: - private: - CMICmnMIValueTuple m_miValueTuple; +class CMICmdCmdStackInfoFrame : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdStackInfoFrame(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdStackInfoFrame() override; + + // Attributes: +private: + CMICmnMIValueTuple m_miValueTuple; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "stack-list-frames". //-- -class CMICmdCmdStackListFrames : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdStackListFrames(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdStackListFrames() override; - - // Typedefs: - private: - typedef std::vector<CMICmnMIValueResult> VecMIValueResult_t; - - // Attributes: - private: - MIuint m_nThreadFrames; - VecMIValueResult_t m_vecMIValueResult; - const CMIUtilString m_constStrArgFrameLow; - const CMIUtilString m_constStrArgFrameHigh; +class CMICmdCmdStackListFrames : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdStackListFrames(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdStackListFrames() override; + + // Typedefs: +private: + typedef std::vector<CMICmnMIValueResult> VecMIValueResult_t; + + // Attributes: +private: + MIuint m_nThreadFrames; + VecMIValueResult_t m_vecMIValueResult; + const CMIUtilString m_constStrArgFrameLow; + const CMIUtilString m_constStrArgFrameHigh; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "stack-list-arguments". //-- -class CMICmdCmdStackListArguments : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdStackListArguments(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdStackListArguments() override; - - // Attributes: - private: - bool m_bThreadInvalid; // True = yes invalid thread, false = thread object valid - CMICmnMIValueList m_miValueList; - const CMIUtilString m_constStrArgPrintValues; - const CMIUtilString m_constStrArgFrameLow; - const CMIUtilString m_constStrArgFrameHigh; +class CMICmdCmdStackListArguments : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdStackListArguments(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdStackListArguments() override; + + // Attributes: +private: + bool m_bThreadInvalid; // True = yes invalid thread, false = thread object + // valid + CMICmnMIValueList m_miValueList; + const CMIUtilString m_constStrArgPrintValues; + const CMIUtilString m_constStrArgFrameLow; + const CMIUtilString m_constStrArgFrameHigh; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "stack-list-locals". //-- -class CMICmdCmdStackListLocals : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdStackListLocals(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdStackListLocals() override; - - // Attributes: - private: - bool m_bThreadInvalid; // True = yes invalid thread, false = thread object valid - CMICmnMIValueList m_miValueList; - const CMIUtilString m_constStrArgPrintValues; +class CMICmdCmdStackListLocals : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdStackListLocals(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdStackListLocals() override; + + // Attributes: +private: + bool m_bThreadInvalid; // True = yes invalid thread, false = thread object + // valid + CMICmnMIValueList m_miValueList; + const CMIUtilString m_constStrArgPrintValues; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "stack-list-variables". //-- -class CMICmdCmdStackListVariables : public CMICmdBase -{ - // Statics: -public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: -public: - /* ctor */ CMICmdCmdStackListVariables(); - - // Overridden: -public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdStackListVariables() override; - - // Attributes +class CMICmdCmdStackListVariables : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdStackListVariables(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdStackListVariables() override; + + // Attributes private: - bool m_bThreadInvalid; // True = yes invalid thread, false = thread object valid - CMICmnMIValueList m_miValueList; - const CMIUtilString m_constStrArgPrintValues; + bool m_bThreadInvalid; // True = yes invalid thread, false = thread object + // valid + CMICmnMIValueList m_miValueList; + const CMIUtilString m_constStrArgPrintValues; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "stack-select-frame". //-- -class CMICmdCmdStackSelectFrame : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdStackSelectFrame(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdStackSelectFrame() override; - - // Attributes: - private: - bool m_bFrameInvalid; // True = yes invalid frame, false = ok - const CMIUtilString m_constStrArgFrameId; +class CMICmdCmdStackSelectFrame : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdStackSelectFrame(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdStackSelectFrame() override; + + // Attributes: +private: + bool m_bFrameInvalid; // True = yes invalid frame, false = ok + const CMIUtilString m_constStrArgFrameId; }; diff --git a/lldb/tools/lldb-mi/MICmdCmdSupportInfo.cpp b/lldb/tools/lldb-mi/MICmdCmdSupportInfo.cpp index 9d926441dd2..e36d398b0a0 100644 --- a/lldb/tools/lldb-mi/MICmdCmdSupportInfo.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdSupportInfo.cpp @@ -11,13 +11,14 @@ // In-house headers: #include "MICmdCmdSupportInfo.h" +#include "MICmdArgValString.h" +#include "MICmdFactory.h" #include "MICmnMIResultRecord.h" #include "MICmnMIValueConst.h" #include "MICmnMIValueTuple.h" -#include "MICmdArgValString.h" -#include "MICmdFactory.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdSupportInfoMiCmdQuery constructor. // Type: Method. // Args: None. @@ -25,29 +26,28 @@ // Throws: None. //-- CMICmdCmdSupportInfoMiCmdQuery::CMICmdCmdSupportInfoMiCmdQuery() - : m_bCmdFound(false) - , m_constStrArgCmdName("cmd_name") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "info-gdb-mi-command"; + : m_bCmdFound(false), m_constStrArgCmdName("cmd_name") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "info-gdb-mi-command"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdSupportInfoMiCmdQuery::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdSupportInfoMiCmdQuery::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdSupportInfoMiCmdQuery destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdSupportInfoMiCmdQuery::~CMICmdCmdSupportInfoMiCmdQuery() -{ -} +CMICmdCmdSupportInfoMiCmdQuery::~CMICmdCmdSupportInfoMiCmdQuery() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -55,39 +55,40 @@ CMICmdCmdSupportInfoMiCmdQuery::~CMICmdCmdSupportInfoMiCmdQuery() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdSupportInfoMiCmdQuery::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgCmdName, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdSupportInfoMiCmdQuery::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgCmdName, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdSupportInfoMiCmdQuery::Execute() -{ - CMICMDBASE_GETOPTION(pArgNamedCmdName, String, m_constStrArgCmdName); - const CMIUtilString &rCmdToQuery(pArgNamedCmdName->GetValue()); - const MIuint nLen = rCmdToQuery.length(); - const CMICmdFactory &rCmdFactory = CMICmdFactory::Instance(); - if ((nLen > 1) && (rCmdToQuery[0] == '-')) - m_bCmdFound = rCmdFactory.CmdExist(rCmdToQuery.substr(1, nLen - 1).c_str()); - else - m_bCmdFound = rCmdFactory.CmdExist(rCmdToQuery); +bool CMICmdCmdSupportInfoMiCmdQuery::Execute() { + CMICMDBASE_GETOPTION(pArgNamedCmdName, String, m_constStrArgCmdName); + const CMIUtilString &rCmdToQuery(pArgNamedCmdName->GetValue()); + const MIuint nLen = rCmdToQuery.length(); + const CMICmdFactory &rCmdFactory = CMICmdFactory::Instance(); + if ((nLen > 1) && (rCmdToQuery[0] == '-')) + m_bCmdFound = rCmdFactory.CmdExist(rCmdToQuery.substr(1, nLen - 1).c_str()); + else + m_bCmdFound = rCmdFactory.CmdExist(rCmdToQuery); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -95,29 +96,29 @@ CMICmdCmdSupportInfoMiCmdQuery::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdSupportInfoMiCmdQuery::Acknowledge() -{ - const CMICmnMIValueConst miValueConst(m_bCmdFound ? "true" : "false"); - const CMICmnMIValueResult miValueResult("exists", miValueConst); - const CMICmnMIValueTuple miValueTuple(miValueResult); - const CMICmnMIValueResult miValueResult2("command", miValueTuple); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult2); - m_miResultRecord = miRecordResult; +bool CMICmdCmdSupportInfoMiCmdQuery::Acknowledge() { + const CMICmnMIValueConst miValueConst(m_bCmdFound ? "true" : "false"); + const CMICmnMIValueResult miValueResult("exists", miValueConst); + const CMICmnMIValueTuple miValueTuple(miValueResult); + const CMICmnMIValueResult miValueResult2("command", miValueTuple); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult2); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdSupportInfoMiCmdQuery::CreateSelf() -{ - return new CMICmdCmdSupportInfoMiCmdQuery(); +CMICmdBase *CMICmdCmdSupportInfoMiCmdQuery::CreateSelf() { + return new CMICmdCmdSupportInfoMiCmdQuery(); } diff --git a/lldb/tools/lldb-mi/MICmdCmdSupportInfo.h b/lldb/tools/lldb-mi/MICmdCmdSupportInfo.h index 62b71261f18..7b503b1ee1a 100644 --- a/lldb/tools/lldb-mi/MICmdCmdSupportInfo.h +++ b/lldb/tools/lldb-mi/MICmdCmdSupportInfo.h @@ -9,13 +9,16 @@ // Overview: CMICmdCmdSupportInfoMiCmdQuery interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands derive a new command class from the +// command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// For an introduction to adding a new command see +// CMICmdCmdSupportInfoMiCmdQuery // command class as an example. #pragma once @@ -23,33 +26,34 @@ // In-house headers: #include "MICmdBase.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "info-gdb-mi-command". // This command does not follow the MI documentation exactly. //-- -class CMICmdCmdSupportInfoMiCmdQuery : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); +class CMICmdCmdSupportInfoMiCmdQuery : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); - // Methods: - public: - /* ctor */ CMICmdCmdSupportInfoMiCmdQuery(); + // Methods: +public: + /* ctor */ CMICmdCmdSupportInfoMiCmdQuery(); - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdSupportInfoMiCmdQuery() override; + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdSupportInfoMiCmdQuery() override; - // Attributes: - private: - bool m_bCmdFound; // True = query for the command in command factory found, false = not found not recognised - const CMIUtilString m_constStrArgCmdName; + // Attributes: +private: + bool m_bCmdFound; // True = query for the command in command factory found, + // false = not found not recognised + const CMIUtilString m_constStrArgCmdName; }; diff --git a/lldb/tools/lldb-mi/MICmdCmdSupportList.cpp b/lldb/tools/lldb-mi/MICmdCmdSupportList.cpp index 06d63612de6..c3a9c9ad257 100644 --- a/lldb/tools/lldb-mi/MICmdCmdSupportList.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdSupportList.cpp @@ -15,52 +15,54 @@ #include "MICmnMIValueConst.h" #include "MICmnMIValueList.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdSupportListFeatures constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdSupportListFeatures::CMICmdCmdSupportListFeatures() -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "list-features"; +CMICmdCmdSupportListFeatures::CMICmdCmdSupportListFeatures() { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "list-features"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdSupportListFeatures::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdSupportListFeatures::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdSupportListFeatures destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdSupportListFeatures::~CMICmdCmdSupportListFeatures() -{ -} +CMICmdCmdSupportListFeatures::~CMICmdCmdSupportListFeatures() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdSupportListFeatures::Execute() -{ - // Do nothing +bool CMICmdCmdSupportListFeatures::Execute() { + // Do nothing - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -68,33 +70,33 @@ CMICmdCmdSupportListFeatures::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdSupportListFeatures::Acknowledge() -{ - // Declare supported features here - const CMICmnMIValueConst miValueConst1("data-read-memory-bytes"); - const CMICmnMIValueConst miValueConst2("exec-run-start-option"); - // Some features may depend on host and/or target, decide what to add below - CMICmnMIValueList miValueList(true); - miValueList.Add(miValueConst1); - miValueList.Add(miValueConst2); - const CMICmnMIValueResult miValueResult("features", miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; +bool CMICmdCmdSupportListFeatures::Acknowledge() { + // Declare supported features here + const CMICmnMIValueConst miValueConst1("data-read-memory-bytes"); + const CMICmnMIValueConst miValueConst2("exec-run-start-option"); + // Some features may depend on host and/or target, decide what to add below + CMICmnMIValueList miValueList(true); + miValueList.Add(miValueConst1); + miValueList.Add(miValueConst2); + const CMICmnMIValueResult miValueResult("features", miValueList); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdSupportListFeatures::CreateSelf() -{ - return new CMICmdCmdSupportListFeatures(); +CMICmdBase *CMICmdCmdSupportListFeatures::CreateSelf() { + return new CMICmdCmdSupportListFeatures(); } diff --git a/lldb/tools/lldb-mi/MICmdCmdSupportList.h b/lldb/tools/lldb-mi/MICmdCmdSupportList.h index 5ac95a34c3b..a9c27960bb9 100644 --- a/lldb/tools/lldb-mi/MICmdCmdSupportList.h +++ b/lldb/tools/lldb-mi/MICmdCmdSupportList.h @@ -9,13 +9,16 @@ // Overview: CMICmdCmdSupportListFeatures interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands derive a new command class from the +// command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// For an introduction to adding a new command see +// CMICmdCmdSupportInfoMiCmdQuery // command class as an example. #pragma once @@ -23,27 +26,27 @@ // In-house headers: #include "MICmdBase.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "list-features". // This command does not follow the MI documentation exactly. //-- -class CMICmdCmdSupportListFeatures : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); +class CMICmdCmdSupportListFeatures : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); - // Methods: - public: - /* ctor */ CMICmdCmdSupportListFeatures(); + // Methods: +public: + /* ctor */ CMICmdCmdSupportListFeatures(); - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdSupportListFeatures() override; + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdSupportListFeatures() override; }; diff --git a/lldb/tools/lldb-mi/MICmdCmdSymbol.cpp b/lldb/tools/lldb-mi/MICmdCmdSymbol.cpp index b2519afb3ff..7b302b12b60 100644 --- a/lldb/tools/lldb-mi/MICmdCmdSymbol.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdSymbol.cpp @@ -23,7 +23,8 @@ #include "MICmnMIValueList.h" #include "MICmnMIValueTuple.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdSymbolListLines constructor. // Type: Method. // Args: None. @@ -31,28 +32,28 @@ // Throws: None. //-- CMICmdCmdSymbolListLines::CMICmdCmdSymbolListLines() - : m_constStrArgNameFile("file") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "symbol-list-lines"; + : m_constStrArgNameFile("file") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "symbol-list-lines"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdSymbolListLines::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdSymbolListLines::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdSymbolListLines destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdSymbolListLines::~CMICmdCmdSymbolListLines() -{ -} +CMICmdCmdSymbolListLines::~CMICmdCmdSymbolListLines() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -60,67 +61,75 @@ CMICmdCmdSymbolListLines::~CMICmdCmdSymbolListLines() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdSymbolListLines::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValFile(m_constStrArgNameFile, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdSymbolListLines::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValFile(m_constStrArgNameFile, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Synopsis: -symbol-list-lines file -// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Symbol-Query.html#GDB_002fMI-Symbol-Query +// Ref: +// http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Symbol-Query.html#GDB_002fMI-Symbol-Query // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdSymbolListLines::Execute() -{ - CMICMDBASE_GETOPTION(pArgFile, File, m_constStrArgNameFile); +bool CMICmdCmdSymbolListLines::Execute() { + CMICMDBASE_GETOPTION(pArgFile, File, m_constStrArgNameFile); - const CMIUtilString &strFilePath(pArgFile->GetValue()); - const CMIUtilString strCmd(CMIUtilString::Format("source info --file \"%s\"", strFilePath.AddSlashes().c_str())); + const CMIUtilString &strFilePath(pArgFile->GetValue()); + const CMIUtilString strCmd(CMIUtilString::Format( + "source info --file \"%s\"", strFilePath.AddSlashes().c_str())); - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - const lldb::ReturnStatus rtn = rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult); - MIunused(rtn); + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + const lldb::ReturnStatus rtn = + rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand( + strCmd.c_str(), m_lldbResult); + MIunused(rtn); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Helper function for parsing the header returned from lldb for the command: +//++ +//------------------------------------------------------------------------------------ +// Details: Helper function for parsing the header returned from lldb for the +// command: // target modules dump line-table <file> // where the header is of the format: // Line table for /path/to/file in `/path/to/module // Args: input - (R) Input string to parse. // file - (W) String representing the file. -// Return: bool - True = input was parsed successfully, false = input could not be parsed. +// Return: bool - True = input was parsed successfully, false = input could not +// be parsed. // Throws: None. //-- -static bool -ParseLLDBLineAddressHeader(const char *input, CMIUtilString &file) -{ - // Match LineEntry using regex. - static llvm::Regex g_lineentry_header_regex( - llvm::StringRef("^ *Lines found for file (.+) in compilation unit (.+) in `(.+)$")); - // ^1=file ^2=cu ^3=module - - llvm::SmallVector<llvm::StringRef, 4> match; - - const bool ok = g_lineentry_header_regex.match(input, &match); - if (ok) - file = match[1]; - return ok; +static bool ParseLLDBLineAddressHeader(const char *input, CMIUtilString &file) { + // Match LineEntry using regex. + static llvm::Regex g_lineentry_header_regex(llvm::StringRef( + "^ *Lines found for file (.+) in compilation unit (.+) in `(.+)$")); + // ^1=file ^2=cu + // ^3=module + + llvm::SmallVector<llvm::StringRef, 4> match; + + const bool ok = g_lineentry_header_regex.match(input, &match); + if (ok) + file = match[1]; + return ok; } -//++ ------------------------------------------------------------------------------------ -// Details: Helper function for parsing a line entry returned from lldb for the command: +//++ +//------------------------------------------------------------------------------------ +// Details: Helper function for parsing a line entry returned from lldb for the +// command: // target modules dump line-table <file> // where the line entry is of the format: // 0x0000000100000e70: /path/to/file:3002[:4] @@ -129,43 +138,45 @@ ParseLLDBLineAddressHeader(const char *input, CMIUtilString &file) // addr - (W) String representing the pc address. // file - (W) String representing the file. // line - (W) String representing the line. -// Return: bool - True = input was parsed successfully, false = input could not be parsed. +// Return: bool - True = input was parsed successfully, false = input could not +// be parsed. // Throws: None. //-- -static bool -ParseLLDBLineAddressEntry(const char *input, CMIUtilString &addr, - CMIUtilString &file, CMIUtilString &line) -{ - // Note: Ambiguities arise because the column is optional, and - // because : can appear in filenames or as a byte in a multibyte - // UTF8 character. We keep those cases to a minimum by using regex - // to work on the string from both the left and right, so that what - // is remains is assumed to be the filename. - - // Match LineEntry using regex. - static llvm::Regex g_lineentry_nocol_regex( - llvm::StringRef("^ *\\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+)$")); - static llvm::Regex g_lineentry_col_regex( - llvm::StringRef("^ *\\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+):[0-9]+$")); - // ^1=start ^2=end ^3=f ^4=line ^5=:col(opt) - - llvm::SmallVector<llvm::StringRef, 6> match; - - // First try matching the LineEntry with the column, - // then try without the column. - const bool ok = g_lineentry_col_regex.match(input, &match) || - g_lineentry_nocol_regex.match(input, &match); - if (ok) - { - addr = match[1]; - file = match[3]; - line = match[4]; - } - return ok; +static bool ParseLLDBLineAddressEntry(const char *input, CMIUtilString &addr, + CMIUtilString &file, + CMIUtilString &line) { + // Note: Ambiguities arise because the column is optional, and + // because : can appear in filenames or as a byte in a multibyte + // UTF8 character. We keep those cases to a minimum by using regex + // to work on the string from both the left and right, so that what + // is remains is assumed to be the filename. + + // Match LineEntry using regex. + static llvm::Regex g_lineentry_nocol_regex(llvm::StringRef( + "^ *\\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+)$")); + static llvm::Regex g_lineentry_col_regex(llvm::StringRef( + "^ *\\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+):[0-9]+$")); + // ^1=start ^2=end ^3=f ^4=line + // ^5=:col(opt) + + llvm::SmallVector<llvm::StringRef, 6> match; + + // First try matching the LineEntry with the column, + // then try without the column. + const bool ok = g_lineentry_col_regex.match(input, &match) || + g_lineentry_nocol_regex.match(input, &match); + if (ok) { + addr = match[1]; + file = match[3]; + line = match[4]; + } + return ok; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -173,83 +184,85 @@ ParseLLDBLineAddressEntry(const char *input, CMIUtilString &addr, // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdSymbolListLines::Acknowledge() -{ - if (m_lldbResult.GetErrorSize() > 0) - { - const char *pLldbErr = m_lldbResult.GetError(); - const CMIUtilString strMsg(CMIUtilString(pLldbErr).StripCRAll()); - const CMICmnMIValueConst miValueConst(strMsg); - const CMICmnMIValueResult miValueResult("message", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; +bool CMICmdCmdSymbolListLines::Acknowledge() { + if (m_lldbResult.GetErrorSize() > 0) { + const char *pLldbErr = m_lldbResult.GetError(); + const CMIUtilString strMsg(CMIUtilString(pLldbErr).StripCRAll()); + const CMICmnMIValueConst miValueConst(strMsg); + const CMICmnMIValueResult miValueResult("message", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + } else { + CMIUtilString::VecString_t vecLines; + const CMIUtilString strLldbMsg(m_lldbResult.GetOutput()); + const MIuint nLines(strLldbMsg.SplitLines(vecLines)); + + // Parse the file from the header. + const CMIUtilString &rWantFile(vecLines[0]); + CMIUtilString strWantFile; + if (!ParseLLDBLineAddressHeader(rWantFile.c_str(), strWantFile)) { + // Unexpected error - parsing failed. + // MI print "%s^error,msg=\"Command '-symbol-list-lines'. Error: Line + // address header is absent or has an unknown format.\"" + const CMICmnMIValueConst miValueConst(CMIUtilString::Format( + MIRSRC(IDS_CMD_ERR_SOME_ERROR), m_cmdData.strMiCmd.c_str(), + "Line address header is absent or has an unknown format.")); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } - else - { - CMIUtilString::VecString_t vecLines; - const CMIUtilString strLldbMsg(m_lldbResult.GetOutput()); - const MIuint nLines(strLldbMsg.SplitLines(vecLines)); - - // Parse the file from the header. - const CMIUtilString &rWantFile(vecLines[0]); - CMIUtilString strWantFile; - if (!ParseLLDBLineAddressHeader(rWantFile.c_str(), strWantFile)) - { - // Unexpected error - parsing failed. - // MI print "%s^error,msg=\"Command '-symbol-list-lines'. Error: Line address header is absent or has an unknown format.\"" - const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SOME_ERROR), m_cmdData.strMiCmd.c_str(), "Line address header is absent or has an unknown format.")); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; - - return MIstatus::success; - } - - // Parse the line address entries. - CMICmnMIValueList miValueList(true); - for (MIuint i = 1; i < nLines; ++i) - { - // String looks like: - // 0x0000000100000e70: /path/to/file:3[:4] - const CMIUtilString &rLine(vecLines[i]); - CMIUtilString strAddr; - CMIUtilString strFile; - CMIUtilString strLine; - - if (!ParseLLDBLineAddressEntry(rLine.c_str(), strAddr, strFile, strLine)) - continue; - - const CMICmnMIValueConst miValueConst(strAddr); - const CMICmnMIValueResult miValueResult("pc", miValueConst); - CMICmnMIValueTuple miValueTuple(miValueResult); - - const CMICmnMIValueConst miValueConst2(strLine); - const CMICmnMIValueResult miValueResult2("line", miValueConst2); - miValueTuple.Add(miValueResult2); - - miValueList.Add(miValueTuple); - } - - // MI print "%s^done,lines=[{pc=\"%d\",line=\"%d\"}...]" - const CMICmnMIValueResult miValueResult("lines", miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; + + // Parse the line address entries. + CMICmnMIValueList miValueList(true); + for (MIuint i = 1; i < nLines; ++i) { + // String looks like: + // 0x0000000100000e70: /path/to/file:3[:4] + const CMIUtilString &rLine(vecLines[i]); + CMIUtilString strAddr; + CMIUtilString strFile; + CMIUtilString strLine; + + if (!ParseLLDBLineAddressEntry(rLine.c_str(), strAddr, strFile, strLine)) + continue; + + const CMICmnMIValueConst miValueConst(strAddr); + const CMICmnMIValueResult miValueResult("pc", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + + const CMICmnMIValueConst miValueConst2(strLine); + const CMICmnMIValueResult miValueResult2("line", miValueConst2); + miValueTuple.Add(miValueResult2); + + miValueList.Add(miValueTuple); } - return MIstatus::success; + // MI print "%s^done,lines=[{pc=\"%d\",line=\"%d\"}...]" + const CMICmnMIValueResult miValueResult("lines", miValueList); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdSymbolListLines::CreateSelf() -{ - return new CMICmdCmdSymbolListLines(); +CMICmdBase *CMICmdCmdSymbolListLines::CreateSelf() { + return new CMICmdCmdSymbolListLines(); } diff --git a/lldb/tools/lldb-mi/MICmdCmdSymbol.h b/lldb/tools/lldb-mi/MICmdCmdSymbol.h index 5bffd4fe91d..56685df07d9 100644 --- a/lldb/tools/lldb-mi/MICmdCmdSymbol.h +++ b/lldb/tools/lldb-mi/MICmdCmdSymbol.h @@ -9,13 +9,16 @@ // Overview: CMICmdCmdSymbolListLines interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands derive a new command class from the +// command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// For an introduction to adding a new command see +// CMICmdCmdSupportInfoMiCmdQuery // command class as an example. #pragma once @@ -26,32 +29,32 @@ // In-house headers: #include "MICmdBase.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "symbol-list-lines". //-- -class CMICmdCmdSymbolListLines : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdSymbolListLines(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdSymbolListLines() override; - - // Attributes: - private: - lldb::SBCommandReturnObject m_lldbResult; - const CMIUtilString m_constStrArgNameFile; +class CMICmdCmdSymbolListLines : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdSymbolListLines(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdSymbolListLines() override; + + // Attributes: +private: + lldb::SBCommandReturnObject m_lldbResult; + const CMIUtilString m_constStrArgNameFile; }; diff --git a/lldb/tools/lldb-mi/MICmdCmdTarget.cpp b/lldb/tools/lldb-mi/MICmdCmdTarget.cpp index 030024bb267..15650163450 100644 --- a/lldb/tools/lldb-mi/MICmdCmdTarget.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdTarget.cpp @@ -10,23 +10,24 @@ // Overview: CMICmdCmdTargetSelect implementation. // Third Party Headers: -#include "lldb/API/SBStream.h" #include "lldb/API/SBCommandInterpreter.h" #include "lldb/API/SBCommandReturnObject.h" +#include "lldb/API/SBStream.h" // In-house headers: +#include "MICmdArgValNumber.h" +#include "MICmdArgValOptionLong.h" +#include "MICmdArgValOptionShort.h" +#include "MICmdArgValString.h" #include "MICmdCmdTarget.h" +#include "MICmnLLDBDebugSessionInfo.h" +#include "MICmnLLDBDebugger.h" +#include "MICmnMIOutOfBandRecord.h" #include "MICmnMIResultRecord.h" #include "MICmnMIValueConst.h" -#include "MICmnMIOutOfBandRecord.h" -#include "MICmnLLDBDebugger.h" -#include "MICmnLLDBDebugSessionInfo.h" -#include "MICmdArgValString.h" -#include "MICmdArgValOptionLong.h" -#include "MICmdArgValOptionShort.h" -#include "MICmdArgValNumber.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdTargetSelect constructor. // Type: Method. // Args: None. @@ -34,29 +35,29 @@ // Throws: None. //-- CMICmdCmdTargetSelect::CMICmdCmdTargetSelect() - : m_constStrArgNamedType("type") - , m_constStrArgNamedParameters("parameters") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "target-select"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdTargetSelect::CreateSelf; + : m_constStrArgNamedType("type"), + m_constStrArgNamedParameters("parameters") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "target-select"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdTargetSelect::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdTargetSelect destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdTargetSelect::~CMICmdCmdTargetSelect() -{ -} +CMICmdCmdTargetSelect::~CMICmdCmdTargetSelect() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -64,106 +65,118 @@ CMICmdCmdTargetSelect::~CMICmdCmdTargetSelect() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdTargetSelect::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedType, true, true)); - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedParameters, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdTargetSelect::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedType, true, true)); + m_setCmdArgs.Add( + new CMICmdArgValString(m_constStrArgNamedParameters, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Synopsis: -target-select type parameters ... -// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation +// Ref: +// http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdTargetSelect::Execute() -{ - CMICMDBASE_GETOPTION(pArgType, String, m_constStrArgNamedType); - CMICMDBASE_GETOPTION(pArgParameters, String, m_constStrArgNamedParameters); - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - - // Check we have a valid target - // Note: target created via 'file-exec-and-symbols' command - if (!rSessionInfo.GetTarget().IsValid()) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT), m_cmdData.strMiCmd.c_str())); - return MIstatus::failure; - } - - // Verify that we are executing remotely - const CMIUtilString &rRemoteType(pArgType->GetValue()); - if (rRemoteType != "remote") - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_TYPE), m_cmdData.strMiCmd.c_str(), rRemoteType.c_str())); - return MIstatus::failure; - } - - // Create a URL pointing to the remote gdb stub - const CMIUtilString strUrl = CMIUtilString::Format("connect://%s", pArgParameters->GetValue().c_str()); - - // Ask LLDB to collect to the target port - const char *pPlugin("gdb-remote"); - lldb::SBError error; - lldb::SBProcess process = rSessionInfo.GetTarget().ConnectRemote(rSessionInfo.GetListener(), strUrl.c_str(), pPlugin, error); - - // Verify that we have managed to connect successfully - lldb::SBStream errMsg; - if (!process.IsValid()) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_PLUGIN), m_cmdData.strMiCmd.c_str(), errMsg.GetData())); - return MIstatus::failure; +bool CMICmdCmdTargetSelect::Execute() { + CMICMDBASE_GETOPTION(pArgType, String, m_constStrArgNamedType); + CMICMDBASE_GETOPTION(pArgParameters, String, m_constStrArgNamedParameters); + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + + // Check we have a valid target + // Note: target created via 'file-exec-and-symbols' command + if (!rSessionInfo.GetTarget().IsValid()) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT), + m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + + // Verify that we are executing remotely + const CMIUtilString &rRemoteType(pArgType->GetValue()); + if (rRemoteType != "remote") { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_TYPE), + m_cmdData.strMiCmd.c_str(), + rRemoteType.c_str())); + return MIstatus::failure; + } + + // Create a URL pointing to the remote gdb stub + const CMIUtilString strUrl = + CMIUtilString::Format("connect://%s", pArgParameters->GetValue().c_str()); + + // Ask LLDB to collect to the target port + const char *pPlugin("gdb-remote"); + lldb::SBError error; + lldb::SBProcess process = rSessionInfo.GetTarget().ConnectRemote( + rSessionInfo.GetListener(), strUrl.c_str(), pPlugin, error); + + // Verify that we have managed to connect successfully + lldb::SBStream errMsg; + if (!process.IsValid()) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_PLUGIN), + m_cmdData.strMiCmd.c_str(), + errMsg.GetData())); + return MIstatus::failure; + } + if (error.Fail()) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_CONNECT_TO_TARGET), + m_cmdData.strMiCmd.c_str(), + errMsg.GetData())); + return MIstatus::failure; + } + + // Set the environment path if we were given one + CMIUtilString strWkDir; + if (rSessionInfo.SharedDataRetrieve<CMIUtilString>( + rSessionInfo.m_constStrSharedDataKeyWkDir, strWkDir)) { + lldb::SBDebugger &rDbgr = rSessionInfo.GetDebugger(); + if (!rDbgr.SetCurrentPlatformSDKRoot(strWkDir.c_str())) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FNFAILED), + m_cmdData.strMiCmd.c_str(), + "target-select")); + return MIstatus::failure; } - if (error.Fail()) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_CONNECT_TO_TARGET), m_cmdData.strMiCmd.c_str(), errMsg.GetData())); - return MIstatus::failure; + } + + // Set the shared object path if we were given one + CMIUtilString strSolibPath; + if (rSessionInfo.SharedDataRetrieve<CMIUtilString>( + rSessionInfo.m_constStrSharedDataSolibPath, strSolibPath)) { + lldb::SBDebugger &rDbgr = rSessionInfo.GetDebugger(); + lldb::SBCommandInterpreter cmdIterpreter = rDbgr.GetCommandInterpreter(); + + CMIUtilString strCmdString = CMIUtilString::Format( + "target modules search-paths add . %s", strSolibPath.c_str()); + + lldb::SBCommandReturnObject retObj; + cmdIterpreter.HandleCommand(strCmdString.c_str(), retObj, false); + + if (!retObj.Succeeded()) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FNFAILED), + m_cmdData.strMiCmd.c_str(), + "target-select")); + return MIstatus::failure; } + } - // Set the environment path if we were given one - CMIUtilString strWkDir; - if (rSessionInfo.SharedDataRetrieve<CMIUtilString>(rSessionInfo.m_constStrSharedDataKeyWkDir, strWkDir)) - { - lldb::SBDebugger &rDbgr = rSessionInfo.GetDebugger(); - if (!rDbgr.SetCurrentPlatformSDKRoot(strWkDir.c_str())) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FNFAILED), m_cmdData.strMiCmd.c_str(), "target-select")); - return MIstatus::failure; - } - } - - // Set the shared object path if we were given one - CMIUtilString strSolibPath; - if (rSessionInfo.SharedDataRetrieve<CMIUtilString>(rSessionInfo.m_constStrSharedDataSolibPath, strSolibPath)) - { - lldb::SBDebugger &rDbgr = rSessionInfo.GetDebugger(); - lldb::SBCommandInterpreter cmdIterpreter = rDbgr.GetCommandInterpreter(); - - CMIUtilString strCmdString = CMIUtilString::Format("target modules search-paths add . %s", strSolibPath.c_str()); - - lldb::SBCommandReturnObject retObj; - cmdIterpreter.HandleCommand(strCmdString.c_str(), retObj, false); - - if (!retObj.Succeeded()) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FNFAILED), m_cmdData.strMiCmd.c_str(), "target-select")); - return MIstatus::failure; - } - } - - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -171,44 +184,47 @@ CMICmdCmdTargetSelect::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdTargetSelect::Acknowledge() -{ - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Connected); - m_miResultRecord = miRecordResult; - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID(); - // Prod the client i.e. Eclipse with out-of-band results to help it 'continue' because it is using LLDB debugger - // Give the client '=thread-group-started,id="i1"' - m_bHasResultRecordExtra = true; - const CMICmnMIValueConst miValueConst2("i1"); - const CMICmnMIValueResult miValueResult2("id", miValueConst2); - const CMIUtilString strPid(CMIUtilString::Format("%lld", pid)); - const CMICmnMIValueConst miValueConst(strPid); - const CMICmnMIValueResult miValueResult("pid", miValueConst); - CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2); - miOutOfBand.Add(miValueResult); - m_miResultRecordExtra = miOutOfBand.GetString(); - - return MIstatus::success; +bool CMICmdCmdTargetSelect::Acknowledge() { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Connected); + m_miResultRecord = miRecordResult; + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID(); + // Prod the client i.e. Eclipse with out-of-band results to help it 'continue' + // because it is using LLDB debugger + // Give the client '=thread-group-started,id="i1"' + m_bHasResultRecordExtra = true; + const CMICmnMIValueConst miValueConst2("i1"); + const CMICmnMIValueResult miValueResult2("id", miValueConst2); + const CMIUtilString strPid(CMIUtilString::Format("%lld", pid)); + const CMICmnMIValueConst miValueConst(strPid); + const CMICmnMIValueResult miValueResult("pid", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBand( + CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2); + miOutOfBand.Add(miValueResult); + m_miResultRecordExtra = miOutOfBand.GetString(); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdTargetSelect::CreateSelf() -{ - return new CMICmdCmdTargetSelect(); +CMICmdBase *CMICmdCmdTargetSelect::CreateSelf() { + return new CMICmdCmdTargetSelect(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdTargetAttach constructor. // Type: Method. // Args: None. @@ -216,30 +232,29 @@ CMICmdCmdTargetSelect::CreateSelf() // Throws: None. //-- CMICmdCmdTargetAttach::CMICmdCmdTargetAttach() -: m_constStrArgPid("pid") -, m_constStrArgNamedFile("n") -, m_constStrArgWaitFor("waitfor") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "target-attach"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdTargetAttach::CreateSelf; + : m_constStrArgPid("pid"), m_constStrArgNamedFile("n"), + m_constStrArgWaitFor("waitfor") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "target-attach"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdTargetAttach::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdTargetAttach destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdTargetAttach::~CMICmdCmdTargetAttach() -{ -} +CMICmdCmdTargetAttach::~CMICmdCmdTargetAttach() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -247,81 +262,82 @@ CMICmdCmdTargetAttach::~CMICmdCmdTargetAttach() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdTargetAttach::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgPid, false, true)); - m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedFile, false, true, - CMICmdArgValListBase::eArgValType_String, 1)); - m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgWaitFor, false, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdTargetAttach::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgPid, false, true)); + m_setCmdArgs.Add( + new CMICmdArgValOptionShort(m_constStrArgNamedFile, false, true, + CMICmdArgValListBase::eArgValType_String, 1)); + m_setCmdArgs.Add( + new CMICmdArgValOptionLong(m_constStrArgWaitFor, false, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Synopsis: -target-attach file -// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation +// Ref: +// http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdTargetAttach::Execute() -{ - CMICMDBASE_GETOPTION(pArgPid, Number, m_constStrArgPid); - CMICMDBASE_GETOPTION(pArgFile, OptionShort, m_constStrArgNamedFile); - CMICMDBASE_GETOPTION(pArgWaitFor, OptionLong, m_constStrArgWaitFor); - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - - // If the current target is invalid, create one - lldb::SBTarget target = rSessionInfo.GetTarget(); - if (!target.IsValid()) - { - target = rSessionInfo.GetDebugger().CreateTarget(NULL); - if (!target.IsValid()) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT), m_cmdData.strMiCmd.c_str())); - return MIstatus::failure; - } - } - - lldb::SBError error; - lldb::SBListener listener; - if (pArgPid->GetFound() && pArgPid->GetValid()) - { - lldb::pid_t pid; - pid = pArgPid->GetValue(); - target.AttachToProcessWithID(listener, pid, error); - } - else if (pArgFile->GetFound() && pArgFile->GetValid()) - { - bool bWaitFor = (pArgWaitFor->GetFound()); - CMIUtilString file; - pArgFile->GetExpectedOption<CMICmdArgValString>(file); - target.AttachToProcessWithName(listener, file.c_str(), bWaitFor, error); +bool CMICmdCmdTargetAttach::Execute() { + CMICMDBASE_GETOPTION(pArgPid, Number, m_constStrArgPid); + CMICMDBASE_GETOPTION(pArgFile, OptionShort, m_constStrArgNamedFile); + CMICMDBASE_GETOPTION(pArgWaitFor, OptionLong, m_constStrArgWaitFor); + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + + // If the current target is invalid, create one + lldb::SBTarget target = rSessionInfo.GetTarget(); + if (!target.IsValid()) { + target = rSessionInfo.GetDebugger().CreateTarget(NULL); + if (!target.IsValid()) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT), + m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; } - else - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_ATTACH_BAD_ARGS), m_cmdData.strMiCmd.c_str())); - return MIstatus::failure; - } - - lldb::SBStream errMsg; - if (error.Fail()) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_ATTACH_FAILED), m_cmdData.strMiCmd.c_str(), errMsg.GetData())); - return MIstatus::failure; - } - - return MIstatus::success; + } + + lldb::SBError error; + lldb::SBListener listener; + if (pArgPid->GetFound() && pArgPid->GetValid()) { + lldb::pid_t pid; + pid = pArgPid->GetValue(); + target.AttachToProcessWithID(listener, pid, error); + } else if (pArgFile->GetFound() && pArgFile->GetValid()) { + bool bWaitFor = (pArgWaitFor->GetFound()); + CMIUtilString file; + pArgFile->GetExpectedOption<CMICmdArgValString>(file); + target.AttachToProcessWithName(listener, file.c_str(), bWaitFor, error); + } else { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_ATTACH_BAD_ARGS), + m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + + lldb::SBStream errMsg; + if (error.Fail()) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_ATTACH_FAILED), + m_cmdData.strMiCmd.c_str(), + errMsg.GetData())); + return MIstatus::failure; + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -329,72 +345,75 @@ CMICmdCmdTargetAttach::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdTargetAttach::Acknowledge() -{ - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); - m_miResultRecord = miRecordResult; - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID(); - // Prod the client i.e. Eclipse with out-of-band results to help it 'continue' because it is using LLDB debugger - // Give the client '=thread-group-started,id="i1"' - m_bHasResultRecordExtra = true; - const CMICmnMIValueConst miValueConst2("i1"); - const CMICmnMIValueResult miValueResult2("id", miValueConst2); - const CMIUtilString strPid(CMIUtilString::Format("%lld", pid)); - const CMICmnMIValueConst miValueConst(strPid); - const CMICmnMIValueResult miValueResult("pid", miValueConst); - CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2); - miOutOfBand.Add(miValueResult); - m_miResultRecordExtra = miOutOfBand.GetString(); - - return MIstatus::success; +bool CMICmdCmdTargetAttach::Acknowledge() { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID(); + // Prod the client i.e. Eclipse with out-of-band results to help it 'continue' + // because it is using LLDB debugger + // Give the client '=thread-group-started,id="i1"' + m_bHasResultRecordExtra = true; + const CMICmnMIValueConst miValueConst2("i1"); + const CMICmnMIValueResult miValueResult2("id", miValueConst2); + const CMIUtilString strPid(CMIUtilString::Format("%lld", pid)); + const CMICmnMIValueConst miValueConst(strPid); + const CMICmnMIValueResult miValueResult("pid", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBand( + CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2); + miOutOfBand.Add(miValueResult); + m_miResultRecordExtra = miOutOfBand.GetString(); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdTargetAttach::CreateSelf() -{ - return new CMICmdCmdTargetAttach(); +CMICmdBase *CMICmdCmdTargetAttach::CreateSelf() { + return new CMICmdCmdTargetAttach(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdTargetDetach constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdTargetDetach::CMICmdCmdTargetDetach() -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "target-detach"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdTargetDetach::CreateSelf; +CMICmdCmdTargetDetach::CMICmdCmdTargetDetach() { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "target-detach"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdTargetDetach::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdTargetDetach destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdTargetDetach::~CMICmdCmdTargetDetach() -{ -} +CMICmdCmdTargetDetach::~CMICmdCmdTargetDetach() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -402,43 +421,44 @@ CMICmdCmdTargetDetach::~CMICmdCmdTargetDetach() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdTargetDetach::ParseArgs() -{ - return MIstatus::success; -} - -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +bool CMICmdCmdTargetDetach::ParseArgs() { return MIstatus::success; } + +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Synopsis: -target-attach file -// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation +// Ref: +// http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdTargetDetach::Execute() -{ - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - - lldb::SBProcess process = rSessionInfo.GetProcess(); - - if (!process.IsValid()) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str())); - return MIstatus::failure; - } - - process.Detach(); - - return MIstatus::success; +bool CMICmdCmdTargetDetach::Execute() { + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + + lldb::SBProcess process = rSessionInfo.GetProcess(); + + if (!process.IsValid()) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), + m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + + process.Detach(); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -446,24 +466,23 @@ CMICmdCmdTargetDetach::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdTargetDetach::Acknowledge() -{ - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); - m_miResultRecord = miRecordResult; - return MIstatus::success; +bool CMICmdCmdTargetDetach::Acknowledge() { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdTargetDetach::CreateSelf() -{ - return new CMICmdCmdTargetDetach(); +CMICmdBase *CMICmdCmdTargetDetach::CreateSelf() { + return new CMICmdCmdTargetDetach(); } diff --git a/lldb/tools/lldb-mi/MICmdCmdTarget.h b/lldb/tools/lldb-mi/MICmdCmdTarget.h index e4c04b11145..f0cad93bdba 100644 --- a/lldb/tools/lldb-mi/MICmdCmdTarget.h +++ b/lldb/tools/lldb-mi/MICmdCmdTarget.h @@ -9,108 +9,110 @@ // Overview: CMICmdCmdTargetSelect interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands derive a new command class from the +// command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// For an introduction to adding a new command see +// CMICmdCmdSupportInfoMiCmdQuery // command class as an example. #pragma once // In-house headers: #include "MICmdBase.h" -#include "MICmnMIValueTuple.h" #include "MICmnMIValueList.h" +#include "MICmnMIValueTuple.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "target-select". // http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation //-- -class CMICmdCmdTargetSelect : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); +class CMICmdCmdTargetSelect : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); - // Methods: - public: - /* ctor */ CMICmdCmdTargetSelect(); + // Methods: +public: + /* ctor */ CMICmdCmdTargetSelect(); - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdTargetSelect() override; + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdTargetSelect() override; - // Attributes: - private: - const CMIUtilString m_constStrArgNamedType; - const CMIUtilString m_constStrArgNamedParameters; + // Attributes: +private: + const CMIUtilString m_constStrArgNamedType; + const CMIUtilString m_constStrArgNamedParameters; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "target-attach". // http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation //-- -class CMICmdCmdTargetAttach : public CMICmdBase -{ - // Statics: +class CMICmdCmdTargetAttach : public CMICmdBase { + // Statics: public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: public: - /* ctor */ CMICmdCmdTargetAttach(); - - // Overridden: + /* ctor */ CMICmdCmdTargetAttach(); + + // Overridden: public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdTargetAttach() override; - - // Attributes: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdTargetAttach() override; + + // Attributes: private: - const CMIUtilString m_constStrArgPid; - const CMIUtilString m_constStrArgNamedFile; - const CMIUtilString m_constStrArgWaitFor; + const CMIUtilString m_constStrArgPid; + const CMIUtilString m_constStrArgNamedFile; + const CMIUtilString m_constStrArgWaitFor; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "target-attach". // http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation //-- -class CMICmdCmdTargetDetach : public CMICmdBase -{ - // Statics: +class CMICmdCmdTargetDetach : public CMICmdBase { + // Statics: public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: public: - /* ctor */ CMICmdCmdTargetDetach(); - - // Overridden: + /* ctor */ CMICmdCmdTargetDetach(); + + // Overridden: public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdTargetDetach() override; + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdTargetDetach() override; }; - diff --git a/lldb/tools/lldb-mi/MICmdCmdThread.cpp b/lldb/tools/lldb-mi/MICmdCmdThread.cpp index 9435655762a..32bdca5265b 100644 --- a/lldb/tools/lldb-mi/MICmdCmdThread.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdThread.cpp @@ -14,14 +14,15 @@ #include "lldb/API/SBThread.h" // In-house headers: +#include "MICmdArgValNumber.h" #include "MICmdCmdThread.h" +#include "MICmnLLDBDebugSessionInfo.h" +#include "MICmnLLDBDebugger.h" #include "MICmnMIResultRecord.h" #include "MICmnMIValueConst.h" -#include "MICmnLLDBDebugger.h" -#include "MICmnLLDBDebugSessionInfo.h" -#include "MICmdArgValNumber.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdThreadInfo constructor. // Type: Method. // Args: None. @@ -29,32 +30,29 @@ // Throws: None. //-- CMICmdCmdThreadInfo::CMICmdCmdThreadInfo() - : m_bSingleThread(false), - m_bThreadInvalid(true), - m_constStrArgNamedThreadId("thread-id"), - m_bHasCurrentThread(false) -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "thread-info"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdThreadInfo::CreateSelf; + : m_bSingleThread(false), m_bThreadInvalid(true), + m_constStrArgNamedThreadId("thread-id"), m_bHasCurrentThread(false) { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "thread-info"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdThreadInfo::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdThreadInfo destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdThreadInfo::~CMICmdCmdThreadInfo() -{ - m_vecMIValueTuple.clear(); -} +CMICmdCmdThreadInfo::~CMICmdCmdThreadInfo() { m_vecMIValueTuple.clear(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -62,83 +60,85 @@ CMICmdCmdThreadInfo::~CMICmdCmdThreadInfo() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdThreadInfo::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNamedThreadId, false, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdThreadInfo::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValNumber(m_constStrArgNamedThreadId, false, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdThreadInfo::Execute() -{ - CMICMDBASE_GETOPTION(pArgThreadId, Number, m_constStrArgNamedThreadId); - MIuint nThreadId = 0; - if (pArgThreadId->GetFound() && pArgThreadId->GetValid()) - { - m_bSingleThread = true; - nThreadId = static_cast<MIuint>(pArgThreadId->GetValue()); - } - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); - lldb::SBThread thread = sbProcess.GetSelectedThread(); - - if (m_bSingleThread) - { - thread = sbProcess.GetThreadByIndexID(nThreadId); - m_bThreadInvalid = !thread.IsValid(); - if (m_bThreadInvalid) - return MIstatus::success; - - CMICmnMIValueTuple miTuple; - if (!rSessionInfo.MIResponseFormThreadInfo(m_cmdData, thread, CMICmnLLDBDebugSessionInfo::eThreadInfoFormat_AllFrames, miTuple)) - return MIstatus::failure; - - m_miValueTupleThread = miTuple; - - return MIstatus::success; - } +bool CMICmdCmdThreadInfo::Execute() { + CMICMDBASE_GETOPTION(pArgThreadId, Number, m_constStrArgNamedThreadId); + MIuint nThreadId = 0; + if (pArgThreadId->GetFound() && pArgThreadId->GetValid()) { + m_bSingleThread = true; + nThreadId = static_cast<MIuint>(pArgThreadId->GetValue()); + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + lldb::SBThread thread = sbProcess.GetSelectedThread(); + + if (m_bSingleThread) { + thread = sbProcess.GetThreadByIndexID(nThreadId); + m_bThreadInvalid = !thread.IsValid(); + if (m_bThreadInvalid) + return MIstatus::success; + + CMICmnMIValueTuple miTuple; + if (!rSessionInfo.MIResponseFormThreadInfo( + m_cmdData, thread, + CMICmnLLDBDebugSessionInfo::eThreadInfoFormat_AllFrames, miTuple)) + return MIstatus::failure; + + m_miValueTupleThread = miTuple; - // Multiple threads - m_vecMIValueTuple.clear(); - const MIuint nThreads = sbProcess.GetNumThreads(); - for (MIuint i = 0; i < nThreads; i++) - { - lldb::SBThread thread = sbProcess.GetThreadAtIndex(i); - if (thread.IsValid()) - { - CMICmnMIValueTuple miTuple; - if (!rSessionInfo.MIResponseFormThreadInfo(m_cmdData, thread, CMICmnLLDBDebugSessionInfo::eThreadInfoFormat_AllFrames, miTuple)) - return MIstatus::failure; - - m_vecMIValueTuple.push_back(miTuple); - } + return MIstatus::success; + } + + // Multiple threads + m_vecMIValueTuple.clear(); + const MIuint nThreads = sbProcess.GetNumThreads(); + for (MIuint i = 0; i < nThreads; i++) { + lldb::SBThread thread = sbProcess.GetThreadAtIndex(i); + if (thread.IsValid()) { + CMICmnMIValueTuple miTuple; + if (!rSessionInfo.MIResponseFormThreadInfo( + m_cmdData, thread, + CMICmnLLDBDebugSessionInfo::eThreadInfoFormat_AllFrames, miTuple)) + return MIstatus::failure; + + m_vecMIValueTuple.push_back(miTuple); } + } - // -thread-info with multiple threads ends with the current thread id if any - if (thread.IsValid()) - { - const CMIUtilString strId(CMIUtilString::Format("%d", thread.GetIndexID())); - CMICmnMIValueConst miValueCurrThreadId(strId); - m_miValueCurrThreadId = miValueCurrThreadId; - m_bHasCurrentThread = true; - } + // -thread-info with multiple threads ends with the current thread id if any + if (thread.IsValid()) { + const CMIUtilString strId(CMIUtilString::Format("%d", thread.GetIndexID())); + CMICmnMIValueConst miValueCurrThreadId(strId); + m_miValueCurrThreadId = miValueCurrThreadId; + m_bHasCurrentThread = true; + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -146,71 +146,73 @@ CMICmdCmdThreadInfo::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdThreadInfo::Acknowledge() -{ - if (m_bSingleThread) - { - if (m_bThreadInvalid) - { - const CMICmnMIValueConst miValueConst("invalid thread id"); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - // MI print "%s^done,threads=[{id=\"%d\",target-id=\"%s\",frame={},state=\"%s\"}] - const CMICmnMIValueList miValueList(m_miValueTupleThread); - const CMICmnMIValueResult miValueResult("threads", miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - // Build up a list of thread information from tuples - VecMIValueTuple_t::const_iterator it = m_vecMIValueTuple.begin(); - if (it == m_vecMIValueTuple.end()) - { - const CMICmnMIValueConst miValueConst("[]"); - const CMICmnMIValueResult miValueResult("threads", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - CMICmnMIValueList miValueList(*it); - ++it; - while (it != m_vecMIValueTuple.end()) - { - const CMICmnMIValueTuple &rTuple(*it); - miValueList.Add(rTuple); - - // Next - ++it; +bool CMICmdCmdThreadInfo::Acknowledge() { + if (m_bSingleThread) { + if (m_bThreadInvalid) { + const CMICmnMIValueConst miValueConst("invalid thread id"); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; } - CMICmnMIValueResult miValueResult("threads", miValueList); - if (m_bHasCurrentThread) - { - CMIUtilString strCurrThreadId = "current-thread-id"; - miValueResult.Add(strCurrThreadId, m_miValueCurrThreadId); - } - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); + // MI print + // "%s^done,threads=[{id=\"%d\",target-id=\"%s\",frame={},state=\"%s\"}] + const CMICmnMIValueList miValueList(m_miValueTupleThread); + const CMICmnMIValueResult miValueResult("threads", miValueList); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); m_miResultRecord = miRecordResult; - return MIstatus::success; + } + + // Build up a list of thread information from tuples + VecMIValueTuple_t::const_iterator it = m_vecMIValueTuple.begin(); + if (it == m_vecMIValueTuple.end()) { + const CMICmnMIValueConst miValueConst("[]"); + const CMICmnMIValueResult miValueResult("threads", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; + } + CMICmnMIValueList miValueList(*it); + ++it; + while (it != m_vecMIValueTuple.end()) { + const CMICmnMIValueTuple &rTuple(*it); + miValueList.Add(rTuple); + + // Next + ++it; + } + + CMICmnMIValueResult miValueResult("threads", miValueList); + if (m_bHasCurrentThread) { + CMIUtilString strCurrThreadId = "current-thread-id"; + miValueResult.Add(strCurrThreadId, m_miValueCurrThreadId); + } + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdThreadInfo::CreateSelf() -{ - return new CMICmdCmdThreadInfo(); +CMICmdBase *CMICmdCmdThreadInfo::CreateSelf() { + return new CMICmdCmdThreadInfo(); } diff --git a/lldb/tools/lldb-mi/MICmdCmdThread.h b/lldb/tools/lldb-mi/MICmdCmdThread.h index e3b0adca613..7635e9fd965 100644 --- a/lldb/tools/lldb-mi/MICmdCmdThread.h +++ b/lldb/tools/lldb-mi/MICmdCmdThread.h @@ -9,59 +9,62 @@ // Overview: CMICmdCmdThreadInfo interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands derive a new command class from the +// command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// For an introduction to adding a new command see +// CMICmdCmdSupportInfoMiCmdQuery // command class as an example. #pragma once // In-house headers: #include "MICmdBase.h" -#include "MICmnMIValueTuple.h" #include "MICmnMIValueList.h" +#include "MICmnMIValueTuple.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "thread-info". //-- -class CMICmdCmdThreadInfo : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); +class CMICmdCmdThreadInfo : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); - // Methods: - public: - /* ctor */ CMICmdCmdThreadInfo(); + // Methods: +public: + /* ctor */ CMICmdCmdThreadInfo(); - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdThreadInfo() override; + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdThreadInfo() override; - // Typedefs: - private: - typedef std::vector<CMICmnMIValueTuple> VecMIValueTuple_t; + // Typedefs: +private: + typedef std::vector<CMICmnMIValueTuple> VecMIValueTuple_t; - // Attributes: - private: - CMICmnMIValueTuple m_miValueTupleThread; - bool m_bSingleThread; // True = yes single thread, false = multiple threads - bool m_bThreadInvalid; // True = invalid, false = ok - VecMIValueTuple_t m_vecMIValueTuple; - const CMIUtilString m_constStrArgNamedThreadId; + // Attributes: +private: + CMICmnMIValueTuple m_miValueTupleThread; + bool m_bSingleThread; // True = yes single thread, false = multiple threads + bool m_bThreadInvalid; // True = invalid, false = ok + VecMIValueTuple_t m_vecMIValueTuple; + const CMIUtilString m_constStrArgNamedThreadId; - // mi value of current-thread-id if multiple threads are requested - bool m_bHasCurrentThread; - CMICmnMIValue m_miValueCurrThreadId; + // mi value of current-thread-id if multiple threads are requested + bool m_bHasCurrentThread; + CMICmnMIValue m_miValueCurrThreadId; }; diff --git a/lldb/tools/lldb-mi/MICmdCmdTrace.cpp b/lldb/tools/lldb-mi/MICmdCmdTrace.cpp index 4eab75bc71f..c98ede225fa 100644 --- a/lldb/tools/lldb-mi/MICmdCmdTrace.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdTrace.cpp @@ -14,51 +14,53 @@ #include "MICmnMIResultRecord.h" #include "MICmnMIValueConst.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdTraceStatus constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdTraceStatus::CMICmdCmdTraceStatus() -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "trace-status"; +CMICmdCmdTraceStatus::CMICmdCmdTraceStatus() { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "trace-status"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdTraceStatus::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdTraceStatus::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdTraceStatus destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdTraceStatus::~CMICmdCmdTraceStatus() -{ -} +CMICmdCmdTraceStatus::~CMICmdCmdTraceStatus() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdTraceStatus::Execute() -{ - // Do nothing - return MIstatus::success; +bool CMICmdCmdTraceStatus::Execute() { + // Do nothing + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -66,27 +68,27 @@ CMICmdCmdTraceStatus::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdTraceStatus::Acknowledge() -{ - const CMICmnMIValueConst miValueConst(MIRSRC(IDS_CMD_ERR_NOT_IMPLEMENTED)); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); - m_miResultRecord = miRecordResult; +bool CMICmdCmdTraceStatus::Acknowledge() { + const CMICmnMIValueConst miValueConst(MIRSRC(IDS_CMD_ERR_NOT_IMPLEMENTED)); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdTraceStatus::CreateSelf() -{ - return new CMICmdCmdTraceStatus(); +CMICmdBase *CMICmdCmdTraceStatus::CreateSelf() { + return new CMICmdCmdTraceStatus(); } diff --git a/lldb/tools/lldb-mi/MICmdCmdTrace.h b/lldb/tools/lldb-mi/MICmdCmdTrace.h index d3751607338..b6cb3aea5d3 100644 --- a/lldb/tools/lldb-mi/MICmdCmdTrace.h +++ b/lldb/tools/lldb-mi/MICmdCmdTrace.h @@ -9,13 +9,16 @@ // Overview: CMICmdCmdTraceStatus interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands derive a new command class from the +// command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// For an introduction to adding a new command see +// CMICmdCmdSupportInfoMiCmdQuery // command class as an example. #pragma once @@ -23,26 +26,26 @@ // In-house headers: #include "MICmdBase.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "trace-status". //-- -class CMICmdCmdTraceStatus : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); +class CMICmdCmdTraceStatus : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); - // Methods: - public: - /* ctor */ CMICmdCmdTraceStatus(); + // Methods: +public: + /* ctor */ CMICmdCmdTraceStatus(); - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdTraceStatus() override; + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdTraceStatus() override; }; diff --git a/lldb/tools/lldb-mi/MICmdCmdVar.cpp b/lldb/tools/lldb-mi/MICmdCmdVar.cpp index d8e81a44b9d..1efbd0b31e7 100644 --- a/lldb/tools/lldb-mi/MICmdCmdVar.cpp +++ b/lldb/tools/lldb-mi/MICmdCmdVar.cpp @@ -19,26 +19,27 @@ // Third Party Headers: #include "lldb/API/SBStream.h" -#include "lldb/API/SBType.h" #include "lldb/API/SBThread.h" +#include "lldb/API/SBType.h" // In-house headers: -#include "MICmdCmdVar.h" -#include "MICmnMIResultRecord.h" -#include "MICmnMIValueConst.h" -#include "MICmnLLDBDebugger.h" -#include "MICmnLLDBDebugSessionInfo.h" +#include "MICmdArgValListOfN.h" #include "MICmdArgValNumber.h" -#include "MICmdArgValString.h" -#include "MICmdArgValThreadGrp.h" #include "MICmdArgValOptionLong.h" #include "MICmdArgValOptionShort.h" #include "MICmdArgValPrintValues.h" -#include "MICmdArgValListOfN.h" +#include "MICmdArgValString.h" +#include "MICmdArgValThreadGrp.h" +#include "MICmdCmdVar.h" +#include "MICmnLLDBDebugSessionInfo.h" +#include "MICmnLLDBDebugger.h" #include "MICmnLLDBProxySBValue.h" #include "MICmnLLDBUtilSBValue.h" +#include "MICmnMIResultRecord.h" +#include "MICmnMIValueConst.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdVarCreate constructor. // Type: Method. // Args: None. @@ -46,35 +47,31 @@ // Throws: None. //-- CMICmdCmdVarCreate::CMICmdCmdVarCreate() - : m_nChildren(0) - , m_nThreadId(0) - , m_strType("??") - , m_bValid(false) - , m_strValue("??") - , m_constStrArgName("name") - , m_constStrArgFrameAddr("frame-addr") - , m_constStrArgExpression("expression") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "var-create"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdVarCreate::CreateSelf; + : m_nChildren(0), m_nThreadId(0), m_strType("??"), m_bValid(false), + m_strValue("??"), m_constStrArgName("name"), + m_constStrArgFrameAddr("frame-addr"), + m_constStrArgExpression("expression") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "var-create"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdVarCreate::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdVarCreate destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdVarCreate::~CMICmdCmdVarCreate() -{ -} +CMICmdCmdVarCreate::~CMICmdCmdVarCreate() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -82,133 +79,140 @@ CMICmdCmdVarCreate::~CMICmdCmdVarCreate() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarCreate::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, false, true)); - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgFrameAddr, false, true)); - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgExpression, true, true, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdVarCreate::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, false, true)); + m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgFrameAddr, false, true)); + m_setCmdArgs.Add( + new CMICmdArgValString(m_constStrArgExpression, true, true, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarCreate::Execute() -{ - CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); - CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame); - CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); - CMICMDBASE_GETOPTION(pArgFrameAddr, String, m_constStrArgFrameAddr); - CMICMDBASE_GETOPTION(pArgExpression, String, m_constStrArgExpression); - - // Retrieve the --thread option's thread ID (only 1) - MIuint64 nThreadId = UINT64_MAX; - if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); - return MIstatus::failure; - } - - // Retrieve the --frame option's number - MIuint64 nFrame = UINT64_MAX; - if (pArgThread->GetFound() && !pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str())); - return MIstatus::failure; - } - - const CMICmdArgValOptionLong::VecArgObjPtr_t &rVecFrameId(pArgFrame->GetExpectedOptions()); - CMICmdArgValOptionLong::VecArgObjPtr_t::const_iterator it2 = rVecFrameId.begin(); - if (it2 != rVecFrameId.end()) - { - const CMICmdArgValNumber *pOption = static_cast<CMICmdArgValNumber *>(*it2); - nFrame = pOption->GetValue(); - } - - m_strVarName = "<unnamedvariable>"; - if (pArgName->GetFound()) - { - const CMIUtilString &rArg = pArgName->GetValue(); - const bool bAutoName = (rArg == "-"); - if (bAutoName) - { - m_strVarName = CMIUtilString::Format("var%u", CMICmnLLDBDebugSessionInfoVarObj::VarObjIdGet()); - CMICmnLLDBDebugSessionInfoVarObj::VarObjIdInc(); - } - else - m_strVarName = rArg; - } - - bool bCurrentFrame = false; - if (pArgFrameAddr->GetFound()) - { - const CMIUtilString &rStrFrameAddr(pArgFrameAddr->GetValue()); - bCurrentFrame = CMIUtilString::Compare(rStrFrameAddr, "*"); - if (!bCurrentFrame && (nFrame == UINT64_MAX)) - { - //FIXME: *addr isn't implemented. Exit with error if --thread isn't specified. - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str())); - return MIstatus::failure; - } - } - - const CMIUtilString &rStrExpression(pArgExpression->GetValue()); - m_strExpression = rStrExpression; - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); - lldb::SBThread thread = (nThreadId != UINT64_MAX) ? sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.GetSelectedThread(); - m_nThreadId = thread.GetIndexID(); - lldb::SBFrame frame = bCurrentFrame ? thread.GetSelectedFrame() : thread.GetFrameAtIndex(nFrame); - lldb::SBValue value; - - if (rStrExpression[0] == '$') - { - const CMIUtilString rStrRegister(rStrExpression.substr(1)); - value = frame.FindRegister(rStrRegister.c_str()); - } - else - { - const bool bArgs = true; - const bool bLocals = true; - const bool bStatics = true; - const bool bInScopeOnly = false; - const lldb::SBValueList valueList = frame.GetVariables(bArgs, bLocals, bStatics, bInScopeOnly); - value = valueList.GetFirstValueByName(rStrExpression.c_str()); - } - - if (!value.IsValid()) - value = frame.EvaluateExpression(rStrExpression.c_str()); - - if (value.IsValid() && value.GetError().Success()) - { - CompleteSBValue(value); - m_bValid = true; - m_nChildren = value.GetNumChildren(); - m_strType = CMICmnLLDBUtilSBValue(value).GetTypeNameDisplay(); - - // This gets added to CMICmnLLDBDebugSessionInfoVarObj static container of varObjs - CMICmnLLDBDebugSessionInfoVarObj varObj(rStrExpression, m_strVarName, value); - m_strValue = varObj.GetValueFormatted(); +bool CMICmdCmdVarCreate::Execute() { + CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); + CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame); + CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); + CMICMDBASE_GETOPTION(pArgFrameAddr, String, m_constStrArgFrameAddr); + CMICMDBASE_GETOPTION(pArgExpression, String, m_constStrArgExpression); + + // Retrieve the --thread option's thread ID (only 1) + MIuint64 nThreadId = UINT64_MAX; + if (pArgThread->GetFound() && + !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), + m_constStrArgThread.c_str())); + return MIstatus::failure; + } + + // Retrieve the --frame option's number + MIuint64 nFrame = UINT64_MAX; + if (pArgThread->GetFound() && + !pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), + m_constStrArgFrame.c_str())); + return MIstatus::failure; + } + + const CMICmdArgValOptionLong::VecArgObjPtr_t &rVecFrameId( + pArgFrame->GetExpectedOptions()); + CMICmdArgValOptionLong::VecArgObjPtr_t::const_iterator it2 = + rVecFrameId.begin(); + if (it2 != rVecFrameId.end()) { + const CMICmdArgValNumber *pOption = static_cast<CMICmdArgValNumber *>(*it2); + nFrame = pOption->GetValue(); + } + + m_strVarName = "<unnamedvariable>"; + if (pArgName->GetFound()) { + const CMIUtilString &rArg = pArgName->GetValue(); + const bool bAutoName = (rArg == "-"); + if (bAutoName) { + m_strVarName = CMIUtilString::Format( + "var%u", CMICmnLLDBDebugSessionInfoVarObj::VarObjIdGet()); + CMICmnLLDBDebugSessionInfoVarObj::VarObjIdInc(); + } else + m_strVarName = rArg; + } + + bool bCurrentFrame = false; + if (pArgFrameAddr->GetFound()) { + const CMIUtilString &rStrFrameAddr(pArgFrameAddr->GetValue()); + bCurrentFrame = CMIUtilString::Compare(rStrFrameAddr, "*"); + if (!bCurrentFrame && (nFrame == UINT64_MAX)) { + // FIXME: *addr isn't implemented. Exit with error if --thread isn't + // specified. + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), + m_cmdData.strMiCmd.c_str(), + m_constStrArgFrame.c_str())); + return MIstatus::failure; } - else - { - m_strValue = value.GetError().GetCString(); - } - - return MIstatus::success; + } + + const CMIUtilString &rStrExpression(pArgExpression->GetValue()); + m_strExpression = rStrExpression; + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + lldb::SBThread thread = (nThreadId != UINT64_MAX) + ? sbProcess.GetThreadByIndexID(nThreadId) + : sbProcess.GetSelectedThread(); + m_nThreadId = thread.GetIndexID(); + lldb::SBFrame frame = bCurrentFrame ? thread.GetSelectedFrame() + : thread.GetFrameAtIndex(nFrame); + lldb::SBValue value; + + if (rStrExpression[0] == '$') { + const CMIUtilString rStrRegister(rStrExpression.substr(1)); + value = frame.FindRegister(rStrRegister.c_str()); + } else { + const bool bArgs = true; + const bool bLocals = true; + const bool bStatics = true; + const bool bInScopeOnly = false; + const lldb::SBValueList valueList = + frame.GetVariables(bArgs, bLocals, bStatics, bInScopeOnly); + value = valueList.GetFirstValueByName(rStrExpression.c_str()); + } + + if (!value.IsValid()) + value = frame.EvaluateExpression(rStrExpression.c_str()); + + if (value.IsValid() && value.GetError().Success()) { + CompleteSBValue(value); + m_bValid = true; + m_nChildren = value.GetNumChildren(); + m_strType = CMICmnLLDBUtilSBValue(value).GetTypeNameDisplay(); + + // This gets added to CMICmnLLDBDebugSessionInfoVarObj static container of + // varObjs + CMICmnLLDBDebugSessionInfoVarObj varObj(rStrExpression, m_strVarName, + value); + m_strValue = varObj.GetValueFormatted(); + } else { + m_strValue = value.GetError().GetCString(); + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -216,60 +220,66 @@ CMICmdCmdVarCreate::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarCreate::Acknowledge() -{ - if (m_bValid) - { - // MI print "%s^done,name=\"%s\",numchild=\"%d\",value=\"%s\",type=\"%s\",thread-id=\"%llu\",has_more=\"%u\"" - const CMICmnMIValueConst miValueConst(m_strVarName); - CMICmnMIValueResult miValueResultAll("name", miValueConst); - const CMIUtilString strNumChild(CMIUtilString::Format("%d", m_nChildren)); - const CMICmnMIValueConst miValueConst2(strNumChild); - miValueResultAll.Add("numchild", miValueConst2); - const CMICmnMIValueConst miValueConst3(m_strValue); - miValueResultAll.Add("value", miValueConst3); - const CMICmnMIValueConst miValueConst4(m_strType); - miValueResultAll.Add("type", miValueConst4); - const CMIUtilString strThreadId(CMIUtilString::Format("%llu", m_nThreadId)); - const CMICmnMIValueConst miValueConst5(strThreadId); - miValueResultAll.Add("thread-id", miValueConst5); - const CMICmnMIValueConst miValueConst6("0"); - miValueResultAll.Add("has_more", miValueConst6); - - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResultAll); - m_miResultRecord = miRecordResult; - - return MIstatus::success; - } - - CMIUtilString strErrMsg(m_strValue); - if (m_strValue.empty()) - strErrMsg = CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_CREATION_FAILED), m_strExpression.c_str()); - const CMICmnMIValueConst miValueConst(strErrMsg.Escape(true /* vbEscapeQuotes */)); - CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); +bool CMICmdCmdVarCreate::Acknowledge() { + if (m_bValid) { + // MI print + // "%s^done,name=\"%s\",numchild=\"%d\",value=\"%s\",type=\"%s\",thread-id=\"%llu\",has_more=\"%u\"" + const CMICmnMIValueConst miValueConst(m_strVarName); + CMICmnMIValueResult miValueResultAll("name", miValueConst); + const CMIUtilString strNumChild(CMIUtilString::Format("%d", m_nChildren)); + const CMICmnMIValueConst miValueConst2(strNumChild); + miValueResultAll.Add("numchild", miValueConst2); + const CMICmnMIValueConst miValueConst3(m_strValue); + miValueResultAll.Add("value", miValueConst3); + const CMICmnMIValueConst miValueConst4(m_strType); + miValueResultAll.Add("type", miValueConst4); + const CMIUtilString strThreadId(CMIUtilString::Format("%llu", m_nThreadId)); + const CMICmnMIValueConst miValueConst5(strThreadId); + miValueResultAll.Add("thread-id", miValueConst5); + const CMICmnMIValueConst miValueConst6("0"); + miValueResultAll.Add("has_more", miValueConst6); + + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResultAll); m_miResultRecord = miRecordResult; return MIstatus::success; + } + + CMIUtilString strErrMsg(m_strValue); + if (m_strValue.empty()) + strErrMsg = CMIUtilString::Format( + MIRSRC(IDS_CMD_ERR_VARIABLE_CREATION_FAILED), m_strExpression.c_str()); + const CMICmnMIValueConst miValueConst( + strErrMsg.Escape(true /* vbEscapeQuotes */)); + CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdVarCreate::CreateSelf() -{ - return new CMICmdCmdVarCreate(); +CMICmdBase *CMICmdCmdVarCreate::CreateSelf() { + return new CMICmdCmdVarCreate(); } -//++ ------------------------------------------------------------------------------------ -// Details: Complete SBValue object and its children to get SBValue::GetValueDidChange +//++ +//------------------------------------------------------------------------------------ +// Details: Complete SBValue object and its children to get +// SBValue::GetValueDidChange // work. // Type: Method. // Args: vrwValue - (R) Value to update. @@ -277,31 +287,28 @@ CMICmdCmdVarCreate::CreateSelf() // MIstatus::failure - Functional failed. // Throws: None. //-- -void -CMICmdCmdVarCreate::CompleteSBValue(lldb::SBValue &vrwValue) -{ - // Force a value to update - vrwValue.GetValueDidChange(); - - // And update its children - lldb::SBType valueType = vrwValue.GetType(); - if (!valueType.IsPointerType() && !valueType.IsReferenceType()) - { - const MIuint nChildren = vrwValue.GetNumChildren(); - for (MIuint i = 0; i < nChildren; ++i) - { - lldb::SBValue member = vrwValue.GetChildAtIndex(i); - if (member.IsValid()) - CompleteSBValue(member); - } +void CMICmdCmdVarCreate::CompleteSBValue(lldb::SBValue &vrwValue) { + // Force a value to update + vrwValue.GetValueDidChange(); + + // And update its children + lldb::SBType valueType = vrwValue.GetType(); + if (!valueType.IsPointerType() && !valueType.IsReferenceType()) { + const MIuint nChildren = vrwValue.GetNumChildren(); + for (MIuint i = 0; i < nChildren; ++i) { + lldb::SBValue member = vrwValue.GetChildAtIndex(i); + if (member.IsValid()) + CompleteSBValue(member); } + } } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdVarUpdate constructor. // Type: Method. // Args: None. @@ -309,31 +316,29 @@ CMICmdCmdVarCreate::CompleteSBValue(lldb::SBValue &vrwValue) // Throws: None. //-- CMICmdCmdVarUpdate::CMICmdCmdVarUpdate() - : m_constStrArgPrintValues("print-values") - , m_constStrArgName("name") - , m_bValueChanged(false) - , m_miValueList(true) -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "var-update"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdVarUpdate::CreateSelf; + : m_constStrArgPrintValues("print-values"), m_constStrArgName("name"), + m_bValueChanged(false), m_miValueList(true) { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "var-update"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdVarUpdate::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdVarUpdate destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdVarUpdate::~CMICmdCmdVarUpdate() -{ -} +CMICmdCmdVarUpdate::~CMICmdCmdVarUpdate() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -341,60 +346,70 @@ CMICmdCmdVarUpdate::~CMICmdCmdVarUpdate() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarUpdate::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValPrintValues(m_constStrArgPrintValues, false, true)); - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdVarUpdate::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValPrintValues(m_constStrArgPrintValues, false, true)); + m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarUpdate::Execute() -{ - CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues); - CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); - - CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat = CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_NoValues; - if (pArgPrintValues->GetFound()) - eVarInfoFormat = static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>(pArgPrintValues->GetValue()); - - const CMIUtilString &rVarObjName(pArgName->GetValue()); - CMICmnLLDBDebugSessionInfoVarObj varObj; - if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str())); - return MIstatus::failure; - } - - lldb::SBValue &rValue = varObj.GetValue(); - if (!ExamineSBValueForChange(rValue, m_bValueChanged)) - return MIstatus::failure; - - if (m_bValueChanged) - { - varObj.UpdateValue(); - const bool bPrintValue((eVarInfoFormat == CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_AllValues) || - (eVarInfoFormat == CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_SimpleValues && rValue.GetNumChildren() == 0)); - const CMIUtilString strValue(bPrintValue ? varObj.GetValueFormatted() : ""); - const CMIUtilString strInScope(rValue.IsInScope() ? "true" : "false"); - MIFormResponse(rVarObjName, bPrintValue ? strValue.c_str() : nullptr, strInScope); - } - - return MIstatus::success; +bool CMICmdCmdVarUpdate::Execute() { + CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues); + CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); + + CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat = + CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_NoValues; + if (pArgPrintValues->GetFound()) + eVarInfoFormat = + static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>( + pArgPrintValues->GetValue()); + + const CMIUtilString &rVarObjName(pArgName->GetValue()); + CMICmnLLDBDebugSessionInfoVarObj varObj; + if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), + m_cmdData.strMiCmd.c_str(), + rVarObjName.c_str())); + return MIstatus::failure; + } + + lldb::SBValue &rValue = varObj.GetValue(); + if (!ExamineSBValueForChange(rValue, m_bValueChanged)) + return MIstatus::failure; + + if (m_bValueChanged) { + varObj.UpdateValue(); + const bool bPrintValue( + (eVarInfoFormat == + CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_AllValues) || + (eVarInfoFormat == + CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_SimpleValues && + rValue.GetNumChildren() == 0)); + const CMIUtilString strValue(bPrintValue ? varObj.GetValueFormatted() : ""); + const CMIUtilString strInScope(rValue.IsInScope() ? "true" : "false"); + MIFormResponse(rVarObjName, bPrintValue ? strValue.c_str() : nullptr, + strInScope); + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -402,77 +417,80 @@ CMICmdCmdVarUpdate::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarUpdate::Acknowledge() -{ - if (m_bValueChanged) - { - // MI print "%s^done,changelist=[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]" - CMICmnMIValueResult miValueResult("changelist", m_miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - } - else - { - // MI print "%s^done,changelist=[]" - const CMICmnMIValueList miValueList(true); - CMICmnMIValueResult miValueResult6("changelist", miValueList); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6); - m_miResultRecord = miRecordResult; - } +bool CMICmdCmdVarUpdate::Acknowledge() { + if (m_bValueChanged) { + // MI print + // "%s^done,changelist=[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]" + CMICmnMIValueResult miValueResult("changelist", m_miValueList); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + } else { + // MI print "%s^done,changelist=[]" + const CMICmnMIValueList miValueList(true); + CMICmnMIValueResult miValueResult6("changelist", miValueList); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult6); + m_miResultRecord = miRecordResult; + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdVarUpdate::CreateSelf() -{ - return new CMICmdCmdVarUpdate(); +CMICmdBase *CMICmdCmdVarUpdate::CreateSelf() { + return new CMICmdCmdVarUpdate(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Form the MI response for multiple variables. // Type: Method. // Args: vrStrVarName - (R) Session var object's name. -// vpValue - (R) Text version of the value held in the variable. +// vpValue - (R) Text version of the value held in the +// variable. // vrStrScope - (R) In scope "yes" or "no". // Return: None. // Throws: None. //-- -void -CMICmdCmdVarUpdate::MIFormResponse(const CMIUtilString &vrStrVarName, const char *const vpValue, const CMIUtilString &vrStrScope) -{ - // MI print "[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]" - const CMICmnMIValueConst miValueConst(vrStrVarName); - const CMICmnMIValueResult miValueResult("name", miValueConst); - CMICmnMIValueTuple miValueTuple(miValueResult); - if (vpValue != nullptr) - { - const CMICmnMIValueConst miValueConst2(vpValue); - const CMICmnMIValueResult miValueResult2("value", miValueConst2); - miValueTuple.Add(miValueResult2); - } - const CMICmnMIValueConst miValueConst3(vrStrScope); - const CMICmnMIValueResult miValueResult3("in_scope", miValueConst3); - miValueTuple.Add(miValueResult3); - const CMICmnMIValueConst miValueConst4("false"); - const CMICmnMIValueResult miValueResult4("type_changed", miValueConst4); - miValueTuple.Add(miValueResult4); - const CMICmnMIValueConst miValueConst5("0"); - const CMICmnMIValueResult miValueResult5("has_more", miValueConst5); - miValueTuple.Add(miValueResult5); - m_miValueList.Add(miValueTuple); +void CMICmdCmdVarUpdate::MIFormResponse(const CMIUtilString &vrStrVarName, + const char *const vpValue, + const CMIUtilString &vrStrScope) { + // MI print + // "[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]" + const CMICmnMIValueConst miValueConst(vrStrVarName); + const CMICmnMIValueResult miValueResult("name", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + if (vpValue != nullptr) { + const CMICmnMIValueConst miValueConst2(vpValue); + const CMICmnMIValueResult miValueResult2("value", miValueConst2); + miValueTuple.Add(miValueResult2); + } + const CMICmnMIValueConst miValueConst3(vrStrScope); + const CMICmnMIValueResult miValueResult3("in_scope", miValueConst3); + miValueTuple.Add(miValueResult3); + const CMICmnMIValueConst miValueConst4("false"); + const CMICmnMIValueResult miValueResult4("type_changed", miValueConst4); + miValueTuple.Add(miValueResult4); + const CMICmnMIValueConst miValueConst5("0"); + const CMICmnMIValueResult miValueResult5("has_more", miValueConst5); + miValueTuple.Add(miValueResult5); + m_miValueList.Add(miValueTuple); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Determine if the var object was changed. // Type: Method. // Args: vrVarObj - (R) Session var object to examine. @@ -482,63 +500,58 @@ CMICmdCmdVarUpdate::MIFormResponse(const CMIUtilString &vrStrVarName, const char // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarUpdate::ExamineSBValueForChange(lldb::SBValue &vrwValue, bool &vrwbChanged) -{ - if (vrwValue.GetValueDidChange()) - { +bool CMICmdCmdVarUpdate::ExamineSBValueForChange(lldb::SBValue &vrwValue, + bool &vrwbChanged) { + if (vrwValue.GetValueDidChange()) { + vrwbChanged = true; + return MIstatus::success; + } + + lldb::SBType valueType = vrwValue.GetType(); + if (!valueType.IsPointerType() && !valueType.IsReferenceType()) { + const MIuint nChildren = vrwValue.GetNumChildren(); + for (MIuint i = 0; i < nChildren; ++i) { + lldb::SBValue member = vrwValue.GetChildAtIndex(i); + if (!member.IsValid()) + continue; + + if (member.GetValueDidChange()) { vrwbChanged = true; return MIstatus::success; + } else if (ExamineSBValueForChange(member, vrwbChanged) && vrwbChanged) + // Handle composite types (i.e. struct or arrays) + return MIstatus::success; } + } - lldb::SBType valueType = vrwValue.GetType(); - if (!valueType.IsPointerType() && !valueType.IsReferenceType()) - { - const MIuint nChildren = vrwValue.GetNumChildren(); - for (MIuint i = 0; i < nChildren; ++i) - { - lldb::SBValue member = vrwValue.GetChildAtIndex(i); - if (!member.IsValid()) - continue; - - if (member.GetValueDidChange()) - { - vrwbChanged = true; - return MIstatus::success; - } - else if (ExamineSBValueForChange(member, vrwbChanged) && vrwbChanged) - // Handle composite types (i.e. struct or arrays) - return MIstatus::success; - } - } - - vrwbChanged = false; - return MIstatus::success; + vrwbChanged = false; + return MIstatus::success; } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdVarDelete constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdVarDelete::CMICmdCmdVarDelete() - : m_constStrArgName("name") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "var-delete"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdVarDelete::CreateSelf; +CMICmdCmdVarDelete::CMICmdCmdVarDelete() : m_constStrArgName("name") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "var-delete"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdVarDelete::CreateSelf; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -546,46 +559,46 @@ CMICmdCmdVarDelete::CMICmdCmdVarDelete() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarDelete::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdVarDelete::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdVarDelete destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdVarDelete::~CMICmdCmdVarDelete() -{ -} - -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +CMICmdCmdVarDelete::~CMICmdCmdVarDelete() {} + +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarDelete::Execute() -{ - CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); +bool CMICmdCmdVarDelete::Execute() { + CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); - const CMIUtilString &rVarObjName(pArgName->GetValue()); - CMICmnLLDBDebugSessionInfoVarObj::VarObjDelete(rVarObjName); + const CMIUtilString &rVarObjName(pArgName->GetValue()); + CMICmnLLDBDebugSessionInfoVarObj::VarObjDelete(rVarObjName); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -593,34 +606,34 @@ CMICmdCmdVarDelete::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarDelete::Acknowledge() -{ - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); - m_miResultRecord = miRecordResult; +bool CMICmdCmdVarDelete::Acknowledge() { + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); + m_miResultRecord = miRecordResult; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdVarDelete::CreateSelf() -{ - return new CMICmdCmdVarDelete(); +CMICmdBase *CMICmdCmdVarDelete::CreateSelf() { + return new CMICmdCmdVarDelete(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdVarAssign constructor. // Type: Method. // Args: None. @@ -628,30 +641,29 @@ CMICmdCmdVarDelete::CreateSelf() // Throws: None. //-- CMICmdCmdVarAssign::CMICmdCmdVarAssign() - : m_bOk(true) - , m_constStrArgName("name") - , m_constStrArgExpression("expression") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "var-assign"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdVarAssign::CreateSelf; + : m_bOk(true), m_constStrArgName("name"), + m_constStrArgExpression("expression") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "var-assign"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdVarAssign::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdVarAssign destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdVarAssign::~CMICmdCmdVarAssign() -{ -} +CMICmdCmdVarAssign::~CMICmdCmdVarAssign() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -659,52 +671,54 @@ CMICmdCmdVarAssign::~CMICmdCmdVarAssign() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarAssign::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true)); - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgExpression, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdVarAssign::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true)); + m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgExpression, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarAssign::Execute() -{ - CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); - CMICMDBASE_GETOPTION(pArgExpression, String, m_constStrArgExpression); - - const CMIUtilString &rVarObjName(pArgName->GetValue()); - const CMIUtilString &rExpression(pArgExpression->GetValue()); - - CMICmnLLDBDebugSessionInfoVarObj varObj; - if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str())); - return MIstatus::failure; - } - m_varObjName = rVarObjName; - - CMIUtilString strExpression(rExpression.Trim()); - strExpression = strExpression.Trim('"'); - lldb::SBValue &rValue(const_cast<lldb::SBValue &>(varObj.GetValue())); - m_bOk = rValue.SetValueFromCString(strExpression.c_str()); - if (m_bOk) - varObj.UpdateValue(); +bool CMICmdCmdVarAssign::Execute() { + CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); + CMICMDBASE_GETOPTION(pArgExpression, String, m_constStrArgExpression); + + const CMIUtilString &rVarObjName(pArgName->GetValue()); + const CMIUtilString &rExpression(pArgExpression->GetValue()); + + CMICmnLLDBDebugSessionInfoVarObj varObj; + if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), + m_cmdData.strMiCmd.c_str(), + rVarObjName.c_str())); + return MIstatus::failure; + } + m_varObjName = rVarObjName; + + CMIUtilString strExpression(rExpression.Trim()); + strExpression = strExpression.Trim('"'); + lldb::SBValue &rValue(const_cast<lldb::SBValue &>(varObj.GetValue())); + m_bOk = rValue.SetValueFromCString(strExpression.c_str()); + if (m_bOk) + varObj.UpdateValue(); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -712,49 +726,51 @@ CMICmdCmdVarAssign::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarAssign::Acknowledge() -{ - if (m_bOk) - { - // MI print "%s^done,value=\"%s\"" - CMICmnLLDBDebugSessionInfoVarObj varObj; - CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(m_varObjName, varObj); - const CMICmnMIValueConst miValueConst(varObj.GetValueFormatted()); - const CMICmnMIValueResult miValueResult("value", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - - return MIstatus::success; - } - - const CMICmnMIValueConst miValueConst("expression could not be evaluated"); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); +bool CMICmdCmdVarAssign::Acknowledge() { + if (m_bOk) { + // MI print "%s^done,value=\"%s\"" + CMICmnLLDBDebugSessionInfoVarObj varObj; + CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(m_varObjName, varObj); + const CMICmnMIValueConst miValueConst(varObj.GetValueFormatted()); + const CMICmnMIValueResult miValueResult("value", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); m_miResultRecord = miRecordResult; return MIstatus::success; + } + + const CMICmnMIValueConst miValueConst("expression could not be evaluated"); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdVarAssign::CreateSelf() -{ - return new CMICmdCmdVarAssign(); +CMICmdBase *CMICmdCmdVarAssign::CreateSelf() { + return new CMICmdCmdVarAssign(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdVarSetFormat constructor. // Type: Method. // Args: None. @@ -762,29 +778,28 @@ CMICmdCmdVarAssign::CreateSelf() // Throws: None. //-- CMICmdCmdVarSetFormat::CMICmdCmdVarSetFormat() - : m_constStrArgName("name") - , m_constStrArgFormatSpec("format-spec") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "var-set-format"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdVarSetFormat::CreateSelf; + : m_constStrArgName("name"), m_constStrArgFormatSpec("format-spec") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "var-set-format"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdVarSetFormat::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdVarSetFormat destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdVarSetFormat::~CMICmdCmdVarSetFormat() -{ -} +CMICmdCmdVarSetFormat::~CMICmdCmdVarSetFormat() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -792,53 +807,57 @@ CMICmdCmdVarSetFormat::~CMICmdCmdVarSetFormat() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarSetFormat::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true)); - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgFormatSpec, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdVarSetFormat::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true)); + m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgFormatSpec, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarSetFormat::Execute() -{ - CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); - CMICMDBASE_GETOPTION(pArgFormatSpec, String, m_constStrArgFormatSpec); - - const CMIUtilString &rVarObjName(pArgName->GetValue()); - const CMIUtilString &rExpression(pArgFormatSpec->GetValue()); - - CMICmnLLDBDebugSessionInfoVarObj varObj; - if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str())); - return MIstatus::failure; - } - if (!varObj.SetVarFormat(CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForString(rExpression))) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_ENUM_INVALID), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str(), - rExpression.c_str())); - return MIstatus::failure; - } - varObj.UpdateValue(); - - m_varObjName = rVarObjName; - - return MIstatus::success; +bool CMICmdCmdVarSetFormat::Execute() { + CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); + CMICMDBASE_GETOPTION(pArgFormatSpec, String, m_constStrArgFormatSpec); + + const CMIUtilString &rVarObjName(pArgName->GetValue()); + const CMIUtilString &rExpression(pArgFormatSpec->GetValue()); + + CMICmnLLDBDebugSessionInfoVarObj varObj; + if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), + m_cmdData.strMiCmd.c_str(), + rVarObjName.c_str())); + return MIstatus::failure; + } + if (!varObj.SetVarFormat( + CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForString( + rExpression))) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_ENUM_INVALID), + m_cmdData.strMiCmd.c_str(), + rVarObjName.c_str(), rExpression.c_str())); + return MIstatus::failure; + } + varObj.UpdateValue(); + + m_varObjName = rVarObjName; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -846,56 +865,58 @@ CMICmdCmdVarSetFormat::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarSetFormat::Acknowledge() -{ - // MI print "%s^done,changelist=[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]" - CMICmnLLDBDebugSessionInfoVarObj varObj; - CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(m_varObjName, varObj); - const CMICmnMIValueConst miValueConst(m_varObjName); - const CMICmnMIValueResult miValueResult("name", miValueConst); - CMICmnMIValueTuple miValueTuple(miValueResult); - const CMICmnMIValueConst miValueConst2(varObj.GetValueFormatted()); - const CMICmnMIValueResult miValueResult2("value", miValueConst2); - miValueTuple.Add(miValueResult2); - lldb::SBValue &rValue = const_cast<lldb::SBValue &>(varObj.GetValue()); - const CMICmnMIValueConst miValueConst3(rValue.IsInScope() ? "true" : "false"); - const CMICmnMIValueResult miValueResult3("in_scope", miValueConst3); - miValueTuple.Add(miValueResult3); - const CMICmnMIValueConst miValueConst4("false"); - const CMICmnMIValueResult miValueResult4("type_changed", miValueConst4); - miValueTuple.Add(miValueResult4); - const CMICmnMIValueConst miValueConst5("0"); - const CMICmnMIValueResult miValueResult5("type_changed", miValueConst5); - miValueTuple.Add(miValueResult5); - const CMICmnMIValueList miValueList(miValueTuple); - const CMICmnMIValueResult miValueResult6("changelist", miValueList); - - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6); - m_miResultRecord = miRecordResult; - - return MIstatus::success; +bool CMICmdCmdVarSetFormat::Acknowledge() { + // MI print + // "%s^done,changelist=[{name=\"%s\",value=\"%s\",in_scope=\"%s\",type_changed=\"false\",has_more=\"0\"}]" + CMICmnLLDBDebugSessionInfoVarObj varObj; + CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(m_varObjName, varObj); + const CMICmnMIValueConst miValueConst(m_varObjName); + const CMICmnMIValueResult miValueResult("name", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const CMICmnMIValueConst miValueConst2(varObj.GetValueFormatted()); + const CMICmnMIValueResult miValueResult2("value", miValueConst2); + miValueTuple.Add(miValueResult2); + lldb::SBValue &rValue = const_cast<lldb::SBValue &>(varObj.GetValue()); + const CMICmnMIValueConst miValueConst3(rValue.IsInScope() ? "true" : "false"); + const CMICmnMIValueResult miValueResult3("in_scope", miValueConst3); + miValueTuple.Add(miValueResult3); + const CMICmnMIValueConst miValueConst4("false"); + const CMICmnMIValueResult miValueResult4("type_changed", miValueConst4); + miValueTuple.Add(miValueResult4); + const CMICmnMIValueConst miValueConst5("0"); + const CMICmnMIValueResult miValueResult5("type_changed", miValueConst5); + miValueTuple.Add(miValueResult5); + const CMICmnMIValueList miValueList(miValueTuple); + const CMICmnMIValueResult miValueResult6("changelist", miValueList); + + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult6); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdVarSetFormat::CreateSelf() -{ - return new CMICmdCmdVarSetFormat(); +CMICmdBase *CMICmdCmdVarSetFormat::CreateSelf() { + return new CMICmdCmdVarSetFormat(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdVarListChildren constructor. // Type: Method. // Args: None. @@ -903,35 +924,30 @@ CMICmdCmdVarSetFormat::CreateSelf() // Throws: None. //-- CMICmdCmdVarListChildren::CMICmdCmdVarListChildren() - : m_constStrArgPrintValues("print-values") - , m_constStrArgName("name") - , m_constStrArgFrom("from") - , m_constStrArgTo("to") - , m_bValueValid(false) - , m_nChildren(0) - , m_miValueList(true) - , m_bHasMore(false) - { - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "var-list-children"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdVarListChildren::CreateSelf; + : m_constStrArgPrintValues("print-values"), m_constStrArgName("name"), + m_constStrArgFrom("from"), m_constStrArgTo("to"), m_bValueValid(false), + m_nChildren(0), m_miValueList(true), m_bHasMore(false) { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "var-list-children"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdVarListChildren::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdVarListChildren destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdVarListChildren::~CMICmdCmdVarListChildren() -{ -} +CMICmdCmdVarListChildren::~CMICmdCmdVarListChildren() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -939,121 +955,132 @@ CMICmdCmdVarListChildren::~CMICmdCmdVarListChildren() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarListChildren::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValPrintValues(m_constStrArgPrintValues, false, true)); - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true, true)); - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrom, false, true)); - m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgTo, false, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdVarListChildren::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValPrintValues(m_constStrArgPrintValues, false, true)); + m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true, true)); + m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgFrom, false, true)); + m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgTo, false, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarListChildren::Execute() -{ - CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues); - CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); - CMICMDBASE_GETOPTION(pArgFrom, Number, m_constStrArgFrom); - CMICMDBASE_GETOPTION(pArgTo, Number, m_constStrArgTo); - - CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat = CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_NoValues; - if (pArgPrintValues->GetFound()) - eVarInfoFormat = static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>(pArgPrintValues->GetValue()); - - const CMIUtilString &rVarObjName(pArgName->GetValue()); - CMICmnLLDBDebugSessionInfoVarObj varObj; - if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str())); - return MIstatus::failure; - } - - MIuint nFrom = 0; - MIuint nTo = UINT32_MAX; - if (pArgFrom->GetFound() && pArgTo->GetFound()) - { - nFrom = pArgFrom->GetValue(); - nTo = pArgTo->GetValue(); - } - else if (pArgFrom->GetFound() || pArgTo->GetFound()) - { - // Only from or to was specified but both are required - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_CHILD_RANGE_INVALID), m_cmdData.strMiCmd.c_str())); - return MIstatus::failure; - } - - lldb::SBValue &rValue = const_cast<lldb::SBValue &>(varObj.GetValue()); - m_bValueValid = rValue.IsValid(); - if (!m_bValueValid) - return MIstatus::success; +bool CMICmdCmdVarListChildren::Execute() { + CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues); + CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); + CMICMDBASE_GETOPTION(pArgFrom, Number, m_constStrArgFrom); + CMICMDBASE_GETOPTION(pArgTo, Number, m_constStrArgTo); + + CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat = + CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_NoValues; + if (pArgPrintValues->GetFound()) + eVarInfoFormat = + static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>( + pArgPrintValues->GetValue()); + + const CMIUtilString &rVarObjName(pArgName->GetValue()); + CMICmnLLDBDebugSessionInfoVarObj varObj; + if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), + m_cmdData.strMiCmd.c_str(), + rVarObjName.c_str())); + return MIstatus::failure; + } + + MIuint nFrom = 0; + MIuint nTo = UINT32_MAX; + if (pArgFrom->GetFound() && pArgTo->GetFound()) { + nFrom = pArgFrom->GetValue(); + nTo = pArgTo->GetValue(); + } else if (pArgFrom->GetFound() || pArgTo->GetFound()) { + // Only from or to was specified but both are required + SetError( + CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_CHILD_RANGE_INVALID), + m_cmdData.strMiCmd.c_str())); + return MIstatus::failure; + } + + lldb::SBValue &rValue = const_cast<lldb::SBValue &>(varObj.GetValue()); + m_bValueValid = rValue.IsValid(); + if (!m_bValueValid) + return MIstatus::success; - const MIuint nChildren = rValue.GetNumChildren(); - m_bHasMore = nTo < nChildren; - nTo = std::min(nTo, nChildren); - m_nChildren = nFrom < nTo ? nTo - nFrom : 0; - for (MIuint i = nFrom; i < nTo; i++) - { - lldb::SBValue member = rValue.GetChildAtIndex(i); - const CMICmnLLDBUtilSBValue utilValue(member); - const CMIUtilString strExp = utilValue.GetName(); - const CMIUtilString name(strExp.empty() ? - CMIUtilString::Format("%s.$%u", rVarObjName.c_str(), i) : - CMIUtilString::Format("%s.%s", rVarObjName.c_str(), strExp.c_str())); - const MIuint nChildren = member.GetNumChildren(); - const CMIUtilString strThreadId(CMIUtilString::Format("%u", member.GetThread().GetIndexID())); - - // Varobj gets added to CMICmnLLDBDebugSessionInfoVarObj static container of varObjs - CMICmnLLDBDebugSessionInfoVarObj var(strExp, name, member, rVarObjName); - - // MI print "child={name=\"%s\",exp=\"%s\",numchild=\"%d\",value=\"%s\",type=\"%s\",thread-id=\"%u\",has_more=\"%u\"}" - const CMICmnMIValueConst miValueConst(name); - const CMICmnMIValueResult miValueResult("name", miValueConst); - CMICmnMIValueTuple miValueTuple(miValueResult); - const CMICmnMIValueConst miValueConst2(strExp); - const CMICmnMIValueResult miValueResult2("exp", miValueConst2); - miValueTuple.Add(miValueResult2); - const CMIUtilString strNumChild(CMIUtilString::Format("%u", nChildren)); - const CMICmnMIValueConst miValueConst3(strNumChild); - const CMICmnMIValueResult miValueResult3("numchild", miValueConst3); - miValueTuple.Add(miValueResult3); - const CMICmnMIValueConst miValueConst5(utilValue.GetTypeNameDisplay()); - const CMICmnMIValueResult miValueResult5("type", miValueConst5); - miValueTuple.Add(miValueResult5); - const CMICmnMIValueConst miValueConst6(strThreadId); - const CMICmnMIValueResult miValueResult6("thread-id", miValueConst6); - miValueTuple.Add(miValueResult6); - // nChildren == 0 is used to check for simple values - if (eVarInfoFormat == CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_AllValues || - (eVarInfoFormat == CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_SimpleValues && nChildren == 0)) - { - const CMIUtilString strValue( - CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(member, CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural)); - const CMICmnMIValueConst miValueConst7(strValue); - const CMICmnMIValueResult miValueResult7("value", miValueConst7); - miValueTuple.Add(miValueResult7); - } - const CMICmnMIValueConst miValueConst8("0"); - const CMICmnMIValueResult miValueResult8("has_more", miValueConst8); - miValueTuple.Add(miValueResult8); - const CMICmnMIValueResult miValueResult9("child", miValueTuple); - m_miValueList.Add(miValueResult9); + const MIuint nChildren = rValue.GetNumChildren(); + m_bHasMore = nTo < nChildren; + nTo = std::min(nTo, nChildren); + m_nChildren = nFrom < nTo ? nTo - nFrom : 0; + for (MIuint i = nFrom; i < nTo; i++) { + lldb::SBValue member = rValue.GetChildAtIndex(i); + const CMICmnLLDBUtilSBValue utilValue(member); + const CMIUtilString strExp = utilValue.GetName(); + const CMIUtilString name( + strExp.empty() ? CMIUtilString::Format("%s.$%u", rVarObjName.c_str(), i) + : CMIUtilString::Format("%s.%s", rVarObjName.c_str(), + strExp.c_str())); + const MIuint nChildren = member.GetNumChildren(); + const CMIUtilString strThreadId( + CMIUtilString::Format("%u", member.GetThread().GetIndexID())); + + // Varobj gets added to CMICmnLLDBDebugSessionInfoVarObj static container of + // varObjs + CMICmnLLDBDebugSessionInfoVarObj var(strExp, name, member, rVarObjName); + + // MI print + // "child={name=\"%s\",exp=\"%s\",numchild=\"%d\",value=\"%s\",type=\"%s\",thread-id=\"%u\",has_more=\"%u\"}" + const CMICmnMIValueConst miValueConst(name); + const CMICmnMIValueResult miValueResult("name", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const CMICmnMIValueConst miValueConst2(strExp); + const CMICmnMIValueResult miValueResult2("exp", miValueConst2); + miValueTuple.Add(miValueResult2); + const CMIUtilString strNumChild(CMIUtilString::Format("%u", nChildren)); + const CMICmnMIValueConst miValueConst3(strNumChild); + const CMICmnMIValueResult miValueResult3("numchild", miValueConst3); + miValueTuple.Add(miValueResult3); + const CMICmnMIValueConst miValueConst5(utilValue.GetTypeNameDisplay()); + const CMICmnMIValueResult miValueResult5("type", miValueConst5); + miValueTuple.Add(miValueResult5); + const CMICmnMIValueConst miValueConst6(strThreadId); + const CMICmnMIValueResult miValueResult6("thread-id", miValueConst6); + miValueTuple.Add(miValueResult6); + // nChildren == 0 is used to check for simple values + if (eVarInfoFormat == + CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_AllValues || + (eVarInfoFormat == + CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_SimpleValues && + nChildren == 0)) { + const CMIUtilString strValue( + CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted( + member, CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural)); + const CMICmnMIValueConst miValueConst7(strValue); + const CMICmnMIValueResult miValueResult7("value", miValueConst7); + miValueTuple.Add(miValueResult7); } - - return MIstatus::success; + const CMICmnMIValueConst miValueConst8("0"); + const CMICmnMIValueResult miValueResult8("has_more", miValueConst8); + miValueTuple.Add(miValueResult8); + const CMICmnMIValueResult miValueResult9("child", miValueTuple); + m_miValueList.Add(miValueResult9); + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -1061,55 +1088,57 @@ CMICmdCmdVarListChildren::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarListChildren::Acknowledge() -{ - if (m_bValueValid) - { - // MI print "%s^done,numchild=\"%u\",children=[%s],has_more=\"%d\"" - const CMIUtilString strNumChild(CMIUtilString::Format("%u", m_nChildren)); - const CMICmnMIValueConst miValueConst(strNumChild); - CMICmnMIValueResult miValueResult("numchild", miValueConst); - if (m_nChildren != 0) - miValueResult.Add("children", m_miValueList); - const CMIUtilString strHasMore(m_bHasMore ? "1" : "0"); - const CMICmnMIValueConst miValueConst2(strHasMore); - miValueResult.Add("has_more", miValueConst2); - - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - - return MIstatus::success; - } - - // MI print "%s^error,msg=\"variable invalid\"" - const CMICmnMIValueConst miValueConst("variable invalid"); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); +bool CMICmdCmdVarListChildren::Acknowledge() { + if (m_bValueValid) { + // MI print "%s^done,numchild=\"%u\",children=[%s],has_more=\"%d\"" + const CMIUtilString strNumChild(CMIUtilString::Format("%u", m_nChildren)); + const CMICmnMIValueConst miValueConst(strNumChild); + CMICmnMIValueResult miValueResult("numchild", miValueConst); + if (m_nChildren != 0) + miValueResult.Add("children", m_miValueList); + const CMIUtilString strHasMore(m_bHasMore ? "1" : "0"); + const CMICmnMIValueConst miValueConst2(strHasMore); + miValueResult.Add("has_more", miValueConst2); + + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); m_miResultRecord = miRecordResult; return MIstatus::success; + } + + // MI print "%s^error,msg=\"variable invalid\"" + const CMICmnMIValueConst miValueConst("variable invalid"); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdVarListChildren::CreateSelf() -{ - return new CMICmdCmdVarListChildren(); +CMICmdBase *CMICmdCmdVarListChildren::CreateSelf() { + return new CMICmdCmdVarListChildren(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdVarEvaluateExpression constructor. // Type: Method. // Args: None. @@ -1117,30 +1146,29 @@ CMICmdCmdVarListChildren::CreateSelf() // Throws: None. //-- CMICmdCmdVarEvaluateExpression::CMICmdCmdVarEvaluateExpression() - : m_bValueValid(true) - , m_constStrArgFormatSpec("-f") - , m_constStrArgName("name") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "var-evaluate-expression"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdVarEvaluateExpression::CreateSelf; + : m_bValueValid(true), m_constStrArgFormatSpec("-f"), + m_constStrArgName("name") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "var-evaluate-expression"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdVarEvaluateExpression::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdVarEvaluateExpression destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdVarEvaluateExpression::~CMICmdCmdVarEvaluateExpression() -{ -} +CMICmdCmdVarEvaluateExpression::~CMICmdCmdVarEvaluateExpression() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -1148,50 +1176,53 @@ CMICmdCmdVarEvaluateExpression::~CMICmdCmdVarEvaluateExpression() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarEvaluateExpression::ParseArgs() -{ - m_setCmdArgs.Add( - new CMICmdArgValOptionShort(m_constStrArgFormatSpec, false, false, CMICmdArgValListBase::eArgValType_String, 1)); - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdVarEvaluateExpression::ParseArgs() { + m_setCmdArgs.Add( + new CMICmdArgValOptionShort(m_constStrArgFormatSpec, false, false, + CMICmdArgValListBase::eArgValType_String, 1)); + m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarEvaluateExpression::Execute() -{ - CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); - - const CMIUtilString &rVarObjName(pArgName->GetValue()); - CMICmnLLDBDebugSessionInfoVarObj varObj; - if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str())); - return MIstatus::failure; - } - - lldb::SBValue &rValue = const_cast<lldb::SBValue &>(varObj.GetValue()); - m_bValueValid = rValue.IsValid(); - if (!m_bValueValid) - return MIstatus::success; +bool CMICmdCmdVarEvaluateExpression::Execute() { + CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); + + const CMIUtilString &rVarObjName(pArgName->GetValue()); + CMICmnLLDBDebugSessionInfoVarObj varObj; + if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), + m_cmdData.strMiCmd.c_str(), + rVarObjName.c_str())); + return MIstatus::failure; + } + + lldb::SBValue &rValue = const_cast<lldb::SBValue &>(varObj.GetValue()); + m_bValueValid = rValue.IsValid(); + if (!m_bValueValid) + return MIstatus::success; - m_varObjName = rVarObjName; - varObj.UpdateValue(); + m_varObjName = rVarObjName; + varObj.UpdateValue(); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -1199,46 +1230,48 @@ CMICmdCmdVarEvaluateExpression::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarEvaluateExpression::Acknowledge() -{ - if (m_bValueValid) - { - CMICmnLLDBDebugSessionInfoVarObj varObj; - CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(m_varObjName, varObj); - const CMICmnMIValueConst miValueConst(varObj.GetValueFormatted()); - const CMICmnMIValueResult miValueResult("value", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - const CMICmnMIValueConst miValueConst("variable invalid"); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); +bool CMICmdCmdVarEvaluateExpression::Acknowledge() { + if (m_bValueValid) { + CMICmnLLDBDebugSessionInfoVarObj varObj; + CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(m_varObjName, varObj); + const CMICmnMIValueConst miValueConst(varObj.GetValueFormatted()); + const CMICmnMIValueResult miValueResult("value", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); m_miResultRecord = miRecordResult; return MIstatus::success; + } + + const CMICmnMIValueConst miValueConst("variable invalid"); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdVarEvaluateExpression::CreateSelf() -{ - return new CMICmdCmdVarEvaluateExpression(); +CMICmdBase *CMICmdCmdVarEvaluateExpression::CreateSelf() { + return new CMICmdCmdVarEvaluateExpression(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdVarInfoPathExpression constructor. // Type: Method. // Args: None. @@ -1246,29 +1279,28 @@ CMICmdCmdVarEvaluateExpression::CreateSelf() // Throws: None. //-- CMICmdCmdVarInfoPathExpression::CMICmdCmdVarInfoPathExpression() - : m_bValueValid(true) - , m_constStrArgName("name") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "var-info-path-expression"; - - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdVarInfoPathExpression::CreateSelf; + : m_bValueValid(true), m_constStrArgName("name") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "var-info-path-expression"; + + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdVarInfoPathExpression::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdVarInfoPathExpression destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdVarInfoPathExpression::~CMICmdCmdVarInfoPathExpression() -{ -} +CMICmdCmdVarInfoPathExpression::~CMICmdCmdVarInfoPathExpression() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -1276,84 +1308,86 @@ CMICmdCmdVarInfoPathExpression::~CMICmdCmdVarInfoPathExpression() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarInfoPathExpression::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdVarInfoPathExpression::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarInfoPathExpression::Execute() -{ - CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); - - const CMIUtilString &rVarObjName(pArgName->GetValue()); - CMICmnLLDBDebugSessionInfoVarObj varObj; - if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str())); - return MIstatus::failure; - } - - lldb::SBValue &rValue = const_cast<lldb::SBValue &>(varObj.GetValue()); - m_bValueValid = rValue.IsValid(); - if (!m_bValueValid) - return MIstatus::success; - - lldb::SBStream stream; - if (!rValue.GetExpressionPath(stream, true)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_EXPRESSIONPATH), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str())); - return MIstatus::failure; - } - - const char *pPathExpression = stream.GetData(); - if (pPathExpression == nullptr) - { - // Build expression from what we do know - m_strPathExpression = varObj.GetNameReal(); - return MIstatus::success; - } +bool CMICmdCmdVarInfoPathExpression::Execute() { + CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); + + const CMIUtilString &rVarObjName(pArgName->GetValue()); + CMICmnLLDBDebugSessionInfoVarObj varObj; + if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), + m_cmdData.strMiCmd.c_str(), + rVarObjName.c_str())); + return MIstatus::failure; + } + + lldb::SBValue &rValue = const_cast<lldb::SBValue &>(varObj.GetValue()); + m_bValueValid = rValue.IsValid(); + if (!m_bValueValid) + return MIstatus::success; - // Has LLDB returned a var signature of it's own - if (pPathExpression[0] != '$') - { - m_strPathExpression = pPathExpression; - return MIstatus::success; - } + lldb::SBStream stream; + if (!rValue.GetExpressionPath(stream, true)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_EXPRESSIONPATH), + m_cmdData.strMiCmd.c_str(), + rVarObjName.c_str())); + return MIstatus::failure; + } + const char *pPathExpression = stream.GetData(); + if (pPathExpression == nullptr) { // Build expression from what we do know - const CMIUtilString &rVarParentName(varObj.GetVarParentName()); - if (rVarParentName.empty()) - { - m_strPathExpression = varObj.GetNameReal(); - } - else - { - CMICmnLLDBDebugSessionInfoVarObj varObjParent; - if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarParentName, varObjParent)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), m_cmdData.strMiCmd.c_str(), rVarParentName.c_str())); - return MIstatus::failure; - } - m_strPathExpression = CMIUtilString::Format("%s.%s", varObjParent.GetNameReal().c_str(), varObj.GetNameReal().c_str()); - } + m_strPathExpression = varObj.GetNameReal(); + return MIstatus::success; + } + // Has LLDB returned a var signature of it's own + if (pPathExpression[0] != '$') { + m_strPathExpression = pPathExpression; return MIstatus::success; + } + + // Build expression from what we do know + const CMIUtilString &rVarParentName(varObj.GetVarParentName()); + if (rVarParentName.empty()) { + m_strPathExpression = varObj.GetNameReal(); + } else { + CMICmnLLDBDebugSessionInfoVarObj varObjParent; + if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarParentName, + varObjParent)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), + m_cmdData.strMiCmd.c_str(), + rVarParentName.c_str())); + return MIstatus::failure; + } + m_strPathExpression = + CMIUtilString::Format("%s.%s", varObjParent.GetNameReal().c_str(), + varObj.GetNameReal().c_str()); + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -1361,45 +1395,47 @@ CMICmdCmdVarInfoPathExpression::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarInfoPathExpression::Acknowledge() -{ - if (m_bValueValid) - { - const CMICmnMIValueConst miValueConst(m_strPathExpression); - const CMICmnMIValueResult miValueResult("path_expr", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - return MIstatus::success; - } - - const CMICmnMIValueConst miValueConst("variable invalid"); - const CMICmnMIValueResult miValueResult("msg", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); +bool CMICmdCmdVarInfoPathExpression::Acknowledge() { + if (m_bValueValid) { + const CMICmnMIValueConst miValueConst(m_strPathExpression); + const CMICmnMIValueResult miValueResult("path_expr", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); m_miResultRecord = miRecordResult; - return MIstatus::success; + } + + const CMICmnMIValueConst miValueConst("variable invalid"); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdVarInfoPathExpression::CreateSelf() -{ - return new CMICmdCmdVarInfoPathExpression(); +CMICmdBase *CMICmdCmdVarInfoPathExpression::CreateSelf() { + return new CMICmdCmdVarInfoPathExpression(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdVarShowAttributes constructor. // Type: Method. // Args: None. @@ -1407,28 +1443,28 @@ CMICmdCmdVarInfoPathExpression::CreateSelf() // Throws: None. //-- CMICmdCmdVarShowAttributes::CMICmdCmdVarShowAttributes() - : m_constStrArgName("name") -{ - // Command factory matches this name with that received from the stdin stream - m_strMiCmd = "var-show-attributes"; + : m_constStrArgName("name") { + // Command factory matches this name with that received from the stdin stream + m_strMiCmd = "var-show-attributes"; - // Required by the CMICmdFactory when registering *this command - m_pSelfCreatorFn = &CMICmdCmdVarShowAttributes::CreateSelf; + // Required by the CMICmdFactory when registering *this command + m_pSelfCreatorFn = &CMICmdCmdVarShowAttributes::CreateSelf; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdCmdVarShowAttributes destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdCmdVarShowAttributes::~CMICmdCmdVarShowAttributes() -{ -} +CMICmdCmdVarShowAttributes::~CMICmdCmdVarShowAttributes() {} -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The parses the command line options +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The parses the command line +// options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. @@ -1436,40 +1472,42 @@ CMICmdCmdVarShowAttributes::~CMICmdCmdVarShowAttributes() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarShowAttributes::ParseArgs() -{ - m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true)); - return ParseValidateCmdOptions(); +bool CMICmdCmdVarShowAttributes::ParseArgs() { + m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgName, true, true)); + return ParseValidateCmdOptions(); } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command does work in this function. -// The command is likely to communicate with the LLDB SBDebugger in here. +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command does work in this +// function. +// The command is likely to communicate with the LLDB SBDebugger in +// here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarShowAttributes::Execute() -{ - CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); - - const CMIUtilString &rVarObjName(pArgName->GetValue()); - CMICmnLLDBDebugSessionInfoVarObj varObj; - if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) - { - SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), m_cmdData.strMiCmd.c_str(), rVarObjName.c_str())); - return MIstatus::failure; - } - - return MIstatus::success; +bool CMICmdCmdVarShowAttributes::Execute() { + CMICMDBASE_GETOPTION(pArgName, String, m_constStrArgName); + + const CMIUtilString &rVarObjName(pArgName->GetValue()); + CMICmnLLDBDebugSessionInfoVarObj varObj; + if (!CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(rVarObjName, varObj)) { + SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_VARIABLE_DOESNOTEXIST), + m_cmdData.strMiCmd.c_str(), + rVarObjName.c_str())); + return MIstatus::failure; + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The invoker requires this function. The command prepares a MI Record Result +//++ +//------------------------------------------------------------------------------------ +// Details: The invoker requires this function. The command prepares a MI Record +// Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. @@ -1477,28 +1515,28 @@ CMICmdCmdVarShowAttributes::Execute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdCmdVarShowAttributes::Acknowledge() -{ - // MI output: "%s^done,status=\"editable\"]" - const CMICmnMIValueConst miValueConst("editable"); - const CMICmnMIValueResult miValueResult("status", miValueConst); - const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); - m_miResultRecord = miRecordResult; - - return MIstatus::success; +bool CMICmdCmdVarShowAttributes::Acknowledge() { + // MI output: "%s^done,status=\"editable\"]" + const CMICmnMIValueConst miValueConst("editable"); + const CMICmnMIValueResult miValueResult("status", miValueConst); + const CMICmnMIResultRecord miRecordResult( + m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, + miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdFactory when registering *this command. The factory +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this command. The +// factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- -CMICmdBase * -CMICmdCmdVarShowAttributes::CreateSelf() -{ - return new CMICmdCmdVarShowAttributes(); +CMICmdBase *CMICmdCmdVarShowAttributes::CreateSelf() { + return new CMICmdCmdVarShowAttributes(); } diff --git a/lldb/tools/lldb-mi/MICmdCmdVar.h b/lldb/tools/lldb-mi/MICmdCmdVar.h index a6790877346..7bf583bfd36 100644 --- a/lldb/tools/lldb-mi/MICmdCmdVar.h +++ b/lldb/tools/lldb-mi/MICmdCmdVar.h @@ -17,328 +17,333 @@ // CMICmdCmdVarInfoPathExpression interface. // CMICmdCmdVarShowAttributes interface. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands derive a new command class from the +// command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp -// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery +// For an introduction to adding a new command see +// CMICmdCmdSupportInfoMiCmdQuery // command class as an example. #pragma once // In-house headers: #include "MICmdBase.h" -#include "MICmnMIValueTuple.h" -#include "MICmnMIValueList.h" #include "MICmnLLDBDebugSessionInfo.h" #include "MICmnLLDBDebugSessionInfoVarObj.h" +#include "MICmnMIValueList.h" +#include "MICmnMIValueTuple.h" // Declarations: class CMICmnLLDBDebugSessionInfoVarObj; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "var-create". //-- -class CMICmdCmdVarCreate : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdVarCreate(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - - // Overridden: - public: - // From CMICmnBase - /* dtor */ ~CMICmdCmdVarCreate() override; - - // Methods: - private: - void CompleteSBValue(lldb::SBValue &vrwValue); - - // Attribute: - private: - CMIUtilString m_strVarName; - MIuint m_nChildren; - MIuint64 m_nThreadId; - CMIUtilString m_strType; - bool m_bValid; // True = Variable is valid, false = not valid - CMIUtilString m_strExpression; - CMIUtilString m_strValue; - const CMIUtilString m_constStrArgName; - const CMIUtilString m_constStrArgFrameAddr; - const CMIUtilString m_constStrArgExpression; +class CMICmdCmdVarCreate : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdVarCreate(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + + // Overridden: +public: + // From CMICmnBase + /* dtor */ ~CMICmdCmdVarCreate() override; + + // Methods: +private: + void CompleteSBValue(lldb::SBValue &vrwValue); + + // Attribute: +private: + CMIUtilString m_strVarName; + MIuint m_nChildren; + MIuint64 m_nThreadId; + CMIUtilString m_strType; + bool m_bValid; // True = Variable is valid, false = not valid + CMIUtilString m_strExpression; + CMIUtilString m_strValue; + const CMIUtilString m_constStrArgName; + const CMIUtilString m_constStrArgFrameAddr; + const CMIUtilString m_constStrArgExpression; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "var-update". //-- -class CMICmdCmdVarUpdate : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdVarUpdate(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - - // Overridden: - public: - // From CMICmnBase - /* dtor */ ~CMICmdCmdVarUpdate() override; - - // Methods: - private: - bool ExamineSBValueForChange(lldb::SBValue &vrwValue, bool &vrwbChanged); - void MIFormResponse(const CMIUtilString &vrStrVarName, const char *const vpValue, const CMIUtilString &vrStrScope); - - // Attribute: - private: - const CMIUtilString m_constStrArgPrintValues; - const CMIUtilString m_constStrArgName; - bool m_bValueChanged; // True = yes value changed, false = no change - CMICmnMIValueList m_miValueList; +class CMICmdCmdVarUpdate : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdVarUpdate(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + + // Overridden: +public: + // From CMICmnBase + /* dtor */ ~CMICmdCmdVarUpdate() override; + + // Methods: +private: + bool ExamineSBValueForChange(lldb::SBValue &vrwValue, bool &vrwbChanged); + void MIFormResponse(const CMIUtilString &vrStrVarName, + const char *const vpValue, + const CMIUtilString &vrStrScope); + + // Attribute: +private: + const CMIUtilString m_constStrArgPrintValues; + const CMIUtilString m_constStrArgName; + bool m_bValueChanged; // True = yes value changed, false = no change + CMICmnMIValueList m_miValueList; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "var-delete". //-- -class CMICmdCmdVarDelete : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdVarDelete(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdVarDelete() override; - - // Attribute: - private: - const CMIUtilString m_constStrArgName; +class CMICmdCmdVarDelete : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdVarDelete(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdVarDelete() override; + + // Attribute: +private: + const CMIUtilString m_constStrArgName; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "var-assign". //-- -class CMICmdCmdVarAssign : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdVarAssign(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdVarAssign() override; - - // Attributes: - private: - bool m_bOk; // True = success, false = failure - CMIUtilString m_varObjName; - const CMIUtilString m_constStrArgName; - const CMIUtilString m_constStrArgExpression; +class CMICmdCmdVarAssign : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdVarAssign(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdVarAssign() override; + + // Attributes: +private: + bool m_bOk; // True = success, false = failure + CMIUtilString m_varObjName; + const CMIUtilString m_constStrArgName; + const CMIUtilString m_constStrArgExpression; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "var-set-format". //-- -class CMICmdCmdVarSetFormat : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdVarSetFormat(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdVarSetFormat() override; - - // Attributes: - private: - CMIUtilString m_varObjName; - const CMIUtilString m_constStrArgName; - const CMIUtilString m_constStrArgFormatSpec; +class CMICmdCmdVarSetFormat : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdVarSetFormat(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdVarSetFormat() override; + + // Attributes: +private: + CMIUtilString m_varObjName; + const CMIUtilString m_constStrArgName; + const CMIUtilString m_constStrArgFormatSpec; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "var-list-children". //-- -class CMICmdCmdVarListChildren : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdVarListChildren(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdVarListChildren() override; - - // Attributes: - private: - const CMIUtilString m_constStrArgPrintValues; - const CMIUtilString m_constStrArgName; - const CMIUtilString m_constStrArgFrom; - const CMIUtilString m_constStrArgTo; - bool m_bValueValid; // True = yes SBValue object is valid, false = not valid - MIuint m_nChildren; - CMICmnMIValueList m_miValueList; - bool m_bHasMore; +class CMICmdCmdVarListChildren : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdVarListChildren(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdVarListChildren() override; + + // Attributes: +private: + const CMIUtilString m_constStrArgPrintValues; + const CMIUtilString m_constStrArgName; + const CMIUtilString m_constStrArgFrom; + const CMIUtilString m_constStrArgTo; + bool m_bValueValid; // True = yes SBValue object is valid, false = not valid + MIuint m_nChildren; + CMICmnMIValueList m_miValueList; + bool m_bHasMore; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "var-evaluate-expression". //-- -class CMICmdCmdVarEvaluateExpression : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdVarEvaluateExpression(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdVarEvaluateExpression() override; - - // Attributes: - private: - bool m_bValueValid; // True = yes SBValue object is valid, false = not valid - CMIUtilString m_varObjName; - const CMIUtilString m_constStrArgFormatSpec; // Not handled by *this command - const CMIUtilString m_constStrArgName; +class CMICmdCmdVarEvaluateExpression : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdVarEvaluateExpression(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdVarEvaluateExpression() override; + + // Attributes: +private: + bool m_bValueValid; // True = yes SBValue object is valid, false = not valid + CMIUtilString m_varObjName; + const CMIUtilString m_constStrArgFormatSpec; // Not handled by *this command + const CMIUtilString m_constStrArgName; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "var-info-path-expression". //-- -class CMICmdCmdVarInfoPathExpression : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdVarInfoPathExpression(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdVarInfoPathExpression() override; - - // Attributes: - private: - bool m_bValueValid; // True = yes SBValue object is valid, false = not valid - CMIUtilString m_strPathExpression; - const CMIUtilString m_constStrArgName; +class CMICmdCmdVarInfoPathExpression : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdVarInfoPathExpression(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdVarInfoPathExpression() override; + + // Attributes: +private: + bool m_bValueValid; // True = yes SBValue object is valid, false = not valid + CMIUtilString m_strPathExpression; + const CMIUtilString m_constStrArgName; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command class. MI commands derived from the command base class. // *this class implements MI command "var-show-attributes". //-- -class CMICmdCmdVarShowAttributes : public CMICmdBase -{ - // Statics: - public: - // Required by the CMICmdFactory when registering *this command - static CMICmdBase *CreateSelf(); - - // Methods: - public: - /* ctor */ CMICmdCmdVarShowAttributes(); - - // Overridden: - public: - // From CMICmdInvoker::ICmd - bool Execute() override; - bool Acknowledge() override; - bool ParseArgs() override; - // From CMICmnBase - /* dtor */ ~CMICmdCmdVarShowAttributes() override; - - // Attributes: - private: - const CMIUtilString m_constStrArgName; +class CMICmdCmdVarShowAttributes : public CMICmdBase { + // Statics: +public: + // Required by the CMICmdFactory when registering *this command + static CMICmdBase *CreateSelf(); + + // Methods: +public: + /* ctor */ CMICmdCmdVarShowAttributes(); + + // Overridden: +public: + // From CMICmdInvoker::ICmd + bool Execute() override; + bool Acknowledge() override; + bool ParseArgs() override; + // From CMICmnBase + /* dtor */ ~CMICmdCmdVarShowAttributes() override; + + // Attributes: +private: + const CMIUtilString m_constStrArgName; }; diff --git a/lldb/tools/lldb-mi/MICmdCommands.cpp b/lldb/tools/lldb-mi/MICmdCommands.cpp index e97cc72f077..42983c42887 100644 --- a/lldb/tools/lldb-mi/MICmdCommands.cpp +++ b/lldb/tools/lldb-mi/MICmdCommands.cpp @@ -9,8 +9,10 @@ // Overview: MI command are registered with the MI command factory. // -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands derive a new command class from the +// command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp @@ -18,7 +20,6 @@ // In-house headers: #include "MICmdCommands.h" -#include "MICmdFactory.h" #include "MICmdCmd.h" #include "MICmdCmdBreak.h" #include "MICmdCmdData.h" @@ -38,30 +39,30 @@ #include "MICmdCmdThread.h" #include "MICmdCmdTrace.h" #include "MICmdCmdVar.h" +#include "MICmdFactory.h" -namespace MICmnCommands -{ +namespace MICmnCommands { template <typename T> static bool Register(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Command to command factory registration function. // Type: Template function. // Args: typename T - A command type class. -// Return: bool - True = yes command is registered, false = command failed to register. +// Return: bool - True = yes command is registered, false = command failed to +// register. // Throws: None. //-- -template <typename T> -static bool -MICmnCommands::Register() -{ - static CMICmdFactory &rCmdFactory = CMICmdFactory::Instance(); - const CMIUtilString strMiCmd = T().GetMiCmd(); - CMICmdFactory::CmdCreatorFnPtr fn = T().GetCmdCreatorFn(); - return rCmdFactory.CmdRegister(strMiCmd, fn); +template <typename T> static bool MICmnCommands::Register() { + static CMICmdFactory &rCmdFactory = CMICmdFactory::Instance(); + const CMIUtilString strMiCmd = T().GetMiCmd(); + CMICmdFactory::CmdCreatorFnPtr fn = T().GetCmdCreatorFn(); + return rCmdFactory.CmdRegister(strMiCmd, fn); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Register commands with MI command factory // Type: Function. // Args: None. @@ -69,70 +70,68 @@ MICmnCommands::Register() // false = one or more commands failed to register. // Throws: None. //-- -bool -MICmnCommands::RegisterAll() -{ - bool bOk = MIstatus::success; +bool MICmnCommands::RegisterAll() { + bool bOk = MIstatus::success; - bOk &= Register<CMICmdCmdSupportInfoMiCmdQuery>(); - bOk &= Register<CMICmdCmdBreakAfter>(); - bOk &= Register<CMICmdCmdBreakCondition>(); - bOk &= Register<CMICmdCmdBreakDelete>(); - bOk &= Register<CMICmdCmdBreakDisable>(); - bOk &= Register<CMICmdCmdBreakEnable>(); - bOk &= Register<CMICmdCmdBreakInsert>(); - bOk &= Register<CMICmdCmdDataDisassemble>(); - bOk &= Register<CMICmdCmdDataEvaluateExpression>(); - bOk &= Register<CMICmdCmdDataInfoLine>(); - bOk &= Register<CMICmdCmdDataReadMemoryBytes>(); - bOk &= Register<CMICmdCmdDataReadMemory>(); - bOk &= Register<CMICmdCmdDataListRegisterNames>(); - bOk &= Register<CMICmdCmdDataListRegisterValues>(); - bOk &= Register<CMICmdCmdDataWriteMemory>(); - bOk &= Register<CMICmdCmdEnablePrettyPrinting>(); - bOk &= Register<CMICmdCmdEnvironmentCd>(); - bOk &= Register<CMICmdCmdExecAbort>(); - bOk &= Register<CMICmdCmdExecArguments>(); - bOk &= Register<CMICmdCmdExecContinue>(); - bOk &= Register<CMICmdCmdExecInterrupt>(); - bOk &= Register<CMICmdCmdExecFinish>(); - bOk &= Register<CMICmdCmdExecNext>(); - bOk &= Register<CMICmdCmdExecNextInstruction>(); - bOk &= Register<CMICmdCmdExecRun>(); - bOk &= Register<CMICmdCmdExecStep>(); - bOk &= Register<CMICmdCmdExecStepInstruction>(); - bOk &= Register<CMICmdCmdFileExecAndSymbols>(); - bOk &= Register<CMICmdCmdGdbExit>(); - bOk &= Register<CMICmdCmdGdbInfo>(); - bOk &= Register<CMICmdCmdGdbSet>(); - bOk &= Register<CMICmdCmdGdbShow>(); - bOk &= Register<CMICmdCmdGdbThread>(); - bOk &= Register<CMICmdCmdInferiorTtySet>(); - bOk &= Register<CMICmdCmdInterpreterExec>(); - bOk &= Register<CMICmdCmdListThreadGroups>(); - bOk &= Register<CMICmdCmdSource>(); - bOk &= Register<CMICmdCmdStackInfoDepth>(); - bOk &= Register<CMICmdCmdStackInfoFrame>(); - bOk &= Register<CMICmdCmdStackListFrames>(); - bOk &= Register<CMICmdCmdStackListArguments>(); - bOk &= Register<CMICmdCmdStackListLocals>(); - bOk &= Register<CMICmdCmdStackListVariables>(); - bOk &= Register<CMICmdCmdStackSelectFrame>(); - bOk &= Register<CMICmdCmdSupportListFeatures>(); - bOk &= Register<CMICmdCmdSymbolListLines>(); - bOk &= Register<CMICmdCmdTargetSelect>(); - bOk &= Register<CMICmdCmdTargetAttach>(); - bOk &= Register<CMICmdCmdTargetDetach>(); - bOk &= Register<CMICmdCmdThreadInfo>(); - bOk &= Register<CMICmdCmdVarAssign>(); - bOk &= Register<CMICmdCmdVarCreate>(); - bOk &= Register<CMICmdCmdVarDelete>(); - bOk &= Register<CMICmdCmdVarEvaluateExpression>(); - bOk &= Register<CMICmdCmdVarInfoPathExpression>(); - bOk &= Register<CMICmdCmdVarListChildren>(); - bOk &= Register<CMICmdCmdVarSetFormat>(); - bOk &= Register<CMICmdCmdVarShowAttributes>(); - bOk &= Register<CMICmdCmdVarUpdate>(); + bOk &= Register<CMICmdCmdSupportInfoMiCmdQuery>(); + bOk &= Register<CMICmdCmdBreakAfter>(); + bOk &= Register<CMICmdCmdBreakCondition>(); + bOk &= Register<CMICmdCmdBreakDelete>(); + bOk &= Register<CMICmdCmdBreakDisable>(); + bOk &= Register<CMICmdCmdBreakEnable>(); + bOk &= Register<CMICmdCmdBreakInsert>(); + bOk &= Register<CMICmdCmdDataDisassemble>(); + bOk &= Register<CMICmdCmdDataEvaluateExpression>(); + bOk &= Register<CMICmdCmdDataInfoLine>(); + bOk &= Register<CMICmdCmdDataReadMemoryBytes>(); + bOk &= Register<CMICmdCmdDataReadMemory>(); + bOk &= Register<CMICmdCmdDataListRegisterNames>(); + bOk &= Register<CMICmdCmdDataListRegisterValues>(); + bOk &= Register<CMICmdCmdDataWriteMemory>(); + bOk &= Register<CMICmdCmdEnablePrettyPrinting>(); + bOk &= Register<CMICmdCmdEnvironmentCd>(); + bOk &= Register<CMICmdCmdExecAbort>(); + bOk &= Register<CMICmdCmdExecArguments>(); + bOk &= Register<CMICmdCmdExecContinue>(); + bOk &= Register<CMICmdCmdExecInterrupt>(); + bOk &= Register<CMICmdCmdExecFinish>(); + bOk &= Register<CMICmdCmdExecNext>(); + bOk &= Register<CMICmdCmdExecNextInstruction>(); + bOk &= Register<CMICmdCmdExecRun>(); + bOk &= Register<CMICmdCmdExecStep>(); + bOk &= Register<CMICmdCmdExecStepInstruction>(); + bOk &= Register<CMICmdCmdFileExecAndSymbols>(); + bOk &= Register<CMICmdCmdGdbExit>(); + bOk &= Register<CMICmdCmdGdbInfo>(); + bOk &= Register<CMICmdCmdGdbSet>(); + bOk &= Register<CMICmdCmdGdbShow>(); + bOk &= Register<CMICmdCmdGdbThread>(); + bOk &= Register<CMICmdCmdInferiorTtySet>(); + bOk &= Register<CMICmdCmdInterpreterExec>(); + bOk &= Register<CMICmdCmdListThreadGroups>(); + bOk &= Register<CMICmdCmdSource>(); + bOk &= Register<CMICmdCmdStackInfoDepth>(); + bOk &= Register<CMICmdCmdStackInfoFrame>(); + bOk &= Register<CMICmdCmdStackListFrames>(); + bOk &= Register<CMICmdCmdStackListArguments>(); + bOk &= Register<CMICmdCmdStackListLocals>(); + bOk &= Register<CMICmdCmdStackListVariables>(); + bOk &= Register<CMICmdCmdStackSelectFrame>(); + bOk &= Register<CMICmdCmdSupportListFeatures>(); + bOk &= Register<CMICmdCmdSymbolListLines>(); + bOk &= Register<CMICmdCmdTargetSelect>(); + bOk &= Register<CMICmdCmdTargetAttach>(); + bOk &= Register<CMICmdCmdTargetDetach>(); + bOk &= Register<CMICmdCmdThreadInfo>(); + bOk &= Register<CMICmdCmdVarAssign>(); + bOk &= Register<CMICmdCmdVarCreate>(); + bOk &= Register<CMICmdCmdVarDelete>(); + bOk &= Register<CMICmdCmdVarEvaluateExpression>(); + bOk &= Register<CMICmdCmdVarInfoPathExpression>(); + bOk &= Register<CMICmdCmdVarListChildren>(); + bOk &= Register<CMICmdCmdVarSetFormat>(); + bOk &= Register<CMICmdCmdVarShowAttributes>(); + bOk &= Register<CMICmdCmdVarUpdate>(); - return bOk; + return bOk; } diff --git a/lldb/tools/lldb-mi/MICmdCommands.h b/lldb/tools/lldb-mi/MICmdCommands.h index 27f128ef4bd..c3f752857b8 100644 --- a/lldb/tools/lldb-mi/MICmdCommands.h +++ b/lldb/tools/lldb-mi/MICmdCommands.h @@ -9,10 +9,10 @@ #pragma once -namespace MICmnCommands -{ +namespace MICmnCommands { -//++ ============================================================================ +//++ +//============================================================================ // Details: MI Command are instantiated and registered automatically with the // Command Factory //-- diff --git a/lldb/tools/lldb-mi/MICmdData.h b/lldb/tools/lldb-mi/MICmdData.h index dcd5754617f..b0d52b5bf80 100644 --- a/lldb/tools/lldb-mi/MICmdData.h +++ b/lldb/tools/lldb-mi/MICmdData.h @@ -12,47 +12,48 @@ // In-house headers: #include "MICmnResources.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command metadata. Holds the command's name, MI number and options -// as found on stdin. Holds the command's MI output (written to stdout). +// as found on stdin. Holds the command's MI output (written to +// stdout). //-- -struct SMICmdData -{ - SMICmdData() - : id(0) - , bCmdValid(false) - , bCmdExecutedSuccessfully(false) - , bMIOldStyle(false) - , bHasResultRecordExtra(false){} +struct SMICmdData { + SMICmdData() + : id(0), bCmdValid(false), bCmdExecutedSuccessfully(false), + bMIOldStyle(false), bHasResultRecordExtra(false) {} - MIuint id; // A command's unique ID i.e. GUID - CMIUtilString strMiCmdToken; // The command's MI token (a number) - CMIUtilString strMiCmd; // The command's name - CMIUtilString strMiCmdOption; // The command's arguments or options - CMIUtilString strMiCmdAll; // The text as received from the client - CMIUtilString strMiCmdResultRecord; // Each command forms 1 response to its input - CMIUtilString strMiCmdResultRecordExtra; // Hack command produce more response text to help the client because of using LLDB - bool bCmdValid; // True = Valid MI format command, false = invalid - bool bCmdExecutedSuccessfully; // True = Command finished successfully, false = Did not start/did not complete - CMIUtilString strErrorDescription; // Command failed this is why - bool bMIOldStyle; // True = format "3thread", false = format "3-thread" - bool - bHasResultRecordExtra; // True = Yes command produced additional MI output to its 1 line response, false = no extra MI output formed + MIuint id; // A command's unique ID i.e. GUID + CMIUtilString strMiCmdToken; // The command's MI token (a number) + CMIUtilString strMiCmd; // The command's name + CMIUtilString strMiCmdOption; // The command's arguments or options + CMIUtilString strMiCmdAll; // The text as received from the client + CMIUtilString + strMiCmdResultRecord; // Each command forms 1 response to its input + CMIUtilString strMiCmdResultRecordExtra; // Hack command produce more response + // text to help the client because of + // using LLDB + bool bCmdValid; // True = Valid MI format command, false = invalid + bool bCmdExecutedSuccessfully; // True = Command finished successfully, false + // = Did not start/did not complete + CMIUtilString strErrorDescription; // Command failed this is why + bool bMIOldStyle; // True = format "3thread", false = format "3-thread" + bool bHasResultRecordExtra; // True = Yes command produced additional MI + // output to its 1 line response, false = no extra + // MI output formed - void - Clear() - { - id = 0; - strMiCmdToken.clear(); - strMiCmd = MIRSRC(IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION); - strMiCmdOption.clear(); - strMiCmdAll.clear(); - strMiCmdResultRecord.clear(); - strMiCmdResultRecordExtra.clear(); - bCmdValid = false; - bCmdExecutedSuccessfully = false; - strErrorDescription.clear(); - bMIOldStyle = false; - bHasResultRecordExtra = false; - } + void Clear() { + id = 0; + strMiCmdToken.clear(); + strMiCmd = MIRSRC(IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION); + strMiCmdOption.clear(); + strMiCmdAll.clear(); + strMiCmdResultRecord.clear(); + strMiCmdResultRecordExtra.clear(); + bCmdValid = false; + bCmdExecutedSuccessfully = false; + strErrorDescription.clear(); + bMIOldStyle = false; + bHasResultRecordExtra = false; + } }; diff --git a/lldb/tools/lldb-mi/MICmdFactory.cpp b/lldb/tools/lldb-mi/MICmdFactory.cpp index e2a8b5bc2ca..8f621546362 100644 --- a/lldb/tools/lldb-mi/MICmdFactory.cpp +++ b/lldb/tools/lldb-mi/MICmdFactory.cpp @@ -9,35 +9,33 @@ // In-house headers: #include "MICmdFactory.h" -#include "MICmnResources.h" -#include "MICmdData.h" #include "MICmdBase.h" #include "MICmdCommands.h" +#include "MICmdData.h" +#include "MICmnResources.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdFactory constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdFactory::CMICmdFactory() -{ -} +CMICmdFactory::CMICmdFactory() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdFactory destructor. // Type: Overridable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdFactory::~CMICmdFactory() -{ - Shutdown(); -} +CMICmdFactory::~CMICmdFactory() { Shutdown(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Initialize resources for *this Command factory. // Type: Method. // Args: None. @@ -45,22 +43,21 @@ CMICmdFactory::~CMICmdFactory() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmdFactory::Initialize() -{ - m_clientUsageRefCnt++; +bool CMICmdFactory::Initialize() { + m_clientUsageRefCnt++; - if (m_bInitialized) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - m_bInitialized = true; + m_bInitialized = true; - MICmnCommands::RegisterAll(); + MICmnCommands::RegisterAll(); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release resources for *this Command Factory. // Type: Method. // Args: None. @@ -68,24 +65,24 @@ CMICmdFactory::Initialize() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmdFactory::Shutdown() -{ - if (--m_clientUsageRefCnt > 0) - return MIstatus::success; +bool CMICmdFactory::Shutdown() { + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - if (!m_bInitialized) - return MIstatus::success; + if (!m_bInitialized) + return MIstatus::success; - m_mapMiCmdToCmdCreatorFn.clear(); + m_mapMiCmdToCmdCreatorFn.clear(); - m_bInitialized = false; + m_bInitialized = false; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Register a command's creator function with the command identifier the MI +//++ +//------------------------------------------------------------------------------------ +// Details: Register a command's creator function with the command identifier +// the MI // command name i.e. 'file-exec-and-symbols'. // Type: Method. // Args: vMiCmd - (R) Command's name, the MI command. @@ -94,33 +91,33 @@ CMICmdFactory::Shutdown() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmdFactory::CmdRegister(const CMIUtilString &vMiCmd, CmdCreatorFnPtr vCmdCreateFn) -{ - if (!IsValid(vMiCmd)) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMDFACTORY_ERR_INVALID_CMD_NAME), vMiCmd.c_str())); - return MIstatus::failure; - } - if (vCmdCreateFn == nullptr) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMDFACTORY_ERR_INVALID_CMD_CR8FN), vMiCmd.c_str())); - return MIstatus::failure; - } - - if (HaveAlready(vMiCmd)) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMDFACTORY_ERR_CMD_ALREADY_REGED), vMiCmd.c_str())); - return MIstatus::failure; - } - - MapPairMiCmdToCmdCreatorFn_t pr(vMiCmd, vCmdCreateFn); - m_mapMiCmdToCmdCreatorFn.insert(pr); - - return MIstatus::success; +bool CMICmdFactory::CmdRegister(const CMIUtilString &vMiCmd, + CmdCreatorFnPtr vCmdCreateFn) { + if (!IsValid(vMiCmd)) { + SetErrorDescription(CMIUtilString::Format( + MIRSRC(IDS_CMDFACTORY_ERR_INVALID_CMD_NAME), vMiCmd.c_str())); + return MIstatus::failure; + } + if (vCmdCreateFn == nullptr) { + SetErrorDescription(CMIUtilString::Format( + MIRSRC(IDS_CMDFACTORY_ERR_INVALID_CMD_CR8FN), vMiCmd.c_str())); + return MIstatus::failure; + } + + if (HaveAlready(vMiCmd)) { + SetErrorDescription(CMIUtilString::Format( + MIRSRC(IDS_CMDFACTORY_ERR_CMD_ALREADY_REGED), vMiCmd.c_str())); + return MIstatus::failure; + } + + MapPairMiCmdToCmdCreatorFn_t pr(vMiCmd, vCmdCreateFn); + m_mapMiCmdToCmdCreatorFn.insert(pr); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Check a command is already registered. // Type: Method. // Args: vMiCmd - (R) Command's name, the MI command. @@ -128,17 +125,17 @@ CMICmdFactory::CmdRegister(const CMIUtilString &vMiCmd, CmdCreatorFnPtr vCmdCrea // False - not found. // Throws: None. //-- -bool -CMICmdFactory::HaveAlready(const CMIUtilString &vMiCmd) const -{ - const MapMiCmdToCmdCreatorFn_t::const_iterator it = m_mapMiCmdToCmdCreatorFn.find(vMiCmd); - if (it != m_mapMiCmdToCmdCreatorFn.end()) - return true; +bool CMICmdFactory::HaveAlready(const CMIUtilString &vMiCmd) const { + const MapMiCmdToCmdCreatorFn_t::const_iterator it = + m_mapMiCmdToCmdCreatorFn.find(vMiCmd); + if (it != m_mapMiCmdToCmdCreatorFn.end()) + return true; - return false; + return false; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Check a command's name is valid: // - name is not empty // - name does not have spaces @@ -148,25 +145,23 @@ CMICmdFactory::HaveAlready(const CMIUtilString &vMiCmd) const // False - not valid. // Throws: None. //-- -bool -CMICmdFactory::IsValid(const CMIUtilString &vMiCmd) const -{ - bool bValid = true; - - if (vMiCmd.empty()) - { - bValid = false; - return false; - } - - const size_t nPos = vMiCmd.find(' '); - if (nPos != std::string::npos) - bValid = false; - - return bValid; +bool CMICmdFactory::IsValid(const CMIUtilString &vMiCmd) const { + bool bValid = true; + + if (vMiCmd.empty()) { + bValid = false; + return false; + } + + const size_t nPos = vMiCmd.find(' '); + if (nPos != std::string::npos) + bValid = false; + + return bValid; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Check a command is already registered. // Type: Method. // Args: vMiCmd - (R) Command's name, the MI command. @@ -174,49 +169,51 @@ CMICmdFactory::IsValid(const CMIUtilString &vMiCmd) const // False - not found. // Throws: None. //-- -bool -CMICmdFactory::CmdExist(const CMIUtilString &vMiCmd) const -{ - return HaveAlready(vMiCmd); +bool CMICmdFactory::CmdExist(const CMIUtilString &vMiCmd) const { + return HaveAlready(vMiCmd); } -//++ ------------------------------------------------------------------------------------ -// Details: Create a command given the specified MI command name. The command data object +//++ +//------------------------------------------------------------------------------------ +// Details: Create a command given the specified MI command name. The command +// data object // contains the options for the command. // Type: Method. // Args: vMiCmd - (R) Command's name, the MI command. -// vCmdData - (RW) Command's metadata status/information/result object. +// vCmdData - (RW) Command's metadata status/information/result +// object. // vpNewCmd - (W) New command instance. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmdFactory::CmdCreate(const CMIUtilString &vMiCmd, const SMICmdData &vCmdData, CMICmdBase *&vpNewCmd) -{ - vpNewCmd = nullptr; - - if (!IsValid(vMiCmd)) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMDFACTORY_ERR_INVALID_CMD_NAME), vMiCmd.c_str())); - return MIstatus::failure; - } - if (!HaveAlready(vMiCmd)) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMDFACTORY_ERR_CMD_NOT_REGISTERED), vMiCmd.c_str())); - return MIstatus::failure; - } - - const MapMiCmdToCmdCreatorFn_t::const_iterator it = m_mapMiCmdToCmdCreatorFn.find(vMiCmd); - const CMIUtilString &rMiCmd((*it).first); - MIunused(rMiCmd); - CmdCreatorFnPtr pFn = (*it).second; - CMICmdBase *pCmd = (*pFn)(); - - SMICmdData cmdData(vCmdData); - cmdData.id = pCmd->GetGUID(); - pCmd->SetCmdData(cmdData); - vpNewCmd = pCmd; - - return MIstatus::success; +bool CMICmdFactory::CmdCreate(const CMIUtilString &vMiCmd, + const SMICmdData &vCmdData, + CMICmdBase *&vpNewCmd) { + vpNewCmd = nullptr; + + if (!IsValid(vMiCmd)) { + SetErrorDescription(CMIUtilString::Format( + MIRSRC(IDS_CMDFACTORY_ERR_INVALID_CMD_NAME), vMiCmd.c_str())); + return MIstatus::failure; + } + if (!HaveAlready(vMiCmd)) { + SetErrorDescription(CMIUtilString::Format( + MIRSRC(IDS_CMDFACTORY_ERR_CMD_NOT_REGISTERED), vMiCmd.c_str())); + return MIstatus::failure; + } + + const MapMiCmdToCmdCreatorFn_t::const_iterator it = + m_mapMiCmdToCmdCreatorFn.find(vMiCmd); + const CMIUtilString &rMiCmd((*it).first); + MIunused(rMiCmd); + CmdCreatorFnPtr pFn = (*it).second; + CMICmdBase *pCmd = (*pFn)(); + + SMICmdData cmdData(vCmdData); + cmdData.id = pCmd->GetGUID(); + pCmd->SetCmdData(cmdData); + vpNewCmd = pCmd; + + return MIstatus::success; } diff --git a/lldb/tools/lldb-mi/MICmdFactory.h b/lldb/tools/lldb-mi/MICmdFactory.h index 99f6f0cb239..6d8a759ec67 100644 --- a/lldb/tools/lldb-mi/MICmdFactory.h +++ b/lldb/tools/lldb-mi/MICmdFactory.h @@ -20,64 +20,66 @@ class CMICmdBase; struct SMICmdData; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI Command Factory. Holds a list of registered MI commands that // MI application understands to interpret. Creates commands objects. // The Command Factory is carried out in the main thread. // A singleton class. //-- -class CMICmdFactory : public CMICmnBase, public MI::ISingleton<CMICmdFactory> -{ - friend class MI::ISingleton<CMICmdFactory>; +class CMICmdFactory : public CMICmnBase, public MI::ISingleton<CMICmdFactory> { + friend class MI::ISingleton<CMICmdFactory>; - // Typedefs: - public: - typedef CMICmdBase *(*CmdCreatorFnPtr)(); + // Typedefs: +public: + typedef CMICmdBase *(*CmdCreatorFnPtr)(); - // Class: + // Class: +public: + //++ + // Description: Command's factory's interface for commands to implement. + //-- + class ICmd { public: - //++ - // Description: Command's factory's interface for commands to implement. - //-- - class ICmd - { - public: - virtual const CMIUtilString &GetMiCmd() const = 0; - virtual CmdCreatorFnPtr GetCmdCreatorFn() const = 0; - // virtual CMICmdBase * CreateSelf( void ) = 0; // Not possible as require a static creator - // function in the command class, here for awareness + virtual const CMIUtilString &GetMiCmd() const = 0; + virtual CmdCreatorFnPtr GetCmdCreatorFn() const = 0; + // virtual CMICmdBase * CreateSelf( void ) = 0; // Not + // possible as require a static creator + // function in the command class, here for awareness - /* dtor */ virtual ~ICmd(){} - }; + /* dtor */ virtual ~ICmd() {} + }; - // Methods: - public: - bool Initialize() override; - bool Shutdown() override; - bool CmdRegister(const CMIUtilString &vMiCmd, CmdCreatorFnPtr vCmdCreateFn); - bool CmdCreate(const CMIUtilString &vMiCmd, const SMICmdData &vCmdData, CMICmdBase *&vpNewCmd); - bool CmdExist(const CMIUtilString &vMiCmd) const; + // Methods: +public: + bool Initialize() override; + bool Shutdown() override; + bool CmdRegister(const CMIUtilString &vMiCmd, CmdCreatorFnPtr vCmdCreateFn); + bool CmdCreate(const CMIUtilString &vMiCmd, const SMICmdData &vCmdData, + CMICmdBase *&vpNewCmd); + bool CmdExist(const CMIUtilString &vMiCmd) const; - // Methods: - private: - /* ctor */ CMICmdFactory(); - /* ctor */ CMICmdFactory(const CMICmdFactory &); - void operator=(const CMICmdFactory &); + // Methods: +private: + /* ctor */ CMICmdFactory(); + /* ctor */ CMICmdFactory(const CMICmdFactory &); + void operator=(const CMICmdFactory &); - bool HaveAlready(const CMIUtilString &vMiCmd) const; - bool IsValid(const CMIUtilString &vMiCmd) const; + bool HaveAlready(const CMIUtilString &vMiCmd) const; + bool IsValid(const CMIUtilString &vMiCmd) const; - // Overridden: - private: - // From CMICmnBase - /* dtor */ ~CMICmdFactory() override; + // Overridden: +private: + // From CMICmnBase + /* dtor */ ~CMICmdFactory() override; - // Typedefs: - private: - typedef std::map<CMIUtilString, CmdCreatorFnPtr> MapMiCmdToCmdCreatorFn_t; - typedef std::pair<CMIUtilString, CmdCreatorFnPtr> MapPairMiCmdToCmdCreatorFn_t; + // Typedefs: +private: + typedef std::map<CMIUtilString, CmdCreatorFnPtr> MapMiCmdToCmdCreatorFn_t; + typedef std::pair<CMIUtilString, CmdCreatorFnPtr> + MapPairMiCmdToCmdCreatorFn_t; - // Attributes: - private: - MapMiCmdToCmdCreatorFn_t m_mapMiCmdToCmdCreatorFn; + // Attributes: +private: + MapMiCmdToCmdCreatorFn_t m_mapMiCmdToCmdCreatorFn; }; diff --git a/lldb/tools/lldb-mi/MICmdInterpreter.cpp b/lldb/tools/lldb-mi/MICmdInterpreter.cpp index 1abcc9a3f42..8dd99ed5e67 100644 --- a/lldb/tools/lldb-mi/MICmdInterpreter.cpp +++ b/lldb/tools/lldb-mi/MICmdInterpreter.cpp @@ -11,7 +11,8 @@ #include "MICmdInterpreter.h" #include "MICmdFactory.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdInterpreter constructor. // Type: Method. // Args: None. @@ -19,23 +20,20 @@ // Throws: None. //-- CMICmdInterpreter::CMICmdInterpreter() - : m_rCmdFactory(CMICmdFactory::Instance()) -{ -} + : m_rCmdFactory(CMICmdFactory::Instance()) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdInterpreter destructor. // Type: Overridable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdInterpreter::~CMICmdInterpreter() -{ - Shutdown(); -} +CMICmdInterpreter::~CMICmdInterpreter() { Shutdown(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Initialize resources for *this Command Interpreter. // Type: Method. // Args: None. @@ -43,20 +41,19 @@ CMICmdInterpreter::~CMICmdInterpreter() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdInterpreter::Initialize() -{ - m_clientUsageRefCnt++; +bool CMICmdInterpreter::Initialize() { + m_clientUsageRefCnt++; - if (m_bInitialized) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - m_bInitialized = true; + m_bInitialized = true; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release resources for *this Command Interpreter. // Type: Method. // Args: None. @@ -64,147 +61,157 @@ CMICmdInterpreter::Initialize() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdInterpreter::Shutdown() -{ - if (--m_clientUsageRefCnt > 0) - return MIstatus::success; +bool CMICmdInterpreter::Shutdown() { + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - if (!m_bInitialized) - return MIstatus::success; + if (!m_bInitialized) + return MIstatus::success; - m_bInitialized = false; + m_bInitialized = false; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Establish whether the text data is an MI format type command. // Type: Method. // Args: vTextLine - (R) Text data to interpret. -// vwbYesValid - (W) True = MI type command, false = not recognised. -// vwbCmdNotInCmdFactor - (W) True = MI command not found in the command factory, false = recognised. +// vwbYesValid - (W) True = MI type command, false = not +// recognised. +// vwbCmdNotInCmdFactor - (W) True = MI command not found in the +// command factory, false = recognised. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdInterpreter::ValidateIsMi(const CMIUtilString &vTextLine, bool &vwbYesValid, bool &vwbCmdNotInCmdFactor, SMICmdData &rwCmdData) -{ - vwbYesValid = false; - vwbCmdNotInCmdFactor = false; - rwCmdData.Clear(); - - if (vTextLine.empty()) - return MIstatus::success; - - // MI format is [cmd #]-[command name]<space>[command arg(s)] - // i.e. 1-file-exec-and-symbols --thread-group i1 DEVICE_EXECUTABLE - // 5-data-evaluate-expression --thread 1 --frame 0 *(argv) - - m_miCmdData.Clear(); - m_miCmdData.strMiCmd = vTextLine; - - // The following change m_miCmdData as valid parts are identified - vwbYesValid = (MiHasCmdTokenEndingHyphen(vTextLine) || MiHasCmdTokenEndingAlpha(vTextLine)); - vwbYesValid = vwbYesValid && MiHasCmd(vTextLine); - if (vwbYesValid) - { - vwbCmdNotInCmdFactor = !HasCmdFactoryGotMiCmd(MiGetCmdData()); - vwbYesValid = !vwbCmdNotInCmdFactor; - } +bool CMICmdInterpreter::ValidateIsMi(const CMIUtilString &vTextLine, + bool &vwbYesValid, + bool &vwbCmdNotInCmdFactor, + SMICmdData &rwCmdData) { + vwbYesValid = false; + vwbCmdNotInCmdFactor = false; + rwCmdData.Clear(); + + if (vTextLine.empty()) + return MIstatus::success; - // Update command's meta data valid state - m_miCmdData.bCmdValid = vwbYesValid; + // MI format is [cmd #]-[command name]<space>[command arg(s)] + // i.e. 1-file-exec-and-symbols --thread-group i1 DEVICE_EXECUTABLE + // 5-data-evaluate-expression --thread 1 --frame 0 *(argv) - // Ok to return new updated command information - rwCmdData = MiGetCmdData(); + m_miCmdData.Clear(); + m_miCmdData.strMiCmd = vTextLine; - return MIstatus::success; + // The following change m_miCmdData as valid parts are identified + vwbYesValid = (MiHasCmdTokenEndingHyphen(vTextLine) || + MiHasCmdTokenEndingAlpha(vTextLine)); + vwbYesValid = vwbYesValid && MiHasCmd(vTextLine); + if (vwbYesValid) { + vwbCmdNotInCmdFactor = !HasCmdFactoryGotMiCmd(MiGetCmdData()); + vwbYesValid = !vwbCmdNotInCmdFactor; + } + + // Update command's meta data valid state + m_miCmdData.bCmdValid = vwbYesValid; + + // Ok to return new updated command information + rwCmdData = MiGetCmdData(); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Establish whether the command name entered on the stdin stream is recognised by +//++ +//------------------------------------------------------------------------------------ +// Details: Establish whether the command name entered on the stdin stream is +// recognised by // the MI driver. // Type: Method. // Args: vCmd - (R) Command information structure. -// Return: bool - True = yes command is recognised, false = command not recognised. +// Return: bool - True = yes command is recognised, false = command not +// recognised. // Throws: None. //-- -bool -CMICmdInterpreter::HasCmdFactoryGotMiCmd(const SMICmdData &vCmd) const -{ - return m_rCmdFactory.CmdExist(vCmd.strMiCmd); +bool CMICmdInterpreter::HasCmdFactoryGotMiCmd(const SMICmdData &vCmd) const { + return m_rCmdFactory.CmdExist(vCmd.strMiCmd); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Does the command entered match the criteria for a MI command format. -// The format to validate against is 'nn-' where there can be 1 to n digits. +// The format to validate against is 'nn-' where there can be 1 to n +// digits. // I.e. '2-gdb-exit'. -// Is the execution token present? The command token is entered into the -// command meta data structure whether correct or not for reporting or later +// Is the execution token present? The command token is entered into +// the +// command meta data structure whether correct or not for reporting or +// later // command execution purposes. // Type: Method. // Args: vTextLine - (R) Text data to interpret. -// Return: bool - True = yes command token present, false = command not recognised. +// Return: bool - True = yes command token present, false = command not +// recognised. // Throws: None. //-- -bool -CMICmdInterpreter::MiHasCmdTokenEndingHyphen(const CMIUtilString &vTextLine) -{ - // The hyphen is mandatory - const size_t nPos = vTextLine.find('-', 0); - if ((nPos == std::string::npos)) - return false; - - if (MiHasCmdTokenPresent(vTextLine)) - { - const std::string strNum = vTextLine.substr(0, nPos); - if (!CMIUtilString(strNum).IsNumber()) - return false; - - m_miCmdData.strMiCmdToken = strNum; - } +bool CMICmdInterpreter::MiHasCmdTokenEndingHyphen( + const CMIUtilString &vTextLine) { + // The hyphen is mandatory + const size_t nPos = vTextLine.find('-', 0); + if ((nPos == std::string::npos)) + return false; + + if (MiHasCmdTokenPresent(vTextLine)) { + const std::string strNum = vTextLine.substr(0, nPos); + if (!CMIUtilString(strNum).IsNumber()) + return false; - m_miCmdData.bMIOldStyle = false; + m_miCmdData.strMiCmdToken = strNum; + } - return true; + m_miCmdData.bMIOldStyle = false; + + return true; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Does the command entered match the criteria for a MI command format. -// The format to validate against is 'nnA' where there can be 1 to n digits. +// The format to validate against is 'nnA' where there can be 1 to n +// digits. // 'A' represents any non numeric token. I.e. '1source .gdbinit'. -// Is the execution token present? The command token is entered into the -// command meta data structure whether correct or not for reporting or later +// Is the execution token present? The command token is entered into +// the +// command meta data structure whether correct or not for reporting or +// later // command execution purposes. // Type: Method. // Args: vTextLine - (R) Text data to interpret. -// Return: bool - True = yes command token present, false = command not recognised. +// Return: bool - True = yes command token present, false = command not +// recognised. // Throws: None. //-- -bool -CMICmdInterpreter::MiHasCmdTokenEndingAlpha(const CMIUtilString &vTextLine) -{ - char cChar = vTextLine[0]; - MIuint i = 0; - while (::isdigit(cChar) != 0) - { - cChar = vTextLine[++i]; - } - if (::isalpha(cChar) == 0) - return false; - if (i == 0) - return false; - - const std::string strNum = vTextLine.substr(0, i); - m_miCmdData.strMiCmdToken = strNum.c_str(); - m_miCmdData.bMIOldStyle = true; - - return true; +bool CMICmdInterpreter::MiHasCmdTokenEndingAlpha( + const CMIUtilString &vTextLine) { + char cChar = vTextLine[0]; + MIuint i = 0; + while (::isdigit(cChar) != 0) { + cChar = vTextLine[++i]; + } + if (::isalpha(cChar) == 0) + return false; + if (i == 0) + return false; + + const std::string strNum = vTextLine.substr(0, i); + m_miCmdData.strMiCmdToken = strNum.c_str(); + m_miCmdData.bMIOldStyle = true; + + return true; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Does the command entered match the criteria for a MI command format. // Is the command token present before the hyphen? // Type: Method. @@ -212,86 +219,84 @@ CMICmdInterpreter::MiHasCmdTokenEndingAlpha(const CMIUtilString &vTextLine) // Return: bool - True = yes command token present, false = token not present. // Throws: None. //-- -bool -CMICmdInterpreter::MiHasCmdTokenPresent(const CMIUtilString &vTextLine) -{ - const size_t nPos = vTextLine.find('-', 0); - return (nPos > 0); +bool CMICmdInterpreter::MiHasCmdTokenPresent(const CMIUtilString &vTextLine) { + const size_t nPos = vTextLine.find('-', 0); + return (nPos > 0); } -//++ ------------------------------------------------------------------------------------ -// Details: Does the command name entered match the criteria for a MI command format. -// Is a recognised command present? The command name is entered into the -// command meta data structure whether correct or not for reporting or later -// command execution purposes. Command options is present are also put into the +//++ +//------------------------------------------------------------------------------------ +// Details: Does the command name entered match the criteria for a MI command +// format. +// Is a recognised command present? The command name is entered into +// the +// command meta data structure whether correct or not for reporting or +// later +// command execution purposes. Command options is present are also put +// into the // command meta data structure. // Type: Method. // Args: vTextLine - (R) Command information structure. -// Return: bool - True = yes command name present, false = command not recognised. +// Return: bool - True = yes command name present, false = command not +// recognised. // Throws: None. //-- -bool -CMICmdInterpreter::MiHasCmd(const CMIUtilString &vTextLine) -{ - size_t nPos = 0; - if (m_miCmdData.bMIOldStyle) - { - char cChar = vTextLine[0]; - size_t i = 0; - while (::isdigit(cChar) != 0) - { - cChar = vTextLine[++i]; - } - nPos = --i; - } - else - { - nPos = vTextLine.find('-', 0); - } - - bool bFoundCmd = false; - const size_t nLen = vTextLine.length(); - const size_t nPos2 = vTextLine.find(' ', nPos); - if (nPos2 != std::string::npos) - { - if (nPos2 == nLen) - return false; - const CMIUtilString cmd = CMIUtilString(vTextLine.substr(nPos + 1, nPos2 - nPos - 1)); - if (cmd.empty()) - return false; - - m_miCmdData.strMiCmd = cmd; - - if (nPos2 < nLen) - m_miCmdData.strMiCmdOption = CMIUtilString(vTextLine.substr(nPos2 + 1, nLen - nPos2 - 1)); - - bFoundCmd = true; - } - else - { - const CMIUtilString cmd = CMIUtilString(vTextLine.substr(nPos + 1, nLen - nPos - 1)); - if (cmd.empty()) - return false; - m_miCmdData.strMiCmd = cmd; - bFoundCmd = true; +bool CMICmdInterpreter::MiHasCmd(const CMIUtilString &vTextLine) { + size_t nPos = 0; + if (m_miCmdData.bMIOldStyle) { + char cChar = vTextLine[0]; + size_t i = 0; + while (::isdigit(cChar) != 0) { + cChar = vTextLine[++i]; } - - if (bFoundCmd) - m_miCmdData.strMiCmdAll = vTextLine; - - return bFoundCmd; + nPos = --i; + } else { + nPos = vTextLine.find('-', 0); + } + + bool bFoundCmd = false; + const size_t nLen = vTextLine.length(); + const size_t nPos2 = vTextLine.find(' ', nPos); + if (nPos2 != std::string::npos) { + if (nPos2 == nLen) + return false; + const CMIUtilString cmd = + CMIUtilString(vTextLine.substr(nPos + 1, nPos2 - nPos - 1)); + if (cmd.empty()) + return false; + + m_miCmdData.strMiCmd = cmd; + + if (nPos2 < nLen) + m_miCmdData.strMiCmdOption = + CMIUtilString(vTextLine.substr(nPos2 + 1, nLen - nPos2 - 1)); + + bFoundCmd = true; + } else { + const CMIUtilString cmd = + CMIUtilString(vTextLine.substr(nPos + 1, nLen - nPos - 1)); + if (cmd.empty()) + return false; + m_miCmdData.strMiCmd = cmd; + bFoundCmd = true; + } + + if (bFoundCmd) + m_miCmdData.strMiCmdAll = vTextLine; + + return bFoundCmd; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the just entered new command from stdin. It contains the command +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the just entered new command from stdin. It contains the +// command // name, number and any options. // Type: Method. // Args: vTextLine - (R) Command information structure. // Return: SMICmdData & - Command meta data information/result/status. // Throws: None. //-- -const SMICmdData & -CMICmdInterpreter::MiGetCmdData() const -{ - return m_miCmdData; +const SMICmdData &CMICmdInterpreter::MiGetCmdData() const { + return m_miCmdData; } diff --git a/lldb/tools/lldb-mi/MICmdInterpreter.h b/lldb/tools/lldb-mi/MICmdInterpreter.h index 5aa9445c97c..948e7515d52 100644 --- a/lldb/tools/lldb-mi/MICmdInterpreter.h +++ b/lldb/tools/lldb-mi/MICmdInterpreter.h @@ -10,52 +10,54 @@ #pragma once // In-house headers: -#include "MICmnBase.h" #include "MICmdData.h" +#include "MICmnBase.h" #include "MIUtilSingletonBase.h" // Declarations: class CMICmdFactory; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command interpreter. It takes text data from the MI driver // (which got it from Stdin singleton) and validate the text to see if // matches Machine Interface (MI) format and commands defined in the // MI application. // A singleton class. //-- -class CMICmdInterpreter : public CMICmnBase, public MI::ISingleton<CMICmdInterpreter> -{ - friend MI::ISingleton<CMICmdInterpreter>; - - // Methods: - public: - // Methods: - public: - bool Initialize() override; - bool Shutdown() override; - bool ValidateIsMi(const CMIUtilString &vTextLine, bool &vwbYesValid, bool &vwbCmdNotInCmdFactor, SMICmdData &rwCmdData); - - // Methods: - private: - /* ctor */ CMICmdInterpreter(); - /* ctor */ CMICmdInterpreter(const CMICmdInterpreter &); - void operator=(const CMICmdInterpreter &); - - bool HasCmdFactoryGotMiCmd(const SMICmdData &vCmdData) const; - bool MiHasCmdTokenEndingHyphen(const CMIUtilString &vTextLine); - bool MiHasCmdTokenEndingAlpha(const CMIUtilString &vTextLine); - bool MiHasCmd(const CMIUtilString &vTextLine); - bool MiHasCmdTokenPresent(const CMIUtilString &vTextLine); - const SMICmdData &MiGetCmdData() const; - - // Overridden: - private: - // From CMICmnBase - /* dtor */ ~CMICmdInterpreter() override; - - // Attributes: - private: - SMICmdData m_miCmdData; // Filled in on each new line being interpreted - CMICmdFactory &m_rCmdFactory; +class CMICmdInterpreter : public CMICmnBase, + public MI::ISingleton<CMICmdInterpreter> { + friend MI::ISingleton<CMICmdInterpreter>; + + // Methods: +public: + // Methods: +public: + bool Initialize() override; + bool Shutdown() override; + bool ValidateIsMi(const CMIUtilString &vTextLine, bool &vwbYesValid, + bool &vwbCmdNotInCmdFactor, SMICmdData &rwCmdData); + + // Methods: +private: + /* ctor */ CMICmdInterpreter(); + /* ctor */ CMICmdInterpreter(const CMICmdInterpreter &); + void operator=(const CMICmdInterpreter &); + + bool HasCmdFactoryGotMiCmd(const SMICmdData &vCmdData) const; + bool MiHasCmdTokenEndingHyphen(const CMIUtilString &vTextLine); + bool MiHasCmdTokenEndingAlpha(const CMIUtilString &vTextLine); + bool MiHasCmd(const CMIUtilString &vTextLine); + bool MiHasCmdTokenPresent(const CMIUtilString &vTextLine); + const SMICmdData &MiGetCmdData() const; + + // Overridden: +private: + // From CMICmnBase + /* dtor */ ~CMICmdInterpreter() override; + + // Attributes: +private: + SMICmdData m_miCmdData; // Filled in on each new line being interpreted + CMICmdFactory &m_rCmdFactory; }; diff --git a/lldb/tools/lldb-mi/MICmdInvoker.cpp b/lldb/tools/lldb-mi/MICmdInvoker.cpp index 124a82d162e..ea7116dd688 100644 --- a/lldb/tools/lldb-mi/MICmdInvoker.cpp +++ b/lldb/tools/lldb-mi/MICmdInvoker.cpp @@ -15,31 +15,28 @@ #include "MICmnStreamStdout.h" #include "MIDriver.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdInvoker constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmdInvoker::CMICmdInvoker() - : m_rStreamOut(CMICmnStreamStdout::Instance()) -{ -} +CMICmdInvoker::CMICmdInvoker() : m_rStreamOut(CMICmnStreamStdout::Instance()) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdInvoker destructor. // Type: Overridable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdInvoker::~CMICmdInvoker() -{ - Shutdown(); -} +CMICmdInvoker::~CMICmdInvoker() { Shutdown(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Initialize resources for *this Command Invoker. // Type: Method. // Args: None. @@ -47,20 +44,19 @@ CMICmdInvoker::~CMICmdInvoker() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdInvoker::Initialize() -{ - m_clientUsageRefCnt++; +bool CMICmdInvoker::Initialize() { + m_clientUsageRefCnt++; - if (m_bInitialized) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - m_bInitialized = true; + m_bInitialized = true; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release resources for *this Stdin stream. // Type: Method. // Args: None. @@ -68,115 +64,114 @@ CMICmdInvoker::Initialize() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdInvoker::Shutdown() -{ - if (--m_clientUsageRefCnt > 0) - return MIstatus::success; +bool CMICmdInvoker::Shutdown() { + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - if (!m_bInitialized) - return MIstatus::success; + if (!m_bInitialized) + return MIstatus::success; - CmdDeleteAll(); + CmdDeleteAll(); - m_bInitialized = false; + m_bInitialized = false; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Empty the map of invoked commands doing work. Command objects are deleted too. +//++ +//------------------------------------------------------------------------------------ +// Details: Empty the map of invoked commands doing work. Command objects are +// deleted too. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -void -CMICmdInvoker::CmdDeleteAll() -{ - CMICmdMgr &rMgr = CMICmdMgr::Instance(); - MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.begin(); - while (it != m_mapCmdIdToCmd.end()) - { - const MIuint cmdId((*it).first); - MIunused(cmdId); - CMICmdBase *pCmd = (*it).second; - const CMIUtilString &rCmdName(pCmd->GetCmdData().strMiCmd); - MIunused(rCmdName); - rMgr.CmdDelete(pCmd->GetCmdData()); - - // Next - ++it; - } - m_mapCmdIdToCmd.clear(); +void CMICmdInvoker::CmdDeleteAll() { + CMICmdMgr &rMgr = CMICmdMgr::Instance(); + MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.begin(); + while (it != m_mapCmdIdToCmd.end()) { + const MIuint cmdId((*it).first); + MIunused(cmdId); + CMICmdBase *pCmd = (*it).second; + const CMIUtilString &rCmdName(pCmd->GetCmdData().strMiCmd); + MIunused(rCmdName); + rMgr.CmdDelete(pCmd->GetCmdData()); + + // Next + ++it; + } + m_mapCmdIdToCmd.clear(); } -//++ ------------------------------------------------------------------------------------ -// Details: Remove from the map of invoked commands doing work a command that has finished +//++ +//------------------------------------------------------------------------------------ +// Details: Remove from the map of invoked commands doing work a command that +// has finished // its work. The command object is deleted too. // Type: Method. // Args: vId - (R) Command object's unique ID. -// vbYesDeleteCmd - (R) True = Delete command object, false = delete via the Command Manager. +// vbYesDeleteCmd - (R) True = Delete command object, false = delete +// via the Command Manager. // Return: None. // Throws: None. //-- -bool -CMICmdInvoker::CmdDelete(const MIuint vId, const bool vbYesDeleteCmd /*= false*/) -{ - CMICmdMgr &rMgr = CMICmdMgr::Instance(); - MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.find(vId); - if (it != m_mapCmdIdToCmd.end()) - { - CMICmdBase *pCmd = (*it).second; - if (vbYesDeleteCmd) - { - // Via registered interest command manager callback *this object to delete the command - m_mapCmdIdToCmd.erase(it); - delete pCmd; - } - else - // Notify other interested object of this command's pending deletion - rMgr.CmdDelete(pCmd->GetCmdData()); - } - - if (m_mapCmdIdToCmd.empty()) - rMgr.CmdUnregisterForDeleteNotification(*this); - - return MIstatus::success; +bool CMICmdInvoker::CmdDelete(const MIuint vId, + const bool vbYesDeleteCmd /*= false*/) { + CMICmdMgr &rMgr = CMICmdMgr::Instance(); + MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.find(vId); + if (it != m_mapCmdIdToCmd.end()) { + CMICmdBase *pCmd = (*it).second; + if (vbYesDeleteCmd) { + // Via registered interest command manager callback *this object to delete + // the command + m_mapCmdIdToCmd.erase(it); + delete pCmd; + } else + // Notify other interested object of this command's pending deletion + rMgr.CmdDelete(pCmd->GetCmdData()); + } + + if (m_mapCmdIdToCmd.empty()) + rMgr.CmdUnregisterForDeleteNotification(*this); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Add to the map of invoked commands doing work a command that is about to +//++ +//------------------------------------------------------------------------------------ +// Details: Add to the map of invoked commands doing work a command that is +// about to // start to do work. // Type: Method. // Args: vCmd - (R) Command object. // Return: None. // Throws: None. //-- -bool -CMICmdInvoker::CmdAdd(const CMICmdBase &vCmd) -{ - if (m_mapCmdIdToCmd.empty()) - { - CMICmdMgr &rMgr = CMICmdMgr::Instance(); - rMgr.CmdRegisterForDeleteNotification(*this); - } +bool CMICmdInvoker::CmdAdd(const CMICmdBase &vCmd) { + if (m_mapCmdIdToCmd.empty()) { + CMICmdMgr &rMgr = CMICmdMgr::Instance(); + rMgr.CmdRegisterForDeleteNotification(*this); + } - const MIuint &cmdId(vCmd.GetCmdData().id); - MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.find(cmdId); - if (it != m_mapCmdIdToCmd.end()) - return MIstatus::success; + const MIuint &cmdId(vCmd.GetCmdData().id); + MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.find(cmdId); + if (it != m_mapCmdIdToCmd.end()) + return MIstatus::success; - MapPairCmdIdToCmd_t pr(cmdId, const_cast<CMICmdBase *>(&vCmd)); - m_mapCmdIdToCmd.insert(pr); + MapPairCmdIdToCmd_t pr(cmdId, const_cast<CMICmdBase *>(&vCmd)); + m_mapCmdIdToCmd.insert(pr); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Having previously had the potential command validated and found valid now +//++ +//------------------------------------------------------------------------------------ +// Details: Having previously had the potential command validated and found +// valid now // get the command executed. -// If the Functionality returns MIstatus::failure call GetErrorDescription(). +// If the Functionality returns MIstatus::failure call +// GetErrorDescription(). // This function is used by the application's main thread. // Type: Method. // Args: vCmd - (RW) Command object. @@ -184,49 +179,49 @@ CMICmdInvoker::CmdAdd(const CMICmdBase &vCmd) // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmdInvoker::CmdExecute(CMICmdBase &vCmd) -{ - bool bOk = CmdAdd(vCmd); - - if (bOk) - { - vCmd.AddCommonArgs(); - if (!vCmd.ParseArgs()) - { - // Report command execution failed - const SMICmdData cmdData(vCmd.GetCmdData()); - CmdStdout(cmdData); - CmdCauseAppExit(vCmd); - CmdDelete(cmdData.id); - - // Proceed to wait or execute next command - return MIstatus::success; - } +bool CMICmdInvoker::CmdExecute(CMICmdBase &vCmd) { + bool bOk = CmdAdd(vCmd); + + if (bOk) { + vCmd.AddCommonArgs(); + if (!vCmd.ParseArgs()) { + // Report command execution failed + const SMICmdData cmdData(vCmd.GetCmdData()); + CmdStdout(cmdData); + CmdCauseAppExit(vCmd); + CmdDelete(cmdData.id); + + // Proceed to wait or execute next command + return MIstatus::success; } + } - if (bOk && !vCmd.Execute()) - { - // Report command execution failed - const SMICmdData cmdData(vCmd.GetCmdData()); - CmdStdout(cmdData); - CmdCauseAppExit(vCmd); - CmdDelete(cmdData.id); + if (bOk && !vCmd.Execute()) { + // Report command execution failed + const SMICmdData cmdData(vCmd.GetCmdData()); + CmdStdout(cmdData); + CmdCauseAppExit(vCmd); + CmdDelete(cmdData.id); - // Proceed to wait or execute next command - return MIstatus::success; - } + // Proceed to wait or execute next command + return MIstatus::success; + } - bOk = CmdExecuteFinished(vCmd); + bOk = CmdExecuteFinished(vCmd); - return bOk; + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Called when a command has finished its Execution() work either synchronously -// because the command executed was the type a non event type or asynchronously -// via the command's callback (because of an SB Listener event). Needs to be called -// so that *this invoker call do some house keeping and then proceed to call +//++ +//------------------------------------------------------------------------------------ +// Details: Called when a command has finished its Execution() work either +// synchronously +// because the command executed was the type a non event type or +// asynchronously +// via the command's callback (because of an SB Listener event). Needs +// to be called +// so that *this invoker call do some house keeping and then proceed to +// call // the command's Acknowledge() function. // Type: Method. // Args: vCmd - (R) Command object. @@ -234,67 +229,69 @@ CMICmdInvoker::CmdExecute(CMICmdBase &vCmd) // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmdInvoker::CmdExecuteFinished(CMICmdBase &vCmd) -{ - // Command finished now get the command to gather it's information and form the MI - // Result record - if (!vCmd.Acknowledge()) - { - // Report command acknowledge functionality failed - const SMICmdData cmdData(vCmd.GetCmdData()); - CmdStdout(cmdData); - CmdCauseAppExit(vCmd); - CmdDelete(cmdData.id); - - // Proceed to wait or execute next command - return MIstatus::success; - } - - // Retrieve the command's latest data/information. Needed for commands of the event type so have - // a record of commands pending finishing execution. - const CMIUtilString &rMIResultRecord(vCmd.GetMIResultRecord()); - SMICmdData cmdData(vCmd.GetCmdData()); // Make a copy as the command will be deleted soon - cmdData.strMiCmdResultRecord = rMIResultRecord; // Precautionary copy as the command might forget to do this - if (vCmd.HasMIResultRecordExtra()) - { - cmdData.bHasResultRecordExtra = true; - const CMIUtilString &rMIExtra(vCmd.GetMIResultRecordExtra()); - cmdData.strMiCmdResultRecordExtra = rMIExtra; // Precautionary copy as the command might forget to do this - } - - // Send command's MI response to the client - bool bOk = CmdStdout(cmdData); - - // Delete the command object as do not require anymore - bOk = bOk && CmdDelete(vCmd.GetCmdData().id); - - return bOk; +bool CMICmdInvoker::CmdExecuteFinished(CMICmdBase &vCmd) { + // Command finished now get the command to gather it's information and form + // the MI + // Result record + if (!vCmd.Acknowledge()) { + // Report command acknowledge functionality failed + const SMICmdData cmdData(vCmd.GetCmdData()); + CmdStdout(cmdData); + CmdCauseAppExit(vCmd); + CmdDelete(cmdData.id); + + // Proceed to wait or execute next command + return MIstatus::success; + } + + // Retrieve the command's latest data/information. Needed for commands of the + // event type so have + // a record of commands pending finishing execution. + const CMIUtilString &rMIResultRecord(vCmd.GetMIResultRecord()); + SMICmdData cmdData( + vCmd.GetCmdData()); // Make a copy as the command will be deleted soon + cmdData.strMiCmdResultRecord = rMIResultRecord; // Precautionary copy as the + // command might forget to do + // this + if (vCmd.HasMIResultRecordExtra()) { + cmdData.bHasResultRecordExtra = true; + const CMIUtilString &rMIExtra(vCmd.GetMIResultRecordExtra()); + cmdData.strMiCmdResultRecordExtra = + rMIExtra; // Precautionary copy as the command might forget to do this + } + + // Send command's MI response to the client + bool bOk = CmdStdout(cmdData); + + // Delete the command object as do not require anymore + bOk = bOk && CmdDelete(vCmd.GetCmdData().id); + + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: If the MI Driver is not operating via a client i.e. Eclipse check the command -// on failure suggests the application exits. A command can be such that a +//++ +//------------------------------------------------------------------------------------ +// Details: If the MI Driver is not operating via a client i.e. Eclipse check +// the command +// on failure suggests the application exits. A command can be such +// that a // failure cannot the allow the application to continue operating. // Args: vCmd - (R) Command object. // Return: None. // Return: None. // Throws: None. //-- -void -CMICmdInvoker::CmdCauseAppExit(const CMICmdBase &vCmd) const -{ - if (vCmd.GetExitAppOnCommandFailure()) - { - CMIDriver &rDriver(CMIDriver::Instance()); - if (rDriver.IsDriverDebuggingArgExecutable()) - { - rDriver.SetExitApplicationFlag(true); - } +void CMICmdInvoker::CmdCauseAppExit(const CMICmdBase &vCmd) const { + if (vCmd.GetExitAppOnCommandFailure()) { + CMIDriver &rDriver(CMIDriver::Instance()); + if (rDriver.IsDriverDebuggingArgExecutable()) { + rDriver.SetExitApplicationFlag(true); } + } } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Write to stdout and the Log file the command's MI formatted result. // Type: vCmdData - (R) A command's information. // Return: MIstatus::success - Functionality succeeded. @@ -302,36 +299,36 @@ CMICmdInvoker::CmdCauseAppExit(const CMICmdBase &vCmd) const // Return: None. // Throws: None. //-- -bool -CMICmdInvoker::CmdStdout(const SMICmdData &vCmdData) const -{ - bool bOk = m_pLog->WriteLog(vCmdData.strMiCmdAll); - const bool bLock = bOk && m_rStreamOut.Lock(); - bOk = bOk && bLock && m_rStreamOut.WriteMIResponse(vCmdData.strMiCmdResultRecord); - if (bOk && vCmdData.bHasResultRecordExtra) - { - bOk = m_rStreamOut.WriteMIResponse(vCmdData.strMiCmdResultRecordExtra); - } - bOk = bLock && m_rStreamOut.Unlock(); - - return bOk; +bool CMICmdInvoker::CmdStdout(const SMICmdData &vCmdData) const { + bool bOk = m_pLog->WriteLog(vCmdData.strMiCmdAll); + const bool bLock = bOk && m_rStreamOut.Lock(); + bOk = bOk && bLock && + m_rStreamOut.WriteMIResponse(vCmdData.strMiCmdResultRecord); + if (bOk && vCmdData.bHasResultRecordExtra) { + bOk = m_rStreamOut.WriteMIResponse(vCmdData.strMiCmdResultRecordExtra); + } + bOk = bLock && m_rStreamOut.Unlock(); + + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Required by the CMICmdMgr::ICmdDeleteCallback. *this object is registered -// with the Command Manager to receive callbacks when a command is being deleted. -// An object, *this invoker, does not delete a command object itself but calls -// the Command Manager to delete a command object. This function is the Invoker's +//++ +//------------------------------------------------------------------------------------ +// Details: Required by the CMICmdMgr::ICmdDeleteCallback. *this object is +// registered +// with the Command Manager to receive callbacks when a command is +// being deleted. +// An object, *this invoker, does not delete a command object itself +// but calls +// the Command Manager to delete a command object. This function is the +// Invoker's // called. -// The Invoker owns the command objects and so can delete them but must do it +// The Invoker owns the command objects and so can delete them but must +// do it // via the manager so other objects can be notified of the deletion. // Type: Method. // Args: vCmd - (RW) Command. // Return: None. // Throws: None. //-- -void -CMICmdInvoker::Delete(SMICmdData &vCmd) -{ - CmdDelete(vCmd.id, true); -} +void CMICmdInvoker::Delete(SMICmdData &vCmd) { CmdDelete(vCmd.id, true); } diff --git a/lldb/tools/lldb-mi/MICmdInvoker.h b/lldb/tools/lldb-mi/MICmdInvoker.h index d70a5296c9f..40c4625f7ab 100644 --- a/lldb/tools/lldb-mi/MICmdInvoker.h +++ b/lldb/tools/lldb-mi/MICmdInvoker.h @@ -13,20 +13,23 @@ #include <map> // In-house headers: -#include "MICmnBase.h" #include "MICmdData.h" #include "MICmdMgrSetCmdDeleteCallback.h" +#include "MICmnBase.h" #include "MIUtilSingletonBase.h" // Declarations: class CMICmdBase; class CMICmnStreamStdout; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI Command Invoker. The Invoker works on the command pattern design. // There two main jobs; action command Execute() function, followed by -// the command's Acknowledge() function. When a command has finished its -// execute function it returns to the invoker. The invoker then calls the +// the command's Acknowledge() function. When a command has finished +// its +// execute function it returns to the invoker. The invoker then calls +// the // command's Acknowledge() function to do more work, form and give // back a MI result. In the meantime the Command Monitor is monitoring // the each command doing their Execute() function work so they do not @@ -34,67 +37,68 @@ class CMICmnStreamStdout; // stop work. // The work by the Invoker is carried out in the main thread. // The Invoker takes ownership of any commands created which means it -// is the only object to delete them when a command is finished working. +// is the only object to delete them when a command is finished +// working. // A singleton class. //-- -class CMICmdInvoker : public CMICmnBase, public CMICmdMgrSetCmdDeleteCallback::ICallback, public MI::ISingleton<CMICmdInvoker> -{ - friend class MI::ISingleton<CMICmdInvoker>; +class CMICmdInvoker : public CMICmnBase, + public CMICmdMgrSetCmdDeleteCallback::ICallback, + public MI::ISingleton<CMICmdInvoker> { + friend class MI::ISingleton<CMICmdInvoker>; - // Class: + // Class: +public: + //++ + // Description: Invoker's interface for commands to implement. + //-- + class ICmd { public: - //++ - // Description: Invoker's interface for commands to implement. - //-- - class ICmd - { - public: - virtual bool Acknowledge() = 0; - virtual bool Execute() = 0; - virtual bool ParseArgs() = 0; - virtual void SetCmdData(const SMICmdData &vCmdData) = 0; - virtual const SMICmdData &GetCmdData() const = 0; - virtual const CMIUtilString &GetErrorDescription() const = 0; - virtual void CmdFinishedTellInvoker() const = 0; - virtual const CMIUtilString &GetMIResultRecord() const = 0; - virtual const CMIUtilString &GetMIResultRecordExtra() const = 0; - virtual bool HasMIResultRecordExtra() const = 0; + virtual bool Acknowledge() = 0; + virtual bool Execute() = 0; + virtual bool ParseArgs() = 0; + virtual void SetCmdData(const SMICmdData &vCmdData) = 0; + virtual const SMICmdData &GetCmdData() const = 0; + virtual const CMIUtilString &GetErrorDescription() const = 0; + virtual void CmdFinishedTellInvoker() const = 0; + virtual const CMIUtilString &GetMIResultRecord() const = 0; + virtual const CMIUtilString &GetMIResultRecordExtra() const = 0; + virtual bool HasMIResultRecordExtra() const = 0; - /* dtor */ virtual ~ICmd(){} - }; + /* dtor */ virtual ~ICmd() {} + }; - // Methods: - public: - bool Initialize() override; - bool Shutdown() override; - bool CmdExecute(CMICmdBase &vCmd); - bool CmdExecuteFinished(CMICmdBase &vCmd); + // Methods: +public: + bool Initialize() override; + bool Shutdown() override; + bool CmdExecute(CMICmdBase &vCmd); + bool CmdExecuteFinished(CMICmdBase &vCmd); - // Typedefs: - private: - typedef std::map<MIuint, CMICmdBase *> MapCmdIdToCmd_t; - typedef std::pair<MIuint, CMICmdBase *> MapPairCmdIdToCmd_t; + // Typedefs: +private: + typedef std::map<MIuint, CMICmdBase *> MapCmdIdToCmd_t; + typedef std::pair<MIuint, CMICmdBase *> MapPairCmdIdToCmd_t; - // Methods: - private: - /* ctor */ CMICmdInvoker(); - /* ctor */ CMICmdInvoker(const CMICmdInvoker &); - void operator=(const CMICmdInvoker &); - void CmdDeleteAll(); - bool CmdDelete(const MIuint vCmdId, const bool vbYesDeleteCmd = false); - bool CmdAdd(const CMICmdBase &vCmd); - bool CmdStdout(const SMICmdData &vCmdData) const; - void CmdCauseAppExit(const CMICmdBase &vCmd) const; + // Methods: +private: + /* ctor */ CMICmdInvoker(); + /* ctor */ CMICmdInvoker(const CMICmdInvoker &); + void operator=(const CMICmdInvoker &); + void CmdDeleteAll(); + bool CmdDelete(const MIuint vCmdId, const bool vbYesDeleteCmd = false); + bool CmdAdd(const CMICmdBase &vCmd); + bool CmdStdout(const SMICmdData &vCmdData) const; + void CmdCauseAppExit(const CMICmdBase &vCmd) const; - // Overridden: - private: - // From CMICmnBase - /* dtor */ ~CMICmdInvoker() override; - // From CMICmdMgrSetCmdDeleteCallback::ICallback - void Delete(SMICmdData &vCmd) override; + // Overridden: +private: + // From CMICmnBase + /* dtor */ ~CMICmdInvoker() override; + // From CMICmdMgrSetCmdDeleteCallback::ICallback + void Delete(SMICmdData &vCmd) override; - // Attributes: - private: - MapCmdIdToCmd_t m_mapCmdIdToCmd; - CMICmnStreamStdout &m_rStreamOut; + // Attributes: +private: + MapCmdIdToCmd_t m_mapCmdIdToCmd; + CMICmnStreamStdout &m_rStreamOut; }; diff --git a/lldb/tools/lldb-mi/MICmdMgr.cpp b/lldb/tools/lldb-mi/MICmdMgr.cpp index 449be44e115..8daa38c1af2 100644 --- a/lldb/tools/lldb-mi/MICmdMgr.cpp +++ b/lldb/tools/lldb-mi/MICmdMgr.cpp @@ -9,16 +9,17 @@ // In-house headers: #include "MICmdMgr.h" -#include "MICmnResources.h" -#include "MICmnLog.h" -#include "MICmdInterpreter.h" +#include "MICmdBase.h" #include "MICmdFactory.h" +#include "MICmdInterpreter.h" #include "MICmdInvoker.h" -#include "MICmdBase.h" +#include "MICmnLog.h" +#include "MICmnResources.h" #include "MIUtilSingletonBase.h" #include "MIUtilSingletonHelper.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdMgr constructor. // Type: Method. // Args: None. @@ -26,25 +27,22 @@ // Throws: None. //-- CMICmdMgr::CMICmdMgr() - : m_interpretor(CMICmdInterpreter::Instance()) - , m_factory(CMICmdFactory::Instance()) - , m_invoker(CMICmdInvoker::Instance()) -{ -} + : m_interpretor(CMICmdInterpreter::Instance()), + m_factory(CMICmdFactory::Instance()), + m_invoker(CMICmdInvoker::Instance()) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmdMgr destructor. // Type: Overridable. // Args: None. // Return: None. // Throws: None. //-- -CMICmdMgr::~CMICmdMgr() -{ - Shutdown(); -} +CMICmdMgr::~CMICmdMgr() { Shutdown(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Initialize resources for *this Command Manager. // Type: Method. // Args: None. @@ -52,48 +50,48 @@ CMICmdMgr::~CMICmdMgr() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmdMgr::Initialize() -{ - m_clientUsageRefCnt++; - - if (m_bInitialized) - return MIstatus::success; - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - - // Note initialization order is important here as some resources depend on previous - MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); - MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); - if (bOk && !m_interpretor.Initialize()) - { - bOk = false; - errMsg = CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_CMDINTERPRETER), m_interpretor.GetErrorDescription().c_str()); - } - if (bOk && !m_factory.Initialize()) - { - bOk = false; - errMsg = CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_CMDFACTORY), m_factory.GetErrorDescription().c_str()); - } - if (bOk && !m_invoker.Initialize()) - { - bOk = false; - errMsg = CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_CMDINVOKER), m_invoker.GetErrorDescription().c_str()); - } - m_bInitialized = bOk; - - if (!bOk) - { - CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_CMDMGR), errMsg.c_str())); - SetErrorDescription(strInitError); - return MIstatus::failure; - } +bool CMICmdMgr::Initialize() { + m_clientUsageRefCnt++; + if (m_bInitialized) return MIstatus::success; + + bool bOk = MIstatus::success; + CMIUtilString errMsg; + + // Note initialization order is important here as some resources depend on + // previous + MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + if (bOk && !m_interpretor.Initialize()) { + bOk = false; + errMsg = CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_CMDINTERPRETER), + m_interpretor.GetErrorDescription().c_str()); + } + if (bOk && !m_factory.Initialize()) { + bOk = false; + errMsg = CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_CMDFACTORY), + m_factory.GetErrorDescription().c_str()); + } + if (bOk && !m_invoker.Initialize()) { + bOk = false; + errMsg = CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_CMDINVOKER), + m_invoker.GetErrorDescription().c_str()); + } + m_bInitialized = bOk; + + if (!bOk) { + CMIUtilString strInitError( + CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_CMDMGR), errMsg.c_str())); + SetErrorDescription(strInitError); + return MIstatus::failure; + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release resources for *this Command Manager. // Type: Method. // Args: None. @@ -101,76 +99,81 @@ CMICmdMgr::Initialize() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmdMgr::Shutdown() -{ - if (--m_clientUsageRefCnt > 0) - return MIstatus::success; - - if (!m_bInitialized) - return MIstatus::success; - - m_bInitialized = false; - - ClrErrorDescription(); - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - - // Tidy up - m_setCmdDeleteCallback.clear(); - - // Note shutdown order is important here - if (!m_invoker.Shutdown()) - { - bOk = false; - errMsg += CMIUtilString::Format(MIRSRC(IDS_MI_SHTDWN_ERR_CMDINVOKER), m_invoker.GetErrorDescription().c_str()); - } - if (!m_factory.Shutdown()) - { - bOk = false; - if (!errMsg.empty()) - errMsg += ", "; - errMsg += CMIUtilString::Format(MIRSRC(IDS_MI_SHTDWN_ERR_CMDFACTORY), m_factory.GetErrorDescription().c_str()); - } - if (!m_interpretor.Shutdown()) - { - bOk = false; - if (!errMsg.empty()) - errMsg += ", "; - errMsg += CMIUtilString::Format(MIRSRC(IDS_MI_SHTDWN_ERR_CMDINTERPRETER), m_interpretor.GetErrorDescription().c_str()); - } - MI::ModuleShutdown<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); - MI::ModuleShutdown<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); - - if (!bOk) - { - SetErrorDescriptionn(MIRSRC(IDS_MI_SHUTDOWN_ERR), errMsg.c_str()); - } +bool CMICmdMgr::Shutdown() { + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; + if (!m_bInitialized) return MIstatus::success; + + m_bInitialized = false; + + ClrErrorDescription(); + + bool bOk = MIstatus::success; + CMIUtilString errMsg; + + // Tidy up + m_setCmdDeleteCallback.clear(); + + // Note shutdown order is important here + if (!m_invoker.Shutdown()) { + bOk = false; + errMsg += CMIUtilString::Format(MIRSRC(IDS_MI_SHTDWN_ERR_CMDINVOKER), + m_invoker.GetErrorDescription().c_str()); + } + if (!m_factory.Shutdown()) { + bOk = false; + if (!errMsg.empty()) + errMsg += ", "; + errMsg += CMIUtilString::Format(MIRSRC(IDS_MI_SHTDWN_ERR_CMDFACTORY), + m_factory.GetErrorDescription().c_str()); + } + if (!m_interpretor.Shutdown()) { + bOk = false; + if (!errMsg.empty()) + errMsg += ", "; + errMsg += + CMIUtilString::Format(MIRSRC(IDS_MI_SHTDWN_ERR_CMDINTERPRETER), + m_interpretor.GetErrorDescription().c_str()); + } + MI::ModuleShutdown<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + MI::ModuleShutdown<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + + if (!bOk) { + SetErrorDescriptionn(MIRSRC(IDS_MI_SHUTDOWN_ERR), errMsg.c_str()); + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Establish whether the text data is an MI format type command. // Type: Method. // Args: vTextLine - (R) Text data to interpret. -// vwbYesValid - (W) True = MI type command, false = not recognised. -// vwbCmdNotInCmdFactor - (W) True = MI command not found in the command factor, false = recognised. +// vwbYesValid - (W) True = MI type command, false = not +// recognised. +// vwbCmdNotInCmdFactor - (W) True = MI command not found in the +// command factor, false = recognised. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmdMgr::CmdInterpret(const CMIUtilString &vTextLine, bool &vwbYesValid, bool &vwbCmdNotInCmdFactor, SMICmdData &rwCmdData) -{ - return m_interpretor.ValidateIsMi(vTextLine, vwbYesValid, vwbCmdNotInCmdFactor, rwCmdData); +bool CMICmdMgr::CmdInterpret(const CMIUtilString &vTextLine, bool &vwbYesValid, + bool &vwbCmdNotInCmdFactor, + SMICmdData &rwCmdData) { + return m_interpretor.ValidateIsMi(vTextLine, vwbYesValid, + vwbCmdNotInCmdFactor, rwCmdData); } -//++ ------------------------------------------------------------------------------------ -// Details: Having previously had the potential command validated and found valid now +//++ +//------------------------------------------------------------------------------------ +// Details: Having previously had the potential command validated and found +// valid now // get the command executed. -// If the Functionality returns MIstatus::failure call GetErrorDescription(). +// If the Functionality returns MIstatus::failure call +// GetErrorDescription(). // This function is used by the application's main thread. // Type: Method. // Args: vCmdData - (RW) Command meta data. @@ -178,55 +181,55 @@ CMICmdMgr::CmdInterpret(const CMIUtilString &vTextLine, bool &vwbYesValid, bool // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmdMgr::CmdExecute(const SMICmdData &vCmdData) -{ - bool bOk = MIstatus::success; - - // Pass the command's meta data structure to the command - // so it can update it if required. (Need to copy it out of the - // command before the command is deleted) - CMICmdBase *pCmd = nullptr; - bOk = m_factory.CmdCreate(vCmdData.strMiCmd, vCmdData, pCmd); - if (!bOk) - { - const CMIUtilString errMsg( - CMIUtilString::Format(MIRSRC(IDS_CMDMGR_ERR_CMD_FAILED_CREATE), m_factory.GetErrorDescription().c_str())); - SetErrorDescription(errMsg); - return MIstatus::failure; - } - - bOk = m_invoker.CmdExecute(*pCmd); - if (!bOk) - { - const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_CMDMGR_ERR_CMD_INVOKER), m_invoker.GetErrorDescription().c_str())); - SetErrorDescription(errMsg); - return MIstatus::failure; - } - - return bOk; +bool CMICmdMgr::CmdExecute(const SMICmdData &vCmdData) { + bool bOk = MIstatus::success; + + // Pass the command's meta data structure to the command + // so it can update it if required. (Need to copy it out of the + // command before the command is deleted) + CMICmdBase *pCmd = nullptr; + bOk = m_factory.CmdCreate(vCmdData.strMiCmd, vCmdData, pCmd); + if (!bOk) { + const CMIUtilString errMsg( + CMIUtilString::Format(MIRSRC(IDS_CMDMGR_ERR_CMD_FAILED_CREATE), + m_factory.GetErrorDescription().c_str())); + SetErrorDescription(errMsg); + return MIstatus::failure; + } + + bOk = m_invoker.CmdExecute(*pCmd); + if (!bOk) { + const CMIUtilString errMsg( + CMIUtilString::Format(MIRSRC(IDS_CMDMGR_ERR_CMD_INVOKER), + m_invoker.GetErrorDescription().c_str())); + SetErrorDescription(errMsg); + return MIstatus::failure; + } + + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Iterate all interested clients and tell them a command is being deleted. +//++ +//------------------------------------------------------------------------------------ +// Details: Iterate all interested clients and tell them a command is being +// deleted. // Type: Method. // Args: vCmdData - (RW) The command to be deleted. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdMgr::CmdDelete(SMICmdData vCmdData) -{ - // Note vCmdData is a copy! The command holding its copy will be deleted soon - // we still need to iterate callback clients after a command object is deleted +bool CMICmdMgr::CmdDelete(SMICmdData vCmdData) { + // Note vCmdData is a copy! The command holding its copy will be deleted soon + // we still need to iterate callback clients after a command object is deleted - m_setCmdDeleteCallback.Delete(vCmdData); + m_setCmdDeleteCallback.Delete(vCmdData); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Register an object to be called when a command object is deleted. // Type: Method. // Args: vObject - (R) A new interested client. @@ -234,22 +237,22 @@ CMICmdMgr::CmdDelete(SMICmdData vCmdData) // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdMgr::CmdRegisterForDeleteNotification(CMICmdMgrSetCmdDeleteCallback::ICallback &vObject) -{ - return m_setCmdDeleteCallback.Register(vObject); +bool CMICmdMgr::CmdRegisterForDeleteNotification( + CMICmdMgrSetCmdDeleteCallback::ICallback &vObject) { + return m_setCmdDeleteCallback.Register(vObject); } -//++ ------------------------------------------------------------------------------------ -// Details: Unregister an object from being called when a command object is deleted. +//++ +//------------------------------------------------------------------------------------ +// Details: Unregister an object from being called when a command object is +// deleted. // Type: Method. // Args: vObject - (R) The was interested client. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmdMgr::CmdUnregisterForDeleteNotification(CMICmdMgrSetCmdDeleteCallback::ICallback &vObject) -{ - return m_setCmdDeleteCallback.Unregister(vObject); +bool CMICmdMgr::CmdUnregisterForDeleteNotification( + CMICmdMgrSetCmdDeleteCallback::ICallback &vObject) { + return m_setCmdDeleteCallback.Unregister(vObject); } diff --git a/lldb/tools/lldb-mi/MICmdMgr.h b/lldb/tools/lldb-mi/MICmdMgr.h index 31363594a9d..1e58b753294 100644 --- a/lldb/tools/lldb-mi/MICmdMgr.h +++ b/lldb/tools/lldb-mi/MICmdMgr.h @@ -13,9 +13,9 @@ #include <set> // In-house headers: -#include "MICmnBase.h" #include "MICmdBase.h" #include "MICmdMgrSetCmdDeleteCallback.h" +#include "MICmnBase.h" #include "MIUtilSingletonBase.h" // Declarations: @@ -24,43 +24,47 @@ class CMICmdFactory; class CMICmdInvoker; class CMICmdBase; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI command manager. Oversees command operations, controls command // production and the running of commands. -// Command Invoker, Command Factory and Command Monitor while independent +// Command Invoker, Command Factory and Command Monitor while +// independent // units are overseen/managed by *this manager. // A singleton class. //-- -class CMICmdMgr : public CMICmnBase, public MI::ISingleton<CMICmdMgr> -{ - friend class MI::ISingleton<CMICmdMgr>; +class CMICmdMgr : public CMICmnBase, public MI::ISingleton<CMICmdMgr> { + friend class MI::ISingleton<CMICmdMgr>; - // Methods: - public: - bool Initialize() override; - bool Shutdown() override; + // Methods: +public: + bool Initialize() override; + bool Shutdown() override; - bool CmdInterpret(const CMIUtilString &vTextLine, bool &vwbYesValid, bool &vwbCmdNotInCmdFactor, SMICmdData &rwCmdData); - bool CmdExecute(const SMICmdData &vCmdData); - bool CmdDelete(SMICmdData vCmdData); - bool CmdRegisterForDeleteNotification(CMICmdMgrSetCmdDeleteCallback::ICallback &vObject); - bool CmdUnregisterForDeleteNotification(CMICmdMgrSetCmdDeleteCallback::ICallback &vObject); + bool CmdInterpret(const CMIUtilString &vTextLine, bool &vwbYesValid, + bool &vwbCmdNotInCmdFactor, SMICmdData &rwCmdData); + bool CmdExecute(const SMICmdData &vCmdData); + bool CmdDelete(SMICmdData vCmdData); + bool CmdRegisterForDeleteNotification( + CMICmdMgrSetCmdDeleteCallback::ICallback &vObject); + bool CmdUnregisterForDeleteNotification( + CMICmdMgrSetCmdDeleteCallback::ICallback &vObject); - // Methods: - private: - /* ctor */ CMICmdMgr(); - /* ctor */ CMICmdMgr(const CMICmdMgr &); - void operator=(const CMICmdMgr &); + // Methods: +private: + /* ctor */ CMICmdMgr(); + /* ctor */ CMICmdMgr(const CMICmdMgr &); + void operator=(const CMICmdMgr &); - // Overridden: - public: - // From CMICmnBase - /* dtor */ ~CMICmdMgr() override; + // Overridden: +public: + // From CMICmnBase + /* dtor */ ~CMICmdMgr() override; - // Attributes: - private: - CMICmdInterpreter &m_interpretor; - CMICmdFactory &m_factory; - CMICmdInvoker &m_invoker; - CMICmdMgrSetCmdDeleteCallback::CSetClients m_setCmdDeleteCallback; + // Attributes: +private: + CMICmdInterpreter &m_interpretor; + CMICmdFactory &m_factory; + CMICmdInvoker &m_invoker; + CMICmdMgrSetCmdDeleteCallback::CSetClients m_setCmdDeleteCallback; }; diff --git a/lldb/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp b/lldb/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp index 3bef535390f..1d21a1baaaf 100644 --- a/lldb/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp +++ b/lldb/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp @@ -10,33 +10,30 @@ // In-house headers: #include "MICmdMgrSetCmdDeleteCallback.h" -namespace CMICmdMgrSetCmdDeleteCallback -{ +namespace CMICmdMgrSetCmdDeleteCallback { -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CSetClients constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CSetClients::CSetClients() - : m_bClientUnregistered(false) -{ -} +CSetClients::CSetClients() : m_bClientUnregistered(false) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CSetClients destructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CSetClients::~CSetClients() -{ -} +CSetClients::~CSetClients() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Register an object to be called when a command object is deleted. // Type: Method. // Args: vObject - (R) A new interested client. @@ -44,58 +41,53 @@ CSetClients::~CSetClients() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CSetClients::Register(ICallback &vObject) -{ - insert(&vObject); +bool CSetClients::Register(ICallback &vObject) { + insert(&vObject); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Unregister an object from being called when a command object is deleted. +//++ +//------------------------------------------------------------------------------------ +// Details: Unregister an object from being called when a command object is +// deleted. // Type: Method. // Args: vObject - (R) The was interested client. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CSetClients::Unregister(ICallback &vObject) -{ - m_bClientUnregistered = true; - erase(&vObject); +bool CSetClients::Unregister(ICallback &vObject) { + m_bClientUnregistered = true; + erase(&vObject); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Iterate all interested clients and tell them a command is being deleted. +//++ +//------------------------------------------------------------------------------------ +// Details: Iterate all interested clients and tell them a command is being +// deleted. // Type: Method. // Args: vCmd - (RW) The command to be deleted. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -void -CSetClients::Delete(SMICmdData &vCmd) -{ - m_bClientUnregistered = false; // Reset - iterator it = begin(); - while (it != end()) - { - ICallback *pObj = *it; - pObj->Delete(vCmd); +void CSetClients::Delete(SMICmdData &vCmd) { + m_bClientUnregistered = false; // Reset + iterator it = begin(); + while (it != end()) { + ICallback *pObj = *it; + pObj->Delete(vCmd); - if (m_bClientUnregistered) - { - m_bClientUnregistered = false; // Reset - it = begin(); - } - else - // Next - ++it; - } + if (m_bClientUnregistered) { + m_bClientUnregistered = false; // Reset + it = begin(); + } else + // Next + ++it; + } } } // namespace CMICmdMgrSetCmdDeleteCallback diff --git a/lldb/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h b/lldb/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h index 7e95d67d871..0363831b765 100644 --- a/lldb/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h +++ b/lldb/tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h @@ -19,50 +19,55 @@ // Declarations: struct SMICmdData; -namespace CMICmdMgrSetCmdDeleteCallback -{ +namespace CMICmdMgrSetCmdDeleteCallback { -//++ ============================================================================ +//++ +//============================================================================ // Details: MI Command Manager interface for client call back. // Objects that want to be notified of a command being deleted // inherit this interface and register interest in command object -// deletion. An object deleting a command must not do it itself but call +// deletion. An object deleting a command must not do it itself but +// call // the Command Manager CmdDelete() function to delete a command object. //-- -class ICallback -{ - public: - virtual void Delete(SMICmdData &vCmd) = 0; +class ICallback { +public: + virtual void Delete(SMICmdData &vCmd) = 0; - /* dtor */ virtual ~ICallback(){} + /* dtor */ virtual ~ICallback() {} }; -//++ ============================================================================ -// Details: MI Command Manager container for clients registered interest in command -// objects being deleted. Objects register an interest so when a command +//++ +//============================================================================ +// Details: MI Command Manager container for clients registered interest in +// command +// objects being deleted. Objects register an interest so when a +// command // is to be deleted that object wanting the delete calls the Command // Manager to delete the command object. In so do all other registered -// objects get called to about the deletion including the object wanting +// objects get called to about the deletion including the object +// wanting // to do the delete in the first place. //-- -class CSetClients : public std::set<class ICallback *>, public CMICmnBase -{ - // Methods: - public: - /* ctor */ CSetClients(); +class CSetClients : public std::set<class ICallback *>, public CMICmnBase { + // Methods: +public: + /* ctor */ CSetClients(); - bool Register(class ICallback &vObject); - bool Unregister(class ICallback &vObject); - void Delete(SMICmdData &vCmdData); + bool Register(class ICallback &vObject); + bool Unregister(class ICallback &vObject); + void Delete(SMICmdData &vCmdData); - // Overridden: - public: - // From CMICmnBase - /* dtor */ ~CSetClients() override; + // Overridden: +public: + // From CMICmnBase + /* dtor */ ~CSetClients() override; - // Attributes: - private: - bool m_bClientUnregistered; // True = yes while deleting a client unregistered, false = no client unregistered during deletion + // Attributes: +private: + bool m_bClientUnregistered; // True = yes while deleting a client + // unregistered, false = no client unregistered + // during deletion }; } // namespace CMICmdMgrSetCmdDeleteCallback diff --git a/lldb/tools/lldb-mi/MICmnBase.cpp b/lldb/tools/lldb-mi/MICmnBase.cpp index 1240df7802d..52100e79c78 100644 --- a/lldb/tools/lldb-mi/MICmnBase.cpp +++ b/lldb/tools/lldb-mi/MICmnBase.cpp @@ -15,7 +15,8 @@ #include "MICmnLog.h" #include "MICmnStreamStderr.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnBase constructor. // Type: Method. // Args: None. @@ -23,102 +24,97 @@ // Throws: None. //-- CMICmnBase::CMICmnBase() - : m_strMILastErrorDescription(CMIUtilString()) - , m_bInitialized(false) - , m_pLog(&CMICmnLog::Instance()) - , m_clientUsageRefCnt(0) -{ -} + : m_strMILastErrorDescription(CMIUtilString()), m_bInitialized(false), + m_pLog(&CMICmnLog::Instance()), m_clientUsageRefCnt(0) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnBase destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmnBase::~CMICmnBase() -{ - m_pLog = NULL; -} +CMICmnBase::~CMICmnBase() { m_pLog = NULL; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve whether *this object has an error description set. // Type: Method. // Args: None. // Return: bool - True = Yes already defined, false = empty description. // Throws: None. //-- -bool -CMICmnBase::HaveErrorDescription() const -{ - return m_strMILastErrorDescription.empty(); +bool CMICmnBase::HaveErrorDescription() const { + return m_strMILastErrorDescription.empty(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve MI's last error condition. // Type: Method. // Args: None. // Return: CMIUtilString & - Text description. // Throws: None. //-- -const CMIUtilString & -CMICmnBase::GetErrorDescription() const -{ - return m_strMILastErrorDescription; +const CMIUtilString &CMICmnBase::GetErrorDescription() const { + return m_strMILastErrorDescription; } -//++ ------------------------------------------------------------------------------------ -// Details: Set MI's error condition description. This may be accessed by clients and -// seen by users. Message is available to the client using the server and sent +//++ +//------------------------------------------------------------------------------------ +// Details: Set MI's error condition description. This may be accessed by +// clients and +// seen by users. Message is available to the client using the server +// and sent // to the Logger. // Type: Method. // Args: vrTxt - (R) Text description. // Return: None. // Throws: None. //-- -void -CMICmnBase::SetErrorDescription(const CMIUtilString &vrTxt) const -{ - m_strMILastErrorDescription = vrTxt; - if (!vrTxt.empty()) - { - const CMIUtilString txt(CMIUtilString::Format("Error: %s", vrTxt.c_str())); - CMICmnStreamStderr::Instance().Write(txt); - } +void CMICmnBase::SetErrorDescription(const CMIUtilString &vrTxt) const { + m_strMILastErrorDescription = vrTxt; + if (!vrTxt.empty()) { + const CMIUtilString txt(CMIUtilString::Format("Error: %s", vrTxt.c_str())); + CMICmnStreamStderr::Instance().Write(txt); + } } -//++ ------------------------------------------------------------------------------------ -// Details: Set MI's error condition description. This may be accessed by clients and -// seen by users. Message is available to the client using the server and sent +//++ +//------------------------------------------------------------------------------------ +// Details: Set MI's error condition description. This may be accessed by +// clients and +// seen by users. Message is available to the client using the server +// and sent // to the Logger. // Type: Method. // Args: vrTxt - (R) Text description. // Return: None. // Throws: None. //-- -void -CMICmnBase::SetErrorDescriptionNoLog(const CMIUtilString &vrTxt) const -{ - m_strMILastErrorDescription = vrTxt; +void CMICmnBase::SetErrorDescriptionNoLog(const CMIUtilString &vrTxt) const { + m_strMILastErrorDescription = vrTxt; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Clear MI's error condition description. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -void -CMICmnBase::ClrErrorDescription() const -{ - m_strMILastErrorDescription.clear(); +void CMICmnBase::ClrErrorDescription() const { + m_strMILastErrorDescription.clear(); } -//++ ------------------------------------------------------------------------------------ -// Details: Set MI's error condition description. This may be accessed by clients and -// seen by users. Message is available to the client using the server and sent +//++ +//------------------------------------------------------------------------------------ +// Details: Set MI's error condition description. This may be accessed by +// clients and +// seen by users. Message is available to the client using the server +// and sent // to the Logger. // Type: Method. // Args: vFormat - (R) Format string. @@ -126,13 +122,11 @@ CMICmnBase::ClrErrorDescription() const // Return: None. // Throws: None. //-- -void -CMICmnBase::SetErrorDescriptionn(const CMIUtilString vFormat, ...) const -{ - va_list args; - va_start(args, vFormat); - CMIUtilString strResult = CMIUtilString::FormatValist(vFormat, args); - va_end(args); +void CMICmnBase::SetErrorDescriptionn(const CMIUtilString vFormat, ...) const { + va_list args; + va_start(args, vFormat); + CMIUtilString strResult = CMIUtilString::FormatValist(vFormat, args); + va_end(args); - SetErrorDescription(strResult); + SetErrorDescription(strResult); } diff --git a/lldb/tools/lldb-mi/MICmnBase.h b/lldb/tools/lldb-mi/MICmnBase.h index befadbeeba8..f739493cc21 100644 --- a/lldb/tools/lldb-mi/MICmnBase.h +++ b/lldb/tools/lldb-mi/MICmnBase.h @@ -16,30 +16,32 @@ // Declarations: class CMICmnLog; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code implementation base class. //-- -class CMICmnBase -{ - // Methods: - public: - /* ctor */ CMICmnBase(); +class CMICmnBase { + // Methods: +public: + /* ctor */ CMICmnBase(); - bool HaveErrorDescription() const; - const CMIUtilString &GetErrorDescription() const; - void SetErrorDescription(const CMIUtilString &vrTxt) const; - void SetErrorDescriptionn(const CMIUtilString vFormat, ...) const; - void SetErrorDescriptionNoLog(const CMIUtilString &vrTxt) const; - void ClrErrorDescription() const; + bool HaveErrorDescription() const; + const CMIUtilString &GetErrorDescription() const; + void SetErrorDescription(const CMIUtilString &vrTxt) const; + void SetErrorDescriptionn(const CMIUtilString vFormat, ...) const; + void SetErrorDescriptionNoLog(const CMIUtilString &vrTxt) const; + void ClrErrorDescription() const; - // Overrideable: - public: - /* dtor */ virtual ~CMICmnBase(); + // Overrideable: +public: + /* dtor */ virtual ~CMICmnBase(); - // Attributes: - protected: - mutable CMIUtilString m_strMILastErrorDescription; - bool m_bInitialized; // True = yes successfully initialized, false = no yet or failed - CMICmnLog *m_pLog; // Allow all derived classes to use the logger - MIint m_clientUsageRefCnt; // Count of client using *this object so not shutdown() object to early + // Attributes: +protected: + mutable CMIUtilString m_strMILastErrorDescription; + bool m_bInitialized; // True = yes successfully initialized, false = no yet or + // failed + CMICmnLog *m_pLog; // Allow all derived classes to use the logger + MIint m_clientUsageRefCnt; // Count of client using *this object so not + // shutdown() object to early }; diff --git a/lldb/tools/lldb-mi/MICmnConfig.h b/lldb/tools/lldb-mi/MICmnConfig.h index 2e31fb629f6..78793c7b020 100644 --- a/lldb/tools/lldb-mi/MICmnConfig.h +++ b/lldb/tools/lldb-mi/MICmnConfig.h @@ -10,9 +10,11 @@ #pragma once // 1 = Show debug process attach modal dialog, 0 = do not show -// For windows only ATM, other OS's code is an infinite loop which a debugger must change a value to continue +// For windows only ATM, other OS's code is an infinite loop which a debugger +// must change a value to continue #define MICONFIG_DEBUG_SHOW_ATTACH_DBG_DLG 0 -// 1 = Write to MI's Log file warnings about commands that did not handle arguments or +// 1 = Write to MI's Log file warnings about commands that did not handle +// arguments or // options present to them by the driver's client, 0 = no warnings given #define MICONFIG_GIVE_WARNING_CMD_ARGS_NOT_HANDLED 1 diff --git a/lldb/tools/lldb-mi/MICmnLLDBBroadcaster.cpp b/lldb/tools/lldb-mi/MICmnLLDBBroadcaster.cpp index 1d51abd1320..8840261eaa5 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBBroadcaster.cpp +++ b/lldb/tools/lldb-mi/MICmnLLDBBroadcaster.cpp @@ -10,7 +10,8 @@ // In-house headers: #include "MICmnLLDBBroadcaster.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLLDBBroadcaster constructor. // Type: Method. // Args: None. @@ -18,23 +19,20 @@ // Throws: None. //-- CMICmnLLDBBroadcaster::CMICmnLLDBBroadcaster() - : lldb::SBBroadcaster("MI driver") -{ -} + : lldb::SBBroadcaster("MI driver") {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLLDBBroadcaster destructor. // Type: Overridable. // Args: None. // Return: None. // Throws: None. //-- -CMICmnLLDBBroadcaster::~CMICmnLLDBBroadcaster() -{ - Shutdown(); -} +CMICmnLLDBBroadcaster::~CMICmnLLDBBroadcaster() { Shutdown(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Initialize resources for *this broadcaster object. // Type: Method. // Args: None. @@ -42,20 +40,19 @@ CMICmnLLDBBroadcaster::~CMICmnLLDBBroadcaster() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBBroadcaster::Initialize() -{ - m_clientUsageRefCnt++; +bool CMICmnLLDBBroadcaster::Initialize() { + m_clientUsageRefCnt++; - if (m_bInitialized) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - m_bInitialized = MIstatus::success; + m_bInitialized = MIstatus::success; - return m_bInitialized; + return m_bInitialized; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release resources for *this broadcaster object. // Type: Method. // Args: None. @@ -63,16 +60,14 @@ CMICmnLLDBBroadcaster::Initialize() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBBroadcaster::Shutdown() -{ - if (--m_clientUsageRefCnt > 0) - return MIstatus::success; +bool CMICmnLLDBBroadcaster::Shutdown() { + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - if (!m_bInitialized) - return MIstatus::success; + if (!m_bInitialized) + return MIstatus::success; - m_bInitialized = false; + m_bInitialized = false; - return MIstatus::success; + return MIstatus::success; } diff --git a/lldb/tools/lldb-mi/MICmnLLDBBroadcaster.h b/lldb/tools/lldb-mi/MICmnLLDBBroadcaster.h index 09b95f482a7..dcf196f16dc 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBBroadcaster.h +++ b/lldb/tools/lldb-mi/MICmnLLDBBroadcaster.h @@ -10,11 +10,12 @@ #pragma once // In-house headers: -#include "lldb/API/SBBroadcaster.h" #include "MICmnBase.h" #include "MIUtilSingletonBase.h" +#include "lldb/API/SBBroadcaster.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI derived class from LLDB SBBroadcaster API. // // *** This class (files) is a place holder until we know we need it or @@ -22,22 +23,23 @@ // // A singleton class. //-- -class CMICmnLLDBBroadcaster : public CMICmnBase, public lldb::SBBroadcaster, public MI::ISingleton<CMICmnLLDBBroadcaster> -{ - friend MI::ISingleton<CMICmnLLDBBroadcaster>; +class CMICmnLLDBBroadcaster : public CMICmnBase, + public lldb::SBBroadcaster, + public MI::ISingleton<CMICmnLLDBBroadcaster> { + friend MI::ISingleton<CMICmnLLDBBroadcaster>; - // Methods: - public: - bool Initialize() override; - bool Shutdown() override; - // Methods: - private: - /* ctor */ CMICmnLLDBBroadcaster(); - /* ctor */ CMICmnLLDBBroadcaster(const CMICmnLLDBBroadcaster &); - void operator=(const CMICmnLLDBBroadcaster &); + // Methods: +public: + bool Initialize() override; + bool Shutdown() override; + // Methods: +private: + /* ctor */ CMICmnLLDBBroadcaster(); + /* ctor */ CMICmnLLDBBroadcaster(const CMICmnLLDBBroadcaster &); + void operator=(const CMICmnLLDBBroadcaster &); - // Overridden: - private: - // From CMICmnBase - /* dtor */ ~CMICmnLLDBBroadcaster() override; + // Overridden: +private: + // From CMICmnBase + /* dtor */ ~CMICmnLLDBBroadcaster() override; }; diff --git a/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp b/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp index 4ded517a14c..6e76c23036f 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp +++ b/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// // Third party headers: -#include <inttypes.h> // For PRIx64 #include "lldb/API/SBThread.h" +#include <inttypes.h> // For PRIx64 #ifdef _WIN32 #include <io.h> // For the ::_access() #else @@ -29,7 +29,8 @@ #include "MICmnResources.h" #include "Platform.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLLDBDebugSessionInfo constructor. // Type: Method. // Args: None. @@ -37,29 +38,26 @@ // Throws: None. //-- CMICmnLLDBDebugSessionInfo::CMICmnLLDBDebugSessionInfo() - : m_nBrkPointCntMax(INT32_MAX) - , m_currentSelectedThread(LLDB_INVALID_THREAD_ID) - , m_constStrSharedDataKeyWkDir("Working Directory") - , m_constStrSharedDataSolibPath("Solib Path") - , m_constStrPrintCharArrayAsString("Print CharArrayAsString") - , m_constStrPrintExpandAggregates("Print ExpandAggregates") - , m_constStrPrintAggregateFieldNames("Print AggregateFieldNames") -{ -} - -//++ ------------------------------------------------------------------------------------ + : m_nBrkPointCntMax(INT32_MAX), + m_currentSelectedThread(LLDB_INVALID_THREAD_ID), + m_constStrSharedDataKeyWkDir("Working Directory"), + m_constStrSharedDataSolibPath("Solib Path"), + m_constStrPrintCharArrayAsString("Print CharArrayAsString"), + m_constStrPrintExpandAggregates("Print ExpandAggregates"), + m_constStrPrintAggregateFieldNames("Print AggregateFieldNames") {} + +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLLDBDebugSessionInfo destructor. // Type: Overridable. // Args: None. // Return: None. // Throws: None. //-- -CMICmnLLDBDebugSessionInfo::~CMICmnLLDBDebugSessionInfo() -{ - Shutdown(); -} +CMICmnLLDBDebugSessionInfo::~CMICmnLLDBDebugSessionInfo() { Shutdown(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Initialize resources for *this object. // Type: Method. // Args: None. @@ -67,23 +65,22 @@ CMICmnLLDBDebugSessionInfo::~CMICmnLLDBDebugSessionInfo() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfo::Initialize() -{ - m_clientUsageRefCnt++; +bool CMICmnLLDBDebugSessionInfo::Initialize() { + m_clientUsageRefCnt++; - if (m_bInitialized) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - m_currentSelectedThread = LLDB_INVALID_THREAD_ID; - CMICmnLLDBDebugSessionInfoVarObj::VarObjIdResetToZero(); + m_currentSelectedThread = LLDB_INVALID_THREAD_ID; + CMICmnLLDBDebugSessionInfoVarObj::VarObjIdResetToZero(); - m_bInitialized = MIstatus::success; + m_bInitialized = MIstatus::success; - return m_bInitialized; + return m_bInitialized; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release resources for *this object. // Type: Method. // Args: None. @@ -91,47 +88,50 @@ CMICmnLLDBDebugSessionInfo::Initialize() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfo::Shutdown() -{ - if (--m_clientUsageRefCnt > 0) - return MIstatus::success; +bool CMICmnLLDBDebugSessionInfo::Shutdown() { + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - if (!m_bInitialized) - return MIstatus::success; + if (!m_bInitialized) + return MIstatus::success; - // Tidy up - SharedDataDestroy(); + // Tidy up + SharedDataDestroy(); - m_vecActiveThreadId.clear(); - CMICmnLLDBDebugSessionInfoVarObj::VarObjClear(); + m_vecActiveThreadId.clear(); + CMICmnLLDBDebugSessionInfoVarObj::VarObjClear(); - m_bInitialized = false; + m_bInitialized = false; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Command instances can create and share data between other instances of commands. -// Data can also be assigned by a command and retrieved by LLDB event handler. -// This function takes down those resources build up over the use of the commands. -// This function should be called when the creation and running of command has +//++ +//------------------------------------------------------------------------------------ +// Details: Command instances can create and share data between other instances +// of commands. +// Data can also be assigned by a command and retrieved by LLDB event +// handler. +// This function takes down those resources build up over the use of +// the commands. +// This function should be called when the creation and running of +// command has // stopped i.e. application shutdown. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -void -CMICmnLLDBDebugSessionInfo::SharedDataDestroy() -{ - m_mapIdToSessionData.Clear(); - m_vecVarObj.clear(); - m_mapBrkPtIdToBrkPtInfo.clear(); +void CMICmnLLDBDebugSessionInfo::SharedDataDestroy() { + m_mapIdToSessionData.Clear(); + m_vecVarObj.clear(); + m_mapBrkPtIdToBrkPtInfo.clear(); } -//++ ------------------------------------------------------------------------------------ -// Details: Record information about a LLDB break point so that is can be recalled in other +//++ +//------------------------------------------------------------------------------------ +// Details: Record information about a LLDB break point so that is can be +// recalled in other // commands or LLDB event handling functions. // Type: Method. // Args: vBrkPtId - (R) LLDB break point ID. @@ -140,17 +140,18 @@ CMICmnLLDBDebugSessionInfo::SharedDataDestroy() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfo::RecordBrkPtInfo(const MIuint vnBrkPtId, const SBrkPtInfo &vrBrkPtInfo) -{ - MapPairBrkPtIdToBrkPtInfo_t pr(vnBrkPtId, vrBrkPtInfo); - m_mapBrkPtIdToBrkPtInfo.insert(pr); +bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfo( + const MIuint vnBrkPtId, const SBrkPtInfo &vrBrkPtInfo) { + MapPairBrkPtIdToBrkPtInfo_t pr(vnBrkPtId, vrBrkPtInfo); + m_mapBrkPtIdToBrkPtInfo.insert(pr); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve information about a LLDB break point previous recorded either by +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve information about a LLDB break point previous recorded +// either by // commands or LLDB event handling functions. // Type: Method. // Args: vBrkPtId - (R) LLDB break point ID. @@ -159,21 +160,22 @@ CMICmnLLDBDebugSessionInfo::RecordBrkPtInfo(const MIuint vnBrkPtId, const SBrkPt // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoGet(const MIuint vnBrkPtId, SBrkPtInfo &vrwBrkPtInfo) const -{ - const MapBrkPtIdToBrkPtInfo_t::const_iterator it = m_mapBrkPtIdToBrkPtInfo.find(vnBrkPtId); - if (it != m_mapBrkPtIdToBrkPtInfo.end()) - { - vrwBrkPtInfo = (*it).second; - return MIstatus::success; - } +bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoGet( + const MIuint vnBrkPtId, SBrkPtInfo &vrwBrkPtInfo) const { + const MapBrkPtIdToBrkPtInfo_t::const_iterator it = + m_mapBrkPtIdToBrkPtInfo.find(vnBrkPtId); + if (it != m_mapBrkPtIdToBrkPtInfo.end()) { + vrwBrkPtInfo = (*it).second; + return MIstatus::success; + } - return MIstatus::failure; + return MIstatus::failure; } -//++ ------------------------------------------------------------------------------------ -// Details: Delete information about a specific LLDB break point object. This function +//++ +//------------------------------------------------------------------------------------ +// Details: Delete information about a specific LLDB break point object. This +// function // should be called when a LLDB break point is deleted. // Type: Method. // Args: vBrkPtId - (R) LLDB break point ID. @@ -181,20 +183,19 @@ CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoGet(const MIuint vnBrkPtId, SBrkPtInf // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoDelete(const MIuint vnBrkPtId) -{ - const MapBrkPtIdToBrkPtInfo_t::const_iterator it = m_mapBrkPtIdToBrkPtInfo.find(vnBrkPtId); - if (it != m_mapBrkPtIdToBrkPtInfo.end()) - { - m_mapBrkPtIdToBrkPtInfo.erase(it); - return MIstatus::success; - } +bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoDelete(const MIuint vnBrkPtId) { + const MapBrkPtIdToBrkPtInfo_t::const_iterator it = + m_mapBrkPtIdToBrkPtInfo.find(vnBrkPtId); + if (it != m_mapBrkPtIdToBrkPtInfo.end()) { + m_mapBrkPtIdToBrkPtInfo.erase(it); + return MIstatus::success; + } - return MIstatus::failure; + return MIstatus::failure; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the specified thread's frame information. // Type: Method. // Args: vCmdData - (R) A command's information. @@ -204,43 +205,44 @@ CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoDelete(const MIuint vnBrkPtId) // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfo::GetThreadFrames(const SMICmdData &vCmdData, const MIuint vThreadIdx, const FrameInfoFormat_e veFrameInfoFormat, - CMIUtilString &vwrThreadFrames) -{ - lldb::SBThread thread = GetProcess().GetThreadByIndexID(vThreadIdx); - const uint32_t nFrames = thread.GetNumFrames(); - if (nFrames == 0) - { - // MI print "frame={}" - CMICmnMIValueTuple miValueTuple; - CMICmnMIValueResult miValueResult("frame", miValueTuple); - vwrThreadFrames = miValueResult.GetString(); - return MIstatus::success; - } - - // MI print - // "frame={level=\"%d\",addr=\"0x%016" PRIx64 "\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},frame={level=\"%d\",addr=\"0x%016" PRIx64 "\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"}, - // ..." - CMIUtilString strListCommaSeparated; - for (MIuint nLevel = 0; nLevel < nFrames; nLevel++) - { - CMICmnMIValueTuple miValueTuple; - if (!MIResponseFormFrameInfo(thread, nLevel, veFrameInfoFormat, miValueTuple)) - return MIstatus::failure; - - const CMICmnMIValueResult miValueResult2("frame", miValueTuple); - if (nLevel != 0) - strListCommaSeparated += ","; - strListCommaSeparated += miValueResult2.GetString(); - } - - vwrThreadFrames = strListCommaSeparated; - +bool CMICmnLLDBDebugSessionInfo::GetThreadFrames( + const SMICmdData &vCmdData, const MIuint vThreadIdx, + const FrameInfoFormat_e veFrameInfoFormat, CMIUtilString &vwrThreadFrames) { + lldb::SBThread thread = GetProcess().GetThreadByIndexID(vThreadIdx); + const uint32_t nFrames = thread.GetNumFrames(); + if (nFrames == 0) { + // MI print "frame={}" + CMICmnMIValueTuple miValueTuple; + CMICmnMIValueResult miValueResult("frame", miValueTuple); + vwrThreadFrames = miValueResult.GetString(); return MIstatus::success; + } + + // MI print + // "frame={level=\"%d\",addr=\"0x%016" PRIx64 + // "\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},frame={level=\"%d\",addr=\"0x%016" + // PRIx64 "\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"}, + // ..." + CMIUtilString strListCommaSeparated; + for (MIuint nLevel = 0; nLevel < nFrames; nLevel++) { + CMICmnMIValueTuple miValueTuple; + if (!MIResponseFormFrameInfo(thread, nLevel, veFrameInfoFormat, + miValueTuple)) + return MIstatus::failure; + + const CMICmnMIValueResult miValueResult2("frame", miValueTuple); + if (nLevel != 0) + strListCommaSeparated += ","; + strListCommaSeparated += miValueResult2.GetString(); + } + + vwrThreadFrames = strListCommaSeparated; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Return the resolved file's path for the given file. // Type: Method. // Args: vCmdData - (R) A command's information. @@ -250,99 +252,100 @@ CMICmnLLDBDebugSessionInfo::GetThreadFrames(const SMICmdData &vCmdData, const MI // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfo::ResolvePath(const SMICmdData &vCmdData, const CMIUtilString &vPath, CMIUtilString &vwrResolvedPath) -{ - // ToDo: Verify this code as it does not work as vPath is always empty - - CMIUtilString strResolvedPath; - if (!SharedDataRetrieve<CMIUtilString>(m_constStrSharedDataKeyWkDir, strResolvedPath)) - { - vwrResolvedPath = ""; - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SHARED_DATA_NOT_FOUND), vCmdData.strMiCmd.c_str(), - m_constStrSharedDataKeyWkDir.c_str())); - return MIstatus::failure; - } +bool CMICmnLLDBDebugSessionInfo::ResolvePath(const SMICmdData &vCmdData, + const CMIUtilString &vPath, + CMIUtilString &vwrResolvedPath) { + // ToDo: Verify this code as it does not work as vPath is always empty + + CMIUtilString strResolvedPath; + if (!SharedDataRetrieve<CMIUtilString>(m_constStrSharedDataKeyWkDir, + strResolvedPath)) { + vwrResolvedPath = ""; + SetErrorDescription(CMIUtilString::Format( + MIRSRC(IDS_CMD_ERR_SHARED_DATA_NOT_FOUND), vCmdData.strMiCmd.c_str(), + m_constStrSharedDataKeyWkDir.c_str())); + return MIstatus::failure; + } - vwrResolvedPath = vPath; + vwrResolvedPath = vPath; - return ResolvePath(strResolvedPath, vwrResolvedPath); + return ResolvePath(strResolvedPath, vwrResolvedPath); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Return the resolved file's path for the given file. // Type: Method. -// Args: vstrUnknown - (R) String assigned to path when resolved path is empty. -// vwrResolvedPath - (RW) The original path overwritten with resolved path. +// Args: vstrUnknown - (R) String assigned to path when resolved path +// is empty. +// vwrResolvedPath - (RW) The original path overwritten with resolved +// path. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfo::ResolvePath(const CMIUtilString &vstrUnknown, CMIUtilString &vwrResolvedPath) -{ - if (vwrResolvedPath.size() < 1) - { - vwrResolvedPath = vstrUnknown; - return MIstatus::success; - } - - bool bOk = MIstatus::success; - - CMIUtilString::VecString_t vecPathFolders; - const MIuint nSplits = vwrResolvedPath.Split("/", vecPathFolders); - MIunused(nSplits); - MIuint nFoldersBack = 1; // 1 is just the file (last element of vector) - while (bOk && (vecPathFolders.size() >= nFoldersBack)) - { - CMIUtilString strTestPath; - MIuint nFoldersToAdd = nFoldersBack; - while (nFoldersToAdd > 0) - { - strTestPath += "/"; - strTestPath += vecPathFolders[vecPathFolders.size() - nFoldersToAdd]; - nFoldersToAdd--; - } - bool bYesAccessible = false; - bOk = AccessPath(strTestPath, bYesAccessible); - if (bYesAccessible) - { - vwrResolvedPath = strTestPath; - return MIstatus::success; - } - else - nFoldersBack++; +bool CMICmnLLDBDebugSessionInfo::ResolvePath(const CMIUtilString &vstrUnknown, + CMIUtilString &vwrResolvedPath) { + if (vwrResolvedPath.size() < 1) { + vwrResolvedPath = vstrUnknown; + return MIstatus::success; + } + + bool bOk = MIstatus::success; + + CMIUtilString::VecString_t vecPathFolders; + const MIuint nSplits = vwrResolvedPath.Split("/", vecPathFolders); + MIunused(nSplits); + MIuint nFoldersBack = 1; // 1 is just the file (last element of vector) + while (bOk && (vecPathFolders.size() >= nFoldersBack)) { + CMIUtilString strTestPath; + MIuint nFoldersToAdd = nFoldersBack; + while (nFoldersToAdd > 0) { + strTestPath += "/"; + strTestPath += vecPathFolders[vecPathFolders.size() - nFoldersToAdd]; + nFoldersToAdd--; } - - // No files exist in the union of working directory and debuginfo path - // Simply use the debuginfo path and let the IDE handle it. - - return bOk; + bool bYesAccessible = false; + bOk = AccessPath(strTestPath, bYesAccessible); + if (bYesAccessible) { + vwrResolvedPath = strTestPath; + return MIstatus::success; + } else + nFoldersBack++; + } + + // No files exist in the union of working directory and debuginfo path + // Simply use the debuginfo path and let the IDE handle it. + + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Determine the given file path exists or not. // Type: Method. // Args: vPath - (R) File name path. -// vwbYesAccessible - (W) True - file exists, false = does not exist. +// vwbYesAccessible - (W) True - file exists, false = does not +// exist. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfo::AccessPath(const CMIUtilString &vPath, bool &vwbYesAccessible) -{ +bool CMICmnLLDBDebugSessionInfo::AccessPath(const CMIUtilString &vPath, + bool &vwbYesAccessible) { #ifdef _WIN32 - vwbYesAccessible = (::_access(vPath.c_str(), 0) == 0); + vwbYesAccessible = (::_access(vPath.c_str(), 0) == 0); #else - vwbYesAccessible = (::access(vPath.c_str(), 0) == 0); + vwbYesAccessible = (::access(vPath.c_str(), 0) == 0); #endif // _WIN32 - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Form MI partial response by appending more MI value type objects to the +//++ +//------------------------------------------------------------------------------------ +// Details: Form MI partial response by appending more MI value type objects to +// the // tuple type object past in. // Type: Method. // Args: vCmdData - (R) A command's information. @@ -352,184 +355,192 @@ CMICmnLLDBDebugSessionInfo::AccessPath(const CMIUtilString &vPath, bool &vwbYesA // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo(const SMICmdData &vCmdData, const lldb::SBThread &vrThread, - const ThreadInfoFormat_e veThreadInfoFormat, CMICmnMIValueTuple &vwrMIValueTuple) -{ - lldb::SBThread &rThread = const_cast<lldb::SBThread &>(vrThread); - - const bool bSuspended = rThread.IsSuspended(); - const lldb::StopReason eReason = rThread.GetStopReason(); - const bool bValidReason = !((eReason == lldb::eStopReasonNone) || (eReason == lldb::eStopReasonInvalid)); - const CMIUtilString strState((bSuspended || bValidReason) ? "stopped" : "running"); - - // Add "id" - const CMIUtilString strId(CMIUtilString::Format("%d", rThread.GetIndexID())); - const CMICmnMIValueConst miValueConst1(strId); - const CMICmnMIValueResult miValueResult1("id", miValueConst1); - vwrMIValueTuple.Add(miValueResult1); - - // Add "target-id" - const char *pThreadName = rThread.GetName(); - const MIuint len = (pThreadName != nullptr) ? CMIUtilString(pThreadName).length() : 0; - const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) && - CMIUtilString::IsAllValidAlphaAndNumeric(pThreadName)); // 32 is arbitrary number - const char *pThrdFmt = bHaveName ? "%s" : "Thread %d"; - CMIUtilString strThread; - if (bHaveName) - strThread = CMIUtilString::Format(pThrdFmt, pThreadName); - else - strThread = CMIUtilString::Format(pThrdFmt, rThread.GetIndexID()); - const CMICmnMIValueConst miValueConst2(strThread); - const CMICmnMIValueResult miValueResult2("target-id", miValueConst2); - vwrMIValueTuple.Add(miValueResult2); - - // Add "frame" - if (veThreadInfoFormat != eThreadInfoFormat_NoFrames) - { - CMIUtilString strFrames; - if (!GetThreadFrames(vCmdData, rThread.GetIndexID(), eFrameInfoFormat_AllArgumentsInSimpleForm, strFrames)) - return MIstatus::failure; - - const CMICmnMIValueConst miValueConst3(strFrames, true); - vwrMIValueTuple.Add(miValueConst3, false); - } - - // Add "state" - const CMICmnMIValueConst miValueConst4(strState); - const CMICmnMIValueResult miValueResult4("state", miValueConst4); - vwrMIValueTuple.Add(miValueResult4); - - return MIstatus::success; +bool CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo( + const SMICmdData &vCmdData, const lldb::SBThread &vrThread, + const ThreadInfoFormat_e veThreadInfoFormat, + CMICmnMIValueTuple &vwrMIValueTuple) { + lldb::SBThread &rThread = const_cast<lldb::SBThread &>(vrThread); + + const bool bSuspended = rThread.IsSuspended(); + const lldb::StopReason eReason = rThread.GetStopReason(); + const bool bValidReason = !((eReason == lldb::eStopReasonNone) || + (eReason == lldb::eStopReasonInvalid)); + const CMIUtilString strState((bSuspended || bValidReason) ? "stopped" + : "running"); + + // Add "id" + const CMIUtilString strId(CMIUtilString::Format("%d", rThread.GetIndexID())); + const CMICmnMIValueConst miValueConst1(strId); + const CMICmnMIValueResult miValueResult1("id", miValueConst1); + vwrMIValueTuple.Add(miValueResult1); + + // Add "target-id" + const char *pThreadName = rThread.GetName(); + const MIuint len = + (pThreadName != nullptr) ? CMIUtilString(pThreadName).length() : 0; + const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) && + CMIUtilString::IsAllValidAlphaAndNumeric( + pThreadName)); // 32 is arbitrary number + const char *pThrdFmt = bHaveName ? "%s" : "Thread %d"; + CMIUtilString strThread; + if (bHaveName) + strThread = CMIUtilString::Format(pThrdFmt, pThreadName); + else + strThread = CMIUtilString::Format(pThrdFmt, rThread.GetIndexID()); + const CMICmnMIValueConst miValueConst2(strThread); + const CMICmnMIValueResult miValueResult2("target-id", miValueConst2); + vwrMIValueTuple.Add(miValueResult2); + + // Add "frame" + if (veThreadInfoFormat != eThreadInfoFormat_NoFrames) { + CMIUtilString strFrames; + if (!GetThreadFrames(vCmdData, rThread.GetIndexID(), + eFrameInfoFormat_AllArgumentsInSimpleForm, strFrames)) + return MIstatus::failure; + + const CMICmnMIValueConst miValueConst3(strFrames, true); + vwrMIValueTuple.Add(miValueConst3, false); + } + + // Add "state" + const CMICmnMIValueConst miValueConst4(strState); + const CMICmnMIValueResult miValueResult4("state", miValueConst4); + vwrMIValueTuple.Add(miValueResult4); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Form MI partial response by appending more MI value type objects to the +//++ +//------------------------------------------------------------------------------------ +// Details: Form MI partial response by appending more MI value type objects to +// the // tuple type object past in. // Type: Method. // Args: vrFrame - (R) LLDB thread object. // vMaskVarTypes - (R) Construed according to VariableType_e. -// veVarInfoFormat - (R) The type of variable info that should be shown. +// veVarInfoFormat - (R) The type of variable info that should be +// shown. // vwrMIValueList - (W) MI value list object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes, - const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList, - const MIuint vnMaxDepth, /* = 10 */ - const bool vbMarkArgs /* = false*/) -{ - bool bOk = MIstatus::success; - lldb::SBFrame &rFrame = const_cast<lldb::SBFrame &>(vrFrame); - - const bool bArg = (vMaskVarTypes & eVariableType_Arguments); - const bool bLocals = (vMaskVarTypes & eVariableType_Locals); - const bool bStatics = (vMaskVarTypes & eVariableType_Statics); - const bool bInScopeOnly = (vMaskVarTypes & eVariableType_InScope); - - // Handle arguments first - lldb::SBValueList listArg = rFrame.GetVariables(bArg, false, false, false); - bOk = bOk && MIResponseForVariableInfoInternal(veVarInfoFormat, vwrMiValueList, listArg, vnMaxDepth, true, vbMarkArgs); - - // Handle remaining variables - lldb::SBValueList listVars = rFrame.GetVariables(false, bLocals, bStatics, bInScopeOnly); - bOk = bOk && MIResponseForVariableInfoInternal(veVarInfoFormat, vwrMiValueList, listVars, vnMaxDepth, false, vbMarkArgs); - - return bOk; +bool CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo( + const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes, + const VariableInfoFormat_e veVarInfoFormat, + CMICmnMIValueList &vwrMiValueList, const MIuint vnMaxDepth, /* = 10 */ + const bool vbMarkArgs /* = false*/) { + bool bOk = MIstatus::success; + lldb::SBFrame &rFrame = const_cast<lldb::SBFrame &>(vrFrame); + + const bool bArg = (vMaskVarTypes & eVariableType_Arguments); + const bool bLocals = (vMaskVarTypes & eVariableType_Locals); + const bool bStatics = (vMaskVarTypes & eVariableType_Statics); + const bool bInScopeOnly = (vMaskVarTypes & eVariableType_InScope); + + // Handle arguments first + lldb::SBValueList listArg = rFrame.GetVariables(bArg, false, false, false); + bOk = bOk && MIResponseForVariableInfoInternal(veVarInfoFormat, + vwrMiValueList, listArg, + vnMaxDepth, true, vbMarkArgs); + + // Handle remaining variables + lldb::SBValueList listVars = + rFrame.GetVariables(false, bLocals, bStatics, bInScopeOnly); + bOk = bOk && MIResponseForVariableInfoInternal(veVarInfoFormat, + vwrMiValueList, listVars, + vnMaxDepth, false, vbMarkArgs); + + return bOk; } -bool -CMICmnLLDBDebugSessionInfo::MIResponseForVariableInfoInternal(const VariableInfoFormat_e veVarInfoFormat, - CMICmnMIValueList &vwrMiValueList, - const lldb::SBValueList &vwrSBValueList, - const MIuint vnMaxDepth, - const bool vbIsArgs, - const bool vbMarkArgs) -{ - const MIuint nArgs = vwrSBValueList.GetSize(); - for (MIuint i = 0; i < nArgs; i++) - { - CMICmnMIValueTuple miValueTuple; - lldb::SBValue value = vwrSBValueList.GetValueAtIndex(i); - // If one stops inside try block with, which catch clause type is unnamed - // (e.g std::exception&) then value name will be nullptr as well as value pointer - const char* name = value.GetName(); - if (name == nullptr) - continue; - const CMICmnMIValueConst miValueConst(name); - const CMICmnMIValueResult miValueResultName("name", miValueConst); - if (vbMarkArgs && vbIsArgs) - { - const CMICmnMIValueConst miValueConstArg("1"); - const CMICmnMIValueResult miValueResultArg("arg", miValueConstArg); - miValueTuple.Add(miValueResultArg); - } - if (veVarInfoFormat != eVariableInfoFormat_NoValues) - { - miValueTuple.Add(miValueResultName); // name - if (veVarInfoFormat == eVariableInfoFormat_SimpleValues) - { - const CMICmnMIValueConst miValueConst3(value.GetTypeName()); - const CMICmnMIValueResult miValueResult3("type", miValueConst3); - miValueTuple.Add(miValueResult3); - } - const MIuint nChildren = value.GetNumChildren(); - const bool bIsPointerType = value.GetType().IsPointerType(); - if (nChildren == 0 || // no children - (bIsPointerType && nChildren == 1) || // pointers - veVarInfoFormat == eVariableInfoFormat_AllValues) // show all values - { - CMIUtilString strValue; - if (GetVariableInfo(value, vnMaxDepth == 0, strValue)) - { - const CMICmnMIValueConst miValueConst2(strValue.Escape().AddSlashes()); - const CMICmnMIValueResult miValueResult2("value", miValueConst2); - miValueTuple.Add(miValueResult2); - } - } - vwrMiValueList.Add(miValueTuple); - continue; - } - - if (vbMarkArgs) - { - // If we are printing names only with vbMarkArgs, we still need to add the name to the value tuple - miValueTuple.Add(miValueResultName); // name - vwrMiValueList.Add(miValueTuple); - } - else - { - // If we are printing name only then no need to put it in the tuple. - vwrMiValueList.Add(miValueResultName); +bool CMICmnLLDBDebugSessionInfo::MIResponseForVariableInfoInternal( + const VariableInfoFormat_e veVarInfoFormat, + CMICmnMIValueList &vwrMiValueList, const lldb::SBValueList &vwrSBValueList, + const MIuint vnMaxDepth, const bool vbIsArgs, const bool vbMarkArgs) { + const MIuint nArgs = vwrSBValueList.GetSize(); + for (MIuint i = 0; i < nArgs; i++) { + CMICmnMIValueTuple miValueTuple; + lldb::SBValue value = vwrSBValueList.GetValueAtIndex(i); + // If one stops inside try block with, which catch clause type is unnamed + // (e.g std::exception&) then value name will be nullptr as well as value + // pointer + const char *name = value.GetName(); + if (name == nullptr) + continue; + const CMICmnMIValueConst miValueConst(name); + const CMICmnMIValueResult miValueResultName("name", miValueConst); + if (vbMarkArgs && vbIsArgs) { + const CMICmnMIValueConst miValueConstArg("1"); + const CMICmnMIValueResult miValueResultArg("arg", miValueConstArg); + miValueTuple.Add(miValueResultArg); + } + if (veVarInfoFormat != eVariableInfoFormat_NoValues) { + miValueTuple.Add(miValueResultName); // name + if (veVarInfoFormat == eVariableInfoFormat_SimpleValues) { + const CMICmnMIValueConst miValueConst3(value.GetTypeName()); + const CMICmnMIValueResult miValueResult3("type", miValueConst3); + miValueTuple.Add(miValueResult3); + } + const MIuint nChildren = value.GetNumChildren(); + const bool bIsPointerType = value.GetType().IsPointerType(); + if (nChildren == 0 || // no children + (bIsPointerType && nChildren == 1) || // pointers + veVarInfoFormat == eVariableInfoFormat_AllValues) // show all values + { + CMIUtilString strValue; + if (GetVariableInfo(value, vnMaxDepth == 0, strValue)) { + const CMICmnMIValueConst miValueConst2( + strValue.Escape().AddSlashes()); + const CMICmnMIValueResult miValueResult2("value", miValueConst2); + miValueTuple.Add(miValueResult2); } + } + vwrMiValueList.Add(miValueTuple); + continue; } - return MIstatus::success; + + if (vbMarkArgs) { + // If we are printing names only with vbMarkArgs, we still need to add the + // name to the value tuple + miValueTuple.Add(miValueResultName); // name + vwrMiValueList.Add(miValueTuple); + } else { + // If we are printing name only then no need to put it in the tuple. + vwrMiValueList.Add(miValueResultName); + } + } + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Extract the value's name and value or recurse into child value object. +//++ +//------------------------------------------------------------------------------------ +// Details: Extract the value's name and value or recurse into child value +// object. // Type: Method. // Args: vrValue - (R) LLDB value object. -// vbInSimpleForm - (R) True = Get variable info in simple form (i.e. don't expand aggregates). -// - False = Get variable info (and expand aggregates if any). +// vbInSimpleForm - (R) True = Get variable info in simple form (i.e. +// don't expand aggregates). +// - False = Get variable info (and expand +// aggregates if any). // vwrStrValue t - (W) The string representation of this value. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfo::GetVariableInfo(const lldb::SBValue &vrValue, const bool vbInSimpleForm, CMIUtilString &vwrStrValue) -{ - const CMICmnLLDBUtilSBValue utilValue(vrValue, true, false); - const bool bExpandAggregates = vbInSimpleForm ? false : true; - vwrStrValue = utilValue.GetValue(bExpandAggregates); - return MIstatus::success; +bool CMICmnLLDBDebugSessionInfo::GetVariableInfo(const lldb::SBValue &vrValue, + const bool vbInSimpleForm, + CMIUtilString &vwrStrValue) { + const CMICmnLLDBUtilSBValue utilValue(vrValue, true, false); + const bool bExpandAggregates = vbInSimpleForm ? false : true; + vwrStrValue = utilValue.GetValue(bExpandAggregates); + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Form MI partial response by appending more MI value type objects to the +//++ +//------------------------------------------------------------------------------------ +// Details: Form MI partial response by appending more MI value type objects to +// the // tuple type object past in. // Type: Method. // Args: vrThread - (R) LLDB thread object. @@ -539,64 +550,66 @@ CMICmnLLDBDebugSessionInfo::GetVariableInfo(const lldb::SBValue &vrValue, const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo(const lldb::SBThread &vrThread, const MIuint vnLevel, - const FrameInfoFormat_e veFrameInfoFormat, CMICmnMIValueTuple &vwrMiValueTuple) -{ - lldb::SBThread &rThread = const_cast<lldb::SBThread &>(vrThread); - - lldb::SBFrame frame = rThread.GetFrameAtIndex(vnLevel); - lldb::addr_t pc = 0; - CMIUtilString fnName; - CMIUtilString fileName; - CMIUtilString path; - MIuint nLine = 0; - if (!GetFrameInfo(frame, pc, fnName, fileName, path, nLine)) - return MIstatus::failure; - - // MI print "{level=\"0\",addr=\"0x%016" PRIx64 "\",func=\"%s\",file=\"%s\",fullname=\"%s\",line=\"%d\"}" - const CMIUtilString strLevel(CMIUtilString::Format("%d", vnLevel)); - const CMICmnMIValueConst miValueConst(strLevel); - const CMICmnMIValueResult miValueResult("level", miValueConst); - vwrMiValueTuple.Add(miValueResult); - const CMIUtilString strAddr(CMIUtilString::Format("0x%016" PRIx64, pc)); - const CMICmnMIValueConst miValueConst2(strAddr); - const CMICmnMIValueResult miValueResult2("addr", miValueConst2); - vwrMiValueTuple.Add(miValueResult2); - const CMICmnMIValueConst miValueConst3(fnName); - const CMICmnMIValueResult miValueResult3("func", miValueConst3); - vwrMiValueTuple.Add(miValueResult3); - if (veFrameInfoFormat != eFrameInfoFormat_NoArguments) - { - CMICmnMIValueList miValueList(true); - const MIuint maskVarTypes = eVariableType_Arguments; - if (veFrameInfoFormat == eFrameInfoFormat_AllArgumentsInSimpleForm) - { - if (!MIResponseFormVariableInfo(frame, maskVarTypes, eVariableInfoFormat_AllValues, miValueList, 0)) - return MIstatus::failure; - } - else - if (!MIResponseFormVariableInfo(frame, maskVarTypes, eVariableInfoFormat_AllValues, miValueList)) - return MIstatus::failure; - - const CMICmnMIValueResult miValueResult4("args", miValueList); - vwrMiValueTuple.Add(miValueResult4); - } - const CMICmnMIValueConst miValueConst5(fileName); - const CMICmnMIValueResult miValueResult5("file", miValueConst5); - vwrMiValueTuple.Add(miValueResult5); - const CMICmnMIValueConst miValueConst6(path); - const CMICmnMIValueResult miValueResult6("fullname", miValueConst6); - vwrMiValueTuple.Add(miValueResult6); - const CMIUtilString strLine(CMIUtilString::Format("%d", nLine)); - const CMICmnMIValueConst miValueConst7(strLine); - const CMICmnMIValueResult miValueResult7("line", miValueConst7); - vwrMiValueTuple.Add(miValueResult7); +bool CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo( + const lldb::SBThread &vrThread, const MIuint vnLevel, + const FrameInfoFormat_e veFrameInfoFormat, + CMICmnMIValueTuple &vwrMiValueTuple) { + lldb::SBThread &rThread = const_cast<lldb::SBThread &>(vrThread); + + lldb::SBFrame frame = rThread.GetFrameAtIndex(vnLevel); + lldb::addr_t pc = 0; + CMIUtilString fnName; + CMIUtilString fileName; + CMIUtilString path; + MIuint nLine = 0; + if (!GetFrameInfo(frame, pc, fnName, fileName, path, nLine)) + return MIstatus::failure; - return MIstatus::success; + // MI print "{level=\"0\",addr=\"0x%016" PRIx64 + // "\",func=\"%s\",file=\"%s\",fullname=\"%s\",line=\"%d\"}" + const CMIUtilString strLevel(CMIUtilString::Format("%d", vnLevel)); + const CMICmnMIValueConst miValueConst(strLevel); + const CMICmnMIValueResult miValueResult("level", miValueConst); + vwrMiValueTuple.Add(miValueResult); + const CMIUtilString strAddr(CMIUtilString::Format("0x%016" PRIx64, pc)); + const CMICmnMIValueConst miValueConst2(strAddr); + const CMICmnMIValueResult miValueResult2("addr", miValueConst2); + vwrMiValueTuple.Add(miValueResult2); + const CMICmnMIValueConst miValueConst3(fnName); + const CMICmnMIValueResult miValueResult3("func", miValueConst3); + vwrMiValueTuple.Add(miValueResult3); + if (veFrameInfoFormat != eFrameInfoFormat_NoArguments) { + CMICmnMIValueList miValueList(true); + const MIuint maskVarTypes = eVariableType_Arguments; + if (veFrameInfoFormat == eFrameInfoFormat_AllArgumentsInSimpleForm) { + if (!MIResponseFormVariableInfo(frame, maskVarTypes, + eVariableInfoFormat_AllValues, + miValueList, 0)) + return MIstatus::failure; + } else if (!MIResponseFormVariableInfo(frame, maskVarTypes, + eVariableInfoFormat_AllValues, + miValueList)) + return MIstatus::failure; + + const CMICmnMIValueResult miValueResult4("args", miValueList); + vwrMiValueTuple.Add(miValueResult4); + } + const CMICmnMIValueConst miValueConst5(fileName); + const CMICmnMIValueResult miValueResult5("file", miValueConst5); + vwrMiValueTuple.Add(miValueResult5); + const CMICmnMIValueConst miValueConst6(path); + const CMICmnMIValueResult miValueResult6("fullname", miValueConst6); + vwrMiValueTuple.Add(miValueResult6); + const CMIUtilString strLine(CMIUtilString::Format("%d", nLine)); + const CMICmnMIValueConst miValueConst7(strLine); + const CMICmnMIValueResult miValueResult7("line", miValueConst7); + vwrMiValueTuple.Add(miValueResult7); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the frame information from LLDB frame object. // Type: Method. // Args: vrFrame - (R) LLDB thread object. @@ -609,36 +622,38 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo(const lldb::SBThread &vrThre // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfo::GetFrameInfo(const lldb::SBFrame &vrFrame, lldb::addr_t &vwPc, CMIUtilString &vwFnName, - CMIUtilString &vwFileName, CMIUtilString &vwPath, MIuint &vwnLine) -{ - lldb::SBFrame &rFrame = const_cast<lldb::SBFrame &>(vrFrame); - - static char pBuffer[PATH_MAX]; - const MIuint nBytes = rFrame.GetLineEntry().GetFileSpec().GetPath(&pBuffer[0], sizeof(pBuffer)); - MIunused(nBytes); - CMIUtilString strResolvedPath(&pBuffer[0]); - const char *pUnkwn = "??"; - if (!ResolvePath(pUnkwn, strResolvedPath)) - return MIstatus::failure; - vwPath = strResolvedPath; +bool CMICmnLLDBDebugSessionInfo::GetFrameInfo( + const lldb::SBFrame &vrFrame, lldb::addr_t &vwPc, CMIUtilString &vwFnName, + CMIUtilString &vwFileName, CMIUtilString &vwPath, MIuint &vwnLine) { + lldb::SBFrame &rFrame = const_cast<lldb::SBFrame &>(vrFrame); + + static char pBuffer[PATH_MAX]; + const MIuint nBytes = + rFrame.GetLineEntry().GetFileSpec().GetPath(&pBuffer[0], sizeof(pBuffer)); + MIunused(nBytes); + CMIUtilString strResolvedPath(&pBuffer[0]); + const char *pUnkwn = "??"; + if (!ResolvePath(pUnkwn, strResolvedPath)) + return MIstatus::failure; + vwPath = strResolvedPath; - vwPc = rFrame.GetPC(); + vwPc = rFrame.GetPC(); - const char *pFnName = rFrame.GetFunctionName(); - vwFnName = (pFnName != nullptr) ? pFnName : pUnkwn; + const char *pFnName = rFrame.GetFunctionName(); + vwFnName = (pFnName != nullptr) ? pFnName : pUnkwn; - const char *pFileName = rFrame.GetLineEntry().GetFileSpec().GetFilename(); - vwFileName = (pFileName != nullptr) ? pFileName : pUnkwn; + const char *pFileName = rFrame.GetLineEntry().GetFileSpec().GetFilename(); + vwFileName = (pFileName != nullptr) ? pFileName : pUnkwn; - vwnLine = rFrame.GetLineEntry().GetLine(); + vwnLine = rFrame.GetLineEntry().GetLine(); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Form MI partial response by appending more MI value type objects to the +//++ +//------------------------------------------------------------------------------------ +// Details: Form MI partial response by appending more MI value type objects to +// the // tuple type object past in. // Type: Method. // Args: vrBrkPtInfo - (R) Break point information object. @@ -646,31 +661,34 @@ CMICmnLLDBDebugSessionInfo::GetFrameInfo(const lldb::SBFrame &vrFrame, lldb::add // Return: None. // Throws: None. //-- -void -CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtFrameInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple) -{ - const CMIUtilString strAddr(CMIUtilString::Format("0x%016" PRIx64, vrBrkPtInfo.m_pc)); - const CMICmnMIValueConst miValueConst2(strAddr); - const CMICmnMIValueResult miValueResult2("addr", miValueConst2); - vwrMiValueTuple.Add(miValueResult2); - const CMICmnMIValueConst miValueConst3(vrBrkPtInfo.m_fnName); - const CMICmnMIValueResult miValueResult3("func", miValueConst3); - vwrMiValueTuple.Add(miValueResult3); - const CMICmnMIValueConst miValueConst5(vrBrkPtInfo.m_fileName); - const CMICmnMIValueResult miValueResult5("file", miValueConst5); - vwrMiValueTuple.Add(miValueResult5); - const CMIUtilString strN5 = CMIUtilString::Format("%s/%s", vrBrkPtInfo.m_path.c_str(), vrBrkPtInfo.m_fileName.c_str()); - const CMICmnMIValueConst miValueConst6(strN5); - const CMICmnMIValueResult miValueResult6("fullname", miValueConst6); - vwrMiValueTuple.Add(miValueResult6); - const CMIUtilString strLine(CMIUtilString::Format("%d", vrBrkPtInfo.m_nLine)); - const CMICmnMIValueConst miValueConst7(strLine); - const CMICmnMIValueResult miValueResult7("line", miValueConst7); - vwrMiValueTuple.Add(miValueResult7); +void CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtFrameInfo( + const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple) { + const CMIUtilString strAddr( + CMIUtilString::Format("0x%016" PRIx64, vrBrkPtInfo.m_pc)); + const CMICmnMIValueConst miValueConst2(strAddr); + const CMICmnMIValueResult miValueResult2("addr", miValueConst2); + vwrMiValueTuple.Add(miValueResult2); + const CMICmnMIValueConst miValueConst3(vrBrkPtInfo.m_fnName); + const CMICmnMIValueResult miValueResult3("func", miValueConst3); + vwrMiValueTuple.Add(miValueResult3); + const CMICmnMIValueConst miValueConst5(vrBrkPtInfo.m_fileName); + const CMICmnMIValueResult miValueResult5("file", miValueConst5); + vwrMiValueTuple.Add(miValueResult5); + const CMIUtilString strN5 = CMIUtilString::Format( + "%s/%s", vrBrkPtInfo.m_path.c_str(), vrBrkPtInfo.m_fileName.c_str()); + const CMICmnMIValueConst miValueConst6(strN5); + const CMICmnMIValueResult miValueResult6("fullname", miValueConst6); + vwrMiValueTuple.Add(miValueResult6); + const CMIUtilString strLine(CMIUtilString::Format("%d", vrBrkPtInfo.m_nLine)); + const CMICmnMIValueConst miValueConst7(strLine); + const CMICmnMIValueResult miValueResult7("line", miValueConst7); + vwrMiValueTuple.Add(miValueResult7); } -//++ ------------------------------------------------------------------------------------ -// Details: Form MI partial response by appending more MI value type objects to the +//++ +//------------------------------------------------------------------------------------ +// Details: Form MI partial response by appending more MI value type objects to +// the // tuple type object past in. // Type: Method. // Args: vrBrkPtInfo - (R) Break point information object. @@ -679,89 +697,94 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtFrameInfo(const SBrkPtInfo &vrBrk // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple) -{ - // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" PRIx64 "\", - // func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" - - // "number=" - const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", vrBrkPtInfo.m_id)); - const CMICmnMIValueResult miValueResult("number", miValueConst); - CMICmnMIValueTuple miValueTuple(miValueResult); - // "type=" - const CMICmnMIValueConst miValueConst2(vrBrkPtInfo.m_strType); - const CMICmnMIValueResult miValueResult2("type", miValueConst2); - miValueTuple.Add(miValueResult2); - // "disp=" - const CMICmnMIValueConst miValueConst3(vrBrkPtInfo.m_bDisp ? "del" : "keep"); - const CMICmnMIValueResult miValueResult3("disp", miValueConst3); - miValueTuple.Add(miValueResult3); - // "enabled=" - const CMICmnMIValueConst miValueConst4(vrBrkPtInfo.m_bEnabled ? "y" : "n"); - const CMICmnMIValueResult miValueResult4("enabled", miValueConst4); - miValueTuple.Add(miValueResult4); - // "addr=" - // "func=" - // "file=" - // "fullname=" - // "line=" - MIResponseFormBrkPtFrameInfo(vrBrkPtInfo, miValueTuple); - // "pending=" - if (vrBrkPtInfo.m_bPending) - { - const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strOrigLoc); - const CMICmnMIValueList miValueList(miValueConst); - const CMICmnMIValueResult miValueResult("pending", miValueList); - miValueTuple.Add(miValueResult); - } - if (vrBrkPtInfo.m_bHaveArgOptionThreadGrp) - { - const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strOptThrdGrp); - const CMICmnMIValueList miValueList(miValueConst); - const CMICmnMIValueResult miValueResult("thread-groups", miValueList); - miValueTuple.Add(miValueResult); - } - // "times=" - const CMICmnMIValueConst miValueConstB(CMIUtilString::Format("%d", vrBrkPtInfo.m_nTimes)); - const CMICmnMIValueResult miValueResultB("times", miValueConstB); - miValueTuple.Add(miValueResultB); - // "thread=" - if (vrBrkPtInfo.m_bBrkPtThreadId) - { - const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", vrBrkPtInfo.m_nBrkPtThreadId)); - const CMICmnMIValueResult miValueResult("thread", miValueConst); - miValueTuple.Add(miValueResult); - } - // "cond=" - if (vrBrkPtInfo.m_bCondition) - { - const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strCondition); - const CMICmnMIValueResult miValueResult("cond", miValueConst); - miValueTuple.Add(miValueResult); - } - // "ignore=" - if (vrBrkPtInfo.m_nIgnore != 0) - { - const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", vrBrkPtInfo.m_nIgnore)); - const CMICmnMIValueResult miValueResult("ignore", miValueConst); - miValueTuple.Add(miValueResult); - } - // "original-location=" - const CMICmnMIValueConst miValueConstC(vrBrkPtInfo.m_strOrigLoc); - const CMICmnMIValueResult miValueResultC("original-location", miValueConstC); - miValueTuple.Add(miValueResultC); - - vwrMiValueTuple = miValueTuple; - - return MIstatus::success; +bool CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtInfo( + const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple) { + // MI print + // "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" + // PRIx64 "\", + // func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" + + // "number=" + const CMICmnMIValueConst miValueConst( + CMIUtilString::Format("%d", vrBrkPtInfo.m_id)); + const CMICmnMIValueResult miValueResult("number", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + // "type=" + const CMICmnMIValueConst miValueConst2(vrBrkPtInfo.m_strType); + const CMICmnMIValueResult miValueResult2("type", miValueConst2); + miValueTuple.Add(miValueResult2); + // "disp=" + const CMICmnMIValueConst miValueConst3(vrBrkPtInfo.m_bDisp ? "del" : "keep"); + const CMICmnMIValueResult miValueResult3("disp", miValueConst3); + miValueTuple.Add(miValueResult3); + // "enabled=" + const CMICmnMIValueConst miValueConst4(vrBrkPtInfo.m_bEnabled ? "y" : "n"); + const CMICmnMIValueResult miValueResult4("enabled", miValueConst4); + miValueTuple.Add(miValueResult4); + // "addr=" + // "func=" + // "file=" + // "fullname=" + // "line=" + MIResponseFormBrkPtFrameInfo(vrBrkPtInfo, miValueTuple); + // "pending=" + if (vrBrkPtInfo.m_bPending) { + const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strOrigLoc); + const CMICmnMIValueList miValueList(miValueConst); + const CMICmnMIValueResult miValueResult("pending", miValueList); + miValueTuple.Add(miValueResult); + } + if (vrBrkPtInfo.m_bHaveArgOptionThreadGrp) { + const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strOptThrdGrp); + const CMICmnMIValueList miValueList(miValueConst); + const CMICmnMIValueResult miValueResult("thread-groups", miValueList); + miValueTuple.Add(miValueResult); + } + // "times=" + const CMICmnMIValueConst miValueConstB( + CMIUtilString::Format("%d", vrBrkPtInfo.m_nTimes)); + const CMICmnMIValueResult miValueResultB("times", miValueConstB); + miValueTuple.Add(miValueResultB); + // "thread=" + if (vrBrkPtInfo.m_bBrkPtThreadId) { + const CMICmnMIValueConst miValueConst( + CMIUtilString::Format("%d", vrBrkPtInfo.m_nBrkPtThreadId)); + const CMICmnMIValueResult miValueResult("thread", miValueConst); + miValueTuple.Add(miValueResult); + } + // "cond=" + if (vrBrkPtInfo.m_bCondition) { + const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strCondition); + const CMICmnMIValueResult miValueResult("cond", miValueConst); + miValueTuple.Add(miValueResult); + } + // "ignore=" + if (vrBrkPtInfo.m_nIgnore != 0) { + const CMICmnMIValueConst miValueConst( + CMIUtilString::Format("%d", vrBrkPtInfo.m_nIgnore)); + const CMICmnMIValueResult miValueResult("ignore", miValueConst); + miValueTuple.Add(miValueResult); + } + // "original-location=" + const CMICmnMIValueConst miValueConstC(vrBrkPtInfo.m_strOrigLoc); + const CMICmnMIValueResult miValueResultC("original-location", miValueConstC); + miValueTuple.Add(miValueResultC); + + vwrMiValueTuple = miValueTuple; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve breakpoint information and write into the given breakpoint information -// object. Note not all possible information is retrieved and so the information -// object may need to be filled in with more information after calling this -// function. Mainly breakpoint location information of information that is +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve breakpoint information and write into the given breakpoint +// information +// object. Note not all possible information is retrieved and so the +// information +// object may need to be filled in with more information after calling +// this +// function. Mainly breakpoint location information of information that +// is // unlikely to change. // Type: Method. // Args: vBrkPt - (R) LLDB break point object. @@ -770,99 +793,95 @@ CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtInfo(const SBrkPtInfo &vrBrkPtInf // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfo::GetBrkPtInfo(const lldb::SBBreakpoint &vBrkPt, SBrkPtInfo &vrwBrkPtInfo) const -{ - lldb::SBBreakpoint &rBrkPt = const_cast<lldb::SBBreakpoint &>(vBrkPt); - lldb::SBBreakpointLocation brkPtLoc = rBrkPt.GetLocationAtIndex(0); - lldb::SBAddress brkPtAddr = brkPtLoc.GetAddress(); - lldb::SBSymbolContext symbolCntxt = brkPtAddr.GetSymbolContext(lldb::eSymbolContextEverything); - const char *pUnkwn = "??"; - lldb::SBModule rModule = symbolCntxt.GetModule(); - const char *pModule = rModule.IsValid() ? rModule.GetFileSpec().GetFilename() : pUnkwn; - MIunused(pModule); - const char *pFile = pUnkwn; - const char *pFn = pUnkwn; - const char *pFilePath = pUnkwn; - size_t nLine = 0; - lldb::addr_t nAddr = brkPtAddr.GetLoadAddress(GetTarget()); - if (nAddr == LLDB_INVALID_ADDRESS) - nAddr = brkPtAddr.GetFileAddress(); - - lldb::SBCompileUnit rCmplUnit = symbolCntxt.GetCompileUnit(); - if (rCmplUnit.IsValid()) - { - lldb::SBFileSpec rFileSpec = rCmplUnit.GetFileSpec(); - pFile = rFileSpec.GetFilename(); - pFilePath = rFileSpec.GetDirectory(); - lldb::SBFunction rFn = symbolCntxt.GetFunction(); - if (rFn.IsValid()) - pFn = rFn.GetName(); - lldb::SBLineEntry rLnEntry = symbolCntxt.GetLineEntry(); - if (rLnEntry.GetLine() > 0) - nLine = rLnEntry.GetLine(); - } - - vrwBrkPtInfo.m_id = vBrkPt.GetID(); - vrwBrkPtInfo.m_strType = "breakpoint"; - vrwBrkPtInfo.m_pc = nAddr; - vrwBrkPtInfo.m_fnName = pFn; - vrwBrkPtInfo.m_fileName = pFile; - vrwBrkPtInfo.m_path = pFilePath; - vrwBrkPtInfo.m_nLine = nLine; - vrwBrkPtInfo.m_nTimes = vBrkPt.GetHitCount(); - - return MIstatus::success; +bool CMICmnLLDBDebugSessionInfo::GetBrkPtInfo(const lldb::SBBreakpoint &vBrkPt, + SBrkPtInfo &vrwBrkPtInfo) const { + lldb::SBBreakpoint &rBrkPt = const_cast<lldb::SBBreakpoint &>(vBrkPt); + lldb::SBBreakpointLocation brkPtLoc = rBrkPt.GetLocationAtIndex(0); + lldb::SBAddress brkPtAddr = brkPtLoc.GetAddress(); + lldb::SBSymbolContext symbolCntxt = + brkPtAddr.GetSymbolContext(lldb::eSymbolContextEverything); + const char *pUnkwn = "??"; + lldb::SBModule rModule = symbolCntxt.GetModule(); + const char *pModule = + rModule.IsValid() ? rModule.GetFileSpec().GetFilename() : pUnkwn; + MIunused(pModule); + const char *pFile = pUnkwn; + const char *pFn = pUnkwn; + const char *pFilePath = pUnkwn; + size_t nLine = 0; + lldb::addr_t nAddr = brkPtAddr.GetLoadAddress(GetTarget()); + if (nAddr == LLDB_INVALID_ADDRESS) + nAddr = brkPtAddr.GetFileAddress(); + + lldb::SBCompileUnit rCmplUnit = symbolCntxt.GetCompileUnit(); + if (rCmplUnit.IsValid()) { + lldb::SBFileSpec rFileSpec = rCmplUnit.GetFileSpec(); + pFile = rFileSpec.GetFilename(); + pFilePath = rFileSpec.GetDirectory(); + lldb::SBFunction rFn = symbolCntxt.GetFunction(); + if (rFn.IsValid()) + pFn = rFn.GetName(); + lldb::SBLineEntry rLnEntry = symbolCntxt.GetLineEntry(); + if (rLnEntry.GetLine() > 0) + nLine = rLnEntry.GetLine(); + } + + vrwBrkPtInfo.m_id = vBrkPt.GetID(); + vrwBrkPtInfo.m_strType = "breakpoint"; + vrwBrkPtInfo.m_pc = nAddr; + vrwBrkPtInfo.m_fnName = pFn; + vrwBrkPtInfo.m_fileName = pFile; + vrwBrkPtInfo.m_path = pFilePath; + vrwBrkPtInfo.m_nLine = nLine; + vrwBrkPtInfo.m_nTimes = vBrkPt.GetHitCount(); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Get current debugger. // Type: Method. // Args: None. // Return: lldb::SBDebugger - current debugger. // Throws: None. //-- -lldb::SBDebugger & -CMICmnLLDBDebugSessionInfo::GetDebugger() const -{ - return CMICmnLLDBDebugger::Instance().GetTheDebugger(); +lldb::SBDebugger &CMICmnLLDBDebugSessionInfo::GetDebugger() const { + return CMICmnLLDBDebugger::Instance().GetTheDebugger(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Get current listener. // Type: Method. // Args: None. // Return: lldb::SBListener - current listener. // Throws: None. //-- -lldb::SBListener & -CMICmnLLDBDebugSessionInfo::GetListener() const -{ - return CMICmnLLDBDebugger::Instance().GetTheListener(); +lldb::SBListener &CMICmnLLDBDebugSessionInfo::GetListener() const { + return CMICmnLLDBDebugger::Instance().GetTheListener(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Get current target. // Type: Method. // Args: None. // Return: lldb::SBTarget - current target. // Throws: None. //-- -lldb::SBTarget -CMICmnLLDBDebugSessionInfo::GetTarget() const -{ - return GetDebugger().GetSelectedTarget(); +lldb::SBTarget CMICmnLLDBDebugSessionInfo::GetTarget() const { + return GetDebugger().GetSelectedTarget(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Get current process. // Type: Method. // Args: None. // Return: lldb::SBProcess - current process. // Throws: None. //-- -lldb::SBProcess -CMICmnLLDBDebugSessionInfo::GetProcess() const -{ - return GetTarget().GetProcess(); +lldb::SBProcess CMICmnLLDBDebugSessionInfo::GetProcess() const { + return GetTarget().GetProcess(); } diff --git a/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h b/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h index dbad0c86159..818df3b81b1 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h +++ b/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.h @@ -10,19 +10,19 @@ #pragma once // Third party headers: -#include <map> -#include <vector> #include "lldb/API/SBDebugger.h" #include "lldb/API/SBListener.h" #include "lldb/API/SBProcess.h" #include "lldb/API/SBTarget.h" +#include <map> +#include <vector> // In-house headers: #include "MICmnBase.h" -#include "MIUtilSingletonBase.h" #include "MICmnLLDBDebugSessionInfoVarObj.h" #include "MICmnMIValueTuple.h" #include "MIUtilMapIdToVariant.h" +#include "MIUtilSingletonBase.h" #include "MIUtilThreadBaseStd.h" // Declarations: @@ -31,7 +31,8 @@ struct SMICmdData; class CMICmnMIValueTuple; class CMICmnMIValueList; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI debug session object that holds debugging information between // instances of MI commands executing their work and producing MI // result records. Information/data is set by one or many commands then @@ -39,186 +40,214 @@ class CMICmnMIValueList; // It primarily holds LLDB type objects. // A singleton class. //-- -class CMICmnLLDBDebugSessionInfo : public CMICmnBase, public MI::ISingleton<CMICmnLLDBDebugSessionInfo> -{ - friend class MI::ISingleton<CMICmnLLDBDebugSessionInfo>; +class CMICmnLLDBDebugSessionInfo + : public CMICmnBase, + public MI::ISingleton<CMICmnLLDBDebugSessionInfo> { + friend class MI::ISingleton<CMICmnLLDBDebugSessionInfo>; - // Structs: - public: - //++ ============================================================================ - // Details: Break point information object. Used to easily pass information about - // a break around and record break point information to be recalled by - // other commands or LLDB event handling functions. - //-- - struct SBrkPtInfo - { - SBrkPtInfo() - : m_id(0) - , m_bDisp(false) - , m_bEnabled(false) - , m_pc(0) - , m_nLine(0) - , m_bHaveArgOptionThreadGrp(false) - , m_nTimes(0) - , m_bPending(false) - , m_nIgnore(0) - , m_bCondition(false) - , m_bBrkPtThreadId(false) - , m_nBrkPtThreadId(0) - { - } + // Structs: +public: + //++ + //============================================================================ + // Details: Break point information object. Used to easily pass information + // about + // a break around and record break point information to be recalled + // by + // other commands or LLDB event handling functions. + //-- + struct SBrkPtInfo { + SBrkPtInfo() + : m_id(0), m_bDisp(false), m_bEnabled(false), m_pc(0), m_nLine(0), + m_bHaveArgOptionThreadGrp(false), m_nTimes(0), m_bPending(false), + m_nIgnore(0), m_bCondition(false), m_bBrkPtThreadId(false), + m_nBrkPtThreadId(0) {} - MIuint m_id; // LLDB break point ID. - CMIUtilString m_strType; // Break point type. - bool m_bDisp; // True = "del", false = "keep". - bool m_bEnabled; // True = enabled, false = disabled break point. - lldb::addr_t m_pc; // Address number. - CMIUtilString m_fnName; // Function name. - CMIUtilString m_fileName; // File name text. - CMIUtilString m_path; // Full file name and path text. - MIuint m_nLine; // File line number. - bool m_bHaveArgOptionThreadGrp; // True = include MI field, false = do not include "thread-groups". - CMIUtilString m_strOptThrdGrp; // Thread group number. - MIuint m_nTimes; // The count of the breakpoint existence. - CMIUtilString m_strOrigLoc; // The name of the break point. - bool m_bPending; // True = the breakpoint has not been established yet, false = location found - MIuint m_nIgnore; // The number of time the breakpoint is run over before it is stopped on a hit - bool m_bCondition; // True = break point is conditional, use condition expression, false = no condition - CMIUtilString m_strCondition; // Break point condition expression - bool m_bBrkPtThreadId; // True = break point is specified to work with a specific thread, false = no specified thread given - MIuint m_nBrkPtThreadId; // Restrict the breakpoint to the specified thread-id - }; + MIuint m_id; // LLDB break point ID. + CMIUtilString m_strType; // Break point type. + bool m_bDisp; // True = "del", false = "keep". + bool m_bEnabled; // True = enabled, false = disabled break point. + lldb::addr_t m_pc; // Address number. + CMIUtilString m_fnName; // Function name. + CMIUtilString m_fileName; // File name text. + CMIUtilString m_path; // Full file name and path text. + MIuint m_nLine; // File line number. + bool m_bHaveArgOptionThreadGrp; // True = include MI field, false = do not + // include "thread-groups". + CMIUtilString m_strOptThrdGrp; // Thread group number. + MIuint m_nTimes; // The count of the breakpoint existence. + CMIUtilString m_strOrigLoc; // The name of the break point. + bool m_bPending; // True = the breakpoint has not been established yet, + // false = location found + MIuint m_nIgnore; // The number of time the breakpoint is run over before it + // is stopped on a hit + bool m_bCondition; // True = break point is conditional, use condition + // expression, false = no condition + CMIUtilString m_strCondition; // Break point condition expression + bool m_bBrkPtThreadId; // True = break point is specified to work with a + // specific thread, false = no specified thread given + MIuint + m_nBrkPtThreadId; // Restrict the breakpoint to the specified thread-id + }; - // Enumerations: - public: - //++ =================================================================== - // Details: The type of variable used by MIResponseFormVariableInfo family functions. - //-- - enum VariableType_e - { - eVariableType_InScope = (1u << 0), // In scope only. - eVariableType_Statics = (1u << 1), // Statics. - eVariableType_Locals = (1u << 2), // Locals. - eVariableType_Arguments = (1u << 3) // Arguments. - }; + // Enumerations: +public: + //++ =================================================================== + // Details: The type of variable used by MIResponseFormVariableInfo family + // functions. + //-- + enum VariableType_e { + eVariableType_InScope = (1u << 0), // In scope only. + eVariableType_Statics = (1u << 1), // Statics. + eVariableType_Locals = (1u << 2), // Locals. + eVariableType_Arguments = (1u << 3) // Arguments. + }; - //++ =================================================================== - // Details: Determine the information that should be shown by using MIResponseFormVariableInfo family functions. - //-- - enum VariableInfoFormat_e - { - eVariableInfoFormat_NoValues = 0, - eVariableInfoFormat_AllValues = 1, - eVariableInfoFormat_SimpleValues = 2 - }; + //++ =================================================================== + // Details: Determine the information that should be shown by using + // MIResponseFormVariableInfo family functions. + //-- + enum VariableInfoFormat_e { + eVariableInfoFormat_NoValues = 0, + eVariableInfoFormat_AllValues = 1, + eVariableInfoFormat_SimpleValues = 2 + }; - //++ =================================================================== - // Details: Determine the information that should be shown by using MIResponseFormThreadInfo family functions. - //-- - enum ThreadInfoFormat_e - { - eThreadInfoFormat_NoFrames, - eThreadInfoFormat_AllFrames - }; + //++ =================================================================== + // Details: Determine the information that should be shown by using + // MIResponseFormThreadInfo family functions. + //-- + enum ThreadInfoFormat_e { + eThreadInfoFormat_NoFrames, + eThreadInfoFormat_AllFrames + }; - //++ =================================================================== - // Details: Determine the information that should be shown by using MIResponseFormFrameInfo family functions. - //-- - enum FrameInfoFormat_e - { - eFrameInfoFormat_NoArguments, - eFrameInfoFormat_AllArguments, - eFrameInfoFormat_AllArgumentsInSimpleForm - }; + //++ =================================================================== + // Details: Determine the information that should be shown by using + // MIResponseFormFrameInfo family functions. + //-- + enum FrameInfoFormat_e { + eFrameInfoFormat_NoArguments, + eFrameInfoFormat_AllArguments, + eFrameInfoFormat_AllArgumentsInSimpleForm + }; - // Typedefs: - public: - typedef std::vector<uint32_t> VecActiveThreadId_t; + // Typedefs: +public: + typedef std::vector<uint32_t> VecActiveThreadId_t; - // Methods: - public: - bool Initialize() override; - bool Shutdown() override; + // Methods: +public: + bool Initialize() override; + bool Shutdown() override; - // Variant type data which can be assigned and retrieved across all command instances - template <typename T> bool SharedDataAdd(const CMIUtilString &vKey, const T &vData); - template <typename T> bool SharedDataRetrieve(const CMIUtilString &vKey, T &vwData); - void SharedDataDestroy(); + // Variant type data which can be assigned and retrieved across all command + // instances + template <typename T> + bool SharedDataAdd(const CMIUtilString &vKey, const T &vData); + template <typename T> + bool SharedDataRetrieve(const CMIUtilString &vKey, T &vwData); + void SharedDataDestroy(); - // Common command required functionality - bool AccessPath(const CMIUtilString &vPath, bool &vwbYesAccessible); - bool ResolvePath(const SMICmdData &vCmdData, const CMIUtilString &vPath, CMIUtilString &vwrResolvedPath); - bool ResolvePath(const CMIUtilString &vstrUnknown, CMIUtilString &vwrResolvedPath); - bool MIResponseFormFrameInfo(const lldb::SBThread &vrThread, const MIuint vnLevel, - const FrameInfoFormat_e veFrameInfoFormat, CMICmnMIValueTuple &vwrMiValueTuple); - bool MIResponseFormThreadInfo(const SMICmdData &vCmdData, const lldb::SBThread &vrThread, - const ThreadInfoFormat_e veThreadInfoFormat, CMICmnMIValueTuple &vwrMIValueTuple); - bool MIResponseFormVariableInfo(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes, - const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList, - const MIuint vnMaxDepth = 10, const bool vbMarkArgs = false); - void MIResponseFormBrkPtFrameInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple); - bool MIResponseFormBrkPtInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple); - bool GetBrkPtInfo(const lldb::SBBreakpoint &vBrkPt, SBrkPtInfo &vrwBrkPtInfo) const; - bool RecordBrkPtInfo(const MIuint vnBrkPtId, const SBrkPtInfo &vrBrkPtInfo); - bool RecordBrkPtInfoGet(const MIuint vnBrkPtId, SBrkPtInfo &vrwBrkPtInfo) const; - bool RecordBrkPtInfoDelete(const MIuint vnBrkPtId); - CMIUtilThreadMutex& GetSessionMutex() { return m_sessionMutex;} - lldb::SBDebugger &GetDebugger() const; - lldb::SBListener &GetListener() const; - lldb::SBTarget GetTarget() const; - lldb::SBProcess GetProcess() const; + // Common command required functionality + bool AccessPath(const CMIUtilString &vPath, bool &vwbYesAccessible); + bool ResolvePath(const SMICmdData &vCmdData, const CMIUtilString &vPath, + CMIUtilString &vwrResolvedPath); + bool ResolvePath(const CMIUtilString &vstrUnknown, + CMIUtilString &vwrResolvedPath); + bool MIResponseFormFrameInfo(const lldb::SBThread &vrThread, + const MIuint vnLevel, + const FrameInfoFormat_e veFrameInfoFormat, + CMICmnMIValueTuple &vwrMiValueTuple); + bool MIResponseFormThreadInfo(const SMICmdData &vCmdData, + const lldb::SBThread &vrThread, + const ThreadInfoFormat_e veThreadInfoFormat, + CMICmnMIValueTuple &vwrMIValueTuple); + bool MIResponseFormVariableInfo(const lldb::SBFrame &vrFrame, + const MIuint vMaskVarTypes, + const VariableInfoFormat_e veVarInfoFormat, + CMICmnMIValueList &vwrMiValueList, + const MIuint vnMaxDepth = 10, + const bool vbMarkArgs = false); + void MIResponseFormBrkPtFrameInfo(const SBrkPtInfo &vrBrkPtInfo, + CMICmnMIValueTuple &vwrMiValueTuple); + bool MIResponseFormBrkPtInfo(const SBrkPtInfo &vrBrkPtInfo, + CMICmnMIValueTuple &vwrMiValueTuple); + bool GetBrkPtInfo(const lldb::SBBreakpoint &vBrkPt, + SBrkPtInfo &vrwBrkPtInfo) const; + bool RecordBrkPtInfo(const MIuint vnBrkPtId, const SBrkPtInfo &vrBrkPtInfo); + bool RecordBrkPtInfoGet(const MIuint vnBrkPtId, + SBrkPtInfo &vrwBrkPtInfo) const; + bool RecordBrkPtInfoDelete(const MIuint vnBrkPtId); + CMIUtilThreadMutex &GetSessionMutex() { return m_sessionMutex; } + lldb::SBDebugger &GetDebugger() const; + lldb::SBListener &GetListener() const; + lldb::SBTarget GetTarget() const; + lldb::SBProcess GetProcess() const; - // Attributes: - public: - // The following are available to all command instances - const MIuint m_nBrkPointCntMax; - VecActiveThreadId_t m_vecActiveThreadId; - lldb::tid_t m_currentSelectedThread; + // Attributes: +public: + // The following are available to all command instances + const MIuint m_nBrkPointCntMax; + VecActiveThreadId_t m_vecActiveThreadId; + lldb::tid_t m_currentSelectedThread; - // These are keys that can be used to access the shared data map - // Note: This list is expected to grow and will be moved and abstracted in the future. - const CMIUtilString m_constStrSharedDataKeyWkDir; - const CMIUtilString m_constStrSharedDataSolibPath; - const CMIUtilString m_constStrPrintCharArrayAsString; - const CMIUtilString m_constStrPrintExpandAggregates; - const CMIUtilString m_constStrPrintAggregateFieldNames; + // These are keys that can be used to access the shared data map + // Note: This list is expected to grow and will be moved and abstracted in the + // future. + const CMIUtilString m_constStrSharedDataKeyWkDir; + const CMIUtilString m_constStrSharedDataSolibPath; + const CMIUtilString m_constStrPrintCharArrayAsString; + const CMIUtilString m_constStrPrintExpandAggregates; + const CMIUtilString m_constStrPrintAggregateFieldNames; - // Typedefs: - private: - typedef std::vector<CMICmnLLDBDebugSessionInfoVarObj> VecVarObj_t; - typedef std::map<MIuint, SBrkPtInfo> MapBrkPtIdToBrkPtInfo_t; - typedef std::pair<MIuint, SBrkPtInfo> MapPairBrkPtIdToBrkPtInfo_t; + // Typedefs: +private: + typedef std::vector<CMICmnLLDBDebugSessionInfoVarObj> VecVarObj_t; + typedef std::map<MIuint, SBrkPtInfo> MapBrkPtIdToBrkPtInfo_t; + typedef std::pair<MIuint, SBrkPtInfo> MapPairBrkPtIdToBrkPtInfo_t; - // Methods: - private: - /* ctor */ CMICmnLLDBDebugSessionInfo(); - /* ctor */ CMICmnLLDBDebugSessionInfo(const CMICmnLLDBDebugSessionInfo &); - void operator=(const CMICmnLLDBDebugSessionInfo &); - // - bool GetVariableInfo(const lldb::SBValue &vrValue, const bool vbInSimpleForm, CMIUtilString &vwrStrValue); - bool GetFrameInfo(const lldb::SBFrame &vrFrame, lldb::addr_t &vwPc, CMIUtilString &vwFnName, CMIUtilString &vwFileName, - CMIUtilString &vwPath, MIuint &vwnLine); - bool GetThreadFrames(const SMICmdData &vCmdData, const MIuint vThreadIdx, const FrameInfoFormat_e veFrameInfoFormat, - CMIUtilString &vwrThreadFrames); - bool MIResponseForVariableInfoInternal(const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList, - const lldb::SBValueList &vwrSBValueList, const MIuint vnMaxDepth, const bool vbIsArgs, const bool vbMarkArgs); + // Methods: +private: + /* ctor */ CMICmnLLDBDebugSessionInfo(); + /* ctor */ CMICmnLLDBDebugSessionInfo(const CMICmnLLDBDebugSessionInfo &); + void operator=(const CMICmnLLDBDebugSessionInfo &); + // + bool GetVariableInfo(const lldb::SBValue &vrValue, const bool vbInSimpleForm, + CMIUtilString &vwrStrValue); + bool GetFrameInfo(const lldb::SBFrame &vrFrame, lldb::addr_t &vwPc, + CMIUtilString &vwFnName, CMIUtilString &vwFileName, + CMIUtilString &vwPath, MIuint &vwnLine); + bool GetThreadFrames(const SMICmdData &vCmdData, const MIuint vThreadIdx, + const FrameInfoFormat_e veFrameInfoFormat, + CMIUtilString &vwrThreadFrames); + bool + MIResponseForVariableInfoInternal(const VariableInfoFormat_e veVarInfoFormat, + CMICmnMIValueList &vwrMiValueList, + const lldb::SBValueList &vwrSBValueList, + const MIuint vnMaxDepth, + const bool vbIsArgs, const bool vbMarkArgs); - // Overridden: - private: - // From CMICmnBase - /* dtor */ ~CMICmnLLDBDebugSessionInfo() override; + // Overridden: +private: + // From CMICmnBase + /* dtor */ ~CMICmnLLDBDebugSessionInfo() override; - // Attributes: - private: - CMIUtilMapIdToVariant m_mapIdToSessionData; // Hold and retrieve key to value data available across all commands - VecVarObj_t m_vecVarObj; // Vector of session variable objects - MapBrkPtIdToBrkPtInfo_t m_mapBrkPtIdToBrkPtInfo; - CMIUtilThreadMutex m_sessionMutex; + // Attributes: +private: + CMIUtilMapIdToVariant m_mapIdToSessionData; // Hold and retrieve key to value + // data available across all + // commands + VecVarObj_t m_vecVarObj; // Vector of session variable objects + MapBrkPtIdToBrkPtInfo_t m_mapBrkPtIdToBrkPtInfo; + CMIUtilThreadMutex m_sessionMutex; }; -//++ ------------------------------------------------------------------------------------ -// Details: Command instances can create and share data between other instances of commands. -// This function adds new data to the shared data. Using the same ID more than +//++ +//------------------------------------------------------------------------------------ +// Details: Command instances can create and share data between other instances +// of commands. +// This function adds new data to the shared data. Using the same ID +// more than // once replaces any previous matching data keys. // Type: Template method. // Args: T - The type of the object to be stored. @@ -229,39 +258,38 @@ class CMICmnLLDBDebugSessionInfo : public CMICmnBase, public MI::ISingleton<CMIC // Throws: None. //-- template <typename T> -bool -CMICmnLLDBDebugSessionInfo::SharedDataAdd(const CMIUtilString &vKey, const T &vData) -{ - if (!m_mapIdToSessionData.Add<T>(vKey, vData)) - { - SetErrorDescription(m_mapIdToSessionData.GetErrorDescription()); - return MIstatus::failure; - } +bool CMICmnLLDBDebugSessionInfo::SharedDataAdd(const CMIUtilString &vKey, + const T &vData) { + if (!m_mapIdToSessionData.Add<T>(vKey, vData)) { + SetErrorDescription(m_mapIdToSessionData.GetErrorDescription()); + return MIstatus::failure; + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Command instances can create and share data between other instances of commands. +//++ +//------------------------------------------------------------------------------------ +// Details: Command instances can create and share data between other instances +// of commands. // This function retrieves data from the shared data container. // Type: Method. // Args: T - The type of the object being retrieved. // vKey - (R) A non empty unique data key to retrieve the data by. // vData - (W) The data. -// Return: bool - True = data found, false = data not found or an error occurred trying to fetch. +// Return: bool - True = data found, false = data not found or an error +// occurred trying to fetch. // Throws: None. //-- template <typename T> -bool -CMICmnLLDBDebugSessionInfo::SharedDataRetrieve(const CMIUtilString &vKey, T &vwData) -{ - bool bDataFound = false; +bool CMICmnLLDBDebugSessionInfo::SharedDataRetrieve(const CMIUtilString &vKey, + T &vwData) { + bool bDataFound = false; - if (!m_mapIdToSessionData.Get<T>(vKey, vwData, bDataFound)) - { - SetErrorDescription(m_mapIdToSessionData.GetErrorDescription()); - return MIstatus::failure; - } + if (!m_mapIdToSessionData.Get<T>(vKey, vwData, bDataFound)) { + SetErrorDescription(m_mapIdToSessionData.GetErrorDescription()); + return MIstatus::failure; + } - return bDataFound; + return bDataFound; } diff --git a/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp b/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp index d4d2896f7ee..234b4e631b4 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp +++ b/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp @@ -16,16 +16,20 @@ const char *CMICmnLLDBDebugSessionInfoVarObj::ms_aVarFormatStrings[] = { // CODETAG_SESSIONINFO_VARFORMAT_ENUM // *** Order is import here. - "<Invalid var format>", "binary", "octal", "decimal", "hexadecimal", "natural"}; + "<Invalid var format>", "binary", "octal", "decimal", + "hexadecimal", "natural"}; const char *CMICmnLLDBDebugSessionInfoVarObj::ms_aVarFormatChars[] = { // CODETAG_SESSIONINFO_VARFORMAT_ENUM // *** Order is import here. "<Invalid var format>", "t", "o", "d", "x", "N"}; -CMICmnLLDBDebugSessionInfoVarObj::MapKeyToVarObj_t CMICmnLLDBDebugSessionInfoVarObj::ms_mapVarIdToVarObj; +CMICmnLLDBDebugSessionInfoVarObj::MapKeyToVarObj_t + CMICmnLLDBDebugSessionInfoVarObj::ms_mapVarIdToVarObj; MIuint CMICmnLLDBDebugSessionInfoVarObj::ms_nVarUniqueId = 0; // Index from 0 -CMICmnLLDBDebugSessionInfoVarObj::varFormat_e CMICmnLLDBDebugSessionInfoVarObj::ms_eDefaultFormat = eVarFormat_Natural; +CMICmnLLDBDebugSessionInfoVarObj::varFormat_e + CMICmnLLDBDebugSessionInfoVarObj::ms_eDefaultFormat = eVarFormat_Natural; -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLLDBDebugSessionInfoVarObj constructor. // Type: Method. // Args: None. @@ -33,119 +37,124 @@ CMICmnLLDBDebugSessionInfoVarObj::varFormat_e CMICmnLLDBDebugSessionInfoVarObj:: // Throws: None. //-- CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj() - : m_eVarFormat(eVarFormat_Natural) - , m_eVarType(eVarType_Internal) -{ - // Do not call UpdateValue() in here as not necessary + : m_eVarFormat(eVarFormat_Natural), m_eVarType(eVarType_Internal) { + // Do not call UpdateValue() in here as not necessary } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLLDBDebugSessionInfoVarObj constructor. // Type: Method. -// Args: vrStrNameReal - (R) The actual name of the variable, the expression. +// Args: vrStrNameReal - (R) The actual name of the variable, the +// expression. // vrStrName - (R) The name given for *this var object. -// vrValue - (R) The LLDB SBValue object represented by *this object. +// vrValue - (R) The LLDB SBValue object represented by *this +// object. // Return: None. // Throws: None. //-- -CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj(const CMIUtilString &vrStrNameReal, const CMIUtilString &vrStrName, - const lldb::SBValue &vrValue) - : m_eVarFormat(eVarFormat_Natural) - , m_eVarType(eVarType_Internal) - , m_strName(vrStrName) - , m_SBValue(vrValue) - , m_strNameReal(vrStrNameReal) -{ - UpdateValue(); +CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj( + const CMIUtilString &vrStrNameReal, const CMIUtilString &vrStrName, + const lldb::SBValue &vrValue) + : m_eVarFormat(eVarFormat_Natural), m_eVarType(eVarType_Internal), + m_strName(vrStrName), m_SBValue(vrValue), m_strNameReal(vrStrNameReal) { + UpdateValue(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLLDBDebugSessionInfoVarObj constructor. // Type: Method. -// Args: vrStrNameReal - (R) The actual name of the variable, the expression. +// Args: vrStrNameReal - (R) The actual name of the variable, the +// expression. // vrStrName - (R) The name given for *this var object. -// vrValue - (R) The LLDB SBValue object represented by *this object. -// vrStrVarObjParentName - (R) The var object parent to *this var object (LLDB SBValue equivalent). +// vrValue - (R) The LLDB SBValue object represented by +// *this object. +// vrStrVarObjParentName - (R) The var object parent to *this var +// object (LLDB SBValue equivalent). // Return: None. // Throws: None. //-- -CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj(const CMIUtilString &vrStrNameReal, const CMIUtilString &vrStrName, - const lldb::SBValue &vrValue, const CMIUtilString &vrStrVarObjParentName) - : m_eVarFormat(eVarFormat_Natural) - , m_eVarType(eVarType_Internal) - , m_strName(vrStrName) - , m_SBValue(vrValue) - , m_strNameReal(vrStrNameReal) - , m_strVarObjParentName(vrStrVarObjParentName) -{ - UpdateValue(); +CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj( + const CMIUtilString &vrStrNameReal, const CMIUtilString &vrStrName, + const lldb::SBValue &vrValue, const CMIUtilString &vrStrVarObjParentName) + : m_eVarFormat(eVarFormat_Natural), m_eVarType(eVarType_Internal), + m_strName(vrStrName), m_SBValue(vrValue), m_strNameReal(vrStrNameReal), + m_strVarObjParentName(vrStrVarObjParentName) { + UpdateValue(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLLDBDebugSessionInfoVarObj copy constructor. // Type: Method. // Args: vrOther - (R) The object to copy from. // Return: None. // Throws: None. //-- -CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj(const CMICmnLLDBDebugSessionInfoVarObj &vrOther) -{ - CopyOther(vrOther); +CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj( + const CMICmnLLDBDebugSessionInfoVarObj &vrOther) { + CopyOther(vrOther); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLLDBDebugSessionInfoVarObj copy constructor. // Type: Method. // Args: vrOther - (R) The object to copy from. // Return: None. // Throws: None. //-- -CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj(CMICmnLLDBDebugSessionInfoVarObj &vrOther) -{ - CopyOther(vrOther); +CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj( + CMICmnLLDBDebugSessionInfoVarObj &vrOther) { + CopyOther(vrOther); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLLDBDebugSessionInfoVarObj move constructor. // Type: Method. // Args: vrwOther - (R) The object to copy from. // Return: None. // Throws: None. //-- -CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj(CMICmnLLDBDebugSessionInfoVarObj &&vrwOther) -{ - MoveOther(vrwOther); +CMICmnLLDBDebugSessionInfoVarObj::CMICmnLLDBDebugSessionInfoVarObj( + CMICmnLLDBDebugSessionInfoVarObj &&vrwOther) { + MoveOther(vrwOther); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLLDBDebugSessionInfoVarObj assignment operator. // Type: Method. // Args: vrOther - (R) The object to copy from. // Return: CMICmnLLDBDebugSessionInfoVarObj & - Updated *this object. // Throws: None. //-- -CMICmnLLDBDebugSessionInfoVarObj &CMICmnLLDBDebugSessionInfoVarObj::operator=(const CMICmnLLDBDebugSessionInfoVarObj &vrOther) -{ - CopyOther(vrOther); +CMICmnLLDBDebugSessionInfoVarObj &CMICmnLLDBDebugSessionInfoVarObj:: +operator=(const CMICmnLLDBDebugSessionInfoVarObj &vrOther) { + CopyOther(vrOther); - return *this; + return *this; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLLDBDebugSessionInfoVarObj assignment operator. // Type: Method. // Args: vrwOther - (R) The object to copy from. // Return: CMICmnLLDBDebugSessionInfoVarObj & - Updated *this object. // Throws: None. //-- -CMICmnLLDBDebugSessionInfoVarObj &CMICmnLLDBDebugSessionInfoVarObj::operator=(CMICmnLLDBDebugSessionInfoVarObj &&vrwOther) -{ - MoveOther(vrwOther); +CMICmnLLDBDebugSessionInfoVarObj &CMICmnLLDBDebugSessionInfoVarObj:: +operator=(CMICmnLLDBDebugSessionInfoVarObj &&vrwOther) { + MoveOther(vrwOther); - return *this; + return *this; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Copy the other instance of that object to *this object. // Type: Method. // Args: vrOther - (R) The object to copy from. @@ -153,25 +162,25 @@ CMICmnLLDBDebugSessionInfoVarObj &CMICmnLLDBDebugSessionInfoVarObj::operator=(CM // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfoVarObj::CopyOther(const CMICmnLLDBDebugSessionInfoVarObj &vrOther) -{ - // Check for self-assignment - if (this == &vrOther) - return MIstatus::success; +bool CMICmnLLDBDebugSessionInfoVarObj::CopyOther( + const CMICmnLLDBDebugSessionInfoVarObj &vrOther) { + // Check for self-assignment + if (this == &vrOther) + return MIstatus::success; - m_eVarFormat = vrOther.m_eVarFormat; - m_eVarType = vrOther.m_eVarType; - m_strName = vrOther.m_strName; - m_SBValue = vrOther.m_SBValue; - m_strNameReal = vrOther.m_strNameReal; - m_strFormattedValue = vrOther.m_strFormattedValue; - m_strVarObjParentName = vrOther.m_strVarObjParentName; + m_eVarFormat = vrOther.m_eVarFormat; + m_eVarType = vrOther.m_eVarType; + m_strName = vrOther.m_strName; + m_SBValue = vrOther.m_SBValue; + m_strNameReal = vrOther.m_strNameReal; + m_strFormattedValue = vrOther.m_strFormattedValue; + m_strVarObjParentName = vrOther.m_strVarObjParentName; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Move that object to *this object. // Type: Method. // Args: vrwOther - (RW) The object to copy from. @@ -179,37 +188,36 @@ CMICmnLLDBDebugSessionInfoVarObj::CopyOther(const CMICmnLLDBDebugSessionInfoVarO // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfoVarObj::MoveOther(CMICmnLLDBDebugSessionInfoVarObj &vrwOther) -{ - // Check for self-assignment - if (this == &vrwOther) - return MIstatus::success; +bool CMICmnLLDBDebugSessionInfoVarObj::MoveOther( + CMICmnLLDBDebugSessionInfoVarObj &vrwOther) { + // Check for self-assignment + if (this == &vrwOther) + return MIstatus::success; - CopyOther(vrwOther); - vrwOther.m_eVarFormat = eVarFormat_Natural; - vrwOther.m_eVarType = eVarType_Internal; - vrwOther.m_strName.clear(); - vrwOther.m_SBValue.Clear(); - vrwOther.m_strNameReal.clear(); - vrwOther.m_strFormattedValue.clear(); - vrwOther.m_strVarObjParentName.clear(); + CopyOther(vrwOther); + vrwOther.m_eVarFormat = eVarFormat_Natural; + vrwOther.m_eVarType = eVarType_Internal; + vrwOther.m_strName.clear(); + vrwOther.m_SBValue.Clear(); + vrwOther.m_strNameReal.clear(); + vrwOther.m_strFormattedValue.clear(); + vrwOther.m_strVarObjParentName.clear(); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLLDBDebugSessionInfoVarObj destructor. // Type: Overridden. // Args: None. // Return: None. // Throws: None. //-- -CMICmnLLDBDebugSessionInfoVarObj::~CMICmnLLDBDebugSessionInfoVarObj() -{ -} +CMICmnLLDBDebugSessionInfoVarObj::~CMICmnLLDBDebugSessionInfoVarObj() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the var format enumeration for the specified string. // Type: Static method. // Args: vrStrFormat - (R) Text description of the var format. @@ -218,20 +226,20 @@ CMICmnLLDBDebugSessionInfoVarObj::~CMICmnLLDBDebugSessionInfoVarObj() // Throws: None. //-- CMICmnLLDBDebugSessionInfoVarObj::varFormat_e -CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForString(const CMIUtilString &vrStrFormat) -{ - // CODETAG_SESSIONINFO_VARFORMAT_ENUM - for (MIuint i = 0; i < eVarFormat_count; i++) - { - const char *pVarFormatString = ms_aVarFormatStrings[i]; - if (vrStrFormat == pVarFormatString) - return static_cast<varFormat_e>(i); - } +CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForString( + const CMIUtilString &vrStrFormat) { + // CODETAG_SESSIONINFO_VARFORMAT_ENUM + for (MIuint i = 0; i < eVarFormat_count; i++) { + const char *pVarFormatString = ms_aVarFormatStrings[i]; + if (vrStrFormat == pVarFormatString) + return static_cast<varFormat_e>(i); + } - return eVarFormat_Invalid; + return eVarFormat_Invalid; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the var format enumeration for the specified character. // Type: Static method. // Args: vcFormat - Character representing the var format. @@ -240,29 +248,33 @@ CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForString(const CMIUtilString &vrS // Throws: None. //-- CMICmnLLDBDebugSessionInfoVarObj::varFormat_e -CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar(char vcFormat) -{ - if ('r' == vcFormat) - return eVarFormat_Hex; - - // CODETAG_SESSIONINFO_VARFORMAT_ENUM - for (MIuint i = 0; i < eVarFormat_count; i++) - { - const char *pVarFormatChar = ms_aVarFormatChars[i]; - if (*pVarFormatChar == vcFormat) - return static_cast<varFormat_e>(i); - } - - return eVarFormat_Invalid; -} - -//++ ------------------------------------------------------------------------------------ -// Details: Return the equivalent var value formatted string for the given value type, -// which was prepared for printing (i.e. value was escaped and now it's ready +CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar(char vcFormat) { + if ('r' == vcFormat) + return eVarFormat_Hex; + + // CODETAG_SESSIONINFO_VARFORMAT_ENUM + for (MIuint i = 0; i < eVarFormat_count; i++) { + const char *pVarFormatChar = ms_aVarFormatChars[i]; + if (*pVarFormatChar == vcFormat) + return static_cast<varFormat_e>(i); + } + + return eVarFormat_Invalid; +} + +//++ +//------------------------------------------------------------------------------------ +// Details: Return the equivalent var value formatted string for the given value +// type, +// which was prepared for printing (i.e. value was escaped and now it's +// ready // for wrapping into quotes). -// The SBValue vrValue parameter is checked by LLDB private code for valid -// scalar type via MI Driver proxy function as the valued returned can also be -// an error condition. The proxy function determines if the check was valid +// The SBValue vrValue parameter is checked by LLDB private code for +// valid +// scalar type via MI Driver proxy function as the valued returned can +// also be +// an error condition. The proxy function determines if the check was +// valid // otherwise return an error condition state by other means saying so. // Type: Static method. // Args: vrValue - (R) The var value object. @@ -270,127 +282,124 @@ CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar(char vcFormat) // Returns: CMIUtilString - Value formatted string. // Throws: None. //-- -CMIUtilString -CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(const lldb::SBValue &vrValue, - const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat) -{ - const CMICmnLLDBUtilSBValue utilValue(vrValue, true); - if (utilValue.IsIntegerType()) - { - MIuint64 nValue = 0; - if (CMICmnLLDBProxySBValue::GetValueAsUnsigned(vrValue, nValue)) - { - lldb::SBValue &rValue = const_cast<lldb::SBValue &>(vrValue); - return GetStringFormatted(nValue, rValue.GetValue(), veVarFormat); - } +CMIUtilString CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted( + const lldb::SBValue &vrValue, + const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat) { + const CMICmnLLDBUtilSBValue utilValue(vrValue, true); + if (utilValue.IsIntegerType()) { + MIuint64 nValue = 0; + if (CMICmnLLDBProxySBValue::GetValueAsUnsigned(vrValue, nValue)) { + lldb::SBValue &rValue = const_cast<lldb::SBValue &>(vrValue); + return GetStringFormatted(nValue, rValue.GetValue(), veVarFormat); } + } - return utilValue.GetValue().AddSlashes(); + return utilValue.GetValue().AddSlashes(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Return number formatted string according to the given value type. // Type: Static method. // Args: vnValue - (R) The number value to get formatted. -// vpStrValueNatural - (R) The natural representation of the number value. +// vpStrValueNatural - (R) The natural representation of the number +// value. // veVarFormat - (R) Var format enumeration. // Returns: CMIUtilString - Numerical formatted string. // Throws: None. //-- -CMIUtilString -CMICmnLLDBDebugSessionInfoVarObj::GetStringFormatted(const MIuint64 vnValue, const char *vpStrValueNatural, - const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat) -{ - CMIUtilString strFormattedValue; - CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veFormat = veVarFormat; - if (ms_eDefaultFormat != eVarFormat_Invalid && veVarFormat == eVarFormat_Natural) - { - veFormat = ms_eDefaultFormat; - } - - switch (veFormat) - { - case eVarFormat_Binary: - strFormattedValue = CMIUtilString::FormatBinary(vnValue); - break; - case eVarFormat_Octal: - strFormattedValue = CMIUtilString::Format("0%llo", vnValue); - break; - case eVarFormat_Decimal: - strFormattedValue = CMIUtilString::Format("%lld", vnValue); - break; - case eVarFormat_Hex: - strFormattedValue = CMIUtilString::Format("0x%llx", vnValue); - break; - case eVarFormat_Natural: - default: - { - strFormattedValue = (vpStrValueNatural != nullptr) ? vpStrValueNatural : ""; - } - } - - return strFormattedValue; -} - -//++ ------------------------------------------------------------------------------------ +CMIUtilString CMICmnLLDBDebugSessionInfoVarObj::GetStringFormatted( + const MIuint64 vnValue, const char *vpStrValueNatural, + const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat) { + CMIUtilString strFormattedValue; + CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veFormat = veVarFormat; + if (ms_eDefaultFormat != eVarFormat_Invalid && + veVarFormat == eVarFormat_Natural) { + veFormat = ms_eDefaultFormat; + } + + switch (veFormat) { + case eVarFormat_Binary: + strFormattedValue = CMIUtilString::FormatBinary(vnValue); + break; + case eVarFormat_Octal: + strFormattedValue = CMIUtilString::Format("0%llo", vnValue); + break; + case eVarFormat_Decimal: + strFormattedValue = CMIUtilString::Format("%lld", vnValue); + break; + case eVarFormat_Hex: + strFormattedValue = CMIUtilString::Format("0x%llx", vnValue); + break; + case eVarFormat_Natural: + default: { + strFormattedValue = (vpStrValueNatural != nullptr) ? vpStrValueNatural : ""; + } + } + + return strFormattedValue; +} + +//++ +//------------------------------------------------------------------------------------ // Details: Delete internal container contents. // Type: Static method. // Args: None. // Returns: None. // Throws: None. //-- -void -CMICmnLLDBDebugSessionInfoVarObj::VarObjClear() -{ - ms_mapVarIdToVarObj.clear(); +void CMICmnLLDBDebugSessionInfoVarObj::VarObjClear() { + ms_mapVarIdToVarObj.clear(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Add a var object to the internal container. // Type: Static method. // Args: vrVarObj - (R) The var value object. // Returns: None. // Throws: None. //-- -void -CMICmnLLDBDebugSessionInfoVarObj::VarObjAdd(const CMICmnLLDBDebugSessionInfoVarObj &vrVarObj) -{ - VarObjDelete(vrVarObj.GetName()); - MapPairKeyToVarObj_t pr(vrVarObj.GetName(), vrVarObj); - ms_mapVarIdToVarObj.insert(pr); +void CMICmnLLDBDebugSessionInfoVarObj::VarObjAdd( + const CMICmnLLDBDebugSessionInfoVarObj &vrVarObj) { + VarObjDelete(vrVarObj.GetName()); + MapPairKeyToVarObj_t pr(vrVarObj.GetName(), vrVarObj); + ms_mapVarIdToVarObj.insert(pr); } -//++ ------------------------------------------------------------------------------------ -// Details: Delete the var object from the internal container matching the specified name. +//++ +//------------------------------------------------------------------------------------ +// Details: Delete the var object from the internal container matching the +// specified name. // Type: Static method. // Args: vrVarName - (R) The var value name. // Returns: None. // Throws: None. //-- -void -CMICmnLLDBDebugSessionInfoVarObj::VarObjDelete(const CMIUtilString &vrVarName) -{ - const MapKeyToVarObj_t::const_iterator it = ms_mapVarIdToVarObj.find(vrVarName); - if (it != ms_mapVarIdToVarObj.end()) - { - ms_mapVarIdToVarObj.erase(it); - } +void CMICmnLLDBDebugSessionInfoVarObj::VarObjDelete( + const CMIUtilString &vrVarName) { + const MapKeyToVarObj_t::const_iterator it = + ms_mapVarIdToVarObj.find(vrVarName); + if (it != ms_mapVarIdToVarObj.end()) { + ms_mapVarIdToVarObj.erase(it); + } } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Update an existing var object in the internal container. // Type: Static method. // Args: vrVarObj - (R) The var value object. // Returns: None. // Throws: None. //-- -void -CMICmnLLDBDebugSessionInfoVarObj::VarObjUpdate(const CMICmnLLDBDebugSessionInfoVarObj &vrVarObj) -{ - VarObjAdd(vrVarObj); +void CMICmnLLDBDebugSessionInfoVarObj::VarObjUpdate( + const CMICmnLLDBDebugSessionInfoVarObj &vrVarObj) { + VarObjAdd(vrVarObj); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the var object matching the specified name. // Type: Static method. // Args: vrVarName - (R) The var value name. @@ -398,104 +407,102 @@ CMICmnLLDBDebugSessionInfoVarObj::VarObjUpdate(const CMICmnLLDBDebugSessionInfoV // Returns: bool - True = object found, false = object not found. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfoVarObj::VarObjGet(const CMIUtilString &vrVarName, CMICmnLLDBDebugSessionInfoVarObj &vrwVarObj) -{ - const MapKeyToVarObj_t::const_iterator it = ms_mapVarIdToVarObj.find(vrVarName); - if (it != ms_mapVarIdToVarObj.end()) - { - const CMICmnLLDBDebugSessionInfoVarObj &rVarObj = (*it).second; - vrwVarObj = rVarObj; - return true; - } +bool CMICmnLLDBDebugSessionInfoVarObj::VarObjGet( + const CMIUtilString &vrVarName, + CMICmnLLDBDebugSessionInfoVarObj &vrwVarObj) { + const MapKeyToVarObj_t::const_iterator it = + ms_mapVarIdToVarObj.find(vrVarName); + if (it != ms_mapVarIdToVarObj.end()) { + const CMICmnLLDBDebugSessionInfoVarObj &rVarObj = (*it).second; + vrwVarObj = rVarObj; + return true; + } - return false; + return false; } -//++ ------------------------------------------------------------------------------------ -// Details: A count is kept of the number of var value objects created. This is count is +//++ +//------------------------------------------------------------------------------------ +// Details: A count is kept of the number of var value objects created. This is +// count is // used to ID the var value object. Reset the count to 0. // Type: Static method. // Args: None. // Returns: None. // Throws: None. //-- -void -CMICmnLLDBDebugSessionInfoVarObj::VarObjIdResetToZero() -{ - ms_nVarUniqueId = 0; +void CMICmnLLDBDebugSessionInfoVarObj::VarObjIdResetToZero() { + ms_nVarUniqueId = 0; } -//++ ------------------------------------------------------------------------------------ -// Details: Default format is globally used as the data format when "natural" is in effect, that is, this overrides the default +//++ +//------------------------------------------------------------------------------------ +// Details: Default format is globally used as the data format when "natural" is +// in effect, that is, this overrides the default // Type: Static method. // Args: None. // Returns: None. // Throws: None. //-- -void -CMICmnLLDBDebugSessionInfoVarObj::VarObjSetFormat(varFormat_e eDefaultFormat) -{ - ms_eDefaultFormat = eDefaultFormat; +void CMICmnLLDBDebugSessionInfoVarObj::VarObjSetFormat( + varFormat_e eDefaultFormat) { + ms_eDefaultFormat = eDefaultFormat; } - -//++ ------------------------------------------------------------------------------------ -// Details: A count is kept of the number of var value objects created. This is count is +//++ +//------------------------------------------------------------------------------------ +// Details: A count is kept of the number of var value objects created. This is +// count is // used to ID the var value object. Increment the count by 1. // Type: Static method. // Args: None. // Returns: None. // Throws: None. //-- -void -CMICmnLLDBDebugSessionInfoVarObj::VarObjIdInc() -{ - ms_nVarUniqueId++; -} +void CMICmnLLDBDebugSessionInfoVarObj::VarObjIdInc() { ms_nVarUniqueId++; } -//++ ------------------------------------------------------------------------------------ -// Details: A count is kept of the number of var value objects created. This is count is +//++ +//------------------------------------------------------------------------------------ +// Details: A count is kept of the number of var value objects created. This is +// count is // used to ID the var value object. Retrieve ID. // Type: Static method. // Args: None. // Returns: None. // Throws: None. //-- -MIuint -CMICmnLLDBDebugSessionInfoVarObj::VarObjIdGet() -{ - return ms_nVarUniqueId; +MIuint CMICmnLLDBDebugSessionInfoVarObj::VarObjIdGet() { + return ms_nVarUniqueId; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the value formatted object's name. // Type: Method. // Args: None. // Returns: CMIUtilString & - Value's var%u name text. // Throws: None. //-- -const CMIUtilString & -CMICmnLLDBDebugSessionInfoVarObj::GetName() const -{ - return m_strName; +const CMIUtilString &CMICmnLLDBDebugSessionInfoVarObj::GetName() const { + return m_strName; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the value formatted object's variable name as given in the MI command +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the value formatted object's variable name as given in the +// MI command // to create the var object. // Type: Method. // Args: None. // Returns: CMIUtilString & - Value's real name text. // Throws: None. //-- -const CMIUtilString & -CMICmnLLDBDebugSessionInfoVarObj::GetNameReal() const -{ - return m_strNameReal; +const CMIUtilString &CMICmnLLDBDebugSessionInfoVarObj::GetNameReal() const { + return m_strNameReal; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the value formatted string. // Type: Method. // Args: None. @@ -503,38 +510,36 @@ CMICmnLLDBDebugSessionInfoVarObj::GetNameReal() const // Throws: None. //-- const CMIUtilString & -CMICmnLLDBDebugSessionInfoVarObj::GetValueFormatted() const -{ - return m_strFormattedValue; +CMICmnLLDBDebugSessionInfoVarObj::GetValueFormatted() const { + return m_strFormattedValue; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the LLDB Value object. // Type: Method. // Args: None. // Returns: lldb::SBValue & - LLDB Value object. // Throws: None. //-- -lldb::SBValue & -CMICmnLLDBDebugSessionInfoVarObj::GetValue() -{ - return m_SBValue; +lldb::SBValue &CMICmnLLDBDebugSessionInfoVarObj::GetValue() { + return m_SBValue; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the LLDB Value object. // Type: Method. // Args: None. // Returns: lldb::SBValue & - Constant LLDB Value object. // Throws: None. //-- -const lldb::SBValue & -CMICmnLLDBDebugSessionInfoVarObj::GetValue() const -{ - return m_SBValue; +const lldb::SBValue &CMICmnLLDBDebugSessionInfoVarObj::GetValue() const { + return m_SBValue; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Set the var format type for *this object and update the formatting. // Type: Method. // Args: None. @@ -542,37 +547,37 @@ CMICmnLLDBDebugSessionInfoVarObj::GetValue() const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebugSessionInfoVarObj::SetVarFormat(const varFormat_e veVarFormat) -{ - if (veVarFormat >= eVarFormat_count) - return MIstatus::failure; +bool CMICmnLLDBDebugSessionInfoVarObj::SetVarFormat( + const varFormat_e veVarFormat) { + if (veVarFormat >= eVarFormat_count) + return MIstatus::failure; - m_eVarFormat = veVarFormat; - UpdateValue(); - return MIstatus::success; + m_eVarFormat = veVarFormat; + UpdateValue(); + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Update *this var obj. Update it's value and type. // Type: Method. // Args: None. // Returns: None. // Throws: None. //-- -void -CMICmnLLDBDebugSessionInfoVarObj::UpdateValue() -{ - m_strFormattedValue = GetValueStringFormatted(m_SBValue, m_eVarFormat); +void CMICmnLLDBDebugSessionInfoVarObj::UpdateValue() { + m_strFormattedValue = GetValueStringFormatted(m_SBValue, m_eVarFormat); - MIuint64 nValue = 0; - if (CMICmnLLDBProxySBValue::GetValueAsUnsigned(m_SBValue, nValue) == MIstatus::failure) - m_eVarType = eVarType_Composite; + MIuint64 nValue = 0; + if (CMICmnLLDBProxySBValue::GetValueAsUnsigned(m_SBValue, nValue) == + MIstatus::failure) + m_eVarType = eVarType_Composite; - CMICmnLLDBDebugSessionInfoVarObj::VarObjUpdate(*this); + CMICmnLLDBDebugSessionInfoVarObj::VarObjUpdate(*this); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the enumeration type of the var object. // Type: Method. // Args: None. @@ -580,14 +585,16 @@ CMICmnLLDBDebugSessionInfoVarObj::UpdateValue() // Throws: None. //-- CMICmnLLDBDebugSessionInfoVarObj::varType_e -CMICmnLLDBDebugSessionInfoVarObj::GetType() const -{ - return m_eVarType; +CMICmnLLDBDebugSessionInfoVarObj::GetType() const { + return m_eVarType; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the parent var object's name, the parent var object to *this var -// object (if assigned). The parent is equivalent to LLDB SBValue variable's +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the parent var object's name, the parent var object to +// *this var +// object (if assigned). The parent is equivalent to LLDB SBValue +// variable's // parent. // Type: Method. // Args: None. @@ -595,7 +602,6 @@ CMICmnLLDBDebugSessionInfoVarObj::GetType() const // Throws: None. //-- const CMIUtilString & -CMICmnLLDBDebugSessionInfoVarObj::GetVarParentName() const -{ - return m_strVarObjParentName; +CMICmnLLDBDebugSessionInfoVarObj::GetVarParentName() const { + return m_strVarObjParentName; } diff --git a/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h b/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h index c4ae8e8e44b..49854051b7f 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h +++ b/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h @@ -10,120 +10,131 @@ #pragma once // Third Party Headers: -#include <map> #include "lldb/API/SBValue.h" +#include <map> // In-house headers: #include "MIUtilString.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI debug session variable object. The static functionality in *this // class manages a map container of *these variable objects. //-- -class CMICmnLLDBDebugSessionInfoVarObj -{ - // Enums: - public: - //++ ---------------------------------------------------------------------- - // Details: Enumeration of a variable type that is not a composite type - //-- - enum varFormat_e - { - // CODETAG_SESSIONINFO_VARFORMAT_ENUM - // *** Order is import here *** - eVarFormat_Invalid = 0, - eVarFormat_Binary, - eVarFormat_Octal, - eVarFormat_Decimal, - eVarFormat_Hex, - eVarFormat_Natural, - eVarFormat_count // Always last one - }; +class CMICmnLLDBDebugSessionInfoVarObj { + // Enums: +public: + //++ ---------------------------------------------------------------------- + // Details: Enumeration of a variable type that is not a composite type + //-- + enum varFormat_e { + // CODETAG_SESSIONINFO_VARFORMAT_ENUM + // *** Order is import here *** + eVarFormat_Invalid = 0, + eVarFormat_Binary, + eVarFormat_Octal, + eVarFormat_Decimal, + eVarFormat_Hex, + eVarFormat_Natural, + eVarFormat_count // Always last one + }; - //++ ---------------------------------------------------------------------- - // Details: Enumeration of a variable type by composite or internal type - //-- - enum varType_e - { - eVarType_InValid = 0, - eVarType_Composite, // i.e. struct - eVarType_Internal, // i.e. int - eVarType_count // Always last one - }; + //++ ---------------------------------------------------------------------- + // Details: Enumeration of a variable type by composite or internal type + //-- + enum varType_e { + eVarType_InValid = 0, + eVarType_Composite, // i.e. struct + eVarType_Internal, // i.e. int + eVarType_count // Always last one + }; - // Statics: - public: - static varFormat_e GetVarFormatForString(const CMIUtilString &vrStrFormat); - static varFormat_e GetVarFormatForChar(char vcFormat); - static CMIUtilString GetValueStringFormatted(const lldb::SBValue &vrValue, const varFormat_e veVarFormat); - static void VarObjAdd(const CMICmnLLDBDebugSessionInfoVarObj &vrVarObj); - static void VarObjDelete(const CMIUtilString &vrVarName); - static bool VarObjGet(const CMIUtilString &vrVarName, CMICmnLLDBDebugSessionInfoVarObj &vrwVarObj); - static void VarObjUpdate(const CMICmnLLDBDebugSessionInfoVarObj &vrVarObj); - static void VarObjIdInc(); - static MIuint VarObjIdGet(); - static void VarObjIdResetToZero(); - static void VarObjClear(); - static void VarObjSetFormat(varFormat_e eDefaultFormat); + // Statics: +public: + static varFormat_e GetVarFormatForString(const CMIUtilString &vrStrFormat); + static varFormat_e GetVarFormatForChar(char vcFormat); + static CMIUtilString GetValueStringFormatted(const lldb::SBValue &vrValue, + const varFormat_e veVarFormat); + static void VarObjAdd(const CMICmnLLDBDebugSessionInfoVarObj &vrVarObj); + static void VarObjDelete(const CMIUtilString &vrVarName); + static bool VarObjGet(const CMIUtilString &vrVarName, + CMICmnLLDBDebugSessionInfoVarObj &vrwVarObj); + static void VarObjUpdate(const CMICmnLLDBDebugSessionInfoVarObj &vrVarObj); + static void VarObjIdInc(); + static MIuint VarObjIdGet(); + static void VarObjIdResetToZero(); + static void VarObjClear(); + static void VarObjSetFormat(varFormat_e eDefaultFormat); - // Methods: - public: - /* ctor */ CMICmnLLDBDebugSessionInfoVarObj(); - /* ctor */ CMICmnLLDBDebugSessionInfoVarObj(const CMIUtilString &vrStrNameReal, const CMIUtilString &vrStrName, - const lldb::SBValue &vrValue); - /* ctor */ CMICmnLLDBDebugSessionInfoVarObj(const CMIUtilString &vrStrNameReal, const CMIUtilString &vrStrName, - const lldb::SBValue &vrValue, const CMIUtilString &vrStrVarObjParentName); - /* ctor */ CMICmnLLDBDebugSessionInfoVarObj(const CMICmnLLDBDebugSessionInfoVarObj &vrOther); - /* ctor */ CMICmnLLDBDebugSessionInfoVarObj(CMICmnLLDBDebugSessionInfoVarObj &vrOther); - /* ctor */ CMICmnLLDBDebugSessionInfoVarObj(CMICmnLLDBDebugSessionInfoVarObj &&vrOther); - // - CMICmnLLDBDebugSessionInfoVarObj &operator=(const CMICmnLLDBDebugSessionInfoVarObj &vrOther); - CMICmnLLDBDebugSessionInfoVarObj &operator=(CMICmnLLDBDebugSessionInfoVarObj &&vrwOther); - // - const CMIUtilString &GetName() const; - const CMIUtilString &GetNameReal() const; - const CMIUtilString &GetValueFormatted() const; - lldb::SBValue &GetValue(); - const lldb::SBValue &GetValue() const; - varType_e GetType() const; - bool SetVarFormat(const varFormat_e veVarFormat); - const CMIUtilString &GetVarParentName() const; - void UpdateValue(); + // Methods: +public: + /* ctor */ CMICmnLLDBDebugSessionInfoVarObj(); + /* ctor */ CMICmnLLDBDebugSessionInfoVarObj( + const CMIUtilString &vrStrNameReal, const CMIUtilString &vrStrName, + const lldb::SBValue &vrValue); + /* ctor */ CMICmnLLDBDebugSessionInfoVarObj( + const CMIUtilString &vrStrNameReal, const CMIUtilString &vrStrName, + const lldb::SBValue &vrValue, const CMIUtilString &vrStrVarObjParentName); + /* ctor */ CMICmnLLDBDebugSessionInfoVarObj( + const CMICmnLLDBDebugSessionInfoVarObj &vrOther); + /* ctor */ CMICmnLLDBDebugSessionInfoVarObj( + CMICmnLLDBDebugSessionInfoVarObj &vrOther); + /* ctor */ CMICmnLLDBDebugSessionInfoVarObj( + CMICmnLLDBDebugSessionInfoVarObj &&vrOther); + // + CMICmnLLDBDebugSessionInfoVarObj & + operator=(const CMICmnLLDBDebugSessionInfoVarObj &vrOther); + CMICmnLLDBDebugSessionInfoVarObj & + operator=(CMICmnLLDBDebugSessionInfoVarObj &&vrwOther); + // + const CMIUtilString &GetName() const; + const CMIUtilString &GetNameReal() const; + const CMIUtilString &GetValueFormatted() const; + lldb::SBValue &GetValue(); + const lldb::SBValue &GetValue() const; + varType_e GetType() const; + bool SetVarFormat(const varFormat_e veVarFormat); + const CMIUtilString &GetVarParentName() const; + void UpdateValue(); - // Overridden: - public: - // From CMICmnBase - /* dtor */ virtual ~CMICmnLLDBDebugSessionInfoVarObj(); + // Overridden: +public: + // From CMICmnBase + /* dtor */ virtual ~CMICmnLLDBDebugSessionInfoVarObj(); - // Typedefs: - private: - typedef std::map<CMIUtilString, CMICmnLLDBDebugSessionInfoVarObj> MapKeyToVarObj_t; - typedef std::pair<CMIUtilString, CMICmnLLDBDebugSessionInfoVarObj> MapPairKeyToVarObj_t; + // Typedefs: +private: + typedef std::map<CMIUtilString, CMICmnLLDBDebugSessionInfoVarObj> + MapKeyToVarObj_t; + typedef std::pair<CMIUtilString, CMICmnLLDBDebugSessionInfoVarObj> + MapPairKeyToVarObj_t; - // Statics: - private: - static CMIUtilString GetStringFormatted(const MIuint64 vnValue, const char *vpStrValueNatural, varFormat_e veVarFormat); + // Statics: +private: + static CMIUtilString GetStringFormatted(const MIuint64 vnValue, + const char *vpStrValueNatural, + varFormat_e veVarFormat); - // Methods: - private: - bool CopyOther(const CMICmnLLDBDebugSessionInfoVarObj &vrOther); - bool MoveOther(CMICmnLLDBDebugSessionInfoVarObj &vrwOther); + // Methods: +private: + bool CopyOther(const CMICmnLLDBDebugSessionInfoVarObj &vrOther); + bool MoveOther(CMICmnLLDBDebugSessionInfoVarObj &vrwOther); - // Attributes: - private: - static const char *ms_aVarFormatStrings[]; - static const char *ms_aVarFormatChars[]; - static MapKeyToVarObj_t ms_mapVarIdToVarObj; - static MIuint ms_nVarUniqueId; - static varFormat_e ms_eDefaultFormat; // overrides "natural" format - // - // *** Update the copy move constructors and assignment operator *** - varFormat_e m_eVarFormat; - varType_e m_eVarType; - CMIUtilString m_strName; - lldb::SBValue m_SBValue; - CMIUtilString m_strNameReal; - CMIUtilString m_strFormattedValue; - CMIUtilString m_strVarObjParentName; - // *** Update the copy move constructors and assignment operator *** + // Attributes: +private: + static const char *ms_aVarFormatStrings[]; + static const char *ms_aVarFormatChars[]; + static MapKeyToVarObj_t ms_mapVarIdToVarObj; + static MIuint ms_nVarUniqueId; + static varFormat_e ms_eDefaultFormat; // overrides "natural" format + // + // *** Update the copy move constructors and assignment operator *** + varFormat_e m_eVarFormat; + varType_e m_eVarType; + CMIUtilString m_strName; + lldb::SBValue m_SBValue; + CMIUtilString m_strNameReal; + CMIUtilString m_strFormattedValue; + CMIUtilString m_strVarObjParentName; + // *** Update the copy move constructors and assignment operator *** }; diff --git a/lldb/tools/lldb-mi/MICmnLLDBDebugger.cpp b/lldb/tools/lldb-mi/MICmnLLDBDebugger.cpp index d5bff15279e..a676ecc9260 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBDebugger.cpp +++ b/lldb/tools/lldb-mi/MICmnLLDBDebugger.cpp @@ -8,64 +8,72 @@ //===----------------------------------------------------------------------===// // Third party headers: +#include "lldb/API/SBCommandInterpreter.h" +#include "lldb/API/SBProcess.h" +#include "lldb/API/SBStream.h" #include "lldb/API/SBTarget.h" #include "lldb/API/SBThread.h" -#include "lldb/API/SBProcess.h" -#include "lldb/API/SBCommandInterpreter.h" -#include "lldb/API/SBTypeSummary.h" +#include "lldb/API/SBType.h" #include "lldb/API/SBTypeCategory.h" #include "lldb/API/SBTypeNameSpecifier.h" -#include "lldb/API/SBStream.h" -#include "lldb/API/SBType.h" +#include "lldb/API/SBTypeSummary.h" // In-house headers: +#include "MICmnLLDBDebugSessionInfo.h" #include "MICmnLLDBDebugger.h" -#include "MICmnResources.h" +#include "MICmnLLDBDebuggerHandleEvents.h" #include "MICmnLog.h" -#include "MIDriverBase.h" +#include "MICmnResources.h" #include "MICmnThreadMgrStd.h" -#include "MICmnLLDBDebuggerHandleEvents.h" -#include "MICmnLLDBDebugSessionInfo.h" +#include "MIDriverBase.h" #include "MIUtilSingletonHelper.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // MI private summary providers -static inline bool -MI_char_summary_provider(lldb::SBValue value, lldb::SBTypeSummaryOptions options, lldb::SBStream &stream) -{ - if (!value.IsValid()) - return false; - - lldb::SBType value_type = value.GetType(); - if(!value_type.IsValid()) - return false; - - lldb::BasicType type_code = value_type.GetBasicType(); - if (type_code == lldb::eBasicTypeSignedChar) - stream.Printf("%d %s", (int)value.GetValueAsSigned(), value.GetValue()); - else if (type_code == lldb::eBasicTypeUnsignedChar) - stream.Printf("%u %s", (unsigned)value.GetValueAsUnsigned(), value.GetValue()); - else - return false; - - return true; +static inline bool MI_char_summary_provider(lldb::SBValue value, + lldb::SBTypeSummaryOptions options, + lldb::SBStream &stream) { + if (!value.IsValid()) + return false; + + lldb::SBType value_type = value.GetType(); + if (!value_type.IsValid()) + return false; + + lldb::BasicType type_code = value_type.GetBasicType(); + if (type_code == lldb::eBasicTypeSignedChar) + stream.Printf("%d %s", (int)value.GetValueAsSigned(), value.GetValue()); + else if (type_code == lldb::eBasicTypeUnsignedChar) + stream.Printf("%u %s", (unsigned)value.GetValueAsUnsigned(), + value.GetValue()); + else + return false; + + return true; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // MI summary helper routines -static inline bool -MI_add_summary(lldb::SBTypeCategory category, const char *typeName, lldb::SBTypeSummary::FormatCallback cb, - uint32_t options, bool regex = false) -{ +static inline bool MI_add_summary(lldb::SBTypeCategory category, + const char *typeName, + lldb::SBTypeSummary::FormatCallback cb, + uint32_t options, bool regex = false) { #if defined(LLDB_DISABLE_PYTHON) - return false; + return false; #else - lldb::SBTypeSummary summary = lldb::SBTypeSummary::CreateWithCallback(cb, options); - return summary.IsValid() ? category.AddTypeSummary(lldb::SBTypeNameSpecifier(typeName, regex), summary) : false; + lldb::SBTypeSummary summary = + lldb::SBTypeSummary::CreateWithCallback(cb, options); + return summary.IsValid() + ? category.AddTypeSummary( + lldb::SBTypeNameSpecifier(typeName, regex), summary) + : false; #endif -} +} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLLDBDebugger constructor. // Type: Method. // Args: None. @@ -73,23 +81,20 @@ MI_add_summary(lldb::SBTypeCategory category, const char *typeName, lldb::SBType // Throws: None. //-- CMICmnLLDBDebugger::CMICmnLLDBDebugger() - : m_constStrThisThreadId("MI debugger event") -{ -} + : m_constStrThisThreadId("MI debugger event") {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLLDBDebugger destructor. // Type: Overridable. // Args: None. // Return: None. // Throws: None. //-- -CMICmnLLDBDebugger::~CMICmnLLDBDebugger() -{ - Shutdown(); -} +CMICmnLLDBDebugger::~CMICmnLLDBDebugger() { Shutdown(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Initialize resources for *this debugger object. // Type: Method. // Args: None. @@ -97,62 +102,61 @@ CMICmnLLDBDebugger::~CMICmnLLDBDebugger() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::Initialize() -{ - m_clientUsageRefCnt++; - - if (m_bInitialized) - return MIstatus::success; - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - ClrErrorDescription(); - - if (m_pClientDriver == nullptr) - { - bOk = false; - errMsg = MIRSRC(IDS_LLDBDEBUGGER_ERR_CLIENTDRIVER); - } +bool CMICmnLLDBDebugger::Initialize() { + m_clientUsageRefCnt++; - // Note initialization order is important here as some resources depend on previous - MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); - MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); - MI::ModuleInit<CMICmnThreadMgrStd>(IDS_MI_INIT_ERR_THREADMGR, bOk, errMsg); - MI::ModuleInit<CMICmnLLDBDebuggerHandleEvents>(IDS_MI_INIT_ERR_OUTOFBANDHANDLER, bOk, errMsg); - MI::ModuleInit<CMICmnLLDBDebugSessionInfo>(IDS_MI_INIT_ERR_DEBUGSESSIONINFO, bOk, errMsg); - - // Note order is important here! - if (bOk) - lldb::SBDebugger::Initialize(); - if (bOk && !InitSBDebugger()) - { - bOk = false; - if (!errMsg.empty()) - errMsg += ", "; - errMsg += GetErrorDescription().c_str(); - } - if (bOk && !InitSBListener()) - { - bOk = false; - if (!errMsg.empty()) - errMsg += ", "; - errMsg += GetErrorDescription().c_str(); - } - bOk = bOk && InitStdStreams(); - bOk = bOk && RegisterMISummaryProviders(); - m_bInitialized = bOk; - - if (!bOk && !HaveErrorDescription()) - { - CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_LLDBDEBUGGER), errMsg.c_str())); - SetErrorDescription(strInitError); - } + if (m_bInitialized) + return MIstatus::success; - return bOk; + bool bOk = MIstatus::success; + CMIUtilString errMsg; + ClrErrorDescription(); + + if (m_pClientDriver == nullptr) { + bOk = false; + errMsg = MIRSRC(IDS_LLDBDEBUGGER_ERR_CLIENTDRIVER); + } + + // Note initialization order is important here as some resources depend on + // previous + MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + MI::ModuleInit<CMICmnThreadMgrStd>(IDS_MI_INIT_ERR_THREADMGR, bOk, errMsg); + MI::ModuleInit<CMICmnLLDBDebuggerHandleEvents>( + IDS_MI_INIT_ERR_OUTOFBANDHANDLER, bOk, errMsg); + MI::ModuleInit<CMICmnLLDBDebugSessionInfo>(IDS_MI_INIT_ERR_DEBUGSESSIONINFO, + bOk, errMsg); + + // Note order is important here! + if (bOk) + lldb::SBDebugger::Initialize(); + if (bOk && !InitSBDebugger()) { + bOk = false; + if (!errMsg.empty()) + errMsg += ", "; + errMsg += GetErrorDescription().c_str(); + } + if (bOk && !InitSBListener()) { + bOk = false; + if (!errMsg.empty()) + errMsg += ", "; + errMsg += GetErrorDescription().c_str(); + } + bOk = bOk && InitStdStreams(); + bOk = bOk && RegisterMISummaryProviders(); + m_bInitialized = bOk; + + if (!bOk && !HaveErrorDescription()) { + CMIUtilString strInitError(CMIUtilString::Format( + MIRSRC(IDS_MI_INIT_ERR_LLDBDEBUGGER), errMsg.c_str())); + SetErrorDescription(strInitError); + } + + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release resources for *this debugger object. // Type: Method. // Args: None. @@ -160,81 +164,85 @@ CMICmnLLDBDebugger::Initialize() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::Shutdown() -{ - if (--m_clientUsageRefCnt > 0) - return MIstatus::success; - - if (!m_bInitialized) - return MIstatus::success; - - m_bInitialized = false; - - ClrErrorDescription(); - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - - // Explicitly delete the remote target in case MI needs to exit prematurely otherwise - // LLDB debugger may hang in its Destroy() fn waiting on events - lldb::SBTarget sbTarget = CMICmnLLDBDebugSessionInfo::Instance().GetTarget(); - m_lldbDebugger.DeleteTarget(sbTarget); - - // Debug: May need this but does seem to work without it so commented out the fudge 19/06/2014 - // It appears we need to wait as hang does not occur when hitting a debug breakpoint here - // const std::chrono::milliseconds time( 1000 ); - // std::this_thread::sleep_for( time ); - - lldb::SBDebugger::Destroy(m_lldbDebugger); - lldb::SBDebugger::Terminate(); - m_pClientDriver = nullptr; - m_mapBroadcastClassNameToEventMask.clear(); - m_mapIdToEventMask.clear(); - - // Note shutdown order is important here - MI::ModuleShutdown<CMICmnLLDBDebugSessionInfo>(IDS_MI_INIT_ERR_DEBUGSESSIONINFO, bOk, errMsg); - MI::ModuleShutdown<CMICmnLLDBDebuggerHandleEvents>(IDS_MI_INIT_ERR_OUTOFBANDHANDLER, bOk, errMsg); - MI::ModuleShutdown<CMICmnThreadMgrStd>(IDS_MI_INIT_ERR_THREADMGR, bOk, errMsg); - MI::ModuleShutdown<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); - MI::ModuleShutdown<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); - - if (!bOk) - { - SetErrorDescriptionn(MIRSRC(IDS_MI_SHTDWN_ERR_LLDBDEBUGGER), errMsg.c_str()); - } +bool CMICmnLLDBDebugger::Shutdown() { + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; + if (!m_bInitialized) return MIstatus::success; + + m_bInitialized = false; + + ClrErrorDescription(); + + bool bOk = MIstatus::success; + CMIUtilString errMsg; + + // Explicitly delete the remote target in case MI needs to exit prematurely + // otherwise + // LLDB debugger may hang in its Destroy() fn waiting on events + lldb::SBTarget sbTarget = CMICmnLLDBDebugSessionInfo::Instance().GetTarget(); + m_lldbDebugger.DeleteTarget(sbTarget); + + // Debug: May need this but does seem to work without it so commented out the + // fudge 19/06/2014 + // It appears we need to wait as hang does not occur when hitting a debug + // breakpoint here + // const std::chrono::milliseconds time( 1000 ); + // std::this_thread::sleep_for( time ); + + lldb::SBDebugger::Destroy(m_lldbDebugger); + lldb::SBDebugger::Terminate(); + m_pClientDriver = nullptr; + m_mapBroadcastClassNameToEventMask.clear(); + m_mapIdToEventMask.clear(); + + // Note shutdown order is important here + MI::ModuleShutdown<CMICmnLLDBDebugSessionInfo>( + IDS_MI_INIT_ERR_DEBUGSESSIONINFO, bOk, errMsg); + MI::ModuleShutdown<CMICmnLLDBDebuggerHandleEvents>( + IDS_MI_INIT_ERR_OUTOFBANDHANDLER, bOk, errMsg); + MI::ModuleShutdown<CMICmnThreadMgrStd>(IDS_MI_INIT_ERR_THREADMGR, bOk, + errMsg); + MI::ModuleShutdown<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + MI::ModuleShutdown<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + + if (!bOk) { + SetErrorDescriptionn(MIRSRC(IDS_MI_SHTDWN_ERR_LLDBDEBUGGER), + errMsg.c_str()); + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Return the LLDB debugger instance created for this debug session. // Type: Method. // Args: None. // Return: lldb::SBDebugger & - LLDB debugger object reference. // Throws: None. //-- -lldb::SBDebugger & -CMICmnLLDBDebugger::GetTheDebugger() -{ - return m_lldbDebugger; +lldb::SBDebugger &CMICmnLLDBDebugger::GetTheDebugger() { + return m_lldbDebugger; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Return the LLDB listener instance created for this debug session. // Type: Method. // Args: None. // Return: lldb::SBListener & - LLDB listener object reference. // Throws: None. //-- -lldb::SBListener & -CMICmnLLDBDebugger::GetTheListener() -{ - return m_lldbListener; +lldb::SBListener &CMICmnLLDBDebugger::GetTheListener() { + return m_lldbListener; } -//++ ------------------------------------------------------------------------------------ -// Details: Set the client driver that wants to use *this LLDB debugger. Call this function +//++ +//------------------------------------------------------------------------------------ +// Details: Set the client driver that wants to use *this LLDB debugger. Call +// this function // prior to Initialize(). // Type: Method. // Args: vClientDriver - (R) A driver. @@ -242,32 +250,33 @@ CMICmnLLDBDebugger::GetTheListener() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::SetDriver(const CMIDriverBase &vClientDriver) -{ - m_pClientDriver = const_cast<CMIDriverBase *>(&vClientDriver); +bool CMICmnLLDBDebugger::SetDriver(const CMIDriverBase &vClientDriver) { + m_pClientDriver = const_cast<CMIDriverBase *>(&vClientDriver); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Get the client driver that is use *this LLDB debugger. // Type: Method. // Args: vClientDriver - (R) A driver. // Return: CMIDriverBase & - A driver instance. // Throws: None. //-- -CMIDriverBase & -CMICmnLLDBDebugger::GetDriver() const -{ - return *m_pClientDriver; +CMIDriverBase &CMICmnLLDBDebugger::GetDriver() const { + return *m_pClientDriver; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Wait until all events have been handled. -// This function works in pair with CMICmnLLDBDebugger::MonitorSBListenerEvents -// that handles events from queue. When all events were handled and queue is -// empty the MonitorSBListenerEvents notifies this function that it's ready to +// This function works in pair with +// CMICmnLLDBDebugger::MonitorSBListenerEvents +// that handles events from queue. When all events were handled and +// queue is +// empty the MonitorSBListenerEvents notifies this function that it's +// ready to // go on. To synchronize them the m_mutexEventQueue and // m_conditionEventQueueEmpty are used. // Type: Method. @@ -275,62 +284,64 @@ CMICmnLLDBDebugger::GetDriver() const // Return: None. // Throws: None. //-- -void -CMICmnLLDBDebugger::WaitForHandleEvent() -{ - std::unique_lock<std::mutex> lock(m_mutexEventQueue); - - lldb::SBEvent event; - if (ThreadIsActive() && m_lldbListener.PeekAtNextEvent(event)) - m_conditionEventQueueEmpty.wait(lock); +void CMICmnLLDBDebugger::WaitForHandleEvent() { + std::unique_lock<std::mutex> lock(m_mutexEventQueue); + + lldb::SBEvent event; + if (ThreadIsActive() && m_lldbListener.PeekAtNextEvent(event)) + m_conditionEventQueueEmpty.wait(lock); } -//++ ------------------------------------------------------------------------------------ -// Details: Check if need to rebroadcast stop event. This function will return true if +//++ +//------------------------------------------------------------------------------------ +// Details: Check if need to rebroadcast stop event. This function will return +// true if // debugger is in synchronouse mode. In such case the -// CMICmnLLDBDebugger::RebroadcastStopEvent should be called to rebroadcast +// CMICmnLLDBDebugger::RebroadcastStopEvent should be called to +// rebroadcast // a new stop event (if any). // Type: Method. // Args: None. // Return: bool - True = Need to rebroadcast stop event, false = otherwise. // Throws: None. //-- -bool -CMICmnLLDBDebugger::CheckIfNeedToRebroadcastStopEvent() -{ - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - if (!rSessionInfo.GetDebugger().GetAsync()) - { - const bool include_expression_stops = false; - m_nLastStopId = CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetStopID(include_expression_stops); - return true; - } +bool CMICmnLLDBDebugger::CheckIfNeedToRebroadcastStopEvent() { + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + if (!rSessionInfo.GetDebugger().GetAsync()) { + const bool include_expression_stops = false; + m_nLastStopId = + CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetStopID( + include_expression_stops); + return true; + } - return false; + return false; } -//++ ------------------------------------------------------------------------------------ -// Details: Rebroadcast stop event if needed. This function should be called only if the -// CMICmnLLDBDebugger::CheckIfNeedToRebroadcastStopEvent() returned true. +//++ +//------------------------------------------------------------------------------------ +// Details: Rebroadcast stop event if needed. This function should be called +// only if the +// CMICmnLLDBDebugger::CheckIfNeedToRebroadcastStopEvent() returned +// true. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -void -CMICmnLLDBDebugger::RebroadcastStopEvent() -{ - lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); - const bool include_expression_stops = false; - const uint32_t nStopId = process.GetStopID(include_expression_stops); - if (m_nLastStopId != nStopId) - { - lldb::SBEvent event = process.GetStopEventForStopID(nStopId); - process.GetBroadcaster().BroadcastEvent(event); - } +void CMICmnLLDBDebugger::RebroadcastStopEvent() { + lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + const bool include_expression_stops = false; + const uint32_t nStopId = process.GetStopID(include_expression_stops); + if (m_nLastStopId != nStopId) { + lldb::SBEvent event = process.GetStopEventForStopID(nStopId); + process.GetBroadcaster().BroadcastEvent(event); + } } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Initialize the LLDB Debugger object. // Type: Method. // Args: None. @@ -338,44 +349,45 @@ CMICmnLLDBDebugger::RebroadcastStopEvent() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::InitSBDebugger() -{ - m_lldbDebugger = lldb::SBDebugger::Create(false); - if (!m_lldbDebugger.IsValid()) - { - SetErrorDescription(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER)); - return MIstatus::failure; - } +bool CMICmnLLDBDebugger::InitSBDebugger() { + m_lldbDebugger = lldb::SBDebugger::Create(false); + if (!m_lldbDebugger.IsValid()) { + SetErrorDescription(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER)); + return MIstatus::failure; + } - m_lldbDebugger.GetCommandInterpreter().SetPromptOnQuit(false); + m_lldbDebugger.GetCommandInterpreter().SetPromptOnQuit(false); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Set the LLDB Debugger's std in, err and out streams. (Not implemented left -// here for reference. Was called in the CMICmnLLDBDebugger::Initialize() ) +//++ +//------------------------------------------------------------------------------------ +// Details: Set the LLDB Debugger's std in, err and out streams. (Not +// implemented left +// here for reference. Was called in the +// CMICmnLLDBDebugger::Initialize() ) // Type: Method. // Args: None. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::InitStdStreams() -{ - // This is not required when operating the MI driver's code as it has its own - // streams. Setting the Stdin for the lldbDebugger especially on LINUX will cause - // another thread to run and partially consume stdin data meant for MI stdin handler - // m_lldbDebugger.SetErrorFileHandle( m_pClientDriver->GetStderr(), false ); - // m_lldbDebugger.SetOutputFileHandle( m_pClientDriver->GetStdout(), false ); - // m_lldbDebugger.SetInputFileHandle( m_pClientDriver->GetStdin(), false ); - - return MIstatus::success; +bool CMICmnLLDBDebugger::InitStdStreams() { + // This is not required when operating the MI driver's code as it has its own + // streams. Setting the Stdin for the lldbDebugger especially on LINUX will + // cause + // another thread to run and partially consume stdin data meant for MI stdin + // handler + // m_lldbDebugger.SetErrorFileHandle( m_pClientDriver->GetStderr(), false ); + // m_lldbDebugger.SetOutputFileHandle( m_pClientDriver->GetStdout(), false ); + // m_lldbDebugger.SetInputFileHandle( m_pClientDriver->GetStdin(), false ); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Set up the events from the SBDebugger's we would like to listen to. // Type: Method. // Args: None. @@ -383,74 +395,94 @@ CMICmnLLDBDebugger::InitStdStreams() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::InitSBListener() -{ - m_lldbListener = m_lldbDebugger.GetListener(); - if (!m_lldbListener.IsValid()) - { - SetErrorDescription(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER)); - return MIstatus::failure; - } - - const CMIUtilString strDbgId("CMICmnLLDBDebugger1"); - MIuint eventMask = lldb::SBTarget::eBroadcastBitBreakpointChanged | lldb::SBTarget::eBroadcastBitModulesLoaded | - lldb::SBTarget::eBroadcastBitModulesUnloaded | lldb::SBTarget::eBroadcastBitWatchpointChanged | - lldb::SBTarget::eBroadcastBitSymbolsLoaded; - bool bOk = RegisterForEvent(strDbgId, CMIUtilString(lldb::SBTarget::GetBroadcasterClassName()), eventMask); - - eventMask = lldb::SBThread::eBroadcastBitStackChanged; - bOk = bOk && RegisterForEvent(strDbgId, CMIUtilString(lldb::SBThread::GetBroadcasterClassName()), eventMask); - - eventMask = lldb::SBProcess::eBroadcastBitStateChanged | lldb::SBProcess::eBroadcastBitInterrupt | - lldb::SBProcess::eBroadcastBitSTDOUT | lldb::SBProcess::eBroadcastBitSTDERR | lldb::SBProcess::eBroadcastBitProfileData | - lldb::SBProcess::eBroadcastBitStructuredData; - bOk = bOk && RegisterForEvent(strDbgId, CMIUtilString(lldb::SBProcess::GetBroadcasterClassName()), eventMask); - - eventMask = lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived | lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit | - lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData | - lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData; - bOk = bOk && RegisterForEvent(strDbgId, m_lldbDebugger.GetCommandInterpreter().GetBroadcaster(), eventMask); - - return bOk; +bool CMICmnLLDBDebugger::InitSBListener() { + m_lldbListener = m_lldbDebugger.GetListener(); + if (!m_lldbListener.IsValid()) { + SetErrorDescription(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER)); + return MIstatus::failure; + } + + const CMIUtilString strDbgId("CMICmnLLDBDebugger1"); + MIuint eventMask = lldb::SBTarget::eBroadcastBitBreakpointChanged | + lldb::SBTarget::eBroadcastBitModulesLoaded | + lldb::SBTarget::eBroadcastBitModulesUnloaded | + lldb::SBTarget::eBroadcastBitWatchpointChanged | + lldb::SBTarget::eBroadcastBitSymbolsLoaded; + bool bOk = RegisterForEvent( + strDbgId, CMIUtilString(lldb::SBTarget::GetBroadcasterClassName()), + eventMask); + + eventMask = lldb::SBThread::eBroadcastBitStackChanged; + bOk = bOk && + RegisterForEvent( + strDbgId, CMIUtilString(lldb::SBThread::GetBroadcasterClassName()), + eventMask); + + eventMask = lldb::SBProcess::eBroadcastBitStateChanged | + lldb::SBProcess::eBroadcastBitInterrupt | + lldb::SBProcess::eBroadcastBitSTDOUT | + lldb::SBProcess::eBroadcastBitSTDERR | + lldb::SBProcess::eBroadcastBitProfileData | + lldb::SBProcess::eBroadcastBitStructuredData; + bOk = bOk && + RegisterForEvent( + strDbgId, CMIUtilString(lldb::SBProcess::GetBroadcasterClassName()), + eventMask); + + eventMask = lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived | + lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit | + lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData | + lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData; + bOk = bOk && + RegisterForEvent( + strDbgId, m_lldbDebugger.GetCommandInterpreter().GetBroadcaster(), + eventMask); + + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Register with the debugger, the SBListener, the type of events you are interested +//++ +//------------------------------------------------------------------------------------ +// Details: Register with the debugger, the SBListener, the type of events you +// are interested // in. Others, like commands, may have already set the mask. // Type: Method. -// Args: vClientName - (R) ID of the client who wants these events set. +// Args: vClientName - (R) ID of the client who wants these events +// set. // vBroadcasterClass - (R) The SBBroadcaster's class name. // vEventMask - (R) The mask of events to listen for. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::RegisterForEvent(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, const MIuint vEventMask) -{ - MIuint existingMask = 0; - if (!BroadcasterGetMask(vBroadcasterClass, existingMask)) - return MIstatus::failure; - - if (!ClientSaveMask(vClientName, vBroadcasterClass, vEventMask)) - return MIstatus::failure; - - const char *pBroadCasterName = vBroadcasterClass.c_str(); - MIuint eventMask = vEventMask; - eventMask += existingMask; - const MIuint result = m_lldbListener.StartListeningForEventClass(m_lldbDebugger, pBroadCasterName, eventMask); - if (result == 0) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_STARTLISTENER), pBroadCasterName)); - return MIstatus::failure; - } +bool CMICmnLLDBDebugger::RegisterForEvent( + const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, + const MIuint vEventMask) { + MIuint existingMask = 0; + if (!BroadcasterGetMask(vBroadcasterClass, existingMask)) + return MIstatus::failure; + + if (!ClientSaveMask(vClientName, vBroadcasterClass, vEventMask)) + return MIstatus::failure; + + const char *pBroadCasterName = vBroadcasterClass.c_str(); + MIuint eventMask = vEventMask; + eventMask += existingMask; + const MIuint result = m_lldbListener.StartListeningForEventClass( + m_lldbDebugger, pBroadCasterName, eventMask); + if (result == 0) { + SetErrorDescription(CMIUtilString::Format( + MIRSRC(IDS_LLDBDEBUGGER_ERR_STARTLISTENER), pBroadCasterName)); + return MIstatus::failure; + } - return BroadcasterSaveMask(vBroadcasterClass, eventMask); + return BroadcasterSaveMask(vBroadcasterClass, eventMask); } -//++ ------------------------------------------------------------------------------------ -// Details: Register with the debugger, the SBListener, the type of events you are interested +//++ +//------------------------------------------------------------------------------------ +// Details: Register with the debugger, the SBListener, the type of events you +// are interested // in. Others, like commands, may have already set the mask. // Type: Method. // Args: vClientName - (R) ID of the client who wants these events set. @@ -460,85 +492,93 @@ CMICmnLLDBDebugger::RegisterForEvent(const CMIUtilString &vClientName, const CMI // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::RegisterForEvent(const CMIUtilString &vClientName, const lldb::SBBroadcaster &vBroadcaster, const MIuint vEventMask) -{ - const char *pBroadcasterName = vBroadcaster.GetName(); - if (pBroadcasterName == nullptr) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_BROADCASTER_NAME), MIRSRC(IDS_WORD_INVALIDNULLPTR))); - return MIstatus::failure; - } - CMIUtilString broadcasterName(pBroadcasterName); - if (broadcasterName.length() == 0) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_BROADCASTER_NAME), MIRSRC(IDS_WORD_INVALIDEMPTY))); - return MIstatus::failure; - } +bool CMICmnLLDBDebugger::RegisterForEvent( + const CMIUtilString &vClientName, const lldb::SBBroadcaster &vBroadcaster, + const MIuint vEventMask) { + const char *pBroadcasterName = vBroadcaster.GetName(); + if (pBroadcasterName == nullptr) { + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_BROADCASTER_NAME), + MIRSRC(IDS_WORD_INVALIDNULLPTR))); + return MIstatus::failure; + } + CMIUtilString broadcasterName(pBroadcasterName); + if (broadcasterName.length() == 0) { + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_BROADCASTER_NAME), + MIRSRC(IDS_WORD_INVALIDEMPTY))); + return MIstatus::failure; + } - MIuint existingMask = 0; - if (!BroadcasterGetMask(broadcasterName, existingMask)) - return MIstatus::failure; + MIuint existingMask = 0; + if (!BroadcasterGetMask(broadcasterName, existingMask)) + return MIstatus::failure; - if (!ClientSaveMask(vClientName, broadcasterName, vEventMask)) - return MIstatus::failure; + if (!ClientSaveMask(vClientName, broadcasterName, vEventMask)) + return MIstatus::failure; - MIuint eventMask = vEventMask; - eventMask += existingMask; - const MIuint result = m_lldbListener.StartListeningForEvents(vBroadcaster, eventMask); - if (result == 0) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_STARTLISTENER), pBroadcasterName)); - return MIstatus::failure; - } + MIuint eventMask = vEventMask; + eventMask += existingMask; + const MIuint result = + m_lldbListener.StartListeningForEvents(vBroadcaster, eventMask); + if (result == 0) { + SetErrorDescription(CMIUtilString::Format( + MIRSRC(IDS_LLDBDEBUGGER_ERR_STARTLISTENER), pBroadcasterName)); + return MIstatus::failure; + } - return BroadcasterSaveMask(broadcasterName, eventMask); + return BroadcasterSaveMask(broadcasterName, eventMask); } -//++ ------------------------------------------------------------------------------------ -// Details: Unregister with the debugger, the SBListener, the type of events you are no -// longer interested in. Others, like commands, may still remain interested so +//++ +//------------------------------------------------------------------------------------ +// Details: Unregister with the debugger, the SBListener, the type of events you +// are no +// longer interested in. Others, like commands, may still remain +// interested so // an event may not necessarily be stopped. // Type: Method. -// Args: vClientName - (R) ID of the client who no longer requires these events. +// Args: vClientName - (R) ID of the client who no longer requires +// these events. // vBroadcasterClass - (R) The SBBroadcaster's class name. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::UnregisterForEvent(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass) -{ - MIuint clientsEventMask = 0; - if (!ClientGetTheirMask(vClientName, vBroadcasterClass, clientsEventMask)) - return MIstatus::failure; - if (!ClientRemoveTheirMask(vClientName, vBroadcasterClass)) - return MIstatus::failure; - - const MIuint otherClientsEventMask = ClientGetMaskForAllClients(vBroadcasterClass); - MIuint newEventMask = 0; - for (MIuint i = 0; i < 32; i++) - { - const MIuint bit = 1 << i; - const MIuint clientBit = bit & clientsEventMask; - const MIuint othersBit = bit & otherClientsEventMask; - if ((clientBit != 0) && (othersBit == 0)) - { - newEventMask += clientBit; - } - } +bool CMICmnLLDBDebugger::UnregisterForEvent( + const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass) { + MIuint clientsEventMask = 0; + if (!ClientGetTheirMask(vClientName, vBroadcasterClass, clientsEventMask)) + return MIstatus::failure; + if (!ClientRemoveTheirMask(vClientName, vBroadcasterClass)) + return MIstatus::failure; - const char *pBroadCasterName = vBroadcasterClass.c_str(); - if (!m_lldbListener.StopListeningForEventClass(m_lldbDebugger, pBroadCasterName, newEventMask)) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_STOPLISTENER), vClientName.c_str(), pBroadCasterName)); - return MIstatus::failure; + const MIuint otherClientsEventMask = + ClientGetMaskForAllClients(vBroadcasterClass); + MIuint newEventMask = 0; + for (MIuint i = 0; i < 32; i++) { + const MIuint bit = 1 << i; + const MIuint clientBit = bit & clientsEventMask; + const MIuint othersBit = bit & otherClientsEventMask; + if ((clientBit != 0) && (othersBit == 0)) { + newEventMask += clientBit; } + } + + const char *pBroadCasterName = vBroadcasterClass.c_str(); + if (!m_lldbListener.StopListeningForEventClass( + m_lldbDebugger, pBroadCasterName, newEventMask)) { + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_STOPLISTENER), + vClientName.c_str(), pBroadCasterName)); + return MIstatus::failure; + } - return BroadcasterSaveMask(vBroadcasterClass, otherClientsEventMask); + return BroadcasterSaveMask(vBroadcasterClass, otherClientsEventMask); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Given the SBBroadcaster class name retrieve it's current event mask. // Type: Method. // Args: vBroadcasterClass - (R) The SBBroadcaster's class name. @@ -547,27 +587,28 @@ CMICmnLLDBDebugger::UnregisterForEvent(const CMIUtilString &vClientName, const C // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::BroadcasterGetMask(const CMIUtilString &vBroadcasterClass, MIuint &vwEventMask) const -{ - vwEventMask = 0; - - if (vBroadcasterClass.empty()) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER), vBroadcasterClass.c_str())); - return MIstatus::failure; - } +bool CMICmnLLDBDebugger::BroadcasterGetMask( + const CMIUtilString &vBroadcasterClass, MIuint &vwEventMask) const { + vwEventMask = 0; + + if (vBroadcasterClass.empty()) { + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER), + vBroadcasterClass.c_str())); + return MIstatus::failure; + } - const MapBroadcastClassNameToEventMask_t::const_iterator it = m_mapBroadcastClassNameToEventMask.find(vBroadcasterClass); - if (it != m_mapBroadcastClassNameToEventMask.end()) - { - vwEventMask = (*it).second; - } + const MapBroadcastClassNameToEventMask_t::const_iterator it = + m_mapBroadcastClassNameToEventMask.find(vBroadcasterClass); + if (it != m_mapBroadcastClassNameToEventMask.end()) { + vwEventMask = (*it).second; + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Remove the event mask for the specified SBBroadcaster class name. // Type: Method. // Args: vBroadcasterClass - (R) The SBBroadcaster's class name. @@ -575,19 +616,19 @@ CMICmnLLDBDebugger::BroadcasterGetMask(const CMIUtilString &vBroadcasterClass, M // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::BroadcasterRemoveMask(const CMIUtilString &vBroadcasterClass) -{ - MapBroadcastClassNameToEventMask_t::const_iterator it = m_mapBroadcastClassNameToEventMask.find(vBroadcasterClass); - if (it != m_mapBroadcastClassNameToEventMask.end()) - { - m_mapBroadcastClassNameToEventMask.erase(it); - } - - return MIstatus::success; +bool CMICmnLLDBDebugger::BroadcasterRemoveMask( + const CMIUtilString &vBroadcasterClass) { + MapBroadcastClassNameToEventMask_t::const_iterator it = + m_mapBroadcastClassNameToEventMask.find(vBroadcasterClass); + if (it != m_mapBroadcastClassNameToEventMask.end()) { + m_mapBroadcastClassNameToEventMask.erase(it); + } + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Given the SBBroadcaster class name save it's current event mask. // Type: Method. // Args: vBroadcasterClass - (R) The SBBroadcaster's class name. @@ -596,81 +637,83 @@ CMICmnLLDBDebugger::BroadcasterRemoveMask(const CMIUtilString &vBroadcasterClass // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::BroadcasterSaveMask(const CMIUtilString &vBroadcasterClass, const MIuint vEventMask) -{ - if (vBroadcasterClass.empty()) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER), vBroadcasterClass.c_str())); - return MIstatus::failure; - } +bool CMICmnLLDBDebugger::BroadcasterSaveMask( + const CMIUtilString &vBroadcasterClass, const MIuint vEventMask) { + if (vBroadcasterClass.empty()) { + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER), + vBroadcasterClass.c_str())); + return MIstatus::failure; + } - BroadcasterRemoveMask(vBroadcasterClass); - MapPairBroadcastClassNameToEventMask_t pr(vBroadcasterClass, vEventMask); - m_mapBroadcastClassNameToEventMask.insert(pr); + BroadcasterRemoveMask(vBroadcasterClass); + MapPairBroadcastClassNameToEventMask_t pr(vBroadcasterClass, vEventMask); + m_mapBroadcastClassNameToEventMask.insert(pr); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Iterate all the clients who have registered event masks against particular +//++ +//------------------------------------------------------------------------------------ +// Details: Iterate all the clients who have registered event masks against +// particular // SBBroadcasters and build up the mask that is for all of them. // Type: Method. // Args: vBroadcasterClass - (R) The broadcaster to retrieve the mask for. // Return: MIuint - Event mask. // Throws: None. //-- -MIuint -CMICmnLLDBDebugger::ClientGetMaskForAllClients(const CMIUtilString &vBroadcasterClass) const -{ - MIuint mask = 0; - MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.begin(); - while (it != m_mapIdToEventMask.end()) - { - const CMIUtilString &rId((*it).first); - if (rId.find(vBroadcasterClass) != std::string::npos) - { - const MIuint clientsMask = (*it).second; - mask |= clientsMask; - } - - // Next - ++it; +MIuint CMICmnLLDBDebugger::ClientGetMaskForAllClients( + const CMIUtilString &vBroadcasterClass) const { + MIuint mask = 0; + MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.begin(); + while (it != m_mapIdToEventMask.end()) { + const CMIUtilString &rId((*it).first); + if (rId.find(vBroadcasterClass) != std::string::npos) { + const MIuint clientsMask = (*it).second; + mask |= clientsMask; } - return mask; + // Next + ++it; + } + + return mask; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Given the client save its particular event requirements. // Type: Method. // Args: vClientName - (R) The Client's unique ID. -// vBroadcasterClass - (R) The SBBroadcaster's class name targeted for the events. +// vBroadcasterClass - (R) The SBBroadcaster's class name targeted for +// the events. // vEventMask - (R) The mask of events to listen for. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::ClientSaveMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, const MIuint vEventMask) -{ - if (vClientName.empty()) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str())); - return MIstatus::failure; - } +bool CMICmnLLDBDebugger::ClientSaveMask(const CMIUtilString &vClientName, + const CMIUtilString &vBroadcasterClass, + const MIuint vEventMask) { + if (vClientName.empty()) { + SetErrorDescription(CMIUtilString::Format( + MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str())); + return MIstatus::failure; + } - CMIUtilString strId(vBroadcasterClass); - strId += vClientName; + CMIUtilString strId(vBroadcasterClass); + strId += vClientName; - ClientRemoveTheirMask(vClientName, vBroadcasterClass); - MapPairIdToEventMask_t pr(strId, vEventMask); - m_mapIdToEventMask.insert(pr); + ClientRemoveTheirMask(vClientName, vBroadcasterClass); + MapPairIdToEventMask_t pr(strId, vEventMask); + m_mapIdToEventMask.insert(pr); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Given the client remove it's particular event requirements. // Type: Method. // Args: vClientName - (R) The Client's unique ID. @@ -679,29 +722,29 @@ CMICmnLLDBDebugger::ClientSaveMask(const CMIUtilString &vClientName, const CMIUt // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::ClientRemoveTheirMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass) -{ - if (vClientName.empty()) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str())); - return MIstatus::failure; - } +bool CMICmnLLDBDebugger::ClientRemoveTheirMask( + const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass) { + if (vClientName.empty()) { + SetErrorDescription(CMIUtilString::Format( + MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str())); + return MIstatus::failure; + } - CMIUtilString strId(vBroadcasterClass); - strId += vClientName; + CMIUtilString strId(vBroadcasterClass); + strId += vClientName; - const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find(strId); - if (it != m_mapIdToEventMask.end()) - { - m_mapIdToEventMask.erase(it); - } + const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find(strId); + if (it != m_mapIdToEventMask.end()) { + m_mapIdToEventMask.erase(it); + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the client's event mask used for on a particular SBBroadcaster. +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the client's event mask used for on a particular +// SBBroadcaster. // Type: Method. // Args: vClientName - (R) The Client's unique ID. // vBroadcasterClass - (R) The SBBroadcaster's class name. @@ -710,105 +753,115 @@ CMICmnLLDBDebugger::ClientRemoveTheirMask(const CMIUtilString &vClientName, cons // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::ClientGetTheirMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, MIuint &vwEventMask) -{ - vwEventMask = 0; - - if (vClientName.empty()) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str())); - return MIstatus::failure; - } +bool CMICmnLLDBDebugger::ClientGetTheirMask( + const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, + MIuint &vwEventMask) { + vwEventMask = 0; + + if (vClientName.empty()) { + SetErrorDescription(CMIUtilString::Format( + MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str())); + return MIstatus::failure; + } - const CMIUtilString strId(vBroadcasterClass + vClientName); - const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find(strId); - if (it != m_mapIdToEventMask.end()) - { - vwEventMask = (*it).second; - } + const CMIUtilString strId(vBroadcasterClass + vClientName); + const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find(strId); + if (it != m_mapIdToEventMask.end()) { + vwEventMask = (*it).second; + } - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERED), vClientName.c_str())); + SetErrorDescription(CMIUtilString::Format( + MIRSRC(IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERED), vClientName.c_str())); - return MIstatus::failure; + return MIstatus::failure; } -//++ ------------------------------------------------------------------------------------ -// Details: Momentarily wait for an events being broadcast and inspect those that do -// come this way. Check if the target should exit event if so start shutting -// down this thread and the application. Any other events pass on to the +//++ +//------------------------------------------------------------------------------------ +// Details: Momentarily wait for an events being broadcast and inspect those +// that do +// come this way. Check if the target should exit event if so start +// shutting +// down this thread and the application. Any other events pass on to +// the // Out-of-band handler to further determine what kind of event arrived. // This function runs in the thread "MI debugger event". // Type: Method. -// Args: vrbIsAlive - (W) False = yes exit event monitoring thread, true = continue. +// Args: vrbIsAlive - (W) False = yes exit event monitoring thread, true = +// continue. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::MonitorSBListenerEvents(bool &vrbIsAlive) -{ - vrbIsAlive = true; - - // Lock the mutex of event queue - // Note that it should be locked while we are in CMICmnLLDBDebugger::MonitorSBListenerEvents to - // avoid a race condition with CMICmnLLDBDebugger::WaitForHandleEvent - std::unique_lock<std::mutex> lock(m_mutexEventQueue); - - lldb::SBEvent event; - const bool bGotEvent = m_lldbListener.GetNextEvent(event); - if (!bGotEvent) - { - // Notify that we are finished and unlock the mutex of event queue before sleeping - m_conditionEventQueueEmpty.notify_one(); - lock.unlock(); - - // Wait a bit to reduce CPU load - const std::chrono::milliseconds time(1); - std::this_thread::sleep_for(time); - return MIstatus::success; - } - assert(event.IsValid()); - assert(event.GetBroadcaster().IsValid()); - - // Debugging - m_pLog->WriteLog(CMIUtilString::Format("##### An event occurred: %s", event.GetBroadcasterClass())); - - bool bHandledEvent = false; - bool bOk = false; - { - // Lock Mutex before handling events so that we don't disturb a running cmd - CMIUtilThreadLock lock(CMICmnLLDBDebugSessionInfo::Instance().GetSessionMutex()); - bOk = CMICmnLLDBDebuggerHandleEvents::Instance().HandleEvent(event, bHandledEvent); - } - - if (!bHandledEvent) - { - const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT), event.GetBroadcasterClass())); - m_pLog->WriteLog(msg); - } - - if (!bOk) - m_pLog->WriteLog(CMICmnLLDBDebuggerHandleEvents::Instance().GetErrorDescription()); - +bool CMICmnLLDBDebugger::MonitorSBListenerEvents(bool &vrbIsAlive) { + vrbIsAlive = true; + + // Lock the mutex of event queue + // Note that it should be locked while we are in + // CMICmnLLDBDebugger::MonitorSBListenerEvents to + // avoid a race condition with CMICmnLLDBDebugger::WaitForHandleEvent + std::unique_lock<std::mutex> lock(m_mutexEventQueue); + + lldb::SBEvent event; + const bool bGotEvent = m_lldbListener.GetNextEvent(event); + if (!bGotEvent) { + // Notify that we are finished and unlock the mutex of event queue before + // sleeping + m_conditionEventQueueEmpty.notify_one(); + lock.unlock(); + + // Wait a bit to reduce CPU load + const std::chrono::milliseconds time(1); + std::this_thread::sleep_for(time); return MIstatus::success; + } + assert(event.IsValid()); + assert(event.GetBroadcaster().IsValid()); + + // Debugging + m_pLog->WriteLog(CMIUtilString::Format("##### An event occurred: %s", + event.GetBroadcasterClass())); + + bool bHandledEvent = false; + bool bOk = false; + { + // Lock Mutex before handling events so that we don't disturb a running cmd + CMIUtilThreadLock lock( + CMICmnLLDBDebugSessionInfo::Instance().GetSessionMutex()); + bOk = CMICmnLLDBDebuggerHandleEvents::Instance().HandleEvent(event, + bHandledEvent); + } + + if (!bHandledEvent) { + const CMIUtilString msg( + CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT), + event.GetBroadcasterClass())); + m_pLog->WriteLog(msg); + } + + if (!bOk) + m_pLog->WriteLog( + CMICmnLLDBDebuggerHandleEvents::Instance().GetErrorDescription()); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: The main worker method for this thread. // Type: Method. -// Args: vrbIsAlive - (W) True = *this thread is working, false = thread has exited. +// Args: vrbIsAlive - (W) True = *this thread is working, false = thread has +// exited. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::ThreadRun(bool &vrbIsAlive) -{ - return MonitorSBListenerEvents(vrbIsAlive); +bool CMICmnLLDBDebugger::ThreadRun(bool &vrbIsAlive) { + return MonitorSBListenerEvents(vrbIsAlive); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Let this thread clean up after itself. // Type: Method. // Args: @@ -816,26 +869,22 @@ CMICmnLLDBDebugger::ThreadRun(bool &vrbIsAlive) // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::ThreadFinish() -{ - return MIstatus::success; -} +bool CMICmnLLDBDebugger::ThreadFinish() { return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve *this thread object's name. // Type: Overridden. // Args: None. // Return: CMIUtilString & - Text. // Throws: None. //-- -const CMIUtilString & -CMICmnLLDBDebugger::ThreadGetName() const -{ - return m_constStrThisThreadId; +const CMIUtilString &CMICmnLLDBDebugger::ThreadGetName() const { + return m_constStrThisThreadId; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Loads lldb-mi formatters // Type: Method. // Args: None. @@ -843,25 +892,27 @@ CMICmnLLDBDebugger::ThreadGetName() const // false - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::LoadMIFormatters(lldb::SBTypeCategory miCategory) -{ - if (!MI_add_summary(miCategory, "char", MI_char_summary_provider, - lldb::eTypeOptionHideValue | lldb::eTypeOptionSkipPointers)) - return false; - - if (!MI_add_summary(miCategory, "unsigned char", MI_char_summary_provider, - lldb::eTypeOptionHideValue | lldb::eTypeOptionSkipPointers)) - return false; - - if (!MI_add_summary(miCategory, "signed char", MI_char_summary_provider, - lldb::eTypeOptionHideValue | lldb::eTypeOptionSkipPointers)) - return false; - - return true; +bool CMICmnLLDBDebugger::LoadMIFormatters(lldb::SBTypeCategory miCategory) { + if (!MI_add_summary(miCategory, "char", MI_char_summary_provider, + lldb::eTypeOptionHideValue | + lldb::eTypeOptionSkipPointers)) + return false; + + if (!MI_add_summary(miCategory, "unsigned char", MI_char_summary_provider, + lldb::eTypeOptionHideValue | + lldb::eTypeOptionSkipPointers)) + return false; + + if (!MI_add_summary(miCategory, "signed char", MI_char_summary_provider, + lldb::eTypeOptionHideValue | + lldb::eTypeOptionSkipPointers)) + return false; + + return true; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Registers lldb-mi custom summary providers // Type: Method. // Args: None. @@ -869,19 +920,17 @@ CMICmnLLDBDebugger::LoadMIFormatters(lldb::SBTypeCategory miCategory) // false - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebugger::RegisterMISummaryProviders() -{ - static const char* miCategoryName = "lldb-mi"; - lldb::SBTypeCategory miCategory = m_lldbDebugger.CreateCategory(miCategoryName); - if (!miCategory.IsValid()) - return false; - - if (!LoadMIFormatters(miCategory)) - { - m_lldbDebugger.DeleteCategory(miCategoryName); - return false; - } - miCategory.SetEnabled(true); - return true; +bool CMICmnLLDBDebugger::RegisterMISummaryProviders() { + static const char *miCategoryName = "lldb-mi"; + lldb::SBTypeCategory miCategory = + m_lldbDebugger.CreateCategory(miCategoryName); + if (!miCategory.IsValid()) + return false; + + if (!LoadMIFormatters(miCategory)) { + m_lldbDebugger.DeleteCategory(miCategoryName); + return false; + } + miCategory.SetEnabled(true); + return true; } diff --git a/lldb/tools/lldb-mi/MICmnLLDBDebugger.h b/lldb/tools/lldb-mi/MICmnLLDBDebugger.h index 83bc3c06bf6..bec9adf1383 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBDebugger.h +++ b/lldb/tools/lldb-mi/MICmnLLDBDebugger.h @@ -10,105 +10,126 @@ #pragma once // Third party headers +#include "lldb/API/SBDebugger.h" +#include "lldb/API/SBEvent.h" +#include "lldb/API/SBListener.h" #include <condition_variable> #include <map> #include <mutex> -#include "lldb/API/SBDebugger.h" -#include "lldb/API/SBListener.h" -#include "lldb/API/SBEvent.h" // In-house headers: #include "MICmnBase.h" -#include "MIUtilThreadBaseStd.h" #include "MIUtilSingletonBase.h" +#include "MIUtilThreadBaseStd.h" // Declarations: class CMIDriverBase; class CMICmnLLDBDebuggerHandleEvents; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI proxy/adapter for the LLDB public SBDebugger API. The CMIDriver // requires *this object. Command classes make calls on *this object // to facilitate their work effort. The instance runs in its own worker // thread. // A singleton class. //-- -class CMICmnLLDBDebugger : public CMICmnBase, public CMIUtilThreadActiveObjBase, public MI::ISingleton<CMICmnLLDBDebugger> -{ - friend class MI::ISingleton<CMICmnLLDBDebugger>; - - // Methods: - public: - bool Initialize() override; - bool Shutdown() override; - - bool SetDriver(const CMIDriverBase &vClientDriver); - CMIDriverBase &GetDriver() const; - lldb::SBDebugger &GetTheDebugger(); - lldb::SBListener &GetTheListener(); - void WaitForHandleEvent(); - bool CheckIfNeedToRebroadcastStopEvent(); - void RebroadcastStopEvent(); - - // MI Commands can use these functions to listen for events they require - bool RegisterForEvent(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, const MIuint vEventMask); - bool UnregisterForEvent(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass); - bool RegisterForEvent(const CMIUtilString &vClientName, const lldb::SBBroadcaster &vBroadcaster, const MIuint vEventMask); - bool UnregisterForEvent(const CMIUtilString &vClientName, const lldb::SBBroadcaster &vBroadcaster); - - // Overridden: - public: - // From CMIUtilThreadActiveObjBase - const CMIUtilString &ThreadGetName() const override; - - // Overridden: - protected: - // From CMIUtilThreadActiveObjBase - bool ThreadRun(bool &vrIsAlive) override; - bool ThreadFinish() override; - - // Typedefs: - private: - typedef std::map<CMIUtilString, MIuint> MapBroadcastClassNameToEventMask_t; - typedef std::pair<CMIUtilString, MIuint> MapPairBroadcastClassNameToEventMask_t; - typedef std::map<CMIUtilString, MIuint> MapIdToEventMask_t; - typedef std::pair<CMIUtilString, MIuint> MapPairIdToEventMask_t; - - // Methods: - private: - /* ctor */ CMICmnLLDBDebugger(); - /* ctor */ CMICmnLLDBDebugger(const CMICmnLLDBDebugger &); - void operator=(const CMICmnLLDBDebugger &); - - bool InitSBDebugger(); - bool InitSBListener(); - bool InitStdStreams(); - bool MonitorSBListenerEvents(bool &vrbYesExit); - - bool BroadcasterGetMask(const CMIUtilString &vBroadcasterClass, MIuint &vEventMask) const; - bool BroadcasterRemoveMask(const CMIUtilString &vBroadcasterClass); - bool BroadcasterSaveMask(const CMIUtilString &vBroadcasterClass, const MIuint vEventMask); - - MIuint ClientGetMaskForAllClients(const CMIUtilString &vBroadcasterClass) const; - bool ClientSaveMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, const MIuint vEventMask); - bool ClientRemoveTheirMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass); - bool ClientGetTheirMask(const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, MIuint &vwEventMask); - bool LoadMIFormatters(lldb::SBTypeCategory miCategory); - bool RegisterMISummaryProviders(); - // Overridden: - private: - // From CMICmnBase - /* dtor */ ~CMICmnLLDBDebugger() override; - - // Attributes: - private: - CMIDriverBase *m_pClientDriver; // The driver that wants to use *this LLDB debugger - lldb::SBDebugger m_lldbDebugger; // SBDebugger is the primordial object that creates SBTargets and provides access to them - lldb::SBListener m_lldbListener; // API clients can register its own listener to debugger events - const CMIUtilString m_constStrThisThreadId; - MapBroadcastClassNameToEventMask_t m_mapBroadcastClassNameToEventMask; - MapIdToEventMask_t m_mapIdToEventMask; - std::mutex m_mutexEventQueue; - std::condition_variable m_conditionEventQueueEmpty; - uint32_t m_nLastStopId; +class CMICmnLLDBDebugger : public CMICmnBase, + public CMIUtilThreadActiveObjBase, + public MI::ISingleton<CMICmnLLDBDebugger> { + friend class MI::ISingleton<CMICmnLLDBDebugger>; + + // Methods: +public: + bool Initialize() override; + bool Shutdown() override; + + bool SetDriver(const CMIDriverBase &vClientDriver); + CMIDriverBase &GetDriver() const; + lldb::SBDebugger &GetTheDebugger(); + lldb::SBListener &GetTheListener(); + void WaitForHandleEvent(); + bool CheckIfNeedToRebroadcastStopEvent(); + void RebroadcastStopEvent(); + + // MI Commands can use these functions to listen for events they require + bool RegisterForEvent(const CMIUtilString &vClientName, + const CMIUtilString &vBroadcasterClass, + const MIuint vEventMask); + bool UnregisterForEvent(const CMIUtilString &vClientName, + const CMIUtilString &vBroadcasterClass); + bool RegisterForEvent(const CMIUtilString &vClientName, + const lldb::SBBroadcaster &vBroadcaster, + const MIuint vEventMask); + bool UnregisterForEvent(const CMIUtilString &vClientName, + const lldb::SBBroadcaster &vBroadcaster); + + // Overridden: +public: + // From CMIUtilThreadActiveObjBase + const CMIUtilString &ThreadGetName() const override; + + // Overridden: +protected: + // From CMIUtilThreadActiveObjBase + bool ThreadRun(bool &vrIsAlive) override; + bool ThreadFinish() override; + + // Typedefs: +private: + typedef std::map<CMIUtilString, MIuint> MapBroadcastClassNameToEventMask_t; + typedef std::pair<CMIUtilString, MIuint> + MapPairBroadcastClassNameToEventMask_t; + typedef std::map<CMIUtilString, MIuint> MapIdToEventMask_t; + typedef std::pair<CMIUtilString, MIuint> MapPairIdToEventMask_t; + + // Methods: +private: + /* ctor */ CMICmnLLDBDebugger(); + /* ctor */ CMICmnLLDBDebugger(const CMICmnLLDBDebugger &); + void operator=(const CMICmnLLDBDebugger &); + + bool InitSBDebugger(); + bool InitSBListener(); + bool InitStdStreams(); + bool MonitorSBListenerEvents(bool &vrbYesExit); + + bool BroadcasterGetMask(const CMIUtilString &vBroadcasterClass, + MIuint &vEventMask) const; + bool BroadcasterRemoveMask(const CMIUtilString &vBroadcasterClass); + bool BroadcasterSaveMask(const CMIUtilString &vBroadcasterClass, + const MIuint vEventMask); + + MIuint + ClientGetMaskForAllClients(const CMIUtilString &vBroadcasterClass) const; + bool ClientSaveMask(const CMIUtilString &vClientName, + const CMIUtilString &vBroadcasterClass, + const MIuint vEventMask); + bool ClientRemoveTheirMask(const CMIUtilString &vClientName, + const CMIUtilString &vBroadcasterClass); + bool ClientGetTheirMask(const CMIUtilString &vClientName, + const CMIUtilString &vBroadcasterClass, + MIuint &vwEventMask); + bool LoadMIFormatters(lldb::SBTypeCategory miCategory); + bool RegisterMISummaryProviders(); + // Overridden: +private: + // From CMICmnBase + /* dtor */ ~CMICmnLLDBDebugger() override; + + // Attributes: +private: + CMIDriverBase + *m_pClientDriver; // The driver that wants to use *this LLDB debugger + lldb::SBDebugger m_lldbDebugger; // SBDebugger is the primordial object that + // creates SBTargets and provides access to + // them + lldb::SBListener m_lldbListener; // API clients can register its own listener + // to debugger events + const CMIUtilString m_constStrThisThreadId; + MapBroadcastClassNameToEventMask_t m_mapBroadcastClassNameToEventMask; + MapIdToEventMask_t m_mapIdToEventMask; + std::mutex m_mutexEventQueue; + std::condition_variable m_conditionEventQueueEmpty; + uint32_t m_nLastStopId; }; diff --git a/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp b/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp index ea6485bdc67..e975dd6525e 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp +++ b/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp @@ -9,14 +9,14 @@ // Third party headers: #include "lldb/API/SBAddress.h" +#include "lldb/API/SBBreakpoint.h" +#include "lldb/API/SBCommandInterpreter.h" +#include "lldb/API/SBCommandReturnObject.h" #include "lldb/API/SBEvent.h" #include "lldb/API/SBProcess.h" -#include "lldb/API/SBBreakpoint.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBTarget.h" #include "lldb/API/SBThread.h" -#include "lldb/API/SBCommandInterpreter.h" -#include "lldb/API/SBCommandReturnObject.h" #include "lldb/API/SBUnixSignals.h" #ifdef _WIN32 #include <io.h> // For the ::_access() @@ -25,45 +25,45 @@ #endif // _WIN32 // In-house headers: +#include "MICmnLLDBDebugSessionInfo.h" +#include "MICmnLLDBDebugger.h" #include "MICmnLLDBDebuggerHandleEvents.h" -#include "MICmnResources.h" #include "MICmnLog.h" -#include "MICmnLLDBDebugger.h" -#include "MICmnLLDBDebugSessionInfo.h" +#include "MICmnMIOutOfBandRecord.h" #include "MICmnMIResultRecord.h" #include "MICmnMIValueConst.h" #include "MICmnMIValueList.h" -#include "MICmnMIOutOfBandRecord.h" -#include "MICmnStreamStdout.h" +#include "MICmnResources.h" #include "MICmnStreamStderr.h" -#include "MIUtilDebug.h" +#include "MICmnStreamStdout.h" #include "MIDriver.h" +#include "MIUtilDebug.h" #include "Platform.h" // for PATH_MAX -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLLDBDebuggerHandleEvents constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmnLLDBDebuggerHandleEvents::CMICmnLLDBDebuggerHandleEvents() -{ -} +CMICmnLLDBDebuggerHandleEvents::CMICmnLLDBDebuggerHandleEvents() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLLDBDebuggerHandleEvents destructor. // Type: Overridable. // Args: None. // Return: None. // Throws: None. //-- -CMICmnLLDBDebuggerHandleEvents::~CMICmnLLDBDebuggerHandleEvents() -{ - Shutdown(); +CMICmnLLDBDebuggerHandleEvents::~CMICmnLLDBDebuggerHandleEvents() { + Shutdown(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Initialize resources for *this broadcaster object. // Type: Method. // Args: None. @@ -71,25 +71,24 @@ CMICmnLLDBDebuggerHandleEvents::~CMICmnLLDBDebuggerHandleEvents() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::Initialize() -{ - m_clientUsageRefCnt++; - - if (m_bInitialized) - return MIstatus::success; - - m_bInitialized = MIstatus::success; - m_bSignalsInitialized = false; - m_SIGINT = 0; - m_SIGSTOP = 0; - m_SIGSEGV = 0; - m_SIGTRAP = 0; - - return m_bInitialized; +bool CMICmnLLDBDebuggerHandleEvents::Initialize() { + m_clientUsageRefCnt++; + + if (m_bInitialized) + return MIstatus::success; + + m_bInitialized = MIstatus::success; + m_bSignalsInitialized = false; + m_SIGINT = 0; + m_SIGSTOP = 0; + m_SIGSEGV = 0; + m_SIGTRAP = 0; + + return m_bInitialized; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release resources for *this broadcaster object. // Type: Method. // Args: None. @@ -97,23 +96,24 @@ CMICmnLLDBDebuggerHandleEvents::Initialize() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::Shutdown() -{ - if (--m_clientUsageRefCnt > 0) - return MIstatus::success; +bool CMICmnLLDBDebuggerHandleEvents::Shutdown() { + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - if (!m_bInitialized) - return MIstatus::success; + if (!m_bInitialized) + return MIstatus::success; - m_bInitialized = false; + m_bInitialized = false; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Interpret the event object to ascertain the action to take or information to -// to form and put in a MI Out-of-band record object which is given to stdout. +//++ +//------------------------------------------------------------------------------------ +// Details: Interpret the event object to ascertain the action to take or +// information to +// to form and put in a MI Out-of-band record object which is given to +// stdout. // Type: Method. // Args: vEvent - (R) An LLDB broadcast event. // vrbHandledEvent - (W) True - event handled, false = not handled. @@ -121,42 +121,34 @@ CMICmnLLDBDebuggerHandleEvents::Shutdown() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleEvent(const lldb::SBEvent &vEvent, bool &vrbHandledEvent) -{ - bool bOk = MIstatus::success; - vrbHandledEvent = false; - - if (lldb::SBProcess::EventIsProcessEvent(vEvent)) - { - vrbHandledEvent = true; - bOk = HandleEventSBProcess(vEvent); - } - else if (lldb::SBBreakpoint::EventIsBreakpointEvent(vEvent)) - { - vrbHandledEvent = true; - bOk = HandleEventSBBreakPoint(vEvent); - } - else if (lldb::SBThread::EventIsThreadEvent(vEvent)) - { - vrbHandledEvent = true; - bOk = HandleEventSBThread(vEvent); - } - else if (lldb::SBTarget::EventIsTargetEvent(vEvent)) - { - vrbHandledEvent = true; - bOk = HandleEventSBTarget(vEvent); - } - else if (lldb::SBCommandInterpreter::EventIsCommandInterpreterEvent(vEvent)) - { - vrbHandledEvent = true; - bOk = HandleEventSBCommandInterpreter(vEvent); - } - - return bOk; +bool CMICmnLLDBDebuggerHandleEvents::HandleEvent(const lldb::SBEvent &vEvent, + bool &vrbHandledEvent) { + bool bOk = MIstatus::success; + vrbHandledEvent = false; + + if (lldb::SBProcess::EventIsProcessEvent(vEvent)) { + vrbHandledEvent = true; + bOk = HandleEventSBProcess(vEvent); + } else if (lldb::SBBreakpoint::EventIsBreakpointEvent(vEvent)) { + vrbHandledEvent = true; + bOk = HandleEventSBBreakPoint(vEvent); + } else if (lldb::SBThread::EventIsThreadEvent(vEvent)) { + vrbHandledEvent = true; + bOk = HandleEventSBThread(vEvent); + } else if (lldb::SBTarget::EventIsTargetEvent(vEvent)) { + vrbHandledEvent = true; + bOk = HandleEventSBTarget(vEvent); + } else if (lldb::SBCommandInterpreter::EventIsCommandInterpreterEvent( + vEvent)) { + vrbHandledEvent = true; + bOk = HandleEventSBCommandInterpreter(vEvent); + } + + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Handle a LLDB SBProcess event. // Type: Method. // Args: vEvent - (R) An LLDB broadcast event. @@ -164,49 +156,119 @@ CMICmnLLDBDebuggerHandleEvents::HandleEvent(const lldb::SBEvent &vEvent, bool &v // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess(const lldb::SBEvent &vEvent) -{ - bool bOk = MIstatus::success; - - const char *pEventType = ""; - const MIuint nEventType = vEvent.GetType(); - switch (nEventType) - { - case lldb::SBProcess::eBroadcastBitInterrupt: - pEventType = "eBroadcastBitInterrupt"; - break; - case lldb::SBProcess::eBroadcastBitProfileData: - pEventType = "eBroadcastBitProfileData"; - break; - case lldb::SBProcess::eBroadcastBitStructuredData: - pEventType = "eBroadcastBitStructuredData"; - break; - case lldb::SBProcess::eBroadcastBitStateChanged: - pEventType = "eBroadcastBitStateChanged"; - bOk = HandleProcessEventBroadcastBitStateChanged(vEvent); - break; - case lldb::SBProcess::eBroadcastBitSTDERR: - pEventType = "eBroadcastBitSTDERR"; - bOk = GetProcessStderr(); - break; - case lldb::SBProcess::eBroadcastBitSTDOUT: - pEventType = "eBroadcastBitSTDOUT"; - bOk = GetProcessStdout(); - break; - default: - { - const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBProcess", (MIuint)nEventType)); - SetErrorDescription(msg); - return MIstatus::failure; - } - } - m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event occurred: %s", pEventType)); +bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess( + const lldb::SBEvent &vEvent) { + bool bOk = MIstatus::success; + + const char *pEventType = ""; + const MIuint nEventType = vEvent.GetType(); + switch (nEventType) { + case lldb::SBProcess::eBroadcastBitInterrupt: + pEventType = "eBroadcastBitInterrupt"; + break; + case lldb::SBProcess::eBroadcastBitProfileData: + pEventType = "eBroadcastBitProfileData"; + break; + case lldb::SBProcess::eBroadcastBitStructuredData: + pEventType = "eBroadcastBitStructuredData"; + break; + case lldb::SBProcess::eBroadcastBitStateChanged: + pEventType = "eBroadcastBitStateChanged"; + bOk = HandleProcessEventBroadcastBitStateChanged(vEvent); + break; + case lldb::SBProcess::eBroadcastBitSTDERR: + pEventType = "eBroadcastBitSTDERR"; + bOk = GetProcessStderr(); + break; + case lldb::SBProcess::eBroadcastBitSTDOUT: + pEventType = "eBroadcastBitSTDOUT"; + bOk = GetProcessStdout(); + break; + default: { + const CMIUtilString msg( + CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), + "SBProcess", (MIuint)nEventType)); + SetErrorDescription(msg); + return MIstatus::failure; + } + } + m_pLog->WriteLog(CMIUtilString::Format( + "##### An SB Process event occurred: %s", pEventType)); + + return bOk; +} - return bOk; +//++ +//------------------------------------------------------------------------------------ +// Details: Handle a LLDB SBBreakpoint event. +// Type: Method. +// Args: vEvent - (R) An LLDB broadcast event. +// Return: MIstatus::success - Functionality succeeded. +// MIstatus::failure - Functionality failed. +// Throws: None. +//-- +bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakPoint( + const lldb::SBEvent &vEvent) { + bool bOk = MIstatus::success; + + const char *pEventType = ""; + const lldb::BreakpointEventType eEvent = + lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent(vEvent); + switch (eEvent) { + case lldb::eBreakpointEventTypeThreadChanged: + pEventType = "eBreakpointEventTypeThreadChanged"; + break; + case lldb::eBreakpointEventTypeLocationsRemoved: + pEventType = "eBreakpointEventTypeLocationsRemoved"; + break; + case lldb::eBreakpointEventTypeInvalidType: + pEventType = "eBreakpointEventTypeInvalidType"; + break; + case lldb::eBreakpointEventTypeLocationsAdded: + pEventType = "eBreakpointEventTypeLocationsAdded"; + bOk = HandleEventSBBreakpointLocationsAdded(vEvent); + break; + case lldb::eBreakpointEventTypeAdded: + pEventType = "eBreakpointEventTypeAdded"; + bOk = HandleEventSBBreakpointAdded(vEvent); + break; + case lldb::eBreakpointEventTypeRemoved: + pEventType = "eBreakpointEventTypeRemoved"; + bOk = HandleEventSBBreakpointCmn(vEvent); + break; + case lldb::eBreakpointEventTypeLocationsResolved: + pEventType = "eBreakpointEventTypeLocationsResolved"; + bOk = HandleEventSBBreakpointCmn(vEvent); + break; + case lldb::eBreakpointEventTypeEnabled: + pEventType = "eBreakpointEventTypeEnabled"; + bOk = HandleEventSBBreakpointCmn(vEvent); + break; + case lldb::eBreakpointEventTypeDisabled: + pEventType = "eBreakpointEventTypeDisabled"; + bOk = HandleEventSBBreakpointCmn(vEvent); + break; + case lldb::eBreakpointEventTypeCommandChanged: + pEventType = "eBreakpointEventTypeCommandChanged"; + bOk = HandleEventSBBreakpointCmn(vEvent); + break; + case lldb::eBreakpointEventTypeConditionChanged: + pEventType = "eBreakpointEventTypeConditionChanged"; + bOk = HandleEventSBBreakpointCmn(vEvent); + break; + case lldb::eBreakpointEventTypeIgnoreChanged: + pEventType = "eBreakpointEventTypeIgnoreChanged"; + bOk = HandleEventSBBreakpointCmn(vEvent); + break; + } + m_pLog->WriteLog(CMIUtilString::Format( + "##### An SB Breakpoint event occurred: %s", pEventType)); + + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Handle a LLDB SBBreakpoint event. // Type: Method. // Args: vEvent - (R) An LLDB broadcast event. @@ -214,67 +276,24 @@ CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess(const lldb::SBEvent &vEvent // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakPoint(const lldb::SBEvent &vEvent) -{ - bool bOk = MIstatus::success; - - const char *pEventType = ""; - const lldb::BreakpointEventType eEvent = lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent(vEvent); - switch (eEvent) - { - case lldb::eBreakpointEventTypeThreadChanged: - pEventType = "eBreakpointEventTypeThreadChanged"; - break; - case lldb::eBreakpointEventTypeLocationsRemoved: - pEventType = "eBreakpointEventTypeLocationsRemoved"; - break; - case lldb::eBreakpointEventTypeInvalidType: - pEventType = "eBreakpointEventTypeInvalidType"; - break; - case lldb::eBreakpointEventTypeLocationsAdded: - pEventType = "eBreakpointEventTypeLocationsAdded"; - bOk = HandleEventSBBreakpointLocationsAdded(vEvent); - break; - case lldb::eBreakpointEventTypeAdded: - pEventType = "eBreakpointEventTypeAdded"; - bOk = HandleEventSBBreakpointAdded(vEvent); - break; - case lldb::eBreakpointEventTypeRemoved: - pEventType = "eBreakpointEventTypeRemoved"; - bOk = HandleEventSBBreakpointCmn(vEvent); - break; - case lldb::eBreakpointEventTypeLocationsResolved: - pEventType = "eBreakpointEventTypeLocationsResolved"; - bOk = HandleEventSBBreakpointCmn(vEvent); - break; - case lldb::eBreakpointEventTypeEnabled: - pEventType = "eBreakpointEventTypeEnabled"; - bOk = HandleEventSBBreakpointCmn(vEvent); - break; - case lldb::eBreakpointEventTypeDisabled: - pEventType = "eBreakpointEventTypeDisabled"; - bOk = HandleEventSBBreakpointCmn(vEvent); - break; - case lldb::eBreakpointEventTypeCommandChanged: - pEventType = "eBreakpointEventTypeCommandChanged"; - bOk = HandleEventSBBreakpointCmn(vEvent); - break; - case lldb::eBreakpointEventTypeConditionChanged: - pEventType = "eBreakpointEventTypeConditionChanged"; - bOk = HandleEventSBBreakpointCmn(vEvent); - break; - case lldb::eBreakpointEventTypeIgnoreChanged: - pEventType = "eBreakpointEventTypeIgnoreChanged"; - bOk = HandleEventSBBreakpointCmn(vEvent); - break; - } - m_pLog->WriteLog(CMIUtilString::Format("##### An SB Breakpoint event occurred: %s", pEventType)); +bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointLocationsAdded( + const lldb::SBEvent &vEvent) { + const MIuint nLoc = + lldb::SBBreakpoint::GetNumBreakpointLocationsFromEvent(vEvent); + if (nLoc == 0) + return MIstatus::success; - return bOk; + lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent); + const CMIUtilString plural((nLoc == 1) ? "" : "s"); + const CMIUtilString msg( + CMIUtilString::Format("%d location%s added to breakpoint %d", nLoc, + plural.c_str(), brkPt.GetID())); + + return TextToStdout(msg); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Handle a LLDB SBBreakpoint event. // Type: Method. // Args: vEvent - (R) An LLDB broadcast event. @@ -282,58 +301,116 @@ CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakPoint(const lldb::SBEvent &vEv // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointLocationsAdded(const lldb::SBEvent &vEvent) -{ - const MIuint nLoc = lldb::SBBreakpoint::GetNumBreakpointLocationsFromEvent(vEvent); - if (nLoc == 0) - return MIstatus::success; - - lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent); - const CMIUtilString plural((nLoc == 1) ? "" : "s"); - const CMIUtilString msg(CMIUtilString::Format("%d location%s added to breakpoint %d", nLoc, plural.c_str(), brkPt.GetID())); - - return TextToStdout(msg); +bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointCmn( + const lldb::SBEvent &vEvent) { + lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent); + if (!brkPt.IsValid()) + return MIstatus::success; + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; + if (!rSessionInfo.GetBrkPtInfo(brkPt, sBrkPtInfo)) { + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET), + "HandleEventSBBreakpointCmn()", brkPt.GetID())); + return MIstatus::failure; + } + + // CODETAG_LLDB_BREAKPOINT_CREATION + // This is in a worker thread + // Add more breakpoint information or overwrite existing information + CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec; + if (!rSessionInfo.RecordBrkPtInfoGet(brkPt.GetID(), sBrkPtInfoRec)) { + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND), + "HandleEventSBBreakpointCmn()", brkPt.GetID())); + return MIstatus::failure; + } + sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp; + sBrkPtInfo.m_bEnabled = brkPt.IsEnabled(); + sBrkPtInfo.m_bHaveArgOptionThreadGrp = false; + sBrkPtInfo.m_strOptThrdGrp = ""; + sBrkPtInfo.m_nTimes = brkPt.GetHitCount(); + sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc; + sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore; + sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending; + sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition; + sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition; + sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId; + sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId; + + // MI print + // "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" + // PRIx64 "\", + // func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" + CMICmnMIValueTuple miValueTuple; + if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple)) { + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), + "HandleEventSBBreakpointCmn()")); + return MIstatus::failure; + } + + const CMICmnMIValueResult miValueResultC("bkpt", miValueTuple); + const CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResultC); + bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); + bOk = bOk && CMICmnStreamStdout::WritePrompt(); + + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Handle a LLDB SBBreakpoint event. +//++ +//------------------------------------------------------------------------------------ +// Details: Handle a LLDB SBBreakpoint added event. +// Add more breakpoint information or overwrite existing information. +// Normally a break point session info objects exists by now when an MI +// command +// was issued to insert a break so the retrieval would normally always +// succeed +// however should a user type "b main" into a console then LLDB will +// create a +// breakpoint directly, hence no MI command, hence no previous record +// of the +// breakpoint so RecordBrkPtInfoGet() will fail. We still get the event +// though +// so need to create a breakpoint info object here and send appropriate +// MI +// response. // Type: Method. // Args: vEvent - (R) An LLDB broadcast event. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointCmn(const lldb::SBEvent &vEvent) -{ - lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent); - if (!brkPt.IsValid()) - return MIstatus::success; - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; - if (!rSessionInfo.GetBrkPtInfo(brkPt, sBrkPtInfo)) - { - SetErrorDescription( - CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET), "HandleEventSBBreakpointCmn()", brkPt.GetID())); - return MIstatus::failure; - } +bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointAdded( + const lldb::SBEvent &vEvent) { + lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent); + if (!brkPt.IsValid()) + return MIstatus::success; - // CODETAG_LLDB_BREAKPOINT_CREATION - // This is in a worker thread - // Add more breakpoint information or overwrite existing information - CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec; - if (!rSessionInfo.RecordBrkPtInfoGet(brkPt.GetID(), sBrkPtInfoRec)) - { - SetErrorDescription( - CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND), "HandleEventSBBreakpointCmn()", brkPt.GetID())); - return MIstatus::failure; - } + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; + if (!rSessionInfo.GetBrkPtInfo(brkPt, sBrkPtInfo)) { + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET), + "HandleEventSBBreakpointAdded()", brkPt.GetID())); + return MIstatus::failure; + } + + // CODETAG_LLDB_BREAKPOINT_CREATION + // This is in a worker thread + CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec; + const bool bBrkPtExistAlready = + rSessionInfo.RecordBrkPtInfoGet(brkPt.GetID(), sBrkPtInfoRec); + if (bBrkPtExistAlready) { + // Update breakpoint information object sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp; sBrkPtInfo.m_bEnabled = brkPt.IsEnabled(); sBrkPtInfo.m_bHaveArgOptionThreadGrp = false; - sBrkPtInfo.m_strOptThrdGrp = ""; + sBrkPtInfo.m_strOptThrdGrp.clear(); sBrkPtInfo.m_nTimes = brkPt.GetHitCount(); sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc; sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore; @@ -342,138 +419,75 @@ CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointCmn(const lldb::SBEvent & sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition; sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId; sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId; - - // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" PRIx64 "\", - // func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" - CMICmnMIValueTuple miValueTuple; - if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple)) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "HandleEventSBBreakpointCmn()")); - return MIstatus::failure; - } - - const CMICmnMIValueResult miValueResultC("bkpt", miValueTuple); - const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResultC); - bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); + } else { + // Create a breakpoint information object + sBrkPtInfo.m_bDisp = brkPt.IsOneShot(); + sBrkPtInfo.m_bEnabled = brkPt.IsEnabled(); + sBrkPtInfo.m_bHaveArgOptionThreadGrp = false; + sBrkPtInfo.m_strOptThrdGrp.clear(); + sBrkPtInfo.m_strOrigLoc = CMIUtilString::Format( + "%s:%d", sBrkPtInfo.m_fileName.c_str(), sBrkPtInfo.m_nLine); + sBrkPtInfo.m_nIgnore = brkPt.GetIgnoreCount(); + sBrkPtInfo.m_bPending = false; + const char *pStrCondition = brkPt.GetCondition(); + sBrkPtInfo.m_bCondition = (pStrCondition != nullptr) ? true : false; + sBrkPtInfo.m_strCondition = + (pStrCondition != nullptr) ? pStrCondition : "??"; + sBrkPtInfo.m_bBrkPtThreadId = (brkPt.GetThreadID() != 0) ? true : false; + sBrkPtInfo.m_nBrkPtThreadId = brkPt.GetThreadID(); + } + + CMICmnMIValueTuple miValueTuple; + if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple)) { + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), + "HandleEventSBBreakpointAdded()")); + return MIstatus::failure; + } + + bool bOk = MIstatus::success; + if (bBrkPtExistAlready) { + // MI print + // "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" + // PRIx64 + // "\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" + const CMICmnMIValueResult miValueResult("bkpt", miValueTuple); + const CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult); + bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); bOk = bOk && CMICmnStreamStdout::WritePrompt(); - - return bOk; -} - -//++ ------------------------------------------------------------------------------------ -// Details: Handle a LLDB SBBreakpoint added event. -// Add more breakpoint information or overwrite existing information. -// Normally a break point session info objects exists by now when an MI command -// was issued to insert a break so the retrieval would normally always succeed -// however should a user type "b main" into a console then LLDB will create a -// breakpoint directly, hence no MI command, hence no previous record of the -// breakpoint so RecordBrkPtInfoGet() will fail. We still get the event though -// so need to create a breakpoint info object here and send appropriate MI -// response. -// Type: Method. -// Args: vEvent - (R) An LLDB broadcast event. -// Return: MIstatus::success - Functionality succeeded. -// MIstatus::failure - Functionality failed. -// Throws: None. -//-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointAdded(const lldb::SBEvent &vEvent) -{ - lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent); - if (!brkPt.IsValid()) - return MIstatus::success; - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; - if (!rSessionInfo.GetBrkPtInfo(brkPt, sBrkPtInfo)) - { - SetErrorDescription( - CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET), "HandleEventSBBreakpointAdded()", brkPt.GetID())); - return MIstatus::failure; + } else { + // CODETAG_LLDB_BRKPT_ID_MAX + if (brkPt.GetID() > (lldb::break_id_t)rSessionInfo.m_nBrkPointCntMax) { + SetErrorDescription(CMIUtilString::Format( + MIRSRC(IDS_CMD_ERR_BRKPT_CNT_EXCEEDED), + "HandleEventSBBreakpointAdded()", rSessionInfo.m_nBrkPointCntMax, + sBrkPtInfo.m_id)); + return MIstatus::failure; } - - // CODETAG_LLDB_BREAKPOINT_CREATION - // This is in a worker thread - CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec; - const bool bBrkPtExistAlready = rSessionInfo.RecordBrkPtInfoGet(brkPt.GetID(), sBrkPtInfoRec); - if (bBrkPtExistAlready) - { - // Update breakpoint information object - sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp; - sBrkPtInfo.m_bEnabled = brkPt.IsEnabled(); - sBrkPtInfo.m_bHaveArgOptionThreadGrp = false; - sBrkPtInfo.m_strOptThrdGrp.clear(); - sBrkPtInfo.m_nTimes = brkPt.GetHitCount(); - sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc; - sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore; - sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending; - sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition; - sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition; - sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId; - sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId; - } - else - { - // Create a breakpoint information object - sBrkPtInfo.m_bDisp = brkPt.IsOneShot(); - sBrkPtInfo.m_bEnabled = brkPt.IsEnabled(); - sBrkPtInfo.m_bHaveArgOptionThreadGrp = false; - sBrkPtInfo.m_strOptThrdGrp.clear(); - sBrkPtInfo.m_strOrigLoc = CMIUtilString::Format("%s:%d", sBrkPtInfo.m_fileName.c_str(), sBrkPtInfo.m_nLine); - sBrkPtInfo.m_nIgnore = brkPt.GetIgnoreCount(); - sBrkPtInfo.m_bPending = false; - const char *pStrCondition = brkPt.GetCondition(); - sBrkPtInfo.m_bCondition = (pStrCondition != nullptr) ? true : false; - sBrkPtInfo.m_strCondition = (pStrCondition != nullptr) ? pStrCondition : "??"; - sBrkPtInfo.m_bBrkPtThreadId = (brkPt.GetThreadID() != 0) ? true : false; - sBrkPtInfo.m_nBrkPtThreadId = brkPt.GetThreadID(); + if (!rSessionInfo.RecordBrkPtInfo(brkPt.GetID(), sBrkPtInfo)) { + SetErrorDescription(CMIUtilString::Format( + MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET), + "HandleEventSBBreakpointAdded()", sBrkPtInfo.m_id)); + return MIstatus::failure; } - CMICmnMIValueTuple miValueTuple; - if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple)) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "HandleEventSBBreakpointAdded()")); - return MIstatus::failure; - } - - bool bOk = MIstatus::success; - if (bBrkPtExistAlready) - { - // MI print - // "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" PRIx64 "\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" - const CMICmnMIValueResult miValueResult("bkpt", miValueTuple); - const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult); - bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); - bOk = bOk && CMICmnStreamStdout::WritePrompt(); - } - else - { - // CODETAG_LLDB_BRKPT_ID_MAX - if (brkPt.GetID() > (lldb::break_id_t)rSessionInfo.m_nBrkPointCntMax) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_CNT_EXCEEDED), "HandleEventSBBreakpointAdded()", - rSessionInfo.m_nBrkPointCntMax, sBrkPtInfo.m_id)); - return MIstatus::failure; - } - if (!rSessionInfo.RecordBrkPtInfo(brkPt.GetID(), sBrkPtInfo)) - { - SetErrorDescription( - CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET), "HandleEventSBBreakpointAdded()", sBrkPtInfo.m_id)); - return MIstatus::failure; - } - - // MI print - // "=breakpoint-created,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" PRIx64 "\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" - const CMICmnMIValueResult miValueResult("bkpt", miValueTuple); - const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, miValueResult); - bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); - bOk = bOk && CMICmnStreamStdout::WritePrompt(); - } + // MI print + // "=breakpoint-created,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" + // PRIx64 + // "\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" + const CMICmnMIValueResult miValueResult("bkpt", miValueTuple); + const CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, miValueResult); + bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); + bOk = bOk && CMICmnStreamStdout::WritePrompt(); + } - return bOk; + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Handle a LLDB SBThread event. // Type: Method. // Args: vEvent - (R) An LLDB broadcast event. @@ -481,47 +495,48 @@ CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointAdded(const lldb::SBEvent // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleEventSBThread(const lldb::SBEvent &vEvent) -{ - if (!ChkForStateChanges()) - return MIstatus::failure; - - bool bOk = MIstatus::success; - const char *pEventType = ""; - const MIuint nEventType = vEvent.GetType(); - switch (nEventType) - { - case lldb::SBThread::eBroadcastBitStackChanged: - pEventType = "eBroadcastBitStackChanged"; - bOk = HandleEventSBThreadBitStackChanged(vEvent); - break; - case lldb::SBThread::eBroadcastBitThreadSuspended: - pEventType = "eBroadcastBitThreadSuspended"; - bOk = HandleEventSBThreadSuspended(vEvent); - break; - case lldb::SBThread::eBroadcastBitThreadResumed: - pEventType = "eBroadcastBitThreadResumed"; - break; - case lldb::SBThread::eBroadcastBitSelectedFrameChanged: - pEventType = "eBroadcastBitSelectedFrameChanged"; - break; - case lldb::SBThread::eBroadcastBitThreadSelected: - pEventType = "eBroadcastBitThreadSelected"; - break; - default: - { - const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBThread", (MIuint)nEventType)); - SetErrorDescription(msg); - return MIstatus::failure; - } - } - m_pLog->WriteLog(CMIUtilString::Format("##### An SBThread event occurred: %s", pEventType)); - - return bOk; +bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThread( + const lldb::SBEvent &vEvent) { + if (!ChkForStateChanges()) + return MIstatus::failure; + + bool bOk = MIstatus::success; + const char *pEventType = ""; + const MIuint nEventType = vEvent.GetType(); + switch (nEventType) { + case lldb::SBThread::eBroadcastBitStackChanged: + pEventType = "eBroadcastBitStackChanged"; + bOk = HandleEventSBThreadBitStackChanged(vEvent); + break; + case lldb::SBThread::eBroadcastBitThreadSuspended: + pEventType = "eBroadcastBitThreadSuspended"; + bOk = HandleEventSBThreadSuspended(vEvent); + break; + case lldb::SBThread::eBroadcastBitThreadResumed: + pEventType = "eBroadcastBitThreadResumed"; + break; + case lldb::SBThread::eBroadcastBitSelectedFrameChanged: + pEventType = "eBroadcastBitSelectedFrameChanged"; + break; + case lldb::SBThread::eBroadcastBitThreadSelected: + pEventType = "eBroadcastBitThreadSelected"; + break; + default: { + const CMIUtilString msg( + CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), + "SBThread", (MIuint)nEventType)); + SetErrorDescription(msg); + return MIstatus::failure; + } + } + m_pLog->WriteLog(CMIUtilString::Format("##### An SBThread event occurred: %s", + pEventType)); + + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Handle a LLDB SBThread event. // Type: Method. // Args: vEvent - (R) An LLDB broadcast event. @@ -529,31 +544,33 @@ CMICmnLLDBDebuggerHandleEvents::HandleEventSBThread(const lldb::SBEvent &vEvent) // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadSuspended(const lldb::SBEvent &vEvent) -{ - lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent(vEvent); - if (!thread.IsValid()) - return MIstatus::success; - - const lldb::StopReason eStopReason = thread.GetStopReason(); - if (eStopReason != lldb::eStopReasonSignal) - return MIstatus::success; - - // MI print "@thread=%d,signal=%lld" - const MIuint64 nId = thread.GetStopReasonDataAtIndex(0); - const CMIUtilString strThread(CMIUtilString::Format("%d", thread.GetThreadID())); - const CMICmnMIValueConst miValueConst(strThread); - const CMICmnMIValueResult miValueResult("thread", miValueConst); - CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Thread, miValueResult); - const CMIUtilString strSignal(CMIUtilString::Format("%lld", nId)); - const CMICmnMIValueConst miValueConst2(strSignal); - const CMICmnMIValueResult miValueResult2("signal", miValueConst2); - miOutOfBandRecord.Add(miValueResult2); - return MiOutOfBandRecordToStdout(miOutOfBandRecord); +bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadSuspended( + const lldb::SBEvent &vEvent) { + lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent(vEvent); + if (!thread.IsValid()) + return MIstatus::success; + + const lldb::StopReason eStopReason = thread.GetStopReason(); + if (eStopReason != lldb::eStopReasonSignal) + return MIstatus::success; + + // MI print "@thread=%d,signal=%lld" + const MIuint64 nId = thread.GetStopReasonDataAtIndex(0); + const CMIUtilString strThread( + CMIUtilString::Format("%d", thread.GetThreadID())); + const CMICmnMIValueConst miValueConst(strThread); + const CMICmnMIValueResult miValueResult("thread", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_Thread, miValueResult); + const CMIUtilString strSignal(CMIUtilString::Format("%lld", nId)); + const CMICmnMIValueConst miValueConst2(strSignal); + const CMICmnMIValueResult miValueResult2("signal", miValueConst2); + miOutOfBandRecord.Add(miValueResult2); + return MiOutOfBandRecordToStdout(miOutOfBandRecord); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Handle a LLDB SBThread event. // Type: Method. // Args: vEvent - (R) An LLDB broadcast event. @@ -561,19 +578,19 @@ CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadSuspended(const lldb::SBEvent // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadBitStackChanged(const lldb::SBEvent &vEvent) -{ - lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent(vEvent); - if (!thread.IsValid()) - return MIstatus::success; +bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadBitStackChanged( + const lldb::SBEvent &vEvent) { + lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent(vEvent); + if (!thread.IsValid()) + return MIstatus::success; - lldb::SBStream streamOut; - const bool bOk = thread.GetStatus(streamOut); - return bOk && TextToStdout(streamOut.GetData()); + lldb::SBStream streamOut; + const bool bOk = thread.GetStatus(streamOut); + return bOk && TextToStdout(streamOut.GetData()); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Handle a LLDB SBTarget event. // Type: Method. // Args: vEvent - (R) An LLDB broadcast event. @@ -581,172 +598,186 @@ CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadBitStackChanged(const lldb::S // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleEventSBTarget(const lldb::SBEvent &vEvent) -{ - if (!ChkForStateChanges()) - return MIstatus::failure; - - bool bOk = MIstatus::success; - const char *pEventType = ""; - const MIuint nEventType = vEvent.GetType(); - switch (nEventType) - { - case lldb::SBTarget::eBroadcastBitBreakpointChanged: - pEventType = "eBroadcastBitBreakpointChanged"; - break; - case lldb::SBTarget::eBroadcastBitModulesLoaded: - pEventType = "eBroadcastBitModulesLoaded"; - bOk = HandleTargetEventBroadcastBitModulesLoaded(vEvent); - break; - case lldb::SBTarget::eBroadcastBitModulesUnloaded: - pEventType = "eBroadcastBitModulesUnloaded"; - bOk = HandleTargetEventBroadcastBitModulesUnloaded(vEvent); - break; - case lldb::SBTarget::eBroadcastBitWatchpointChanged: - pEventType = "eBroadcastBitWatchpointChanged"; - break; - case lldb::SBTarget::eBroadcastBitSymbolsLoaded: - pEventType = "eBroadcastBitSymbolsLoaded"; - break; - default: - { - const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBTarget", (MIuint)nEventType)); - SetErrorDescription(msg); - return MIstatus::failure; - } - } - m_pLog->WriteLog(CMIUtilString::Format("##### An SBTarget event occurred: %s", pEventType)); - - return bOk; +bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBTarget( + const lldb::SBEvent &vEvent) { + if (!ChkForStateChanges()) + return MIstatus::failure; + + bool bOk = MIstatus::success; + const char *pEventType = ""; + const MIuint nEventType = vEvent.GetType(); + switch (nEventType) { + case lldb::SBTarget::eBroadcastBitBreakpointChanged: + pEventType = "eBroadcastBitBreakpointChanged"; + break; + case lldb::SBTarget::eBroadcastBitModulesLoaded: + pEventType = "eBroadcastBitModulesLoaded"; + bOk = HandleTargetEventBroadcastBitModulesLoaded(vEvent); + break; + case lldb::SBTarget::eBroadcastBitModulesUnloaded: + pEventType = "eBroadcastBitModulesUnloaded"; + bOk = HandleTargetEventBroadcastBitModulesUnloaded(vEvent); + break; + case lldb::SBTarget::eBroadcastBitWatchpointChanged: + pEventType = "eBroadcastBitWatchpointChanged"; + break; + case lldb::SBTarget::eBroadcastBitSymbolsLoaded: + pEventType = "eBroadcastBitSymbolsLoaded"; + break; + default: { + const CMIUtilString msg( + CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), + "SBTarget", (MIuint)nEventType)); + SetErrorDescription(msg); + return MIstatus::failure; + } + } + m_pLog->WriteLog(CMIUtilString::Format("##### An SBTarget event occurred: %s", + pEventType)); + + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Print to stdout "=library-loaded,id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded="%d"[,symbols-path=\"%s\"],loaded_addr=\"0x%016" PRIx64"\"" +//++ +//------------------------------------------------------------------------------------ +// Details: Print to stdout +// "=library-loaded,id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded="%d"[,symbols-path=\"%s\"],loaded_addr=\"0x%016" +// PRIx64"\"" // Type: Method. // Args: None. // Return: MIstatus::success - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleTargetEventBroadcastBitModulesLoaded(const lldb::SBEvent &vEvent) -{ - bool bOk = MIstatus::failure; - const MIuint nSize = lldb::SBTarget::GetNumModulesFromEvent(vEvent); - for (MIuint nIndex = 0; nIndex < nSize; ++nIndex) - { - const lldb::SBModule sbModule = lldb::SBTarget::GetModuleAtIndexFromEvent(nIndex, vEvent); - CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleLoaded); - const bool bWithExtraFields = true; - bOk = MiHelpGetModuleInfo(sbModule, bWithExtraFields, miOutOfBandRecord); - bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); - if (!bOk) - break; - } +bool CMICmnLLDBDebuggerHandleEvents::HandleTargetEventBroadcastBitModulesLoaded( + const lldb::SBEvent &vEvent) { + bool bOk = MIstatus::failure; + const MIuint nSize = lldb::SBTarget::GetNumModulesFromEvent(vEvent); + for (MIuint nIndex = 0; nIndex < nSize; ++nIndex) { + const lldb::SBModule sbModule = + lldb::SBTarget::GetModuleAtIndexFromEvent(nIndex, vEvent); + CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleLoaded); + const bool bWithExtraFields = true; + bOk = MiHelpGetModuleInfo(sbModule, bWithExtraFields, miOutOfBandRecord); + bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); + if (!bOk) + break; + } - return bOk; + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Print to stdout "=library-unloaded,id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded="%d"[,symbols-path=\"%s\"],loaded_addr=\"0x%016" PRIx64"\"" +//++ +//------------------------------------------------------------------------------------ +// Details: Print to stdout +// "=library-unloaded,id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded="%d"[,symbols-path=\"%s\"],loaded_addr=\"0x%016" +// PRIx64"\"" // Type: Method. // Args: None. // Return: MIstatus::success - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleTargetEventBroadcastBitModulesUnloaded(const lldb::SBEvent &vEvent) -{ - bool bOk = MIstatus::failure; - const MIuint nSize = lldb::SBTarget::GetNumModulesFromEvent(vEvent); - for (MIuint nIndex = 0; nIndex < nSize; ++nIndex) - { - const lldb::SBModule sbModule = lldb::SBTarget::GetModuleAtIndexFromEvent(nIndex, vEvent); - CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleUnloaded); - const bool bWithExtraFields = false; - bOk = MiHelpGetModuleInfo(sbModule, bWithExtraFields, miOutOfBandRecord); - bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); - if (!bOk) - break; - } +bool CMICmnLLDBDebuggerHandleEvents:: + HandleTargetEventBroadcastBitModulesUnloaded(const lldb::SBEvent &vEvent) { + bool bOk = MIstatus::failure; + const MIuint nSize = lldb::SBTarget::GetNumModulesFromEvent(vEvent); + for (MIuint nIndex = 0; nIndex < nSize; ++nIndex) { + const lldb::SBModule sbModule = + lldb::SBTarget::GetModuleAtIndexFromEvent(nIndex, vEvent); + CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleUnloaded); + const bool bWithExtraFields = false; + bOk = MiHelpGetModuleInfo(sbModule, bWithExtraFields, miOutOfBandRecord); + bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); + if (!bOk) + break; + } - return bOk; + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Build module information for =library-loaded/=library-unloaded: "id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded="%d"[,symbols-path=\"%s\"],loaded_addr=\"0x%016" PRIx64"\"" +//++ +//------------------------------------------------------------------------------------ +// Details: Build module information for =library-loaded/=library-unloaded: +// "id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded="%d"[,symbols-path=\"%s\"],loaded_addr=\"0x%016" +// PRIx64"\"" // Type: Method. // Args: vwrMiValueList - (W) MI value list object. // Return: MIstatus::success - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::MiHelpGetModuleInfo(const lldb::SBModule &vModule, const bool vbWithExtraFields, - CMICmnMIOutOfBandRecord &vwrMiOutOfBandRecord) -{ - bool bOk = MIstatus::success; - - // First, build standard fields: - // Build "id" field - std::unique_ptr<char[]> apPath(new char[PATH_MAX]); - vModule.GetFileSpec().GetPath(apPath.get(), PATH_MAX); - const CMIUtilString strTargetPath(apPath.get()); - const CMICmnMIValueConst miValueConst(strTargetPath.AddSlashes()); - const CMICmnMIValueResult miValueResult("id", miValueConst); - vwrMiOutOfBandRecord.Add(miValueResult); - // Build "target-name" field - const CMICmnMIValueConst miValueConst2(strTargetPath.AddSlashes()); - const CMICmnMIValueResult miValueResult2("target-name", miValueConst2); - vwrMiOutOfBandRecord.Add(miValueResult2); - // Build "host-name" field - vModule.GetPlatformFileSpec().GetPath(apPath.get(), PATH_MAX); - const CMIUtilString strHostPath(apPath.get()); - const CMICmnMIValueConst miValueConst3(strHostPath.AddSlashes()); - const CMICmnMIValueResult miValueResult3("host-name", miValueConst3); - vwrMiOutOfBandRecord.Add(miValueResult3); - - // Then build extra fields if needed: - if (vbWithExtraFields) - { - // Build "symbols-loaded" field - vModule.GetSymbolFileSpec().GetPath(apPath.get(), PATH_MAX); - const CMIUtilString strSymbolsPath(apPath.get()); - const bool bSymbolsLoaded = !CMIUtilString::Compare(strHostPath, strSymbolsPath); - const CMICmnMIValueConst miValueConst4(CMIUtilString::Format("%d", bSymbolsLoaded)); - const CMICmnMIValueResult miValueResult4("symbols-loaded", miValueConst4); - vwrMiOutOfBandRecord.Add(miValueResult4); - // Build "symbols-path" field - if (bSymbolsLoaded) - { - const CMICmnMIValueConst miValueConst5(strSymbolsPath.AddSlashes()); - const CMICmnMIValueResult miValueResult5("symbols-path", miValueConst5); - vwrMiOutOfBandRecord.Add(miValueResult5); - } - // Build "loaded_addr" field - lldb::SBAddress sbAddress(vModule.GetObjectFileHeaderAddress()); - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - const lldb::addr_t nLoadAddress(sbAddress.GetLoadAddress(rSessionInfo.GetTarget())); - const CMIUtilString strLoadedAddr(nLoadAddress != LLDB_INVALID_ADDRESS ? - CMIUtilString::Format("0x%016" PRIx64, nLoadAddress) : "-"); - const CMICmnMIValueConst miValueConst6(strLoadedAddr); - const CMICmnMIValueResult miValueResult6("loaded_addr", miValueConst6); - vwrMiOutOfBandRecord.Add(miValueResult6); - - // Build "size" field - lldb::SBSection sbSection = sbAddress.GetSection(); - const CMIUtilString strSize(CMIUtilString::Format("%" PRIu64, sbSection.GetByteSize())); - const CMICmnMIValueConst miValueConst7(strSize); - const CMICmnMIValueResult miValueResult7("size", miValueConst7); - vwrMiOutOfBandRecord.Add(miValueResult7); +bool CMICmnLLDBDebuggerHandleEvents::MiHelpGetModuleInfo( + const lldb::SBModule &vModule, const bool vbWithExtraFields, + CMICmnMIOutOfBandRecord &vwrMiOutOfBandRecord) { + bool bOk = MIstatus::success; + + // First, build standard fields: + // Build "id" field + std::unique_ptr<char[]> apPath(new char[PATH_MAX]); + vModule.GetFileSpec().GetPath(apPath.get(), PATH_MAX); + const CMIUtilString strTargetPath(apPath.get()); + const CMICmnMIValueConst miValueConst(strTargetPath.AddSlashes()); + const CMICmnMIValueResult miValueResult("id", miValueConst); + vwrMiOutOfBandRecord.Add(miValueResult); + // Build "target-name" field + const CMICmnMIValueConst miValueConst2(strTargetPath.AddSlashes()); + const CMICmnMIValueResult miValueResult2("target-name", miValueConst2); + vwrMiOutOfBandRecord.Add(miValueResult2); + // Build "host-name" field + vModule.GetPlatformFileSpec().GetPath(apPath.get(), PATH_MAX); + const CMIUtilString strHostPath(apPath.get()); + const CMICmnMIValueConst miValueConst3(strHostPath.AddSlashes()); + const CMICmnMIValueResult miValueResult3("host-name", miValueConst3); + vwrMiOutOfBandRecord.Add(miValueResult3); + + // Then build extra fields if needed: + if (vbWithExtraFields) { + // Build "symbols-loaded" field + vModule.GetSymbolFileSpec().GetPath(apPath.get(), PATH_MAX); + const CMIUtilString strSymbolsPath(apPath.get()); + const bool bSymbolsLoaded = + !CMIUtilString::Compare(strHostPath, strSymbolsPath); + const CMICmnMIValueConst miValueConst4( + CMIUtilString::Format("%d", bSymbolsLoaded)); + const CMICmnMIValueResult miValueResult4("symbols-loaded", miValueConst4); + vwrMiOutOfBandRecord.Add(miValueResult4); + // Build "symbols-path" field + if (bSymbolsLoaded) { + const CMICmnMIValueConst miValueConst5(strSymbolsPath.AddSlashes()); + const CMICmnMIValueResult miValueResult5("symbols-path", miValueConst5); + vwrMiOutOfBandRecord.Add(miValueResult5); } - - return bOk; + // Build "loaded_addr" field + lldb::SBAddress sbAddress(vModule.GetObjectFileHeaderAddress()); + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + const lldb::addr_t nLoadAddress( + sbAddress.GetLoadAddress(rSessionInfo.GetTarget())); + const CMIUtilString strLoadedAddr( + nLoadAddress != LLDB_INVALID_ADDRESS + ? CMIUtilString::Format("0x%016" PRIx64, nLoadAddress) + : "-"); + const CMICmnMIValueConst miValueConst6(strLoadedAddr); + const CMICmnMIValueResult miValueResult6("loaded_addr", miValueConst6); + vwrMiOutOfBandRecord.Add(miValueResult6); + + // Build "size" field + lldb::SBSection sbSection = sbAddress.GetSection(); + const CMIUtilString strSize( + CMIUtilString::Format("%" PRIu64, sbSection.GetByteSize())); + const CMICmnMIValueConst miValueConst7(strSize); + const CMICmnMIValueResult miValueResult7("size", miValueConst7); + vwrMiOutOfBandRecord.Add(miValueResult7); + } + + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Handle a LLDB SBCommandInterpreter event. // Type: Method. // Args: vEvent - (R) An LLDB command interpreter event. @@ -754,57 +785,58 @@ CMICmnLLDBDebuggerHandleEvents::MiHelpGetModuleInfo(const lldb::SBModule &vModul // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleEventSBCommandInterpreter(const lldb::SBEvent &vEvent) -{ - // This function is not used - // *** This function is under development - - const char *pEventType = ""; - const MIuint nEventType = vEvent.GetType(); - switch (nEventType) - { - case lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit: - pEventType = "eBroadcastBitThreadShouldExit"; - // ToDo: IOR: Reminder to maybe handle this here - // const MIuint nEventType = event.GetType(); - // if (nEventType & lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit) - //{ - // m_pClientDriver->SetExitApplicationFlag(); - // vrbYesExit = true; - // return MIstatus::success; - //} - break; - case lldb::SBCommandInterpreter::eBroadcastBitResetPrompt: - pEventType = "eBroadcastBitResetPrompt"; - break; - case lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived: - { - pEventType = "eBroadcastBitQuitCommandReceived"; - const bool bForceExit = true; - CMICmnLLDBDebugger::Instance().GetDriver().SetExitApplicationFlag(bForceExit); - break; - } - case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData: - pEventType = "eBroadcastBitAsynchronousOutputData"; - break; - case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData: - pEventType = "eBroadcastBitAsynchronousErrorData"; - break; - default: - { - const CMIUtilString msg( - CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBCommandInterpreter", (MIuint)nEventType)); - SetErrorDescription(msg); - return MIstatus::failure; - } - } - m_pLog->WriteLog(CMIUtilString::Format("##### An SBCommandInterpreter event occurred: %s", pEventType)); - - return MIstatus::success; +bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBCommandInterpreter( + const lldb::SBEvent &vEvent) { + // This function is not used + // *** This function is under development + + const char *pEventType = ""; + const MIuint nEventType = vEvent.GetType(); + switch (nEventType) { + case lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit: + pEventType = "eBroadcastBitThreadShouldExit"; + // ToDo: IOR: Reminder to maybe handle this here + // const MIuint nEventType = event.GetType(); + // if (nEventType & + // lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit) + //{ + // m_pClientDriver->SetExitApplicationFlag(); + // vrbYesExit = true; + // return MIstatus::success; + //} + break; + case lldb::SBCommandInterpreter::eBroadcastBitResetPrompt: + pEventType = "eBroadcastBitResetPrompt"; + break; + case lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived: { + pEventType = "eBroadcastBitQuitCommandReceived"; + const bool bForceExit = true; + CMICmnLLDBDebugger::Instance().GetDriver().SetExitApplicationFlag( + bForceExit); + break; + } + case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData: + pEventType = "eBroadcastBitAsynchronousOutputData"; + break; + case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData: + pEventType = "eBroadcastBitAsynchronousErrorData"; + break; + default: { + const CMIUtilString msg( + CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), + "SBCommandInterpreter", (MIuint)nEventType)); + SetErrorDescription(msg); + return MIstatus::failure; + } + } + m_pLog->WriteLog(CMIUtilString::Format( + "##### An SBCommandInterpreter event occurred: %s", pEventType)); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Handle SBProcess event eBroadcastBitStateChanged. // Type: Method. // Args: vEvent - (R) An LLDB event object. @@ -812,91 +844,94 @@ CMICmnLLDBDebuggerHandleEvents::HandleEventSBCommandInterpreter(const lldb::SBEv // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged(const lldb::SBEvent &vEvent) -{ - // Make sure the program hasn't been auto-restarted: - if (lldb::SBProcess::GetRestartedFromEvent(vEvent)) - return MIstatus::success; - - bool bOk = ChkForStateChanges(); - bOk = bOk && GetProcessStdout(); - bOk = bOk && GetProcessStderr(); - if (!bOk) - return MIstatus::failure; - - // Something changed in the process; get the event and report the process's current - // status and location - const lldb::StateType eEventState = lldb::SBProcess::GetStateFromEvent(vEvent); - if (eEventState == lldb::eStateInvalid) - return MIstatus::success; - - lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent(vEvent); - if (!process.IsValid()) - { - const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID), "SBProcess", - "HandleProcessEventBroadcastBitStateChanged()")); - SetErrorDescription(msg); - return MIstatus::failure; - } - - bool bShouldBrk = true; - const char *pEventType = ""; - switch (eEventState) - { - case lldb::eStateUnloaded: - pEventType = "eStateUnloaded"; - break; - case lldb::eStateConnected: - pEventType = "eStateConnected"; - break; - case lldb::eStateAttaching: - pEventType = "eStateAttaching"; - break; - case lldb::eStateLaunching: - pEventType = "eStateLaunching"; - break; - case lldb::eStateStopped: - pEventType = "eStateStopped"; - bOk = HandleProcessEventStateStopped(vEvent, bShouldBrk); - if (bShouldBrk) - break; - case lldb::eStateCrashed: - case lldb::eStateSuspended: - pEventType = "eStateSuspended"; - bOk = HandleProcessEventStateSuspended(vEvent); - break; - case lldb::eStateRunning: - pEventType = "eStateRunning"; - bOk = HandleProcessEventStateRunning(); - break; - case lldb::eStateStepping: - pEventType = "eStateStepping"; - break; - case lldb::eStateDetached: - pEventType = "eStateDetached"; - break; - case lldb::eStateExited: - // Don't exit from lldb-mi here. We should be able to re-run target. - pEventType = "eStateExited"; - bOk = HandleProcessEventStateExited(); - break; - default: - { - const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBProcess BroadcastBitStateChanged", - (MIuint)eEventState)); - SetErrorDescription(msg); - return MIstatus::failure; - } - } +bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged( + const lldb::SBEvent &vEvent) { + // Make sure the program hasn't been auto-restarted: + if (lldb::SBProcess::GetRestartedFromEvent(vEvent)) + return MIstatus::success; - // ToDo: Remove when finished coding application - m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event BroadcastBitStateChanged occurred: %s", pEventType)); + bool bOk = ChkForStateChanges(); + bOk = bOk && GetProcessStdout(); + bOk = bOk && GetProcessStderr(); + if (!bOk) + return MIstatus::failure; + + // Something changed in the process; get the event and report the process's + // current + // status and location + const lldb::StateType eEventState = + lldb::SBProcess::GetStateFromEvent(vEvent); + if (eEventState == lldb::eStateInvalid) + return MIstatus::success; - return bOk; + lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent(vEvent); + if (!process.IsValid()) { + const CMIUtilString msg(CMIUtilString::Format( + MIRSRC(IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID), "SBProcess", + "HandleProcessEventBroadcastBitStateChanged()")); + SetErrorDescription(msg); + return MIstatus::failure; + } + + bool bShouldBrk = true; + const char *pEventType = ""; + switch (eEventState) { + case lldb::eStateUnloaded: + pEventType = "eStateUnloaded"; + break; + case lldb::eStateConnected: + pEventType = "eStateConnected"; + break; + case lldb::eStateAttaching: + pEventType = "eStateAttaching"; + break; + case lldb::eStateLaunching: + pEventType = "eStateLaunching"; + break; + case lldb::eStateStopped: + pEventType = "eStateStopped"; + bOk = HandleProcessEventStateStopped(vEvent, bShouldBrk); + if (bShouldBrk) + break; + case lldb::eStateCrashed: + case lldb::eStateSuspended: + pEventType = "eStateSuspended"; + bOk = HandleProcessEventStateSuspended(vEvent); + break; + case lldb::eStateRunning: + pEventType = "eStateRunning"; + bOk = HandleProcessEventStateRunning(); + break; + case lldb::eStateStepping: + pEventType = "eStateStepping"; + break; + case lldb::eStateDetached: + pEventType = "eStateDetached"; + break; + case lldb::eStateExited: + // Don't exit from lldb-mi here. We should be able to re-run target. + pEventType = "eStateExited"; + bOk = HandleProcessEventStateExited(); + break; + default: { + const CMIUtilString msg(CMIUtilString::Format( + MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), + "SBProcess BroadcastBitStateChanged", (MIuint)eEventState)); + SetErrorDescription(msg); + return MIstatus::failure; + } + } + + // ToDo: Remove when finished coding application + m_pLog->WriteLog(CMIUtilString::Format( + "##### An SB Process event BroadcastBitStateChanged occurred: %s", + pEventType)); + + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Asynchronous event handler for LLDB Process state suspended. // Type: Method. // Args: vEvent - (R) An LLDB event object. @@ -904,41 +939,42 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged(const // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateSuspended(const lldb::SBEvent &vEvent) -{ - bool bOk = MIstatus::success; - lldb::SBDebugger &rDebugger = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger(); - lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); - lldb::SBTarget target = sbProcess.GetTarget(); - if (rDebugger.GetSelectedTarget() == target) - { - if (!UpdateSelectedThread()) - return MIstatus::failure; - - lldb::SBCommandReturnObject result; - const lldb::ReturnStatus status = rDebugger.GetCommandInterpreter().HandleCommand("process status", result, false); - MIunused(status); - bOk = TextToStderr(result.GetError()); - bOk = bOk && TextToStdout(result.GetOutput()); - } +bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateSuspended( + const lldb::SBEvent &vEvent) { + bool bOk = MIstatus::success; + lldb::SBDebugger &rDebugger = + CMICmnLLDBDebugSessionInfo::Instance().GetDebugger(); + lldb::SBProcess sbProcess = + CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + lldb::SBTarget target = sbProcess.GetTarget(); + if (rDebugger.GetSelectedTarget() == target) { + if (!UpdateSelectedThread()) + return MIstatus::failure; + + lldb::SBCommandReturnObject result; + const lldb::ReturnStatus status = + rDebugger.GetCommandInterpreter().HandleCommand("process status", + result, false); + MIunused(status); + bOk = TextToStderr(result.GetError()); + bOk = bOk && TextToStdout(result.GetOutput()); + } else { + lldb::SBStream streamOut; + const MIuint nTargetIndex = rDebugger.GetIndexOfTarget(target); + if (nTargetIndex != UINT_MAX) + streamOut.Printf("Target %d: (", nTargetIndex); else - { - lldb::SBStream streamOut; - const MIuint nTargetIndex = rDebugger.GetIndexOfTarget(target); - if (nTargetIndex != UINT_MAX) - streamOut.Printf("Target %d: (", nTargetIndex); - else - streamOut.Printf("Target <unknown index>: ("); - target.GetDescription(streamOut, lldb::eDescriptionLevelBrief); - streamOut.Printf(") stopped.\n"); - bOk = TextToStdout(streamOut.GetData()); - } + streamOut.Printf("Target <unknown index>: ("); + target.GetDescription(streamOut, lldb::eDescriptionLevelBrief); + streamOut.Printf(") stopped.\n"); + bOk = TextToStdout(streamOut.GetData()); + } - return bOk; + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Print to stdout MI formatted text to indicate process stopped. // Type: Method. // Args: vwrbShouldBrk - (W) True = Yes break, false = do not. @@ -946,66 +982,68 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateSuspended(const lldb::SBE // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateStopped(const lldb::SBEvent &vrEvent, bool &vwrbShouldBrk) -{ - if (!UpdateSelectedThread()) - return MIstatus::failure; - - const char *pEventType = ""; - bool bOk = MIstatus::success; - lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); - const lldb::StopReason eStoppedReason = sbProcess.GetSelectedThread().GetStopReason(); - switch (eStoppedReason) - { - case lldb::eStopReasonInvalid: - pEventType = "eStopReasonInvalid"; - vwrbShouldBrk = false; - break; - case lldb::eStopReasonNone: - pEventType = "eStopReasonNone"; - break; - case lldb::eStopReasonTrace: - pEventType = "eStopReasonTrace"; - bOk = HandleProcessEventStopReasonTrace(); - break; - case lldb::eStopReasonBreakpoint: - pEventType = "eStopReasonBreakpoint"; - bOk = HandleProcessEventStopReasonBreakpoint(); - break; - case lldb::eStopReasonWatchpoint: - pEventType = "eStopReasonWatchpoint"; - break; - case lldb::eStopReasonSignal: - pEventType = "eStopReasonSignal"; - bOk = HandleProcessEventStopSignal(vrEvent); - break; - case lldb::eStopReasonException: - pEventType = "eStopReasonException"; - bOk = HandleProcessEventStopException(); - break; - case lldb::eStopReasonExec: - pEventType = "eStopReasonExec"; - break; - case lldb::eStopReasonPlanComplete: - pEventType = "eStopReasonPlanComplete"; - bOk = HandleProcessEventStopReasonTrace(); - break; - case lldb::eStopReasonThreadExiting: - pEventType = "eStopReasonThreadExiting"; - break; - case lldb::eStopReasonInstrumentation: - pEventType = "eStopReasonInstrumentation"; - break; - } - - // ToDo: Remove when finished coding application - m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event stop state occurred: %s", pEventType)); - - return bOk; +bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateStopped( + const lldb::SBEvent &vrEvent, bool &vwrbShouldBrk) { + if (!UpdateSelectedThread()) + return MIstatus::failure; + + const char *pEventType = ""; + bool bOk = MIstatus::success; + lldb::SBProcess sbProcess = + CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + const lldb::StopReason eStoppedReason = + sbProcess.GetSelectedThread().GetStopReason(); + switch (eStoppedReason) { + case lldb::eStopReasonInvalid: + pEventType = "eStopReasonInvalid"; + vwrbShouldBrk = false; + break; + case lldb::eStopReasonNone: + pEventType = "eStopReasonNone"; + break; + case lldb::eStopReasonTrace: + pEventType = "eStopReasonTrace"; + bOk = HandleProcessEventStopReasonTrace(); + break; + case lldb::eStopReasonBreakpoint: + pEventType = "eStopReasonBreakpoint"; + bOk = HandleProcessEventStopReasonBreakpoint(); + break; + case lldb::eStopReasonWatchpoint: + pEventType = "eStopReasonWatchpoint"; + break; + case lldb::eStopReasonSignal: + pEventType = "eStopReasonSignal"; + bOk = HandleProcessEventStopSignal(vrEvent); + break; + case lldb::eStopReasonException: + pEventType = "eStopReasonException"; + bOk = HandleProcessEventStopException(); + break; + case lldb::eStopReasonExec: + pEventType = "eStopReasonExec"; + break; + case lldb::eStopReasonPlanComplete: + pEventType = "eStopReasonPlanComplete"; + bOk = HandleProcessEventStopReasonTrace(); + break; + case lldb::eStopReasonThreadExiting: + pEventType = "eStopReasonThreadExiting"; + break; + case lldb::eStopReasonInstrumentation: + pEventType = "eStopReasonInstrumentation"; + break; + } + + // ToDo: Remove when finished coding application + m_pLog->WriteLog(CMIUtilString::Format( + "##### An SB Process event stop state occurred: %s", pEventType)); + + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Asynchronous event handler for LLDB Process stop signal. // Type: Method. // Args: vrEvent - (R) An LLDB broadcast event. @@ -1013,147 +1051,150 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateStopped(const lldb::SBEve // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal(const lldb::SBEvent &vrEvent) -{ - bool bOk = MIstatus::success; - - InitializeSignals (); - lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); - const MIuint64 nStopReason = sbProcess.GetSelectedThread().GetStopReasonDataAtIndex(0); - const bool bInterrupted = lldb::SBProcess::GetInterruptedFromEvent(vrEvent); - if (nStopReason == m_SIGINT || (nStopReason == m_SIGSTOP && bInterrupted)) - { - // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGINT\",signal-meaning=\"Interrupt\",frame={%s},thread-id=\"%d\",stopped-threads=\"all\"" - const CMICmnMIValueConst miValueConst("signal-received"); - const CMICmnMIValueResult miValueResult("reason", miValueConst); - CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); - const CMICmnMIValueConst miValueConst2("SIGINT"); - const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2); - miOutOfBandRecord.Add(miValueResult2); - const CMICmnMIValueConst miValueConst3("Interrupt"); - const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3); - miOutOfBandRecord.Add(miValueResult3); - CMICmnMIValueTuple miValueTuple; - bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple); - const CMICmnMIValueResult miValueResult4("frame", miValueTuple); - miOutOfBandRecord.Add(miValueResult4); - const CMIUtilString strThreadId(CMIUtilString::Format("%" PRIu32, sbProcess.GetSelectedThread().GetIndexID())); - const CMICmnMIValueConst miValueConst5(strThreadId); - const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5); - miOutOfBandRecord.Add(miValueResult5); - const CMICmnMIValueConst miValueConst6("all"); - const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6); - miOutOfBandRecord.Add(miValueResult6); - bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); - bOk = bOk && CMICmnStreamStdout::WritePrompt(); - } - else if (nStopReason == m_SIGSTOP) - { - // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGSTOP\",signal-meaning=\"Stop\",frame={%s},thread-id=\"%d\",stopped-threads=\"all\"" - const CMICmnMIValueConst miValueConst("signal-received"); - const CMICmnMIValueResult miValueResult("reason", miValueConst); - CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); - const CMICmnMIValueConst miValueConst2("SIGSTOP"); - const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2); - miOutOfBandRecord.Add(miValueResult2); - const CMICmnMIValueConst miValueConst3("Stop"); - const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3); - miOutOfBandRecord.Add(miValueResult3); - CMICmnMIValueTuple miValueTuple; - bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple); - const CMICmnMIValueResult miValueResult4("frame", miValueTuple); - miOutOfBandRecord.Add(miValueResult4); - const CMIUtilString strThreadId(CMIUtilString::Format("%" PRIu32, sbProcess.GetSelectedThread().GetIndexID())); - const CMICmnMIValueConst miValueConst5(strThreadId); - const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5); - miOutOfBandRecord.Add(miValueResult5); - const CMICmnMIValueConst miValueConst6("all"); - const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6); - miOutOfBandRecord.Add(miValueResult6); - bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); - bOk = bOk && CMICmnStreamStdout::WritePrompt(); - } - else if (nStopReason == m_SIGSEGV) - { - // MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGSEGV\",signal-meaning=\"Segmentation fault\",thread-id=\"%d\",frame={%s}" - const CMICmnMIValueConst miValueConst("signal-received"); - const CMICmnMIValueResult miValueResult("reason", miValueConst); - CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); - const CMICmnMIValueConst miValueConst2("SIGSEGV"); - const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2); - miOutOfBandRecord.Add(miValueResult2); - const CMICmnMIValueConst miValueConst3("Segmentation fault"); - const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3); - miOutOfBandRecord.Add(miValueResult3); - CMICmnMIValueTuple miValueTuple; - bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple); - const CMICmnMIValueResult miValueResult4("frame", miValueTuple); - miOutOfBandRecord.Add(miValueResult4); - const CMIUtilString strThreadId(CMIUtilString::Format("%d", sbProcess.GetSelectedThread().GetIndexID())); - const CMICmnMIValueConst miValueConst5(strThreadId); - const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5); - miOutOfBandRecord.Add(miValueResult5); - bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); - // Note no "(gdb)" output here - } - else if (nStopReason == m_SIGTRAP) - { - lldb::SBThread thread = sbProcess.GetSelectedThread(); - const MIuint nFrames = thread.GetNumFrames(); - if (nFrames > 0) - { - lldb::SBFrame frame = thread.GetFrameAtIndex(0); - const char *pFnName = frame.GetFunctionName(); - if (pFnName != nullptr) - { - const CMIUtilString fnName = CMIUtilString(pFnName); - static const CMIUtilString threadCloneFn = CMIUtilString("__pthread_clone"); - - if (CMIUtilString::Compare(threadCloneFn, fnName)) - { - if (sbProcess.IsValid()) - sbProcess.Continue(); - } - } +bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal( + const lldb::SBEvent &vrEvent) { + bool bOk = MIstatus::success; + + InitializeSignals(); + lldb::SBProcess sbProcess = + CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + const MIuint64 nStopReason = + sbProcess.GetSelectedThread().GetStopReasonDataAtIndex(0); + const bool bInterrupted = lldb::SBProcess::GetInterruptedFromEvent(vrEvent); + if (nStopReason == m_SIGINT || (nStopReason == m_SIGSTOP && bInterrupted)) { + // MI print + // "*stopped,reason=\"signal-received\",signal-name=\"SIGINT\",signal-meaning=\"Interrupt\",frame={%s},thread-id=\"%d\",stopped-threads=\"all\"" + const CMICmnMIValueConst miValueConst("signal-received"); + const CMICmnMIValueResult miValueResult("reason", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); + const CMICmnMIValueConst miValueConst2("SIGINT"); + const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2); + miOutOfBandRecord.Add(miValueResult2); + const CMICmnMIValueConst miValueConst3("Interrupt"); + const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3); + miOutOfBandRecord.Add(miValueResult3); + CMICmnMIValueTuple miValueTuple; + bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple); + const CMICmnMIValueResult miValueResult4("frame", miValueTuple); + miOutOfBandRecord.Add(miValueResult4); + const CMIUtilString strThreadId(CMIUtilString::Format( + "%" PRIu32, sbProcess.GetSelectedThread().GetIndexID())); + const CMICmnMIValueConst miValueConst5(strThreadId); + const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5); + miOutOfBandRecord.Add(miValueResult5); + const CMICmnMIValueConst miValueConst6("all"); + const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6); + miOutOfBandRecord.Add(miValueResult6); + bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); + bOk = bOk && CMICmnStreamStdout::WritePrompt(); + } else if (nStopReason == m_SIGSTOP) { + // MI print + // "*stopped,reason=\"signal-received\",signal-name=\"SIGSTOP\",signal-meaning=\"Stop\",frame={%s},thread-id=\"%d\",stopped-threads=\"all\"" + const CMICmnMIValueConst miValueConst("signal-received"); + const CMICmnMIValueResult miValueResult("reason", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); + const CMICmnMIValueConst miValueConst2("SIGSTOP"); + const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2); + miOutOfBandRecord.Add(miValueResult2); + const CMICmnMIValueConst miValueConst3("Stop"); + const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3); + miOutOfBandRecord.Add(miValueResult3); + CMICmnMIValueTuple miValueTuple; + bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple); + const CMICmnMIValueResult miValueResult4("frame", miValueTuple); + miOutOfBandRecord.Add(miValueResult4); + const CMIUtilString strThreadId(CMIUtilString::Format( + "%" PRIu32, sbProcess.GetSelectedThread().GetIndexID())); + const CMICmnMIValueConst miValueConst5(strThreadId); + const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5); + miOutOfBandRecord.Add(miValueResult5); + const CMICmnMIValueConst miValueConst6("all"); + const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6); + miOutOfBandRecord.Add(miValueResult6); + bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); + bOk = bOk && CMICmnStreamStdout::WritePrompt(); + } else if (nStopReason == m_SIGSEGV) { + // MI print + // "*stopped,reason=\"signal-received\",signal-name=\"SIGSEGV\",signal-meaning=\"Segmentation + // fault\",thread-id=\"%d\",frame={%s}" + const CMICmnMIValueConst miValueConst("signal-received"); + const CMICmnMIValueResult miValueResult("reason", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); + const CMICmnMIValueConst miValueConst2("SIGSEGV"); + const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2); + miOutOfBandRecord.Add(miValueResult2); + const CMICmnMIValueConst miValueConst3("Segmentation fault"); + const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3); + miOutOfBandRecord.Add(miValueResult3); + CMICmnMIValueTuple miValueTuple; + bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple); + const CMICmnMIValueResult miValueResult4("frame", miValueTuple); + miOutOfBandRecord.Add(miValueResult4); + const CMIUtilString strThreadId(CMIUtilString::Format( + "%d", sbProcess.GetSelectedThread().GetIndexID())); + const CMICmnMIValueConst miValueConst5(strThreadId); + const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5); + miOutOfBandRecord.Add(miValueResult5); + bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); + // Note no "(gdb)" output here + } else if (nStopReason == m_SIGTRAP) { + lldb::SBThread thread = sbProcess.GetSelectedThread(); + const MIuint nFrames = thread.GetNumFrames(); + if (nFrames > 0) { + lldb::SBFrame frame = thread.GetFrameAtIndex(0); + const char *pFnName = frame.GetFunctionName(); + if (pFnName != nullptr) { + const CMIUtilString fnName = CMIUtilString(pFnName); + static const CMIUtilString threadCloneFn = + CMIUtilString("__pthread_clone"); + + if (CMIUtilString::Compare(threadCloneFn, fnName)) { + if (sbProcess.IsValid()) + sbProcess.Continue(); } + } } - else - { - // MI print "*stopped,reason=\"signal-received\",signal-name=\"%s\",thread-id=\"%d\",stopped-threads=\"all\"" - // MI print "*stopped,reason=\"signal-received\",signal=\"%d\",thread-id=\"%d\",stopped-threads=\"all\"" - const CMICmnMIValueConst miValueConst("signal-received"); - const CMICmnMIValueResult miValueResult("reason", miValueConst); - CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); - lldb::SBUnixSignals sbUnixSignals = sbProcess.GetUnixSignals(); - const char *pSignal = sbUnixSignals.GetSignalAsCString(nStopReason); - if (pSignal) - { - const CMICmnMIValueConst miValueConst2(pSignal); - const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2); - miOutOfBandRecord.Add(miValueResult2); - } - else - { - const CMIUtilString strSignal(CMIUtilString::Format("%" PRIu64, nStopReason)); - const CMICmnMIValueConst miValueConst2(strSignal); - const CMICmnMIValueResult miValueResult2("signal", miValueConst2); - miOutOfBandRecord.Add(miValueResult2); - } - const CMIUtilString strThreadId(CMIUtilString::Format("%d", sbProcess.GetSelectedThread().GetIndexID())); - const CMICmnMIValueConst miValueConst3(strThreadId); - const CMICmnMIValueResult miValueResult3("thread-id", miValueConst3); - miOutOfBandRecord.Add(miValueResult3); - const CMICmnMIValueConst miValueConst4("all"); - const CMICmnMIValueResult miValueResult4("stopped-threads", miValueConst4); - miOutOfBandRecord.Add(miValueResult4); - bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); - bOk = bOk && CMICmnStreamStdout::WritePrompt(); + } else { + // MI print + // "*stopped,reason=\"signal-received\",signal-name=\"%s\",thread-id=\"%d\",stopped-threads=\"all\"" + // MI print + // "*stopped,reason=\"signal-received\",signal=\"%d\",thread-id=\"%d\",stopped-threads=\"all\"" + const CMICmnMIValueConst miValueConst("signal-received"); + const CMICmnMIValueResult miValueResult("reason", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); + lldb::SBUnixSignals sbUnixSignals = sbProcess.GetUnixSignals(); + const char *pSignal = sbUnixSignals.GetSignalAsCString(nStopReason); + if (pSignal) { + const CMICmnMIValueConst miValueConst2(pSignal); + const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2); + miOutOfBandRecord.Add(miValueResult2); + } else { + const CMIUtilString strSignal( + CMIUtilString::Format("%" PRIu64, nStopReason)); + const CMICmnMIValueConst miValueConst2(strSignal); + const CMICmnMIValueResult miValueResult2("signal", miValueConst2); + miOutOfBandRecord.Add(miValueResult2); } - return bOk; + const CMIUtilString strThreadId(CMIUtilString::Format( + "%d", sbProcess.GetSelectedThread().GetIndexID())); + const CMICmnMIValueConst miValueConst3(strThreadId); + const CMICmnMIValueResult miValueResult3("thread-id", miValueConst3); + miOutOfBandRecord.Add(miValueResult3); + const CMICmnMIValueConst miValueConst4("all"); + const CMICmnMIValueResult miValueResult4("stopped-threads", miValueConst4); + miOutOfBandRecord.Add(miValueResult4); + bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); + bOk = bOk && CMICmnStreamStdout::WritePrompt(); + } + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Asynchronous event handler for LLDB Process stop exception. // Type: Method. // Args: None. @@ -1161,37 +1202,40 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal(const lldb::SBEvent // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopException() -{ - const lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); - lldb::SBThread sbThread = sbProcess.GetSelectedThread(); - const size_t nStopDescriptionLen = sbThread.GetStopDescription(nullptr, 0); - std::unique_ptr<char[]> apStopDescription(new char[nStopDescriptionLen]); - sbThread.GetStopDescription(apStopDescription.get(), nStopDescriptionLen); - - // MI print "*stopped,reason=\"exception-received\",exception=\"%s\",thread-id=\"%d\",stopped-threads=\"all\"" - const CMICmnMIValueConst miValueConst("exception-received"); - const CMICmnMIValueResult miValueResult("reason", miValueConst); - CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); - const CMIUtilString strReason(apStopDescription.get()); - const CMICmnMIValueConst miValueConst2(strReason); - const CMICmnMIValueResult miValueResult2("exception", miValueConst2); - miOutOfBandRecord.Add(miValueResult2); - const CMIUtilString strThreadId(CMIUtilString::Format("%d", sbThread.GetIndexID())); - const CMICmnMIValueConst miValueConst3(strThreadId); - const CMICmnMIValueResult miValueResult3("thread-id", miValueConst3); - miOutOfBandRecord.Add(miValueResult3); - const CMICmnMIValueConst miValueConst4("all"); - const CMICmnMIValueResult miValueResult4("stopped-threads", miValueConst4); - miOutOfBandRecord.Add(miValueResult4); - bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); - bOk = bOk && CMICmnStreamStdout::WritePrompt(); - - return bOk; +bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopException() { + const lldb::SBProcess sbProcess = + CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + lldb::SBThread sbThread = sbProcess.GetSelectedThread(); + const size_t nStopDescriptionLen = sbThread.GetStopDescription(nullptr, 0); + std::unique_ptr<char[]> apStopDescription(new char[nStopDescriptionLen]); + sbThread.GetStopDescription(apStopDescription.get(), nStopDescriptionLen); + + // MI print + // "*stopped,reason=\"exception-received\",exception=\"%s\",thread-id=\"%d\",stopped-threads=\"all\"" + const CMICmnMIValueConst miValueConst("exception-received"); + const CMICmnMIValueResult miValueResult("reason", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); + const CMIUtilString strReason(apStopDescription.get()); + const CMICmnMIValueConst miValueConst2(strReason); + const CMICmnMIValueResult miValueResult2("exception", miValueConst2); + miOutOfBandRecord.Add(miValueResult2); + const CMIUtilString strThreadId( + CMIUtilString::Format("%d", sbThread.GetIndexID())); + const CMICmnMIValueConst miValueConst3(strThreadId); + const CMICmnMIValueResult miValueResult3("thread-id", miValueConst3); + miOutOfBandRecord.Add(miValueResult3); + const CMICmnMIValueConst miValueConst4("all"); + const CMICmnMIValueResult miValueResult4("stopped-threads", miValueConst4); + miOutOfBandRecord.Add(miValueResult4); + bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); + bOk = bOk && CMICmnStreamStdout::WritePrompt(); + + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Form partial MI response in a MI value tuple object. // Type: Method. // Args: vwrMiValueTuple - (W) MI value tuple object. @@ -1199,46 +1243,50 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopException() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::MiHelpGetCurrentThreadFrame(CMICmnMIValueTuple &vwrMiValueTuple) -{ - CMIUtilString strThreadFrame; - lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); - lldb::SBThread thread = sbProcess.GetSelectedThread(); - const MIuint nFrame = thread.GetNumFrames(); - if (nFrame == 0) - { - // MI print "addr=\"??\",func=\"??\",file=\"??\",fullname=\"??\",line=\"??\"" - const CMICmnMIValueConst miValueConst("??"); - const CMICmnMIValueResult miValueResult("addr", miValueConst); - CMICmnMIValueTuple miValueTuple(miValueResult); - const CMICmnMIValueResult miValueResult2("func", miValueConst); - miValueTuple.Add(miValueResult2); - const CMICmnMIValueResult miValueResult4("file", miValueConst); - miValueTuple.Add(miValueResult4); - const CMICmnMIValueResult miValueResult5("fullname", miValueConst); - miValueTuple.Add(miValueResult5); - const CMICmnMIValueResult miValueResult6("line", miValueConst); - miValueTuple.Add(miValueResult6); - - vwrMiValueTuple = miValueTuple; - - return MIstatus::success; - } - - CMICmnMIValueTuple miValueTuple; - if (!CMICmnLLDBDebugSessionInfo::Instance().MIResponseFormFrameInfo(thread, 0, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_NoArguments, miValueTuple)) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "MiHelpGetCurrentThreadFrame()")); - return MIstatus::failure; - } +bool CMICmnLLDBDebuggerHandleEvents::MiHelpGetCurrentThreadFrame( + CMICmnMIValueTuple &vwrMiValueTuple) { + CMIUtilString strThreadFrame; + lldb::SBProcess sbProcess = + CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + lldb::SBThread thread = sbProcess.GetSelectedThread(); + const MIuint nFrame = thread.GetNumFrames(); + if (nFrame == 0) { + // MI print + // "addr=\"??\",func=\"??\",file=\"??\",fullname=\"??\",line=\"??\"" + const CMICmnMIValueConst miValueConst("??"); + const CMICmnMIValueResult miValueResult("addr", miValueConst); + CMICmnMIValueTuple miValueTuple(miValueResult); + const CMICmnMIValueResult miValueResult2("func", miValueConst); + miValueTuple.Add(miValueResult2); + const CMICmnMIValueResult miValueResult4("file", miValueConst); + miValueTuple.Add(miValueResult4); + const CMICmnMIValueResult miValueResult5("fullname", miValueConst); + miValueTuple.Add(miValueResult5); + const CMICmnMIValueResult miValueResult6("line", miValueConst); + miValueTuple.Add(miValueResult6); vwrMiValueTuple = miValueTuple; return MIstatus::success; + } + + CMICmnMIValueTuple miValueTuple; + if (!CMICmnLLDBDebugSessionInfo::Instance().MIResponseFormFrameInfo( + thread, 0, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_NoArguments, + miValueTuple)) { + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), + "MiHelpGetCurrentThreadFrame()")); + return MIstatus::failure; + } + + vwrMiValueTuple = miValueTuple; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Asynchronous event handler for LLDB Process stop reason breakpoint. // Type: Method. // Args: None. @@ -1246,27 +1294,31 @@ CMICmnLLDBDebuggerHandleEvents::MiHelpGetCurrentThreadFrame(CMICmnMIValueTuple & // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint() -{ - // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM - if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging()) - { - const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE), - "HandleProcessEventStopReasonBreakpoint()", rErrMsg.c_str())); - return MIstatus::failure; - } - - lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); - const MIuint64 brkPtId = sbProcess.GetSelectedThread().GetStopReasonDataAtIndex(0); - lldb::SBBreakpoint brkPt = CMICmnLLDBDebugSessionInfo::Instance().GetTarget().GetBreakpointAtIndex((MIuint)brkPtId); - - return MiStoppedAtBreakPoint(brkPtId, brkPt); +bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint() { + // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM + if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging()) { + const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); + SetErrorDescription(CMIUtilString::Format( + MIRSRC(IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE), + "HandleProcessEventStopReasonBreakpoint()", rErrMsg.c_str())); + return MIstatus::failure; + } + + lldb::SBProcess sbProcess = + CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + const MIuint64 brkPtId = + sbProcess.GetSelectedThread().GetStopReasonDataAtIndex(0); + lldb::SBBreakpoint brkPt = + CMICmnLLDBDebugSessionInfo::Instance().GetTarget().GetBreakpointAtIndex( + (MIuint)brkPtId); + + return MiStoppedAtBreakPoint(brkPtId, brkPt); } -//++ ------------------------------------------------------------------------------------ -// Details: Form the MI Out-of-band response for stopped reason on hitting a break point. +//++ +//------------------------------------------------------------------------------------ +// Details: Form the MI Out-of-band response for stopped reason on hitting a +// break point. // Type: Method. // Args: vBrkPtId - (R) The LLDB break point's ID // vBrkPt - (R) THe LLDB break point object. @@ -1274,87 +1326,97 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, const lldb::SBBreakpoint &vBrkPt) -{ - bool bOk = MIstatus::success; - - lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); - lldb::SBThread thread = sbProcess.GetSelectedThread(); - const MIuint nFrame = thread.GetNumFrames(); - if (nFrame == 0) - { - // MI print "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={},thread-id=\"%d\",stopped-threads=\"all\"" - const CMICmnMIValueConst miValueConst("breakpoint-hit"); - const CMICmnMIValueResult miValueResult("reason", miValueConst); - CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); - const CMICmnMIValueConst miValueConst2("del"); - const CMICmnMIValueResult miValueResult2("disp", miValueConst2); - miOutOfBandRecord.Add(miValueResult2); - const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId)); - const CMICmnMIValueConst miValueConst3(strBkp); - CMICmnMIValueResult miValueResult3("bkptno", miValueConst3); - miOutOfBandRecord.Add(miValueResult3); - const CMICmnMIValueConst miValueConst4("{}"); - const CMICmnMIValueResult miValueResult4("frame", miValueConst4); - miOutOfBandRecord.Add(miValueResult4); - const CMIUtilString strThreadId(CMIUtilString::Format("%d", vBrkPt.GetThreadIndex())); - const CMICmnMIValueConst miValueConst5(strThreadId); - const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5); - miOutOfBandRecord.Add(miValueResult5); - const CMICmnMIValueConst miValueConst6("all"); - const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6); - miOutOfBandRecord.Add(miValueResult6); - bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); - bOk = bOk && CMICmnStreamStdout::WritePrompt(); - return bOk; - } - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - +bool CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint( + const MIuint64 vBrkPtId, const lldb::SBBreakpoint &vBrkPt) { + bool bOk = MIstatus::success; + + lldb::SBProcess sbProcess = + CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + lldb::SBThread thread = sbProcess.GetSelectedThread(); + const MIuint nFrame = thread.GetNumFrames(); + if (nFrame == 0) { // MI print - // "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={addr=\"0x%016" PRIx64 "\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\"" + // "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={},thread-id=\"%d\",stopped-threads=\"all\"" const CMICmnMIValueConst miValueConst("breakpoint-hit"); const CMICmnMIValueResult miValueResult("reason", miValueConst); - CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); - const CMICmnMIValueConst miValueConstA("del"); - const CMICmnMIValueResult miValueResultA("disp", miValueConstA); - miOutOfBandRecord.Add(miValueResultA); + CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); + const CMICmnMIValueConst miValueConst2("del"); + const CMICmnMIValueResult miValueResult2("disp", miValueConst2); + miOutOfBandRecord.Add(miValueResult2); const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId)); - const CMICmnMIValueConst miValueConstB(strBkp); - CMICmnMIValueResult miValueResultB("bkptno", miValueConstB); - miOutOfBandRecord.Add(miValueResultB); - - // frame={addr=\"0x%016" PRIx64 "\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"} - if (bOk) - { - CMICmnMIValueTuple miValueTuple; - bOk = bOk && rSessionInfo.MIResponseFormFrameInfo(thread, 0, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_AllArguments, miValueTuple); - const CMICmnMIValueResult miValueResult8("frame", miValueTuple); - miOutOfBandRecord.Add(miValueResult8); - } + const CMICmnMIValueConst miValueConst3(strBkp); + CMICmnMIValueResult miValueResult3("bkptno", miValueConst3); + miOutOfBandRecord.Add(miValueResult3); + const CMICmnMIValueConst miValueConst4("{}"); + const CMICmnMIValueResult miValueResult4("frame", miValueConst4); + miOutOfBandRecord.Add(miValueResult4); + const CMIUtilString strThreadId( + CMIUtilString::Format("%d", vBrkPt.GetThreadIndex())); + const CMICmnMIValueConst miValueConst5(strThreadId); + const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5); + miOutOfBandRecord.Add(miValueResult5); + const CMICmnMIValueConst miValueConst6("all"); + const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6); + miOutOfBandRecord.Add(miValueResult6); + bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord); + bOk = bOk && CMICmnStreamStdout::WritePrompt(); + return bOk; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + + // MI print + // "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={addr=\"0x%016" + // PRIx64 + // "\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\"" + const CMICmnMIValueConst miValueConst("breakpoint-hit"); + const CMICmnMIValueResult miValueResult("reason", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); + const CMICmnMIValueConst miValueConstA("del"); + const CMICmnMIValueResult miValueResultA("disp", miValueConstA); + miOutOfBandRecord.Add(miValueResultA); + const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId)); + const CMICmnMIValueConst miValueConstB(strBkp); + CMICmnMIValueResult miValueResultB("bkptno", miValueConstB); + miOutOfBandRecord.Add(miValueResultB); + + // frame={addr=\"0x%016" PRIx64 + // "\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"} + if (bOk) { + CMICmnMIValueTuple miValueTuple; + bOk = bOk && + rSessionInfo.MIResponseFormFrameInfo( + thread, 0, + CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_AllArguments, + miValueTuple); + const CMICmnMIValueResult miValueResult8("frame", miValueTuple); + miOutOfBandRecord.Add(miValueResult8); + } - // Add to MI thread-id=\"%d\",stopped-threads=\"all\" - if (bOk) - { - const CMIUtilString strThreadId(CMIUtilString::Format("%d", thread.GetIndexID())); - const CMICmnMIValueConst miValueConst8(strThreadId); - const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8); - miOutOfBandRecord.Add(miValueResult8); - } - if (bOk) - { - const CMICmnMIValueConst miValueConst9("all"); - const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9); - miOutOfBandRecord.Add(miValueResult9); - bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); - bOk = bOk && CMICmnStreamStdout::WritePrompt(); - } + // Add to MI thread-id=\"%d\",stopped-threads=\"all\" + if (bOk) { + const CMIUtilString strThreadId( + CMIUtilString::Format("%d", thread.GetIndexID())); + const CMICmnMIValueConst miValueConst8(strThreadId); + const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8); + miOutOfBandRecord.Add(miValueResult8); + } + if (bOk) { + const CMICmnMIValueConst miValueConst9("all"); + const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9); + miOutOfBandRecord.Add(miValueResult9); + bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); + bOk = bOk && CMICmnStreamStdout::WritePrompt(); + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Asynchronous event handler for LLDB Process stop reason trace. // Type: Method. // Args: None. @@ -1362,59 +1424,65 @@ CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, c // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace() -{ - bool bOk = true; - lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); - lldb::SBThread thread = sbProcess.GetSelectedThread(); - const MIuint nFrame = thread.GetNumFrames(); - if (nFrame == 0) - { - // MI print "*stopped,reason=\"trace\",stopped-threads=\"all\"" - const CMICmnMIValueConst miValueConst("trace"); - const CMICmnMIValueResult miValueResult("reason", miValueConst); - CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); - const CMICmnMIValueConst miValueConst2("all"); - const CMICmnMIValueResult miValueResult2("stopped-threads", miValueConst2); - miOutOfBandRecord.Add(miValueResult2); - bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); - bOk = bOk && CMICmnStreamStdout::WritePrompt(); - return bOk; - } - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - - // MI print - // "*stopped,reason=\"end-stepping-range\",frame={addr=\"0x%016" PRIx64 "\",func=\"%s\",args=[\"%s\"],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\"" - - // Function args - CMICmnMIValueTuple miValueTuple; - if (!rSessionInfo.MIResponseFormFrameInfo(thread, 0, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_AllArguments, miValueTuple)) - return MIstatus::failure; - - const CMICmnMIValueConst miValueConst("end-stepping-range"); +bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace() { + bool bOk = true; + lldb::SBProcess sbProcess = + CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + lldb::SBThread thread = sbProcess.GetSelectedThread(); + const MIuint nFrame = thread.GetNumFrames(); + if (nFrame == 0) { + // MI print "*stopped,reason=\"trace\",stopped-threads=\"all\"" + const CMICmnMIValueConst miValueConst("trace"); const CMICmnMIValueResult miValueResult("reason", miValueConst); - CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); - const CMICmnMIValueResult miValueResult2("frame", miValueTuple); + CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); + const CMICmnMIValueConst miValueConst2("all"); + const CMICmnMIValueResult miValueResult2("stopped-threads", miValueConst2); miOutOfBandRecord.Add(miValueResult2); - - // Add to MI thread-id=\"%d\",stopped-threads=\"all\" - const CMIUtilString strThreadId(CMIUtilString::Format("%d", thread.GetIndexID())); - const CMICmnMIValueConst miValueConst8(strThreadId); - const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8); - miOutOfBandRecord.Add(miValueResult8); - - const CMICmnMIValueConst miValueConst9("all"); - const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9); - miOutOfBandRecord.Add(miValueResult9); bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); bOk = bOk && CMICmnStreamStdout::WritePrompt(); - return bOk; + } + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + + // MI print + // "*stopped,reason=\"end-stepping-range\",frame={addr=\"0x%016" PRIx64 + // "\",func=\"%s\",args=[\"%s\"],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\"" + + // Function args + CMICmnMIValueTuple miValueTuple; + if (!rSessionInfo.MIResponseFormFrameInfo( + thread, 0, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_AllArguments, + miValueTuple)) + return MIstatus::failure; + + const CMICmnMIValueConst miValueConst("end-stepping-range"); + const CMICmnMIValueResult miValueResult("reason", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult); + const CMICmnMIValueResult miValueResult2("frame", miValueTuple); + miOutOfBandRecord.Add(miValueResult2); + + // Add to MI thread-id=\"%d\",stopped-threads=\"all\" + const CMIUtilString strThreadId( + CMIUtilString::Format("%d", thread.GetIndexID())); + const CMICmnMIValueConst miValueConst8(strThreadId); + const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8); + miOutOfBandRecord.Add(miValueResult8); + + const CMICmnMIValueConst miValueConst9("all"); + const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9); + miOutOfBandRecord.Add(miValueResult9); + bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); + bOk = bOk && CMICmnStreamStdout::WritePrompt(); + + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Asynchronous function update selected thread. // Type: Method. // Args: None. @@ -1422,70 +1490,72 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::UpdateSelectedThread() -{ - lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().GetSelectedTarget().GetProcess(); - if (!process.IsValid()) - return MIstatus::success; - - lldb::SBThread currentThread = process.GetSelectedThread(); - lldb::SBThread thread; - const lldb::StopReason eCurrentThreadStoppedReason = currentThread.GetStopReason(); - if (!currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) || - (eCurrentThreadStoppedReason == lldb::eStopReasonNone)) - { - // Prefer a thread that has just completed its plan over another thread as current thread - lldb::SBThread planThread; - lldb::SBThread otherThread; - const size_t nThread = process.GetNumThreads(); - for (MIuint i = 0; i < nThread; i++) - { - // GetThreadAtIndex() uses a base 0 index - // GetThreadByIndexID() uses a base 1 index - thread = process.GetThreadAtIndex(i); - const lldb::StopReason eThreadStopReason = thread.GetStopReason(); - switch (eThreadStopReason) - { - case lldb::eStopReasonTrace: - case lldb::eStopReasonBreakpoint: - case lldb::eStopReasonWatchpoint: - case lldb::eStopReasonSignal: - case lldb::eStopReasonException: - if (!otherThread.IsValid()) - otherThread = thread; - break; - case lldb::eStopReasonPlanComplete: - if (!planThread.IsValid()) - planThread = thread; - break; - case lldb::eStopReasonInvalid: - case lldb::eStopReasonNone: - default: - break; - } - } - if (planThread.IsValid()) - process.SetSelectedThread(planThread); - else if (otherThread.IsValid()) - process.SetSelectedThread(otherThread); - else - { - if (currentThread.IsValid()) - thread = currentThread; - else - thread = process.GetThreadAtIndex(0); - - if (thread.IsValid()) - process.SetSelectedThread(thread); - } - } // if( !currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) || (eCurrentThreadStoppedReason == - // lldb::eStopReasonNone) ) - +bool CMICmnLLDBDebuggerHandleEvents::UpdateSelectedThread() { + lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance() + .GetDebugger() + .GetSelectedTarget() + .GetProcess(); + if (!process.IsValid()) return MIstatus::success; + + lldb::SBThread currentThread = process.GetSelectedThread(); + lldb::SBThread thread; + const lldb::StopReason eCurrentThreadStoppedReason = + currentThread.GetStopReason(); + if (!currentThread.IsValid() || + (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) || + (eCurrentThreadStoppedReason == lldb::eStopReasonNone)) { + // Prefer a thread that has just completed its plan over another thread as + // current thread + lldb::SBThread planThread; + lldb::SBThread otherThread; + const size_t nThread = process.GetNumThreads(); + for (MIuint i = 0; i < nThread; i++) { + // GetThreadAtIndex() uses a base 0 index + // GetThreadByIndexID() uses a base 1 index + thread = process.GetThreadAtIndex(i); + const lldb::StopReason eThreadStopReason = thread.GetStopReason(); + switch (eThreadStopReason) { + case lldb::eStopReasonTrace: + case lldb::eStopReasonBreakpoint: + case lldb::eStopReasonWatchpoint: + case lldb::eStopReasonSignal: + case lldb::eStopReasonException: + if (!otherThread.IsValid()) + otherThread = thread; + break; + case lldb::eStopReasonPlanComplete: + if (!planThread.IsValid()) + planThread = thread; + break; + case lldb::eStopReasonInvalid: + case lldb::eStopReasonNone: + default: + break; + } + } + if (planThread.IsValid()) + process.SetSelectedThread(planThread); + else if (otherThread.IsValid()) + process.SetSelectedThread(otherThread); + else { + if (currentThread.IsValid()) + thread = currentThread; + else + thread = process.GetThreadAtIndex(0); + + if (thread.IsValid()) + process.SetSelectedThread(thread); + } + } // if( !currentThread.IsValid() || (eCurrentThreadStoppedReason == + // lldb::eStopReasonInvalid) || (eCurrentThreadStoppedReason == + // lldb::eStopReasonNone) ) + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Print to stdout "*running,thread-id=\"all\"", "(gdb)". // Type: Method. // Args: None. @@ -1493,19 +1563,19 @@ CMICmnLLDBDebuggerHandleEvents::UpdateSelectedThread() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateRunning() -{ - CMICmnMIValueConst miValueConst("all"); - CMICmnMIValueResult miValueResult("thread-id", miValueConst); - CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Running, miValueResult); - bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); - bOk = bOk && CMICmnStreamStdout::WritePrompt(); - - return bOk; +bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateRunning() { + CMICmnMIValueConst miValueConst("all"); + CMICmnMIValueResult miValueResult("thread-id", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_Running, miValueResult); + bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); + bOk = bOk && CMICmnStreamStdout::WritePrompt(); + + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Print to stdout "=thread-exited,id=\"%ld\",group-id=\"i1\"", // "=thread-group-exited,id=\"i1\",exit-code=\"0\""), // "*stopped,reason=\"exited-normally\"", @@ -1516,42 +1586,44 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateRunning() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited() -{ - const CMIUtilString strId(CMIUtilString::Format("%ld", 1)); - CMICmnMIValueConst miValueConst(strId); - CMICmnMIValueResult miValueResult("id", miValueConst); - CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult); - CMICmnMIValueConst miValueConst2("i1"); - CMICmnMIValueResult miValueResult2("group-id", miValueConst2); - miOutOfBandRecord.Add(miValueResult2); - bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); - if (bOk) - { - CMICmnMIValueConst miValueConst3("i1"); - CMICmnMIValueResult miValueResult3("id", miValueConst3); - CMICmnMIOutOfBandRecord miOutOfBandRecord2(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult3); - CMICmnMIValueConst miValueConst2("0"); - CMICmnMIValueResult miValueResult2("exit-code", miValueConst2); - miOutOfBandRecord2.Add(miValueResult2); - bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord2); - } - if (bOk) - { - CMICmnMIValueConst miValueConst4("exited-normally"); - CMICmnMIValueResult miValueResult4("reason", miValueConst4); - CMICmnMIOutOfBandRecord miOutOfBandRecord3(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult4); - bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord3); - } - bOk = bOk && CMICmnStreamStdout::WritePrompt(); - - return bOk; +bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited() { + const CMIUtilString strId(CMIUtilString::Format("%ld", 1)); + CMICmnMIValueConst miValueConst(strId); + CMICmnMIValueResult miValueResult("id", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult); + CMICmnMIValueConst miValueConst2("i1"); + CMICmnMIValueResult miValueResult2("group-id", miValueConst2); + miOutOfBandRecord.Add(miValueResult2); + bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); + if (bOk) { + CMICmnMIValueConst miValueConst3("i1"); + CMICmnMIValueResult miValueResult3("id", miValueConst3); + CMICmnMIOutOfBandRecord miOutOfBandRecord2( + CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult3); + CMICmnMIValueConst miValueConst2("0"); + CMICmnMIValueResult miValueResult2("exit-code", miValueConst2); + miOutOfBandRecord2.Add(miValueResult2); + bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord2); + } + if (bOk) { + CMICmnMIValueConst miValueConst4("exited-normally"); + CMICmnMIValueResult miValueResult4("reason", miValueConst4); + CMICmnMIOutOfBandRecord miOutOfBandRecord3( + CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult4); + bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord3); + } + bOk = bOk && CMICmnStreamStdout::WritePrompt(); + + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Drain all stdout so we don't see any output come after we print our prompts. -// The process has stuff waiting for stdout; get it and write it out to the +//++ +//------------------------------------------------------------------------------------ +// Details: Drain all stdout so we don't see any output come after we print our +// prompts. +// The process has stuff waiting for stdout; get it and write it out to +// the // appropriate place. // Type: Method. // Args: None. @@ -1559,52 +1631,55 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::GetProcessStdout() -{ - CMIUtilString text; - std::unique_ptr<char[]> apStdoutBuffer(new char[1024]); - lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().GetSelectedTarget().GetProcess(); - while (1) - { - const size_t nBytes = process.GetSTDOUT(apStdoutBuffer.get(), 1024); - text.append(apStdoutBuffer.get(), nBytes); - - while (1) - { - const size_t nNewLine = text.find('\n'); - if (nNewLine == std::string::npos) - break; - - const CMIUtilString line(text.substr(0, nNewLine + 1)); - text.erase(0, nNewLine + 1); - const bool bEscapeQuotes(true); - CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes)); - CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst); - const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); - if (!bOk) - return MIstatus::failure; - } +bool CMICmnLLDBDebuggerHandleEvents::GetProcessStdout() { + CMIUtilString text; + std::unique_ptr<char[]> apStdoutBuffer(new char[1024]); + lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance() + .GetDebugger() + .GetSelectedTarget() + .GetProcess(); + while (1) { + const size_t nBytes = process.GetSTDOUT(apStdoutBuffer.get(), 1024); + text.append(apStdoutBuffer.get(), nBytes); + + while (1) { + const size_t nNewLine = text.find('\n'); + if (nNewLine == std::string::npos) + break; + + const CMIUtilString line(text.substr(0, nNewLine + 1)); + text.erase(0, nNewLine + 1); + const bool bEscapeQuotes(true); + CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes)); + CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst); + const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); + if (!bOk) + return MIstatus::failure; + } - if (nBytes == 0) - { - if (!text.empty()) - { - const bool bEscapeQuotes(true); - CMICmnMIValueConst miValueConst(text.Escape(bEscapeQuotes)); - CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst); - return MiOutOfBandRecordToStdout(miOutOfBandRecord); - } - break; - } + if (nBytes == 0) { + if (!text.empty()) { + const bool bEscapeQuotes(true); + CMICmnMIValueConst miValueConst(text.Escape(bEscapeQuotes)); + CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, + miValueConst); + return MiOutOfBandRecordToStdout(miOutOfBandRecord); + } + break; } + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Drain all stderr so we don't see any output come after we print our prompts. -// The process has stuff waiting for stderr; get it and write it out to the +//++ +//------------------------------------------------------------------------------------ +// Details: Drain all stderr so we don't see any output come after we print our +// prompts. +// The process has stuff waiting for stderr; get it and write it out to +// the // appropriate place. // Type: Method. // Args: None. @@ -1612,49 +1687,50 @@ CMICmnLLDBDebuggerHandleEvents::GetProcessStdout() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::GetProcessStderr() -{ - CMIUtilString text; - std::unique_ptr<char[]> apStderrBuffer(new char[1024]); - lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().GetSelectedTarget().GetProcess(); - while (1) - { - const size_t nBytes = process.GetSTDERR(apStderrBuffer.get(), 1024); - text.append(apStderrBuffer.get(), nBytes); - - while (1) - { - const size_t nNewLine = text.find('\n'); - if (nNewLine == std::string::npos) - break; - - const CMIUtilString line(text.substr(0, nNewLine + 1)); - const bool bEscapeQuotes(true); - CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes)); - CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst); - const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); - if (!bOk) - return MIstatus::failure; - } +bool CMICmnLLDBDebuggerHandleEvents::GetProcessStderr() { + CMIUtilString text; + std::unique_ptr<char[]> apStderrBuffer(new char[1024]); + lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance() + .GetDebugger() + .GetSelectedTarget() + .GetProcess(); + while (1) { + const size_t nBytes = process.GetSTDERR(apStderrBuffer.get(), 1024); + text.append(apStderrBuffer.get(), nBytes); + + while (1) { + const size_t nNewLine = text.find('\n'); + if (nNewLine == std::string::npos) + break; + + const CMIUtilString line(text.substr(0, nNewLine + 1)); + const bool bEscapeQuotes(true); + CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes)); + CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst); + const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord); + if (!bOk) + return MIstatus::failure; + } - if (nBytes == 0) - { - if (!text.empty()) - { - const bool bEscapeQuotes(true); - CMICmnMIValueConst miValueConst(text.Escape(bEscapeQuotes)); - CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst); - return MiOutOfBandRecordToStdout(miOutOfBandRecord); - } - break; - } + if (nBytes == 0) { + if (!text.empty()) { + const bool bEscapeQuotes(true); + CMICmnMIValueConst miValueConst(text.Escape(bEscapeQuotes)); + CMICmnMIOutOfBandRecord miOutOfBandRecord( + CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, + miValueConst); + return MiOutOfBandRecordToStdout(miOutOfBandRecord); + } + break; } + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Asynchronous event function check for state changes. // Type: Method. // Args: None. @@ -1662,94 +1738,95 @@ CMICmnLLDBDebuggerHandleEvents::GetProcessStderr() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges() -{ - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); - if (!sbProcess.IsValid()) - return MIstatus::success; - - // Check for created threads - const MIuint nThread = sbProcess.GetNumThreads(); - for (MIuint i = 0; i < nThread; i++) - { - // GetThreadAtIndex() uses a base 0 index - // GetThreadByIndexID() uses a base 1 index - lldb::SBThread thread = sbProcess.GetThreadAtIndex(i); - if (!thread.IsValid()) - continue; - - const MIuint threadIndexID = thread.GetIndexID(); - const bool bFound = std::find(rSessionInfo.m_vecActiveThreadId.cbegin(), rSessionInfo.m_vecActiveThreadId.cend(), threadIndexID) != rSessionInfo.m_vecActiveThreadId.end(); - if (!bFound) - { - rSessionInfo.m_vecActiveThreadId.push_back(threadIndexID); - - // Form MI "=thread-created,id=\"%d\",group-id=\"i1\"" - const CMIUtilString strValue(CMIUtilString::Format("%d", threadIndexID)); - const CMICmnMIValueConst miValueConst(strValue); - const CMICmnMIValueResult miValueResult("id", miValueConst); - CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, miValueResult); - const CMICmnMIValueConst miValueConst2("i1"); - const CMICmnMIValueResult miValueResult2("group-id", miValueConst2); - miOutOfBand.Add(miValueResult2); - bool bOk = MiOutOfBandRecordToStdout(miOutOfBand); - if (!bOk) - return MIstatus::failure; - } - } +bool CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges() { + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + if (!sbProcess.IsValid()) + return MIstatus::success; - lldb::SBThread currentThread = sbProcess.GetSelectedThread(); - if (currentThread.IsValid()) - { - const MIuint currentThreadIndexID = currentThread.GetIndexID(); - if (rSessionInfo.m_currentSelectedThread != currentThreadIndexID) - { - rSessionInfo.m_currentSelectedThread = currentThreadIndexID; - - // Form MI "=thread-selected,id=\"%d\"" - const CMIUtilString strValue(CMIUtilString::Format("%d", currentThreadIndexID)); - const CMICmnMIValueConst miValueConst(strValue); - const CMICmnMIValueResult miValueResult("id", miValueConst); - CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, miValueResult); - if (!MiOutOfBandRecordToStdout(miOutOfBand)) - return MIstatus::failure; - } + // Check for created threads + const MIuint nThread = sbProcess.GetNumThreads(); + for (MIuint i = 0; i < nThread; i++) { + // GetThreadAtIndex() uses a base 0 index + // GetThreadByIndexID() uses a base 1 index + lldb::SBThread thread = sbProcess.GetThreadAtIndex(i); + if (!thread.IsValid()) + continue; + + const MIuint threadIndexID = thread.GetIndexID(); + const bool bFound = + std::find(rSessionInfo.m_vecActiveThreadId.cbegin(), + rSessionInfo.m_vecActiveThreadId.cend(), + threadIndexID) != rSessionInfo.m_vecActiveThreadId.end(); + if (!bFound) { + rSessionInfo.m_vecActiveThreadId.push_back(threadIndexID); + + // Form MI "=thread-created,id=\"%d\",group-id=\"i1\"" + const CMIUtilString strValue(CMIUtilString::Format("%d", threadIndexID)); + const CMICmnMIValueConst miValueConst(strValue); + const CMICmnMIValueResult miValueResult("id", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBand( + CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, miValueResult); + const CMICmnMIValueConst miValueConst2("i1"); + const CMICmnMIValueResult miValueResult2("group-id", miValueConst2); + miOutOfBand.Add(miValueResult2); + bool bOk = MiOutOfBandRecordToStdout(miOutOfBand); + if (!bOk) + return MIstatus::failure; } - - // Check for invalid (removed) threads - CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::iterator it = rSessionInfo.m_vecActiveThreadId.begin(); - while (it != rSessionInfo.m_vecActiveThreadId.end()) - { - const MIuint threadIndexID = *it; - lldb::SBThread thread = sbProcess.GetThreadByIndexID(threadIndexID); - if (!thread.IsValid()) - { - // Form MI "=thread-exited,id=\"%ld\",group-id=\"i1\"" - const CMIUtilString strValue(CMIUtilString::Format("%ld", threadIndexID)); - const CMICmnMIValueConst miValueConst(strValue); - const CMICmnMIValueResult miValueResult("id", miValueConst); - CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult); - const CMICmnMIValueConst miValueConst2("i1"); - const CMICmnMIValueResult miValueResult2("group-id", miValueConst2); - miOutOfBand.Add(miValueResult2); - bool bOk = MiOutOfBandRecordToStdout(miOutOfBand); - if (!bOk) - return MIstatus::failure; - - // Remove current thread from cache and get next - it = rSessionInfo.m_vecActiveThreadId.erase(it); - } - else - // Next - ++it; + } + + lldb::SBThread currentThread = sbProcess.GetSelectedThread(); + if (currentThread.IsValid()) { + const MIuint currentThreadIndexID = currentThread.GetIndexID(); + if (rSessionInfo.m_currentSelectedThread != currentThreadIndexID) { + rSessionInfo.m_currentSelectedThread = currentThreadIndexID; + + // Form MI "=thread-selected,id=\"%d\"" + const CMIUtilString strValue( + CMIUtilString::Format("%d", currentThreadIndexID)); + const CMICmnMIValueConst miValueConst(strValue); + const CMICmnMIValueResult miValueResult("id", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBand( + CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, miValueResult); + if (!MiOutOfBandRecordToStdout(miOutOfBand)) + return MIstatus::failure; } + } + + // Check for invalid (removed) threads + CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::iterator it = + rSessionInfo.m_vecActiveThreadId.begin(); + while (it != rSessionInfo.m_vecActiveThreadId.end()) { + const MIuint threadIndexID = *it; + lldb::SBThread thread = sbProcess.GetThreadByIndexID(threadIndexID); + if (!thread.IsValid()) { + // Form MI "=thread-exited,id=\"%ld\",group-id=\"i1\"" + const CMIUtilString strValue(CMIUtilString::Format("%ld", threadIndexID)); + const CMICmnMIValueConst miValueConst(strValue); + const CMICmnMIValueResult miValueResult("id", miValueConst); + CMICmnMIOutOfBandRecord miOutOfBand( + CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult); + const CMICmnMIValueConst miValueConst2("i1"); + const CMICmnMIValueResult miValueResult2("group-id", miValueConst2); + miOutOfBand.Add(miValueResult2); + bool bOk = MiOutOfBandRecordToStdout(miOutOfBand); + if (!bOk) + return MIstatus::failure; - return CMICmnStreamStdout::WritePrompt(); + // Remove current thread from cache and get next + it = rSessionInfo.m_vecActiveThreadId.erase(it); + } else + // Next + ++it; + } + + return CMICmnStreamStdout::WritePrompt(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Take a fully formed MI result record and send to the stdout stream. // Also output to the MI Log file. // Type: Method. @@ -1758,14 +1835,15 @@ CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::MiResultRecordToStdout(const CMICmnMIResultRecord &vrMiResultRecord) -{ - return TextToStdout(vrMiResultRecord.GetString()); +bool CMICmnLLDBDebuggerHandleEvents::MiResultRecordToStdout( + const CMICmnMIResultRecord &vrMiResultRecord) { + return TextToStdout(vrMiResultRecord.GetString()); } -//++ ------------------------------------------------------------------------------------ -// Details: Take a fully formed MI Out-of-band record and send to the stdout stream. +//++ +//------------------------------------------------------------------------------------ +// Details: Take a fully formed MI Out-of-band record and send to the stdout +// stream. // Also output to the MI Log file. // Type: Method. // Args: vrMiOutOfBandRecord - (R) MI Out-of-band record object. @@ -1773,14 +1851,15 @@ CMICmnLLDBDebuggerHandleEvents::MiResultRecordToStdout(const CMICmnMIResultRecor // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::MiOutOfBandRecordToStdout(const CMICmnMIOutOfBandRecord &vrMiOutOfBandRecord) -{ - return TextToStdout(vrMiOutOfBandRecord.GetString()); +bool CMICmnLLDBDebuggerHandleEvents::MiOutOfBandRecordToStdout( + const CMICmnMIOutOfBandRecord &vrMiOutOfBandRecord) { + return TextToStdout(vrMiOutOfBandRecord.GetString()); } -//++ ------------------------------------------------------------------------------------ -// Details: Take a text data and send to the stdout stream. Also output to the MI Log +//++ +//------------------------------------------------------------------------------------ +// Details: Take a text data and send to the stdout stream. Also output to the +// MI Log // file. // Type: Method. // Args: vrTxt - (R) Text. @@ -1788,14 +1867,14 @@ CMICmnLLDBDebuggerHandleEvents::MiOutOfBandRecordToStdout(const CMICmnMIOutOfBan // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::TextToStdout(const CMIUtilString &vrTxt) -{ - return CMICmnStreamStdout::TextToStdout(vrTxt); +bool CMICmnLLDBDebuggerHandleEvents::TextToStdout(const CMIUtilString &vrTxt) { + return CMICmnStreamStdout::TextToStdout(vrTxt); } -//++ ------------------------------------------------------------------------------------ -// Details: Take a text data and send to the stderr stream. Also output to the MI Log +//++ +//------------------------------------------------------------------------------------ +// Details: Take a text data and send to the stderr stream. Also output to the +// MI Log // file. // Type: Method. // Args: vrTxt - (R) Text. @@ -1803,34 +1882,31 @@ CMICmnLLDBDebuggerHandleEvents::TextToStdout(const CMIUtilString &vrTxt) // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBDebuggerHandleEvents::TextToStderr(const CMIUtilString &vrTxt) -{ - return CMICmnStreamStderr::TextToStderr(vrTxt); +bool CMICmnLLDBDebuggerHandleEvents::TextToStderr(const CMIUtilString &vrTxt) { + return CMICmnStreamStderr::TextToStderr(vrTxt); } -//++ ------------------------------------------------------------------------------------ -// Details: Initialize the member variables with the signal values in this process +//++ +//------------------------------------------------------------------------------------ +// Details: Initialize the member variables with the signal values in this +// process // file. // Type: Method. // Args: None // Return: Noen // Throws: None. //-- -void -CMICmnLLDBDebuggerHandleEvents::InitializeSignals() -{ - if (!m_bSignalsInitialized) - { - lldb::SBProcess sbProcess = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); - if (sbProcess.IsValid()) - { - lldb::SBUnixSignals unix_signals = sbProcess.GetUnixSignals(); - m_SIGINT = unix_signals.GetSignalNumberFromName("SIGINT"); - m_SIGSTOP = unix_signals.GetSignalNumberFromName("SIGSTOP"); - m_SIGSEGV = unix_signals.GetSignalNumberFromName("SIGSEGV"); - m_SIGTRAP = unix_signals.GetSignalNumberFromName("SIGTRAP"); - m_bSignalsInitialized = true; - } +void CMICmnLLDBDebuggerHandleEvents::InitializeSignals() { + if (!m_bSignalsInitialized) { + lldb::SBProcess sbProcess = + CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + if (sbProcess.IsValid()) { + lldb::SBUnixSignals unix_signals = sbProcess.GetUnixSignals(); + m_SIGINT = unix_signals.GetSignalNumberFromName("SIGINT"); + m_SIGSTOP = unix_signals.GetSignalNumberFromName("SIGSTOP"); + m_SIGSEGV = unix_signals.GetSignalNumberFromName("SIGSEGV"); + m_SIGTRAP = unix_signals.GetSignalNumberFromName("SIGTRAP"); + m_bSignalsInitialized = true; } + } } diff --git a/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h b/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h index f5075d10209..f4773053c28 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h +++ b/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h @@ -21,71 +21,79 @@ class CMICmnMIResultRecord; class CMICmnStreamStdout; class CMICmnMIOutOfBandRecord; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI class to take LLDB SBEvent objects, filter them and form // MI Out-of-band records from the information inside the event object. // These records are then pushed to stdout. // A singleton class. //-- -class CMICmnLLDBDebuggerHandleEvents : public CMICmnBase, public MI::ISingleton<CMICmnLLDBDebuggerHandleEvents> -{ - friend class MI::ISingleton<CMICmnLLDBDebuggerHandleEvents>; +class CMICmnLLDBDebuggerHandleEvents + : public CMICmnBase, + public MI::ISingleton<CMICmnLLDBDebuggerHandleEvents> { + friend class MI::ISingleton<CMICmnLLDBDebuggerHandleEvents>; - // Methods: - public: - bool Initialize() override; - bool Shutdown() override; - // - bool HandleEvent(const lldb::SBEvent &vEvent, bool &vrbHandledEvent); + // Methods: +public: + bool Initialize() override; + bool Shutdown() override; + // + bool HandleEvent(const lldb::SBEvent &vEvent, bool &vrbHandledEvent); - // Methods: - private: - /* ctor */ CMICmnLLDBDebuggerHandleEvents(); - /* ctor */ CMICmnLLDBDebuggerHandleEvents(const CMICmnLLDBDebuggerHandleEvents &); - void operator=(const CMICmnLLDBDebuggerHandleEvents &); - // - bool ChkForStateChanges(); - bool GetProcessStdout(); - bool GetProcessStderr(); - bool HandleEventSBBreakPoint(const lldb::SBEvent &vEvent); - bool HandleEventSBBreakpointCmn(const lldb::SBEvent &vEvent); - bool HandleEventSBBreakpointAdded(const lldb::SBEvent &vEvent); - bool HandleEventSBBreakpointLocationsAdded(const lldb::SBEvent &vEvent); - bool HandleEventSBProcess(const lldb::SBEvent &vEvent); - bool HandleEventSBTarget(const lldb::SBEvent &vEvent); - bool HandleEventSBThread(const lldb::SBEvent &vEvent); - bool HandleEventSBThreadBitStackChanged(const lldb::SBEvent &vEvent); - bool HandleEventSBThreadSuspended(const lldb::SBEvent &vEvent); - bool HandleEventSBCommandInterpreter(const lldb::SBEvent &vEvent); - bool HandleProcessEventBroadcastBitStateChanged(const lldb::SBEvent &vEvent); - bool HandleProcessEventStateRunning(); - bool HandleProcessEventStateExited(); - bool HandleProcessEventStateStopped(const lldb::SBEvent &vrEvent, bool &vwrbShouldBrk); - bool HandleProcessEventStopReasonTrace(); - bool HandleProcessEventStopReasonBreakpoint(); - bool HandleProcessEventStopSignal(const lldb::SBEvent &vrEvent); - bool HandleProcessEventStopException(); - bool HandleProcessEventStateSuspended(const lldb::SBEvent &vEvent); - bool HandleTargetEventBroadcastBitModulesLoaded(const lldb::SBEvent &vEvent); - bool HandleTargetEventBroadcastBitModulesUnloaded(const lldb::SBEvent &vEvent); - bool MiHelpGetModuleInfo(const lldb::SBModule &vModule, const bool vbWithExtraFields, - CMICmnMIOutOfBandRecord &vwrMiOutOfBandRecord); - bool MiHelpGetCurrentThreadFrame(CMICmnMIValueTuple &vwrMiValueTuple); - bool MiResultRecordToStdout(const CMICmnMIResultRecord &vrMiResultRecord); - bool MiOutOfBandRecordToStdout(const CMICmnMIOutOfBandRecord &vrMiResultRecord); - bool MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, const lldb::SBBreakpoint &vBrkPt); - bool TextToStdout(const CMIUtilString &vrTxt); - bool TextToStderr(const CMIUtilString &vrTxt); - bool UpdateSelectedThread(); + // Methods: +private: + /* ctor */ CMICmnLLDBDebuggerHandleEvents(); + /* ctor */ CMICmnLLDBDebuggerHandleEvents( + const CMICmnLLDBDebuggerHandleEvents &); + void operator=(const CMICmnLLDBDebuggerHandleEvents &); + // + bool ChkForStateChanges(); + bool GetProcessStdout(); + bool GetProcessStderr(); + bool HandleEventSBBreakPoint(const lldb::SBEvent &vEvent); + bool HandleEventSBBreakpointCmn(const lldb::SBEvent &vEvent); + bool HandleEventSBBreakpointAdded(const lldb::SBEvent &vEvent); + bool HandleEventSBBreakpointLocationsAdded(const lldb::SBEvent &vEvent); + bool HandleEventSBProcess(const lldb::SBEvent &vEvent); + bool HandleEventSBTarget(const lldb::SBEvent &vEvent); + bool HandleEventSBThread(const lldb::SBEvent &vEvent); + bool HandleEventSBThreadBitStackChanged(const lldb::SBEvent &vEvent); + bool HandleEventSBThreadSuspended(const lldb::SBEvent &vEvent); + bool HandleEventSBCommandInterpreter(const lldb::SBEvent &vEvent); + bool HandleProcessEventBroadcastBitStateChanged(const lldb::SBEvent &vEvent); + bool HandleProcessEventStateRunning(); + bool HandleProcessEventStateExited(); + bool HandleProcessEventStateStopped(const lldb::SBEvent &vrEvent, + bool &vwrbShouldBrk); + bool HandleProcessEventStopReasonTrace(); + bool HandleProcessEventStopReasonBreakpoint(); + bool HandleProcessEventStopSignal(const lldb::SBEvent &vrEvent); + bool HandleProcessEventStopException(); + bool HandleProcessEventStateSuspended(const lldb::SBEvent &vEvent); + bool HandleTargetEventBroadcastBitModulesLoaded(const lldb::SBEvent &vEvent); + bool + HandleTargetEventBroadcastBitModulesUnloaded(const lldb::SBEvent &vEvent); + bool MiHelpGetModuleInfo(const lldb::SBModule &vModule, + const bool vbWithExtraFields, + CMICmnMIOutOfBandRecord &vwrMiOutOfBandRecord); + bool MiHelpGetCurrentThreadFrame(CMICmnMIValueTuple &vwrMiValueTuple); + bool MiResultRecordToStdout(const CMICmnMIResultRecord &vrMiResultRecord); + bool + MiOutOfBandRecordToStdout(const CMICmnMIOutOfBandRecord &vrMiResultRecord); + bool MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, + const lldb::SBBreakpoint &vBrkPt); + bool TextToStdout(const CMIUtilString &vrTxt); + bool TextToStderr(const CMIUtilString &vrTxt); + bool UpdateSelectedThread(); - // Overridden: - private: - // From CMICmnBase - /* dtor */ ~CMICmnLLDBDebuggerHandleEvents() override; - void InitializeSignals(); - bool m_bSignalsInitialized; - MIuint64 m_SIGINT; - MIuint64 m_SIGSTOP; - MIuint64 m_SIGSEGV; - MIuint64 m_SIGTRAP; + // Overridden: +private: + // From CMICmnBase + /* dtor */ ~CMICmnLLDBDebuggerHandleEvents() override; + void InitializeSignals(); + bool m_bSignalsInitialized; + MIuint64 m_SIGINT; + MIuint64 m_SIGSTOP; + MIuint64 m_SIGSEGV; + MIuint64 m_SIGTRAP; }; diff --git a/lldb/tools/lldb-mi/MICmnLLDBProxySBValue.cpp b/lldb/tools/lldb-mi/MICmnLLDBProxySBValue.cpp index eeafa9ddd2a..5a3e8e43b5f 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBProxySBValue.cpp +++ b/lldb/tools/lldb-mi/MICmnLLDBProxySBValue.cpp @@ -13,13 +13,16 @@ #include "lldb/API/SBError.h" // In-house headers: +#include "MICmnLLDBDebugSessionInfo.h" #include "MICmnLLDBProxySBValue.h" #include "MIUtilString.h" -#include "MICmnLLDBDebugSessionInfo.h" -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the numerical value from the SBValue object. If the function fails -// it could indicate the SBValue object does not represent an internal type. +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the numerical value from the SBValue object. If the +// function fails +// it could indicate the SBValue object does not represent an internal +// type. // Type: Static method. // Args: vrValue - (R) The SBValue object to get a value from. // vwValue - (W) The numerical value. @@ -27,35 +30,33 @@ // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBProxySBValue::GetValueAsUnsigned(const lldb::SBValue &vrValue, MIuint64 &vwValue) -{ - lldb::SBValue &rValue = const_cast<lldb::SBValue &>(vrValue); - bool bCompositeType = true; - MIuint64 nFailValue = 0; - MIuint64 nValue = rValue.GetValueAsUnsigned(nFailValue); - if (nValue == nFailValue) - { - nFailValue = 5; // Some arbitrary number - nValue = rValue.GetValueAsUnsigned(nFailValue); - if (nValue != nFailValue) - { - bCompositeType = false; - vwValue = nValue; - } - } - else - { - bCompositeType = false; - vwValue = nValue; +bool CMICmnLLDBProxySBValue::GetValueAsUnsigned(const lldb::SBValue &vrValue, + MIuint64 &vwValue) { + lldb::SBValue &rValue = const_cast<lldb::SBValue &>(vrValue); + bool bCompositeType = true; + MIuint64 nFailValue = 0; + MIuint64 nValue = rValue.GetValueAsUnsigned(nFailValue); + if (nValue == nFailValue) { + nFailValue = 5; // Some arbitrary number + nValue = rValue.GetValueAsUnsigned(nFailValue); + if (nValue != nFailValue) { + bCompositeType = false; + vwValue = nValue; } + } else { + bCompositeType = false; + vwValue = nValue; + } - return (bCompositeType ? MIstatus::failure : MIstatus::success); + return (bCompositeType ? MIstatus::failure : MIstatus::success); } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the numerical value from the SBValue object. If the function fails -// it could indicate the SBValue object does not represent an internal type. +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the numerical value from the SBValue object. If the +// function fails +// it could indicate the SBValue object does not represent an internal +// type. // Type: Static method. // Args: vrValue - (R) The SBValue object to get a value from. // vwValue - (W) The numerical value. @@ -63,34 +64,31 @@ CMICmnLLDBProxySBValue::GetValueAsUnsigned(const lldb::SBValue &vrValue, MIuint6 // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnLLDBProxySBValue::GetValueAsSigned(const lldb::SBValue &vrValue, MIint64 &vwValue) -{ - lldb::SBValue &rValue = const_cast<lldb::SBValue &>(vrValue); - bool bCompositeType = true; - MIuint64 nFailValue = 0; - MIuint64 nValue = rValue.GetValueAsSigned(nFailValue); - if (nValue == nFailValue) - { - nFailValue = 5; // Some arbitrary number - nValue = rValue.GetValueAsSigned(nFailValue); - if (nValue != nFailValue) - { - bCompositeType = false; - vwValue = nValue; - } - } - else - { - bCompositeType = false; - vwValue = nValue; +bool CMICmnLLDBProxySBValue::GetValueAsSigned(const lldb::SBValue &vrValue, + MIint64 &vwValue) { + lldb::SBValue &rValue = const_cast<lldb::SBValue &>(vrValue); + bool bCompositeType = true; + MIuint64 nFailValue = 0; + MIuint64 nValue = rValue.GetValueAsSigned(nFailValue); + if (nValue == nFailValue) { + nFailValue = 5; // Some arbitrary number + nValue = rValue.GetValueAsSigned(nFailValue); + if (nValue != nFailValue) { + bCompositeType = false; + vwValue = nValue; } + } else { + bCompositeType = false; + vwValue = nValue; + } - return (bCompositeType ? MIstatus::failure : MIstatus::success); + return (bCompositeType ? MIstatus::failure : MIstatus::success); } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the NUL terminated string from the SBValue object if it of the type +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the NUL terminated string from the SBValue object if it of +// the type // unsigned char *. // Type: Static method. // Args: vrValue - (R) The SBValue object to get a value from. @@ -99,44 +97,42 @@ CMICmnLLDBProxySBValue::GetValueAsSigned(const lldb::SBValue &vrValue, MIint64 & // MIstatus::failure - Functionality failed, not suitable type. // Throws: None. //-- -bool -CMICmnLLDBProxySBValue::GetCString(const lldb::SBValue &vrValue, CMIUtilString &vwCString) -{ - lldb::SBValue &rValue = const_cast<lldb::SBValue &>(vrValue); - const char *pCType = rValue.GetTypeName(); - if (pCType == nullptr) - return MIstatus::failure; +bool CMICmnLLDBProxySBValue::GetCString(const lldb::SBValue &vrValue, + CMIUtilString &vwCString) { + lldb::SBValue &rValue = const_cast<lldb::SBValue &>(vrValue); + const char *pCType = rValue.GetTypeName(); + if (pCType == nullptr) + return MIstatus::failure; - const char *pType = "unsigned char *"; - if (!CMIUtilString::Compare(pCType, pType)) - return MIstatus::failure; + const char *pType = "unsigned char *"; + if (!CMIUtilString::Compare(pCType, pType)) + return MIstatus::failure; - const CMIUtilString strAddr(rValue.GetValue()); - MIint64 nNum = 0; - if (!strAddr.ExtractNumber(nNum)) - return MIstatus::failure; + const CMIUtilString strAddr(rValue.GetValue()); + MIint64 nNum = 0; + if (!strAddr.ExtractNumber(nNum)) + return MIstatus::failure; - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); - MIuint nBufferSize = 64; - bool bNeedResize = false; - char *pBuffer = static_cast<char *>(::malloc(nBufferSize)); - do - { - lldb::SBError error; - const size_t nReadSize = sbProcess.ReadCStringFromMemory((lldb::addr_t)nNum, pBuffer, nBufferSize, error); - if (nReadSize == (nBufferSize - 1)) - { - bNeedResize = true; - nBufferSize = nBufferSize << 1; - pBuffer = static_cast<char *>(::realloc(pBuffer, nBufferSize)); - } - else - bNeedResize = false; - } while (bNeedResize); + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); + MIuint nBufferSize = 64; + bool bNeedResize = false; + char *pBuffer = static_cast<char *>(::malloc(nBufferSize)); + do { + lldb::SBError error; + const size_t nReadSize = sbProcess.ReadCStringFromMemory( + (lldb::addr_t)nNum, pBuffer, nBufferSize, error); + if (nReadSize == (nBufferSize - 1)) { + bNeedResize = true; + nBufferSize = nBufferSize << 1; + pBuffer = static_cast<char *>(::realloc(pBuffer, nBufferSize)); + } else + bNeedResize = false; + } while (bNeedResize); - vwCString = pBuffer; - free((void *)pBuffer); + vwCString = pBuffer; + free((void *)pBuffer); - return MIstatus::success; + return MIstatus::success; } diff --git a/lldb/tools/lldb-mi/MICmnLLDBProxySBValue.h b/lldb/tools/lldb-mi/MICmnLLDBProxySBValue.h index 2ae3acf3d7e..2559a60a114 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBProxySBValue.h +++ b/lldb/tools/lldb-mi/MICmnLLDBProxySBValue.h @@ -18,15 +18,18 @@ // Declarations: class CMIUtilString; -//++ ============================================================================ -// Details: MI proxy wrapper class to lldb::SBValue. The class provides functionality +//++ +//============================================================================ +// Details: MI proxy wrapper class to lldb::SBValue. The class provides +// functionality // to assist in the use of SBValue's particular function usage. //-- -class CMICmnLLDBProxySBValue -{ - // Statics: - public: - static bool GetValueAsSigned(const lldb::SBValue &vrValue, MIint64 &vwValue); - static bool GetValueAsUnsigned(const lldb::SBValue &vrValue, MIuint64 &vwValue); - static bool GetCString(const lldb::SBValue &vrValue, CMIUtilString &vwCString); +class CMICmnLLDBProxySBValue { + // Statics: +public: + static bool GetValueAsSigned(const lldb::SBValue &vrValue, MIint64 &vwValue); + static bool GetValueAsUnsigned(const lldb::SBValue &vrValue, + MIuint64 &vwValue); + static bool GetCString(const lldb::SBValue &vrValue, + CMIUtilString &vwCString); }; diff --git a/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp b/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp index d3d85d32c03..7e2b23307ca 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp +++ b/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.cpp @@ -8,108 +8,118 @@ //===----------------------------------------------------------------------===// // Third party headers: -#include <cinttypes> #include "lldb/API/SBTypeSummary.h" +#include <cinttypes> // In-house headers: -#include "MICmnLLDBUtilSBValue.h" #include "MICmnLLDBDebugSessionInfo.h" +#include "MICmnLLDBUtilSBValue.h" #include "MICmnMIValueConst.h" #include "MICmnMIValueTuple.h" #include "MIUtilString.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLLDBUtilSBValue constructor. // Type: Method. // Args: vrValue - (R) The LLDB value object. -// vbHandleCharType - (R) True = Yes return text molding to char type, +// vbHandleCharType - (R) True = Yes return text molding to char +// type, // False = just return data. // Return: None. // Throws: None. //-- -CMICmnLLDBUtilSBValue::CMICmnLLDBUtilSBValue(const lldb::SBValue &vrValue, const bool vbHandleCharType /* = false */, - const bool vbHandleArrayType /* = true */) - : m_rValue(const_cast<lldb::SBValue &>(vrValue)) - , m_pUnkwn("??") - , m_pComposite("{...}") - , m_bHandleCharType(vbHandleCharType) - , m_bHandleArrayType(vbHandleArrayType) -{ - m_bValidSBValue = m_rValue.IsValid(); +CMICmnLLDBUtilSBValue::CMICmnLLDBUtilSBValue( + const lldb::SBValue &vrValue, const bool vbHandleCharType /* = false */, + const bool vbHandleArrayType /* = true */) + : m_rValue(const_cast<lldb::SBValue &>(vrValue)), m_pUnkwn("??"), + m_pComposite("{...}"), m_bHandleCharType(vbHandleCharType), + m_bHandleArrayType(vbHandleArrayType) { + m_bValidSBValue = m_rValue.IsValid(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLLDBUtilSBValue destructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmnLLDBUtilSBValue::~CMICmnLLDBUtilSBValue() -{ -} +CMICmnLLDBUtilSBValue::~CMICmnLLDBUtilSBValue() {} -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve from the LLDB SB Value object the name of the variable. If the name +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve from the LLDB SB Value object the name of the variable. If +// the name // is invalid (or the SBValue object invalid) then "??" is returned. // Type: Method. // Args: None. // Return: CMIUtilString - Name of the variable or "??" for unknown. // Throws: None. //-- -CMIUtilString -CMICmnLLDBUtilSBValue::GetName() const -{ - const char *pName = m_bValidSBValue ? m_rValue.GetName() : nullptr; - const CMIUtilString text((pName != nullptr) ? pName : CMIUtilString()); +CMIUtilString CMICmnLLDBUtilSBValue::GetName() const { + const char *pName = m_bValidSBValue ? m_rValue.GetName() : nullptr; + const CMIUtilString text((pName != nullptr) ? pName : CMIUtilString()); - return text; + return text; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve from the LLDB SB Value object the value of the variable described in -// text. If the value is invalid (or the SBValue object invalid) then "??" is +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve from the LLDB SB Value object the value of the variable +// described in +// text. If the value is invalid (or the SBValue object invalid) then +// "??" is // returned. // Type: Method. // Args: None. // Return: CMIUtilString - Text description of the variable's value or "??". // Throws: None. //-- -CMIUtilString -CMICmnLLDBUtilSBValue::GetValue(const bool vbExpandAggregates /* = false */) const -{ - if (!m_bValidSBValue) - return m_pUnkwn; - - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - bool bPrintExpandAggregates = false; - bPrintExpandAggregates = rSessionInfo.SharedDataRetrieve<bool>(rSessionInfo.m_constStrPrintExpandAggregates, - bPrintExpandAggregates) && bPrintExpandAggregates; - - const bool bHandleArrayTypeAsSimple = m_bHandleArrayType && !vbExpandAggregates && !bPrintExpandAggregates; - CMIUtilString value; - const bool bIsSimpleValue = GetSimpleValue(bHandleArrayTypeAsSimple, value); - if (bIsSimpleValue) - return value; +CMIUtilString CMICmnLLDBUtilSBValue::GetValue( + const bool vbExpandAggregates /* = false */) const { + if (!m_bValidSBValue) + return m_pUnkwn; + + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + bool bPrintExpandAggregates = false; + bPrintExpandAggregates = rSessionInfo.SharedDataRetrieve<bool>( + rSessionInfo.m_constStrPrintExpandAggregates, + bPrintExpandAggregates) && + bPrintExpandAggregates; + + const bool bHandleArrayTypeAsSimple = + m_bHandleArrayType && !vbExpandAggregates && !bPrintExpandAggregates; + CMIUtilString value; + const bool bIsSimpleValue = GetSimpleValue(bHandleArrayTypeAsSimple, value); + if (bIsSimpleValue) + return value; - if (!vbExpandAggregates && !bPrintExpandAggregates) - return m_pComposite; + if (!vbExpandAggregates && !bPrintExpandAggregates) + return m_pComposite; - bool bPrintAggregateFieldNames = false; - bPrintAggregateFieldNames = !rSessionInfo.SharedDataRetrieve<bool>(rSessionInfo.m_constStrPrintAggregateFieldNames, - bPrintAggregateFieldNames) || bPrintAggregateFieldNames; + bool bPrintAggregateFieldNames = false; + bPrintAggregateFieldNames = + !rSessionInfo.SharedDataRetrieve<bool>( + rSessionInfo.m_constStrPrintAggregateFieldNames, + bPrintAggregateFieldNames) || + bPrintAggregateFieldNames; - CMICmnMIValueTuple miValueTuple; - const bool bOk = GetCompositeValue(bPrintAggregateFieldNames, miValueTuple); - if (!bOk) - return m_pUnkwn; + CMICmnMIValueTuple miValueTuple; + const bool bOk = GetCompositeValue(bPrintAggregateFieldNames, miValueTuple); + if (!bOk) + return m_pUnkwn; - value = miValueTuple.GetString(); - return value; + value = miValueTuple.GetString(); + return value; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve from the LLDB SB Value object the value of the variable described in +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve from the LLDB SB Value object the value of the variable +// described in // text if it has a simple format (not composite). // Type: Method. // Args: vwrValue - (W) The SBValue in a string format. @@ -117,267 +127,263 @@ CMICmnLLDBUtilSBValue::GetValue(const bool vbExpandAggregates /* = false */) con // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmnLLDBUtilSBValue::GetSimpleValue(const bool vbHandleArrayType, CMIUtilString &vwrValue) const -{ - const MIuint nChildren = m_rValue.GetNumChildren(); - if (nChildren == 0) - { - vwrValue = GetValueSummary(!m_bHandleCharType && IsCharType(), m_pUnkwn); - return MIstatus::success; - } - else if (IsPointerType()) - { - vwrValue = GetValueSummary(!m_bHandleCharType && IsPointeeCharType(), m_pUnkwn); - return MIstatus::success; - } - else if (IsArrayType()) - { - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - bool bPrintCharArrayAsString = false; - bPrintCharArrayAsString = rSessionInfo.SharedDataRetrieve<bool>(rSessionInfo.m_constStrPrintCharArrayAsString, - bPrintCharArrayAsString) && bPrintCharArrayAsString; - if (bPrintCharArrayAsString && m_bHandleCharType && IsFirstChildCharType()) - { - vwrValue = GetValueSummary(false); - return MIstatus::success; - } - else if (vbHandleArrayType) - { - vwrValue = CMIUtilString::Format("[%u]", nChildren); - return MIstatus::success; - } - } - else - { - // Treat composite value which has registered summary - // (for example with AddCXXSummary) as simple value - vwrValue = GetValueSummary(false); - if (!vwrValue.empty()) - return MIstatus::success; +bool CMICmnLLDBUtilSBValue::GetSimpleValue(const bool vbHandleArrayType, + CMIUtilString &vwrValue) const { + const MIuint nChildren = m_rValue.GetNumChildren(); + if (nChildren == 0) { + vwrValue = GetValueSummary(!m_bHandleCharType && IsCharType(), m_pUnkwn); + return MIstatus::success; + } else if (IsPointerType()) { + vwrValue = + GetValueSummary(!m_bHandleCharType && IsPointeeCharType(), m_pUnkwn); + return MIstatus::success; + } else if (IsArrayType()) { + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + bool bPrintCharArrayAsString = false; + bPrintCharArrayAsString = rSessionInfo.SharedDataRetrieve<bool>( + rSessionInfo.m_constStrPrintCharArrayAsString, + bPrintCharArrayAsString) && + bPrintCharArrayAsString; + if (bPrintCharArrayAsString && m_bHandleCharType && + IsFirstChildCharType()) { + vwrValue = GetValueSummary(false); + return MIstatus::success; + } else if (vbHandleArrayType) { + vwrValue = CMIUtilString::Format("[%u]", nChildren); + return MIstatus::success; } - - // Composite variable type i.e. struct - return MIstatus::failure; + } else { + // Treat composite value which has registered summary + // (for example with AddCXXSummary) as simple value + vwrValue = GetValueSummary(false); + if (!vwrValue.empty()) + return MIstatus::success; + } + + // Composite variable type i.e. struct + return MIstatus::failure; } -bool -CMICmnLLDBUtilSBValue::GetCompositeValue(const bool vbPrintFieldNames, CMICmnMIValueTuple &vwrMiValueTuple, - const MIuint vnDepth /* = 1 */) const -{ - const MIuint nMaxDepth = 10; - const MIuint nChildren = m_rValue.GetNumChildren(); - for (MIuint i = 0; i < nChildren; ++i) - { - const lldb::SBValue member = m_rValue.GetChildAtIndex(i); - const CMICmnLLDBUtilSBValue utilMember(member, m_bHandleCharType, m_bHandleArrayType); - const bool bHandleArrayTypeAsSimple = false; - CMIUtilString value; - const bool bIsSimpleValue = utilMember.GetSimpleValue(bHandleArrayTypeAsSimple, value); - if (bIsSimpleValue) - { - // OK. Value is simple (not composite) and was successfully got - } - else if (vnDepth < nMaxDepth) - { - // Need to get value from composite type - CMICmnMIValueTuple miValueTuple; - const bool bOk = utilMember.GetCompositeValue(vbPrintFieldNames, miValueTuple, vnDepth + 1); - if (!bOk) - // Can't obtain composite type - value = m_pUnkwn; - else - // OK. Value is composite and was successfully got - value = miValueTuple.GetString(); - } - else - { - // Need to get value from composite type, but vnMaxDepth is reached - value = m_pComposite; - } - const bool bNoQuotes = true; - const CMICmnMIValueConst miValueConst(value, bNoQuotes); - if (vbPrintFieldNames) - { - const bool bUseSpacing = true; - const CMICmnMIValueResult miValueResult(utilMember.GetName(), miValueConst, bUseSpacing); - vwrMiValueTuple.Add(miValueResult, bUseSpacing); - } - else - { - const bool bUseSpacing = false; - vwrMiValueTuple.Add(miValueConst, bUseSpacing); - } +bool CMICmnLLDBUtilSBValue::GetCompositeValue( + const bool vbPrintFieldNames, CMICmnMIValueTuple &vwrMiValueTuple, + const MIuint vnDepth /* = 1 */) const { + const MIuint nMaxDepth = 10; + const MIuint nChildren = m_rValue.GetNumChildren(); + for (MIuint i = 0; i < nChildren; ++i) { + const lldb::SBValue member = m_rValue.GetChildAtIndex(i); + const CMICmnLLDBUtilSBValue utilMember(member, m_bHandleCharType, + m_bHandleArrayType); + const bool bHandleArrayTypeAsSimple = false; + CMIUtilString value; + const bool bIsSimpleValue = + utilMember.GetSimpleValue(bHandleArrayTypeAsSimple, value); + if (bIsSimpleValue) { + // OK. Value is simple (not composite) and was successfully got + } else if (vnDepth < nMaxDepth) { + // Need to get value from composite type + CMICmnMIValueTuple miValueTuple; + const bool bOk = utilMember.GetCompositeValue(vbPrintFieldNames, + miValueTuple, vnDepth + 1); + if (!bOk) + // Can't obtain composite type + value = m_pUnkwn; + else + // OK. Value is composite and was successfully got + value = miValueTuple.GetString(); + } else { + // Need to get value from composite type, but vnMaxDepth is reached + value = m_pComposite; + } + const bool bNoQuotes = true; + const CMICmnMIValueConst miValueConst(value, bNoQuotes); + if (vbPrintFieldNames) { + const bool bUseSpacing = true; + const CMICmnMIValueResult miValueResult(utilMember.GetName(), + miValueConst, bUseSpacing); + vwrMiValueTuple.Add(miValueResult, bUseSpacing); + } else { + const bool bUseSpacing = false; + vwrMiValueTuple.Add(miValueConst, bUseSpacing); } + } - return MIstatus::success; + return MIstatus::success; } // Returns value or value + summary, depending on valueOnly parameter value. // If result is an empty string returns failVal. CMIUtilString -CMICmnLLDBUtilSBValue::GetValueSummary(bool valueOnly, const CMIUtilString& failVal) const -{ - if (!m_rValue.IsValid()) - return failVal; - - CMIUtilString value, valSummary; - const char* c_value = m_rValue.GetValue(); - if (valueOnly) - return c_value == nullptr ? failVal : c_value; - - const char* c_summary = m_rValue.GetSummary(); - if (c_value) - value = c_value; - else if (c_summary == nullptr) - return failVal; - - if (c_summary && c_summary[0]) - { - valSummary = c_summary; - lldb::SBTypeSummary summary = m_rValue.GetTypeSummary(); - if (summary.IsValid() && summary.DoesPrintValue(m_rValue) && !value.empty()) - { - valSummary.insert(0, value + " "); - } - return valSummary; +CMICmnLLDBUtilSBValue::GetValueSummary(bool valueOnly, + const CMIUtilString &failVal) const { + if (!m_rValue.IsValid()) + return failVal; + + CMIUtilString value, valSummary; + const char *c_value = m_rValue.GetValue(); + if (valueOnly) + return c_value == nullptr ? failVal : c_value; + + const char *c_summary = m_rValue.GetSummary(); + if (c_value) + value = c_value; + else if (c_summary == nullptr) + return failVal; + + if (c_summary && c_summary[0]) { + valSummary = c_summary; + lldb::SBTypeSummary summary = m_rValue.GetTypeSummary(); + if (summary.IsValid() && summary.DoesPrintValue(m_rValue) && + !value.empty()) { + valSummary.insert(0, value + " "); } - // no summary - return just value - return value; + return valSummary; + } + // no summary - return just value + return value; } -//++ ------------------------------------------------------------------------------------ -// Details: Check that basic type is a char type. Char type can be signed or unsigned. +//++ +//------------------------------------------------------------------------------------ +// Details: Check that basic type is a char type. Char type can be signed or +// unsigned. // Type: Static. // Args: eType - type to check // Return: bool - True = Yes is a char type, false = some other type. // Throws: None. //-- -bool -CMICmnLLDBUtilSBValue::IsCharBasicType(lldb::BasicType eType) -{ - switch (eType) - { - case lldb::eBasicTypeChar: - case lldb::eBasicTypeSignedChar: - case lldb::eBasicTypeUnsignedChar: - case lldb::eBasicTypeChar16: - case lldb::eBasicTypeChar32: - return true; - default: - return false; - } +bool CMICmnLLDBUtilSBValue::IsCharBasicType(lldb::BasicType eType) { + switch (eType) { + case lldb::eBasicTypeChar: + case lldb::eBasicTypeSignedChar: + case lldb::eBasicTypeUnsignedChar: + case lldb::eBasicTypeChar16: + case lldb::eBasicTypeChar32: + return true; + default: + return false; + } } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the flag stating whether this value object is a char type or some +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the flag stating whether this value object is a char type +// or some // other type. Char type can be signed or unsigned. // Type: Method. // Args: None. // Return: bool - True = Yes is a char type, false = some other type. // Throws: None. //-- -bool -CMICmnLLDBUtilSBValue::IsCharType() const -{ - const lldb::BasicType eType = m_rValue.GetType().GetBasicType(); - return IsCharBasicType(eType); +bool CMICmnLLDBUtilSBValue::IsCharType() const { + const lldb::BasicType eType = m_rValue.GetType().GetBasicType(); + return IsCharBasicType(eType); } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the flag stating whether first child value object of *this object is -// a char type or some other type. Returns false if there are not children. Char +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the flag stating whether first child value object of *this +// object is +// a char type or some other type. Returns false if there are not +// children. Char // type can be signed or unsigned. // Type: Method. // Args: None. // Return: bool - True = Yes is a char type, false = some other type. // Throws: None. //-- -bool -CMICmnLLDBUtilSBValue::IsFirstChildCharType() const -{ - const MIuint nChildren = m_rValue.GetNumChildren(); - - // Is it a basic type - if (nChildren == 0) - return false; - - const lldb::SBValue member = m_rValue.GetChildAtIndex(0); - const CMICmnLLDBUtilSBValue utilValue(member); - return utilValue.IsCharType(); +bool CMICmnLLDBUtilSBValue::IsFirstChildCharType() const { + const MIuint nChildren = m_rValue.GetNumChildren(); + + // Is it a basic type + if (nChildren == 0) + return false; + + const lldb::SBValue member = m_rValue.GetChildAtIndex(0); + const CMICmnLLDBUtilSBValue utilValue(member); + return utilValue.IsCharType(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the flag stating whether pointee object of *this object is -// a char type or some other type. Returns false if there are not children. Char +// a char type or some other type. Returns false if there are not +// children. Char // type can be signed or unsigned. // Type: Method. // Args: None. // Return: bool - True = Yes is a char type, false = some other type. // Throws: None. //-- -bool -CMICmnLLDBUtilSBValue::IsPointeeCharType() const -{ - const MIuint nChildren = m_rValue.GetNumChildren(); +bool CMICmnLLDBUtilSBValue::IsPointeeCharType() const { + const MIuint nChildren = m_rValue.GetNumChildren(); - // Is it a basic type - if (nChildren == 0) - return false; + // Is it a basic type + if (nChildren == 0) + return false; - const lldb::BasicType eType = m_rValue.GetType().GetPointeeType().GetBasicType(); - return IsCharBasicType(eType); + const lldb::BasicType eType = + m_rValue.GetType().GetPointeeType().GetBasicType(); + return IsCharBasicType(eType); } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the flag stating whether this value object is a integer type or some -// other type. Char type can be signed or unsigned and short or long/very long. +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the flag stating whether this value object is a integer +// type or some +// other type. Char type can be signed or unsigned and short or +// long/very long. // Type: Method. // Args: None. // Return: bool - True = Yes is a integer type, false = some other type. // Throws: None. //-- -bool -CMICmnLLDBUtilSBValue::IsIntegerType() const -{ - const lldb::BasicType eType = m_rValue.GetType().GetBasicType(); - return ((eType == lldb::eBasicTypeShort) || (eType == lldb::eBasicTypeUnsignedShort) || - (eType == lldb::eBasicTypeInt) || (eType == lldb::eBasicTypeUnsignedInt) || - (eType == lldb::eBasicTypeLong) || (eType == lldb::eBasicTypeUnsignedLong) || - (eType == lldb::eBasicTypeLongLong) || (eType == lldb::eBasicTypeUnsignedLongLong) || - (eType == lldb::eBasicTypeInt128) || (eType == lldb::eBasicTypeUnsignedInt128)); +bool CMICmnLLDBUtilSBValue::IsIntegerType() const { + const lldb::BasicType eType = m_rValue.GetType().GetBasicType(); + return ((eType == lldb::eBasicTypeShort) || + (eType == lldb::eBasicTypeUnsignedShort) || + (eType == lldb::eBasicTypeInt) || + (eType == lldb::eBasicTypeUnsignedInt) || + (eType == lldb::eBasicTypeLong) || + (eType == lldb::eBasicTypeUnsignedLong) || + (eType == lldb::eBasicTypeLongLong) || + (eType == lldb::eBasicTypeUnsignedLongLong) || + (eType == lldb::eBasicTypeInt128) || + (eType == lldb::eBasicTypeUnsignedInt128)); } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the flag stating whether this value object is a pointer type or some +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the flag stating whether this value object is a pointer +// type or some // other type. // Type: Method. // Args: None. // Return: bool - True = Yes is a pointer type, false = some other type. // Throws: None. //-- -bool -CMICmnLLDBUtilSBValue::IsPointerType() const -{ - return m_rValue.GetType().IsPointerType(); +bool CMICmnLLDBUtilSBValue::IsPointerType() const { + return m_rValue.GetType().IsPointerType(); } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the flag stating whether this value object is an array type or some +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the flag stating whether this value object is an array type +// or some // other type. // Type: Method. // Args: None. // Return: bool - True = Yes is an array type, false = some other type. // Throws: None. //-- -bool -CMICmnLLDBUtilSBValue::IsArrayType() const -{ - return m_rValue.GetType().IsArrayType(); +bool CMICmnLLDBUtilSBValue::IsArrayType() const { + return m_rValue.GetType().IsArrayType(); } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the C string data of value object by read the memory where the +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the C string data of value object by read the memory where +// the // variable is held. // Type: Method. // Args: vrValue - (R) LLDB SBValue variable object. @@ -386,131 +392,124 @@ CMICmnLLDBUtilSBValue::IsArrayType() const //-- template <typename charT> CMIUtilString -CMICmnLLDBUtilSBValue::ReadCStringFromHostMemory(lldb::SBValue &vrValue, const MIuint vnMaxLen) const -{ - std::string result; - lldb::addr_t addr = vrValue.GetLoadAddress(), end_addr = addr + vnMaxLen * sizeof(charT); - lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); - lldb::SBError error; - while (addr < end_addr) - { - charT ch; - const MIuint64 nReadBytes = process.ReadMemory(addr, &ch, sizeof(ch), error); - if (error.Fail() || nReadBytes != sizeof(ch)) - return m_pUnkwn; - else if (ch == 0) - break; - result.append(CMIUtilString::ConvertToPrintableASCII(ch, true /* bEscapeQuotes */)); - addr += sizeof(ch); - } - - return result; +CMICmnLLDBUtilSBValue::ReadCStringFromHostMemory(lldb::SBValue &vrValue, + const MIuint vnMaxLen) const { + std::string result; + lldb::addr_t addr = vrValue.GetLoadAddress(), + end_addr = addr + vnMaxLen * sizeof(charT); + lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().GetProcess(); + lldb::SBError error; + while (addr < end_addr) { + charT ch; + const MIuint64 nReadBytes = + process.ReadMemory(addr, &ch, sizeof(ch), error); + if (error.Fail() || nReadBytes != sizeof(ch)) + return m_pUnkwn; + else if (ch == 0) + break; + result.append( + CMIUtilString::ConvertToPrintableASCII(ch, true /* bEscapeQuotes */)); + addr += sizeof(ch); + } + + return result; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the state of the value object's name. // Type: Method. // Args: None. // Return: bool - True = yes name is indeterminate, false = name is valid. // Throws: None. //-- -bool -CMICmnLLDBUtilSBValue::IsNameUnknown() const -{ - const CMIUtilString name(GetName()); - return (name == m_pUnkwn); +bool CMICmnLLDBUtilSBValue::IsNameUnknown() const { + const CMIUtilString name(GetName()); + return (name == m_pUnkwn); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the state of the value object's value data. // Type: Method. // Args: None. // Return: bool - True = yes value is indeterminate, false = value valid. // Throws: None. //-- -bool -CMICmnLLDBUtilSBValue::IsValueUnknown() const -{ - const CMIUtilString value(GetValue()); - return (value == m_pUnkwn); +bool CMICmnLLDBUtilSBValue::IsValueUnknown() const { + const CMIUtilString value(GetValue()); + return (value == m_pUnkwn); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the value object's type name if valid. // Type: Method. // Args: None. // Return: CMIUtilString - The type name or "??". // Throws: None. //-- -CMIUtilString -CMICmnLLDBUtilSBValue::GetTypeName() const -{ - const char *pName = m_bValidSBValue ? m_rValue.GetTypeName() : nullptr; - const CMIUtilString text((pName != nullptr) ? pName : m_pUnkwn); +CMIUtilString CMICmnLLDBUtilSBValue::GetTypeName() const { + const char *pName = m_bValidSBValue ? m_rValue.GetTypeName() : nullptr; + const CMIUtilString text((pName != nullptr) ? pName : m_pUnkwn); - return text; + return text; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the value object's display type name if valid. // Type: Method. // Args: None. // Return: CMIUtilString - The type name or "??". // Throws: None. //-- -CMIUtilString -CMICmnLLDBUtilSBValue::GetTypeNameDisplay() const -{ - const char *pName = m_bValidSBValue ? m_rValue.GetDisplayTypeName() : nullptr; - const CMIUtilString text((pName != nullptr) ? pName : m_pUnkwn); +CMIUtilString CMICmnLLDBUtilSBValue::GetTypeNameDisplay() const { + const char *pName = m_bValidSBValue ? m_rValue.GetDisplayTypeName() : nullptr; + const CMIUtilString text((pName != nullptr) ? pName : m_pUnkwn); - return text; + return text; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve whether the value object's is valid or not. // Type: Method. // Args: None. // Return: bool - True = valid, false = not valid. // Throws: None. //-- -bool -CMICmnLLDBUtilSBValue::IsValid() const -{ - return m_bValidSBValue; -} +bool CMICmnLLDBUtilSBValue::IsValid() const { return m_bValidSBValue; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the value object' has a name. A value object can be valid but still +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the value object' has a name. A value object can be valid +// but still // have no name which suggest it is not a variable. // Type: Method. // Args: None. // Return: bool - True = valid, false = not valid. // Throws: None. //-- -bool -CMICmnLLDBUtilSBValue::HasName() const -{ - bool bHasAName = false; - - const char *pName = m_bValidSBValue ? m_rValue.GetDisplayTypeName() : nullptr; - if (pName != nullptr) - { - bHasAName = (CMIUtilString(pName).length() > 0); - } +bool CMICmnLLDBUtilSBValue::HasName() const { + bool bHasAName = false; + + const char *pName = m_bValidSBValue ? m_rValue.GetDisplayTypeName() : nullptr; + if (pName != nullptr) { + bHasAName = (CMIUtilString(pName).length() > 0); + } - return bHasAName; + return bHasAName; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Determine if the value object' represents a LLDB variable i.e. "$0". // Type: Method. // Args: None. // Return: bool - True = Yes LLDB variable, false = no. // Throws: None. //-- -bool -CMICmnLLDBUtilSBValue::IsLLDBVariable() const -{ - return (GetName().at(0) == '$'); +bool CMICmnLLDBUtilSBValue::IsLLDBVariable() const { + return (GetName().at(0) == '$'); } diff --git a/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.h b/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.h index 36264da1e16..13057e007af 100644 --- a/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.h +++ b/lldb/tools/lldb-mi/MICmnLLDBUtilSBValue.h @@ -13,57 +13,68 @@ #include "lldb/API/SBValue.h" // In-house headers: -#include "MIDataTypes.h" #include "MICmnMIValueTuple.h" +#include "MIDataTypes.h" // Declarations: class CMIUtilString; -//++ ============================================================================ +//++ +//============================================================================ // Details: Utility helper class to lldb::SBValue. Using a lldb::SBValue extract // value object information to help form verbose debug information. //-- -class CMICmnLLDBUtilSBValue -{ - // Methods: - public: - /* ctor */ CMICmnLLDBUtilSBValue(const lldb::SBValue &vrValue, const bool vbHandleCharType = false, - const bool vbHandleArrayType = true); - /* dtor */ ~CMICmnLLDBUtilSBValue(); - // - CMIUtilString GetName() const; - CMIUtilString GetValue(const bool vbExpandAggregates = false) const; - CMIUtilString GetTypeName() const; - CMIUtilString GetTypeNameDisplay() const; - bool IsCharType() const; - bool IsFirstChildCharType() const; - bool IsPointeeCharType() const; - bool IsIntegerType() const; - bool IsPointerType() const; - bool IsArrayType() const; - bool IsLLDBVariable() const; - bool IsNameUnknown() const; - bool IsValueUnknown() const; - bool IsValid() const; - bool HasName() const; +class CMICmnLLDBUtilSBValue { + // Methods: +public: + /* ctor */ CMICmnLLDBUtilSBValue(const lldb::SBValue &vrValue, + const bool vbHandleCharType = false, + const bool vbHandleArrayType = true); + /* dtor */ ~CMICmnLLDBUtilSBValue(); + // + CMIUtilString GetName() const; + CMIUtilString GetValue(const bool vbExpandAggregates = false) const; + CMIUtilString GetTypeName() const; + CMIUtilString GetTypeNameDisplay() const; + bool IsCharType() const; + bool IsFirstChildCharType() const; + bool IsPointeeCharType() const; + bool IsIntegerType() const; + bool IsPointerType() const; + bool IsArrayType() const; + bool IsLLDBVariable() const; + bool IsNameUnknown() const; + bool IsValueUnknown() const; + bool IsValid() const; + bool HasName() const; - // Methods: - private: - template <typename charT> CMIUtilString ReadCStringFromHostMemory(lldb::SBValue &vrValue, const MIuint vnMaxLen = UINT32_MAX) const; - bool GetSimpleValue(const bool vbHandleArrayType, CMIUtilString &vrValue) const; - bool GetCompositeValue(const bool vbPrintFieldNames, CMICmnMIValueTuple &vwrMiValueTuple, const MIuint vnDepth = 1) const; - CMIUtilString GetValueSummary(bool valueOnly, const CMIUtilString& failVal = CMIUtilString()) const; + // Methods: +private: + template <typename charT> + CMIUtilString + ReadCStringFromHostMemory(lldb::SBValue &vrValue, + const MIuint vnMaxLen = UINT32_MAX) const; + bool GetSimpleValue(const bool vbHandleArrayType, + CMIUtilString &vrValue) const; + bool GetCompositeValue(const bool vbPrintFieldNames, + CMICmnMIValueTuple &vwrMiValueTuple, + const MIuint vnDepth = 1) const; + CMIUtilString + GetValueSummary(bool valueOnly, + const CMIUtilString &failVal = CMIUtilString()) const; - // Statics: - private: - static bool IsCharBasicType(lldb::BasicType eType); + // Statics: +private: + static bool IsCharBasicType(lldb::BasicType eType); - // Attributes: - private: - lldb::SBValue &m_rValue; - const char *m_pUnkwn; - const char *m_pComposite; - bool m_bValidSBValue; // True = SBValue is a valid object, false = not valid. - bool m_bHandleCharType; // True = Yes return text molding to char type, false = just return data. - bool m_bHandleArrayType; // True = Yes return special stub for array type, false = just return data. + // Attributes: +private: + lldb::SBValue &m_rValue; + const char *m_pUnkwn; + const char *m_pComposite; + bool m_bValidSBValue; // True = SBValue is a valid object, false = not valid. + bool m_bHandleCharType; // True = Yes return text molding to char type, false + // = just return data. + bool m_bHandleArrayType; // True = Yes return special stub for array type, + // false = just return data. }; diff --git a/lldb/tools/lldb-mi/MICmnLog.cpp b/lldb/tools/lldb-mi/MICmnLog.cpp index e85ddba316a..8643a8784e3 100644 --- a/lldb/tools/lldb-mi/MICmnLog.cpp +++ b/lldb/tools/lldb-mi/MICmnLog.cpp @@ -10,37 +10,34 @@ // In-house headers: #include "MICmnLog.h" #include "MICmnLogMediumFile.h" -#include "MIDriverMgr.h" #include "MICmnResources.h" +#include "MIDriverMgr.h" #include "MIUtilDateTimeStd.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLog constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmnLog::CMICmnLog() - : m_bEnabled(false) - , m_bInitializingATM(false) -{ - // Do not use this constructor, use Initialize() +CMICmnLog::CMICmnLog() : m_bEnabled(false), m_bInitializingATM(false) { + // Do not use this constructor, use Initialize() } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLog destructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmnLog::~CMICmnLog() -{ - Shutdown(); -} +CMICmnLog::~CMICmnLog() { Shutdown(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Initialize resources for *this Logger. // Type: Method. // Args: None. @@ -48,52 +45,57 @@ CMICmnLog::~CMICmnLog() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLog::Initialize() -{ - m_clientUsageRefCnt++; - - if (m_bInitialized) - return MIstatus::success; - - ClrErrorDescription(); - - // Mediums set inside because explicitly initing in MIDriverMain.cpp causes compile errors with CAtlFile - CMICmnLogMediumFile &rFileLog(CMICmnLogMediumFile::Instance()); - bool bOk = RegisterMedium(rFileLog); - if (bOk) - { - // Set the Log trace file's header - const CMIUtilString &rCR(rFileLog.GetLineReturn()); - CMIUtilDateTimeStd date; - CMIUtilString msg; - msg = CMIUtilString::Format("%s\n", CMIDriverMgr::Instance().GetAppVersion().c_str()); - CMIUtilString logHdr(msg); - msg = CMIUtilString::Format(MIRSRC(IDS_LOG_MSG_CREATION_DATE), date.GetDate().c_str(), date.GetTime().c_str(), rCR.c_str()); - logHdr += msg; - msg = CMIUtilString::Format(MIRSRC(IDS_LOG_MSG_FILE_LOGGER_PATH), rFileLog.GetFileNamePath().c_str(), rCR.c_str()); - logHdr += msg; - - bOk = rFileLog.SetHeaderTxt(logHdr); - - // Note log file medium's status is not available until we write at least once to the file (so just write the title 1st line) - m_bInitializingATM = true; - CMICmnLog::WriteLog("."); - if (!rFileLog.IsOk()) - { - const CMIUtilString msg( - CMIUtilString::Format(MIRSRC(IDS_LOG_ERR_FILE_LOGGER_DISABLED), rFileLog.GetErrorDescription().c_str())); - CMICmnLog::WriteLog(msg); - } - m_bInitializingATM = false; +bool CMICmnLog::Initialize() { + m_clientUsageRefCnt++; + + if (m_bInitialized) + return MIstatus::success; + + ClrErrorDescription(); + + // Mediums set inside because explicitly initing in MIDriverMain.cpp causes + // compile errors with CAtlFile + CMICmnLogMediumFile &rFileLog(CMICmnLogMediumFile::Instance()); + bool bOk = RegisterMedium(rFileLog); + if (bOk) { + // Set the Log trace file's header + const CMIUtilString &rCR(rFileLog.GetLineReturn()); + CMIUtilDateTimeStd date; + CMIUtilString msg; + msg = CMIUtilString::Format( + "%s\n", CMIDriverMgr::Instance().GetAppVersion().c_str()); + CMIUtilString logHdr(msg); + msg = CMIUtilString::Format(MIRSRC(IDS_LOG_MSG_CREATION_DATE), + date.GetDate().c_str(), date.GetTime().c_str(), + rCR.c_str()); + logHdr += msg; + msg = + CMIUtilString::Format(MIRSRC(IDS_LOG_MSG_FILE_LOGGER_PATH), + rFileLog.GetFileNamePath().c_str(), rCR.c_str()); + logHdr += msg; + + bOk = rFileLog.SetHeaderTxt(logHdr); + + // Note log file medium's status is not available until we write at least + // once to the file (so just write the title 1st line) + m_bInitializingATM = true; + CMICmnLog::WriteLog("."); + if (!rFileLog.IsOk()) { + const CMIUtilString msg( + CMIUtilString::Format(MIRSRC(IDS_LOG_ERR_FILE_LOGGER_DISABLED), + rFileLog.GetErrorDescription().c_str())); + CMICmnLog::WriteLog(msg); } + m_bInitializingATM = false; + } - m_bInitialized = bOk; + m_bInitialized = bOk; - return bOk; + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release resources for *this Logger. // Type: Method. // Args: None. @@ -101,55 +103,52 @@ CMICmnLog::Initialize() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLog::Shutdown() -{ - if (--m_clientUsageRefCnt > 0) - return MIstatus::success; +bool CMICmnLog::Shutdown() { + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - if (!m_bInitialized) - return MIstatus::success; + if (!m_bInitialized) + return MIstatus::success; - ClrErrorDescription(); + ClrErrorDescription(); - const bool bOk = UnregisterMediumAll(); + const bool bOk = UnregisterMediumAll(); - m_bInitialized = bOk; + m_bInitialized = bOk; - return bOk; + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Enabled or disable *this Logger from writing any data to registered clients. +//++ +//------------------------------------------------------------------------------------ +// Details: Enabled or disable *this Logger from writing any data to registered +// clients. // Type: Method. // Args: vbYes - (R) True = Logger enabled, false = disabled. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLog::SetEnabled(const bool vbYes) -{ - m_bEnabled = vbYes; +bool CMICmnLog::SetEnabled(const bool vbYes) { + m_bEnabled = vbYes; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve state whether *this Logger is enabled writing data to registered clients. +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve state whether *this Logger is enabled writing data to +// registered clients. // Type: Method. // Args: None. // Return: True = Logger enable. // False = disabled. // Throws: None. //-- -bool -CMICmnLog::GetEnabled() const -{ - return m_bEnabled; -} +bool CMICmnLog::GetEnabled() const { return m_bEnabled; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Unregister all the Mediums registered with *this Logger. // Type: Method. // Args: None. @@ -157,22 +156,20 @@ CMICmnLog::GetEnabled() const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLog::UnregisterMediumAll() -{ - MapMediumToName_t::const_iterator it = m_mapMediumToName.begin(); - for (; it != m_mapMediumToName.end(); it++) - { - IMedium *pMedium = (*it).first; - pMedium->Shutdown(); - } +bool CMICmnLog::UnregisterMediumAll() { + MapMediumToName_t::const_iterator it = m_mapMediumToName.begin(); + for (; it != m_mapMediumToName.end(); it++) { + IMedium *pMedium = (*it).first; + pMedium->Shutdown(); + } - m_mapMediumToName.clear(); + m_mapMediumToName.clear(); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Register a Medium with *this Logger. // Type: Method. // Args: vrMedium - (R) The medium to register. @@ -180,28 +177,28 @@ CMICmnLog::UnregisterMediumAll() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLog::RegisterMedium(const IMedium &vrMedium) -{ - if (HaveMediumAlready(vrMedium)) - return MIstatus::success; - - IMedium *pMedium = const_cast<IMedium *>(&vrMedium); - if (!pMedium->Initialize()) - { - const CMIUtilString &rStrMedName(pMedium->GetName()); - const CMIUtilString &rStrMedErr(pMedium->GetError()); - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LOG_MEDIUM_ERR_INIT), rStrMedName.c_str(), rStrMedErr.c_str())); - return MIstatus::failure; - } +bool CMICmnLog::RegisterMedium(const IMedium &vrMedium) { + if (HaveMediumAlready(vrMedium)) + return MIstatus::success; - MapPairMediumToName_t pr(pMedium, pMedium->GetName()); - m_mapMediumToName.insert(pr); + IMedium *pMedium = const_cast<IMedium *>(&vrMedium); + if (!pMedium->Initialize()) { + const CMIUtilString &rStrMedName(pMedium->GetName()); + const CMIUtilString &rStrMedErr(pMedium->GetError()); + SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LOG_MEDIUM_ERR_INIT), + rStrMedName.c_str(), + rStrMedErr.c_str())); + return MIstatus::failure; + } - return MIstatus::success; + MapPairMediumToName_t pr(pMedium, pMedium->GetName()); + m_mapMediumToName.insert(pr); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Query the Logger to see if a medium is already registered. // Type: Method. // Args: vrMedium - (R) The medium to query. @@ -209,18 +206,17 @@ CMICmnLog::RegisterMedium(const IMedium &vrMedium) // False - not registered. // Throws: None. //-- -bool -CMICmnLog::HaveMediumAlready(const IMedium &vrMedium) const -{ - IMedium *pMedium = const_cast<IMedium *>(&vrMedium); - const MapMediumToName_t::const_iterator it = m_mapMediumToName.find(pMedium); - if (it != m_mapMediumToName.end()) - return true; - - return false; +bool CMICmnLog::HaveMediumAlready(const IMedium &vrMedium) const { + IMedium *pMedium = const_cast<IMedium *>(&vrMedium); + const MapMediumToName_t::const_iterator it = m_mapMediumToName.find(pMedium); + if (it != m_mapMediumToName.end()) + return true; + + return false; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Unregister a medium from the Logger. // Type: Method. // Args: vrMedium - (R) The medium to unregister. @@ -228,22 +224,26 @@ CMICmnLog::HaveMediumAlready(const IMedium &vrMedium) const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLog::UnregisterMedium(const IMedium &vrMedium) -{ - IMedium *pMedium = const_cast<IMedium *>(&vrMedium); - m_mapMediumToName.erase(pMedium); +bool CMICmnLog::UnregisterMedium(const IMedium &vrMedium) { + IMedium *pMedium = const_cast<IMedium *>(&vrMedium); + m_mapMediumToName.erase(pMedium); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: The callee client uses this function to write to the Logger. The data to be -// written is given out to all the mediums registered. The verbosity type parameter -// indicates to the medium(s) the type of data or message given to it. The medium has -// modes of verbosity and depending on the verbosity set determines which writes +//++ +//------------------------------------------------------------------------------------ +// Details: The callee client uses this function to write to the Logger. The +// data to be +// written is given out to all the mediums registered. The verbosity +// type parameter +// indicates to the medium(s) the type of data or message given to it. +// The medium has +// modes of verbosity and depending on the verbosity set determines +// which writes // go in to the logger. -// The logger must be initialized successfully before a write to any registered +// The logger must be initialized successfully before a write to any +// registered // can be carried out. // Type: Method. // Args: vData - (R) The data to write to the logger. @@ -252,58 +252,55 @@ CMICmnLog::UnregisterMedium(const IMedium &vrMedium) // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLog::Write(const CMIUtilString &vData, const ELogVerbosity veType) -{ - if (!m_bInitialized && !m_bInitializingATM) - return MIstatus::success; - if (m_bRecursiveDive) - return MIstatus::success; - if (!m_bEnabled) - return MIstatus::success; - - m_bRecursiveDive = true; - - MIuint cnt = 0; - MIuint cntErr = 0; - { - MapMediumToName_t::const_iterator it = m_mapMediumToName.begin(); - while (it != m_mapMediumToName.end()) - { - IMedium *pMedium = (*it).first; - const CMIUtilString &rNameMedium = (*it).second; - MIunused(rNameMedium); - if (pMedium->Write(vData, veType)) - cnt++; - else - cntErr++; - - // Next - ++it; - } - } - - bool bOk = MIstatus::success; - const MIuint mediumCnt = m_mapMediumToName.size(); - if ((cnt == 0) && (mediumCnt > 0)) - { - SetErrorDescription(MIRSRC(IDS_LOG_MEDIUM_ERR_WRITE_ANY)); - bOk = MIstatus::failure; - } - if (bOk && (cntErr != 0)) - { - SetErrorDescription(MIRSRC(IDS_LOG_MEDIUM_ERR_WRITE_MEDIUMFAIL)); - bOk = MIstatus::failure; - } +bool CMICmnLog::Write(const CMIUtilString &vData, const ELogVerbosity veType) { + if (!m_bInitialized && !m_bInitializingATM) + return MIstatus::success; + if (m_bRecursiveDive) + return MIstatus::success; + if (!m_bEnabled) + return MIstatus::success; - m_bRecursiveDive = false; + m_bRecursiveDive = true; - return bOk; + MIuint cnt = 0; + MIuint cntErr = 0; + { + MapMediumToName_t::const_iterator it = m_mapMediumToName.begin(); + while (it != m_mapMediumToName.end()) { + IMedium *pMedium = (*it).first; + const CMIUtilString &rNameMedium = (*it).second; + MIunused(rNameMedium); + if (pMedium->Write(vData, veType)) + cnt++; + else + cntErr++; + + // Next + ++it; + } + } + + bool bOk = MIstatus::success; + const MIuint mediumCnt = m_mapMediumToName.size(); + if ((cnt == 0) && (mediumCnt > 0)) { + SetErrorDescription(MIRSRC(IDS_LOG_MEDIUM_ERR_WRITE_ANY)); + bOk = MIstatus::failure; + } + if (bOk && (cntErr != 0)) { + SetErrorDescription(MIRSRC(IDS_LOG_MEDIUM_ERR_WRITE_MEDIUMFAIL)); + bOk = MIstatus::failure; + } + + m_bRecursiveDive = false; + + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Short cut function call to write only to the Log file. -// The logger must be initialized successfully before a write to any registered +// The logger must be initialized successfully before a write to any +// registered // can be carried out. // Type: Static. // Args: vData - (R) The data to write to the logger. @@ -311,47 +308,42 @@ CMICmnLog::Write(const CMIUtilString &vData, const ELogVerbosity veType) // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLog::WriteLog(const CMIUtilString &vData) -{ - return CMICmnLog::Instance().Write(vData, CMICmnLog::eLogVerbosity_Log); +bool CMICmnLog::WriteLog(const CMIUtilString &vData) { + return CMICmnLog::Instance().Write(vData, CMICmnLog::eLogVerbosity_Log); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve a string detailing the last error. // Type: Method. // Args: None, // Return: CMIUtilString. // Throws: None. //-- -const CMIUtilString & -CMICmnLog::GetErrorDescription() const -{ - return m_strMILastErrorDescription; +const CMIUtilString &CMICmnLog::GetErrorDescription() const { + return m_strMILastErrorDescription; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Set the internal description of the last error. // Type: Method. // Args: (R) String containing a description of the last error. // Return: None. // Throws: None. //-- -void -CMICmnLog::SetErrorDescription(const CMIUtilString &vrTxt) const -{ - m_strMILastErrorDescription = vrTxt; +void CMICmnLog::SetErrorDescription(const CMIUtilString &vrTxt) const { + m_strMILastErrorDescription = vrTxt; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Clear the last error. // Type: None. // Args: None. // Return: None. // Throws: None. //-- -void -CMICmnLog::ClrErrorDescription() const -{ - m_strMILastErrorDescription = CMIUtilString(""); +void CMICmnLog::ClrErrorDescription() const { + m_strMILastErrorDescription = CMIUtilString(""); } diff --git a/lldb/tools/lldb-mi/MICmnLog.h b/lldb/tools/lldb-mi/MICmnLog.h index a346cf4bd1d..4b19c625a87 100644 --- a/lldb/tools/lldb-mi/MICmnLog.h +++ b/lldb/tools/lldb-mi/MICmnLog.h @@ -13,11 +13,12 @@ #include <map> // In-house headers: -#include "MIUtilString.h" #include "MICmnBase.h" #include "MIUtilSingletonBase.h" +#include "MIUtilString.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code implementation class. Handle application trace // activity logging. Medium objects derived from the Medium abstract /// class are registered with this logger. The function Write is called @@ -27,102 +28,112 @@ // application. // Singleton class. //-- -class CMICmnLog : public MI::ISingleton<CMICmnLog> -{ - friend MI::ISingleton<CMICmnLog>; - - // Enumeration: - public: - //++ - // Description: Data given to the Logger can be of several types. The Logger can be - // set at levels of verbosity. Can determine how data is sent to one or - // mediums. - //-- - enum ELogVerbosity - { // Descriptions of what 'may' occur, depends ultimately on the medium itself. See the medium. - eLogVerbosity_FnTrace = 0x00000004, // Debug function stack call tracing - eLogVerbosity_DbgOp = 0x00000008, // Send a string to the debugger for display (not implemented) - eLogVerbosity_ClientMsg = 0x00000010, // A client using MI can insert messages into the log (not implemented) - eLogVerbosity_Log = 0x00000020 // Send to only the Log file. - }; - - // Class: - public: - //++ - // Description: Register a medium derived from this interface which will be - // called writing log trace data i.e. a file or a console. - // Medium objects registered are not owned by *this logger. - //-- - class IMedium - { - public: - virtual bool Initialize() = 0; - virtual const CMIUtilString &GetName() const = 0; - virtual bool Write(const CMIUtilString &vData, const ELogVerbosity veType) = 0; - virtual const CMIUtilString &GetError() const = 0; - virtual bool Shutdown() = 0; - - // Not part of the interface, ignore - // AD: This virtual destructor seems to hit a bug in the stdlib - // where vector delete is incorrectly called. Workaround is - // to comment this out while I investigate. - /* dtor */ virtual ~IMedium() {} - }; - - // Statics: - public: - static bool WriteLog(const CMIUtilString &vData); - - // Methods: - public: - bool RegisterMedium(const IMedium &vrMedium); - bool UnregisterMedium(const IMedium &vrMedium); - bool Write(const CMIUtilString &vData, const ELogVerbosity veType); - bool SetEnabled(const bool vbYes); - bool GetEnabled() const; - - // MI common object handling - duplicate of CMICmnBase functions, necessary for LINUX build - // Done to stop locking on object construction init circular dependency. - const CMIUtilString &GetErrorDescription() const; - void SetErrorDescription(const CMIUtilString &vrTxt) const; - void ClrErrorDescription() const; - - // Overridden: +class CMICmnLog : public MI::ISingleton<CMICmnLog> { + friend MI::ISingleton<CMICmnLog>; + + // Enumeration: +public: + //++ + // Description: Data given to the Logger can be of several types. The Logger + // can be + // set at levels of verbosity. Can determine how data is sent to + // one or + // mediums. + //-- + enum ELogVerbosity { // Descriptions of what 'may' occur, depends ultimately + // on the medium itself. See the medium. + eLogVerbosity_FnTrace = 0x00000004, // Debug function stack call tracing + eLogVerbosity_DbgOp = 0x00000008, // Send a string to the debugger for + // display (not implemented) + eLogVerbosity_ClientMsg = 0x00000010, // A client using MI can insert + // messages into the log (not + // implemented) + eLogVerbosity_Log = 0x00000020 // Send to only the Log file. + }; + + // Class: +public: + //++ + // Description: Register a medium derived from this interface which will be + // called writing log trace data i.e. a file or a console. + // Medium objects registered are not owned by *this logger. + //-- + class IMedium { public: - // From MI::ISingleton - bool Initialize() override; - bool Shutdown() override; - - // Methods: - private: - /* ctor */ CMICmnLog(); - /* ctor */ CMICmnLog(const CMICmnLog &); - void operator=(const CMICmnLog &); - - // Overridden: - private: - // From CMICmnBase - /* dtor */ ~CMICmnLog() override; - - // Typedef: - private: - typedef std::map<IMedium *, CMIUtilString> MapMediumToName_t; - typedef std::pair<IMedium *, CMIUtilString> MapPairMediumToName_t; - - // Methods: - private: - bool HaveMediumAlready(const IMedium &vrMedium) const; - bool UnregisterMediumAll(); - - // Attributes: - private: - bool m_bRecursiveDive; // True = yes recursive, false = no - MapMediumToName_t m_mapMediumToName; - bool m_bEnabled; // True = Logger enabled for writing to mediums, false = medium not written to - bool m_bInitializingATM; // True = Yes in process of initing *this logger, false = not initing - // - // MI common object handling - duplicate of CMICmnBase functions, necessary for LINUX build - bool m_bInitialized; // True = yes successfully initialized, false = no yet or failed - mutable CMIUtilString m_strMILastErrorDescription; - MIint m_clientUsageRefCnt; // Count of client using *this object so not shutdown() object to early + virtual bool Initialize() = 0; + virtual const CMIUtilString &GetName() const = 0; + virtual bool Write(const CMIUtilString &vData, + const ELogVerbosity veType) = 0; + virtual const CMIUtilString &GetError() const = 0; + virtual bool Shutdown() = 0; + + // Not part of the interface, ignore + // AD: This virtual destructor seems to hit a bug in the stdlib + // where vector delete is incorrectly called. Workaround is + // to comment this out while I investigate. + /* dtor */ virtual ~IMedium() {} + }; + + // Statics: +public: + static bool WriteLog(const CMIUtilString &vData); + + // Methods: +public: + bool RegisterMedium(const IMedium &vrMedium); + bool UnregisterMedium(const IMedium &vrMedium); + bool Write(const CMIUtilString &vData, const ELogVerbosity veType); + bool SetEnabled(const bool vbYes); + bool GetEnabled() const; + + // MI common object handling - duplicate of CMICmnBase functions, necessary + // for LINUX build + // Done to stop locking on object construction init circular dependency. + const CMIUtilString &GetErrorDescription() const; + void SetErrorDescription(const CMIUtilString &vrTxt) const; + void ClrErrorDescription() const; + + // Overridden: +public: + // From MI::ISingleton + bool Initialize() override; + bool Shutdown() override; + + // Methods: +private: + /* ctor */ CMICmnLog(); + /* ctor */ CMICmnLog(const CMICmnLog &); + void operator=(const CMICmnLog &); + + // Overridden: +private: + // From CMICmnBase + /* dtor */ ~CMICmnLog() override; + + // Typedef: +private: + typedef std::map<IMedium *, CMIUtilString> MapMediumToName_t; + typedef std::pair<IMedium *, CMIUtilString> MapPairMediumToName_t; + + // Methods: +private: + bool HaveMediumAlready(const IMedium &vrMedium) const; + bool UnregisterMediumAll(); + + // Attributes: +private: + bool m_bRecursiveDive; // True = yes recursive, false = no + MapMediumToName_t m_mapMediumToName; + bool m_bEnabled; // True = Logger enabled for writing to mediums, false = + // medium not written to + bool m_bInitializingATM; // True = Yes in process of initing *this logger, + // false = not initing + // + // MI common object handling - duplicate of CMICmnBase functions, necessary + // for LINUX build + bool m_bInitialized; // True = yes successfully initialized, false = no yet or + // failed + mutable CMIUtilString m_strMILastErrorDescription; + MIint m_clientUsageRefCnt; // Count of client using *this object so not + // shutdown() object to early }; diff --git a/lldb/tools/lldb-mi/MICmnLogMediumFile.cpp b/lldb/tools/lldb-mi/MICmnLogMediumFile.cpp index a1dbf53c60a..9f94caf3be7 100644 --- a/lldb/tools/lldb-mi/MICmnLogMediumFile.cpp +++ b/lldb/tools/lldb-mi/MICmnLogMediumFile.cpp @@ -11,7 +11,8 @@ #include "MICmnLogMediumFile.h" #include "MICmnResources.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLogMediumFile constructor. // Type: Method. // Args: None. @@ -19,44 +20,41 @@ // Throws: None. //-- CMICmnLogMediumFile::CMICmnLogMediumFile() - : m_constThisMediumName(MIRSRC(IDS_MEDIUMFILE_NAME)) - , m_constMediumFileNameFormat("lldb-mi-%s.log") - , m_strMediumFileName(MIRSRC(IDS_MEDIUMFILE_ERR_INVALID_PATH)) - , m_strMediumFileDirectory(".") - , m_fileNamePath(MIRSRC(IDS_MEDIUMFILE_ERR_INVALID_PATH)) - , m_eVerbosityType(CMICmnLog::eLogVerbosity_Log) - , m_strDate(CMIUtilDateTimeStd().GetDate()) - , m_fileHeaderTxt(MIRSRC(IDS_MEDIUMFILE_ERR_FILE_HEADER)) -{ -} - -//++ ------------------------------------------------------------------------------------ + : m_constThisMediumName(MIRSRC(IDS_MEDIUMFILE_NAME)), + m_constMediumFileNameFormat("lldb-mi-%s.log"), + m_strMediumFileName(MIRSRC(IDS_MEDIUMFILE_ERR_INVALID_PATH)), + m_strMediumFileDirectory("."), + m_fileNamePath(MIRSRC(IDS_MEDIUMFILE_ERR_INVALID_PATH)), + m_eVerbosityType(CMICmnLog::eLogVerbosity_Log), + m_strDate(CMIUtilDateTimeStd().GetDate()), + m_fileHeaderTxt(MIRSRC(IDS_MEDIUMFILE_ERR_FILE_HEADER)) {} + +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnLogMediumFile destructor. // Type: Overridden. // Args: None. // Return: None. // Throws: None. //-- -CMICmnLogMediumFile::~CMICmnLogMediumFile() -{ -} +CMICmnLogMediumFile::~CMICmnLogMediumFile() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Get the singleton instance of *this class. // Type: Static. // Args: None. // Return: CMICmnLogMediumFile - Reference to *this object. // Throws: None. //-- -CMICmnLogMediumFile & -CMICmnLogMediumFile::Instance() -{ - static CMICmnLogMediumFile instance; +CMICmnLogMediumFile &CMICmnLogMediumFile::Instance() { + static CMICmnLogMediumFile instance; - return instance; + return instance; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Initialize setup *this medium ready for use. // Type: Overridden. // Args: None. @@ -64,49 +62,49 @@ CMICmnLogMediumFile::Instance() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLogMediumFile::Initialize() -{ - m_bInitialized = true; - return FileFormFileNamePath(); +bool CMICmnLogMediumFile::Initialize() { + m_bInitialized = true; + return FileFormFileNamePath(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Unbind detach or release resources used by *this medium. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -bool -CMICmnLogMediumFile::Shutdown() -{ - if (m_bInitialized) - { - m_bInitialized = false; - m_file.Close(); - } - return MIstatus::success; +bool CMICmnLogMediumFile::Shutdown() { + if (m_bInitialized) { + m_bInitialized = false; + m_file.Close(); + } + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the name of *this medium. // Type: Overridden. // Args: None. // Return: CMIUtilString - Text data. // Throws: None. //-- -const CMIUtilString & -CMICmnLogMediumFile::GetName() const -{ - return m_constThisMediumName; +const CMIUtilString &CMICmnLogMediumFile::GetName() const { + return m_constThisMediumName; } -//++ ------------------------------------------------------------------------------------ -// Details: The callee client calls the write function on the Logger. The data to be -// written is given out to all the mediums registered. The verbosity type parameter -// indicates to the medium the type of data or message given to it. The medium has -// modes of verbosity and depending on the verbosity set determines which data is +//++ +//------------------------------------------------------------------------------------ +// Details: The callee client calls the write function on the Logger. The data +// to be +// written is given out to all the mediums registered. The verbosity +// type parameter +// indicates to the medium the type of data or message given to it. The +// medium has +// modes of verbosity and depending on the verbosity set determines +// which data is // sent to the medium's output. // Type: Method. // Args: vData - (R) The data to write to the logger. @@ -115,43 +113,39 @@ CMICmnLogMediumFile::GetName() const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLogMediumFile::Write(const CMIUtilString &vData, const CMICmnLog::ELogVerbosity veType) -{ - if (m_bInitialized && m_file.IsOk()) - { - const bool bDoWrite = (m_eVerbosityType & veType); - if (bDoWrite) - { - bool bNewCreated = false; - bool bOk = m_file.CreateWrite(m_fileNamePath, bNewCreated); - if (bOk) - { - if (bNewCreated) - bOk = FileWriteHeader(); - bOk = bOk && FileWriteEnglish(MassagedData(vData, veType)); - } - return bOk; - } +bool CMICmnLogMediumFile::Write(const CMIUtilString &vData, + const CMICmnLog::ELogVerbosity veType) { + if (m_bInitialized && m_file.IsOk()) { + const bool bDoWrite = (m_eVerbosityType & veType); + if (bDoWrite) { + bool bNewCreated = false; + bool bOk = m_file.CreateWrite(m_fileNamePath, bNewCreated); + if (bOk) { + if (bNewCreated) + bOk = FileWriteHeader(); + bOk = bOk && FileWriteEnglish(MassagedData(vData, veType)); + } + return bOk; } + } - return MIstatus::failure; + return MIstatus::failure; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve *this medium's last error condition. // Type: Method. // Args: None. // Return: CString & - Text description. // Throws: None. //-- -const CMIUtilString & -CMICmnLogMediumFile::GetError() const -{ - return m_strMILastErrorDescription; +const CMIUtilString &CMICmnLogMediumFile::GetError() const { + return m_strMILastErrorDescription; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Set the verbosity mode for this medium. // Type: Method. // Args: veType - (R) Mask value. @@ -159,40 +153,35 @@ CMICmnLogMediumFile::GetError() const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLogMediumFile::SetVerbosity(const MIuint veType) -{ - m_eVerbosityType = veType; - return MIstatus::success; +bool CMICmnLogMediumFile::SetVerbosity(const MIuint veType) { + m_eVerbosityType = veType; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Get the verbosity mode for this medium. // Type: Method. // Args: veType - (R) Mask value. // Return: CMICmnLog::ELogVerbosity - Mask value. // Throws: None. //-- -MIuint -CMICmnLogMediumFile::GetVerbosity() const -{ - return m_eVerbosityType; -} +MIuint CMICmnLogMediumFile::GetVerbosity() const { return m_eVerbosityType; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Write data to a file English font. // Type: Method. // Args: vData - (R) The data to write to the logger. // Return: None. // Throws: None. //-- -bool -CMICmnLogMediumFile::FileWriteEnglish(const CMIUtilString &vData) -{ - return m_file.Write(vData); +bool CMICmnLogMediumFile::FileWriteEnglish(const CMIUtilString &vData) { + return m_file.Write(vData); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Determine and form the medium file's directory path and name. // Type: Method. // Args: None. @@ -200,55 +189,59 @@ CMICmnLogMediumFile::FileWriteEnglish(const CMIUtilString &vData) // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLogMediumFile::FileFormFileNamePath() -{ - ClrErrorDescription(); +bool CMICmnLogMediumFile::FileFormFileNamePath() { + ClrErrorDescription(); - m_fileNamePath = MIRSRC(IDS_MEDIUMFILE_ERR_INVALID_PATH); + m_fileNamePath = MIRSRC(IDS_MEDIUMFILE_ERR_INVALID_PATH); - CMIUtilDateTimeStd date; - m_strMediumFileName = CMIUtilString::Format(m_constMediumFileNameFormat.c_str(), date.GetDateTimeLogFilename().c_str()); + CMIUtilDateTimeStd date; + m_strMediumFileName = + CMIUtilString::Format(m_constMediumFileNameFormat.c_str(), + date.GetDateTimeLogFilename().c_str()); #if defined(_MSC_VER) - m_fileNamePath = CMIUtilString::Format("%s\\%s", m_strMediumFileDirectory.c_str(), m_strMediumFileName.c_str()); + m_fileNamePath = CMIUtilString::Format( + "%s\\%s", m_strMediumFileDirectory.c_str(), m_strMediumFileName.c_str()); #else - m_fileNamePath = CMIUtilString::Format("%s/%s", m_strMediumFileDirectory.c_str(), m_strMediumFileName.c_str()); + m_fileNamePath = CMIUtilString::Format( + "%s/%s", m_strMediumFileDirectory.c_str(), m_strMediumFileName.c_str()); #endif // defined ( _MSC_VER ) - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the medium file's directory path and name. // Type: Method. // Args: None. // Return: CMIUtilString & - File path. // Throws: None. //-- -const CMIUtilString & -CMICmnLogMediumFile::GetFileNamePath() const -{ - return m_fileNamePath; +const CMIUtilString &CMICmnLogMediumFile::GetFileNamePath() const { + return m_fileNamePath; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the medium file's name. // Type: Method. // Args: None. // Return: CMIUtilString & - File name. // Throws: None. //-- -const CMIUtilString & -CMICmnLogMediumFile::GetFileName() const -{ - return m_strMediumFileName; +const CMIUtilString &CMICmnLogMediumFile::GetFileName() const { + return m_strMediumFileName; } -//++ ------------------------------------------------------------------------------------ -// Details: Massage the data to behave correct when submitted to file. Insert extra log -// specific text. The veType is there to allow in the future to parse the log and -// filter in out specific types of message to make viewing the log more manageable. +//++ +//------------------------------------------------------------------------------------ +// Details: Massage the data to behave correct when submitted to file. Insert +// extra log +// specific text. The veType is there to allow in the future to parse +// the log and +// filter in out specific types of message to make viewing the log more +// manageable. // Type: Method. // Args: vData - (R) Raw data. // veType - (R) Message type. @@ -256,58 +249,58 @@ CMICmnLogMediumFile::GetFileName() const // Throws: None. //-- CMIUtilString -CMICmnLogMediumFile::MassagedData(const CMIUtilString &vData, const CMICmnLog::ELogVerbosity veType) -{ - const CMIUtilString strCr("\n"); - CMIUtilString data; - const char verbosityCode(ConvertLogVerbosityTypeToId(veType)); - const CMIUtilString dt(CMIUtilString::Format("%s %s", m_strDate.c_str(), m_dateTime.GetTime().c_str())); - - data = CMIUtilString::Format("%c,%s,%s", verbosityCode, dt.c_str(), vData.c_str()); - data = ConvertCr(data); - - // Look for EOL... - const size_t pos = vData.rfind(strCr); - if (pos == vData.size()) - return data; +CMICmnLogMediumFile::MassagedData(const CMIUtilString &vData, + const CMICmnLog::ELogVerbosity veType) { + const CMIUtilString strCr("\n"); + CMIUtilString data; + const char verbosityCode(ConvertLogVerbosityTypeToId(veType)); + const CMIUtilString dt(CMIUtilString::Format("%s %s", m_strDate.c_str(), + m_dateTime.GetTime().c_str())); + + data = CMIUtilString::Format("%c,%s,%s", verbosityCode, dt.c_str(), + vData.c_str()); + data = ConvertCr(data); + + // Look for EOL... + const size_t pos = vData.rfind(strCr); + if (pos == vData.size()) + return data; - // ... did not have an EOL so add one - data += GetLineReturn(); + // ... did not have an EOL so add one + data += GetLineReturn(); - return data; + return data; } -//++ ------------------------------------------------------------------------------------ -// Details: Convert the Log's verbosity type number into a single char character. +//++ +//------------------------------------------------------------------------------------ +// Details: Convert the Log's verbosity type number into a single char +// character. // Type: Method. // Args: veType - (R) Message type. // Return: wchar_t - A letter. // Throws: None. //-- -char -CMICmnLogMediumFile::ConvertLogVerbosityTypeToId(const CMICmnLog::ELogVerbosity veType) const -{ - char c = 0; - if (veType != 0) - { - MIuint cnt = 0; - MIuint number(veType); - while (1 != number) - { - number = number >> 1; - ++cnt; - } - c = 'A' + cnt; - } - else - { - c = '*'; +char CMICmnLogMediumFile::ConvertLogVerbosityTypeToId( + const CMICmnLog::ELogVerbosity veType) const { + char c = 0; + if (veType != 0) { + MIuint cnt = 0; + MIuint number(veType); + while (1 != number) { + number = number >> 1; + ++cnt; } + c = 'A' + cnt; + } else { + c = '*'; + } - return c; + return c; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve state of whether the file medium is ok. // Type: Method. // Args: None. @@ -315,13 +308,10 @@ CMICmnLogMediumFile::ConvertLogVerbosityTypeToId(const CMICmnLog::ELogVerbosity // False - file has a problem. // Throws: None. //-- -bool -CMICmnLogMediumFile::IsOk() const -{ - return m_file.IsOk(); -} +bool CMICmnLogMediumFile::IsOk() const { return m_file.IsOk(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Status on the file log medium existing already. // Type: Method. // Args: None. @@ -329,13 +319,12 @@ CMICmnLogMediumFile::IsOk() const // False - Not found. // Throws: None. //-- -bool -CMICmnLogMediumFile::IsFileExist() const -{ - return m_file.IsFileExist(GetFileNamePath()); +bool CMICmnLogMediumFile::IsFileExist() const { + return m_file.IsFileExist(GetFileNamePath()); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Write the header text the logger file. // Type: Method. // Args: vText - (R) Text. @@ -343,72 +332,69 @@ CMICmnLogMediumFile::IsFileExist() const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLogMediumFile::FileWriteHeader() -{ - return FileWriteEnglish(ConvertCr(m_fileHeaderTxt)); +bool CMICmnLogMediumFile::FileWriteHeader() { + return FileWriteEnglish(ConvertCr(m_fileHeaderTxt)); } -//++ ------------------------------------------------------------------------------------ -// Details: Convert any carriage line returns to be compatible with the platform the +//++ +//------------------------------------------------------------------------------------ +// Details: Convert any carriage line returns to be compatible with the platform +// the // Log file is being written to. // Type: Method. // Args: vData - (R) Text data. // Return: CMIUtilString - Converted string data. // Throws: None. //-- -CMIUtilString -CMICmnLogMediumFile::ConvertCr(const CMIUtilString &vData) const -{ - const CMIUtilString strCr("\n"); - const CMIUtilString &rCrCmpat(GetLineReturn()); - - if (strCr == rCrCmpat) - return vData; - - const size_t nSizeCmpat(rCrCmpat.size()); - const size_t nSize(strCr.size()); - CMIUtilString strConv(vData); - size_t pos = strConv.find(strCr); - while (pos != CMIUtilString::npos) - { - strConv.replace(pos, nSize, rCrCmpat); - pos = strConv.find(strCr, pos + nSizeCmpat); - } - - return strConv; +CMIUtilString CMICmnLogMediumFile::ConvertCr(const CMIUtilString &vData) const { + const CMIUtilString strCr("\n"); + const CMIUtilString &rCrCmpat(GetLineReturn()); + + if (strCr == rCrCmpat) + return vData; + + const size_t nSizeCmpat(rCrCmpat.size()); + const size_t nSize(strCr.size()); + CMIUtilString strConv(vData); + size_t pos = strConv.find(strCr); + while (pos != CMIUtilString::npos) { + strConv.replace(pos, nSize, rCrCmpat); + pos = strConv.find(strCr, pos + nSizeCmpat); + } + + return strConv; } -//++ ------------------------------------------------------------------------------------ -// Details: Set the header text that is written to the logger file at the beginning. +//++ +//------------------------------------------------------------------------------------ +// Details: Set the header text that is written to the logger file at the +// beginning. // Type: Method. // Args: vText - (R) Text. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLogMediumFile::SetHeaderTxt(const CMIUtilString &vText) -{ - m_fileHeaderTxt = vText; +bool CMICmnLogMediumFile::SetHeaderTxt(const CMIUtilString &vText) { + m_fileHeaderTxt = vText; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the file current carriage line return characters used. // Type: Method. // Args: None. // Return: CMIUtilString & - Text. // Throws: None. //-- -const CMIUtilString & -CMICmnLogMediumFile::GetLineReturn() const -{ - return m_file.GetLineReturn(); +const CMIUtilString &CMICmnLogMediumFile::GetLineReturn() const { + return m_file.GetLineReturn(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Set the directory to place the log file. // Type: Method. // Args: vPath - (R) Path to log. @@ -416,10 +402,8 @@ CMICmnLogMediumFile::GetLineReturn() const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnLogMediumFile::SetDirectory(const CMIUtilString &vPath) -{ - m_strMediumFileDirectory = vPath; +bool CMICmnLogMediumFile::SetDirectory(const CMIUtilString &vPath) { + m_strMediumFileDirectory = vPath; - return FileFormFileNamePath(); + return FileFormFileNamePath(); } diff --git a/lldb/tools/lldb-mi/MICmnLogMediumFile.h b/lldb/tools/lldb-mi/MICmnLogMediumFile.h index 249da71a42c..0a734a1c77d 100644 --- a/lldb/tools/lldb-mi/MICmnLogMediumFile.h +++ b/lldb/tools/lldb-mi/MICmnLogMediumFile.h @@ -10,73 +10,76 @@ #pragma once // In-house headers: -#include "MIUtilFileStd.h" -#include "MIUtilString.h" #include "MICmnBase.h" #include "MICmnLog.h" #include "MIUtilDateTimeStd.h" +#include "MIUtilFileStd.h" +#include "MIUtilString.h" -//++ ============================================================================ -// Details: MI common code implementation class. Logs application fn trace/message/ +//++ +//============================================================================ +// Details: MI common code implementation class. Logs application fn +// trace/message/ // error messages to a file. Used as part of the CMICmnLog Logger // system. When instantiated *this object is register with the Logger // which the Logger when given data to write to registered medium comes // *this medium. // Singleton class. //-- -class CMICmnLogMediumFile : public CMICmnBase, public CMICmnLog::IMedium -{ - // Statics: - public: - static CMICmnLogMediumFile &Instance(); +class CMICmnLogMediumFile : public CMICmnBase, public CMICmnLog::IMedium { + // Statics: +public: + static CMICmnLogMediumFile &Instance(); - // Methods: - public: - bool SetHeaderTxt(const CMIUtilString &vText); - bool SetVerbosity(const MIuint veType); - MIuint GetVerbosity() const; - const CMIUtilString &GetFileName() const; - const CMIUtilString &GetFileNamePath() const; - bool IsOk() const; - bool IsFileExist() const; - const CMIUtilString &GetLineReturn() const; - bool SetDirectory(const CMIUtilString &vPath); + // Methods: +public: + bool SetHeaderTxt(const CMIUtilString &vText); + bool SetVerbosity(const MIuint veType); + MIuint GetVerbosity() const; + const CMIUtilString &GetFileName() const; + const CMIUtilString &GetFileNamePath() const; + bool IsOk() const; + bool IsFileExist() const; + const CMIUtilString &GetLineReturn() const; + bool SetDirectory(const CMIUtilString &vPath); - // Overridden: - public: - // From CMICmnBase - /* dtor */ ~CMICmnLogMediumFile() override; - // From CMICmnLog::IMedium - bool Initialize() override; - const CMIUtilString &GetName() const override; - bool Write(const CMIUtilString &vData, const CMICmnLog::ELogVerbosity veType) override; - const CMIUtilString &GetError() const override; - bool Shutdown() override; + // Overridden: +public: + // From CMICmnBase + /* dtor */ ~CMICmnLogMediumFile() override; + // From CMICmnLog::IMedium + bool Initialize() override; + const CMIUtilString &GetName() const override; + bool Write(const CMIUtilString &vData, + const CMICmnLog::ELogVerbosity veType) override; + const CMIUtilString &GetError() const override; + bool Shutdown() override; - // Methods: - private: - /* ctor */ CMICmnLogMediumFile(); - /* ctor */ CMICmnLogMediumFile(const CMICmnLogMediumFile &); - void operator=(const CMICmnLogMediumFile &); + // Methods: +private: + /* ctor */ CMICmnLogMediumFile(); + /* ctor */ CMICmnLogMediumFile(const CMICmnLogMediumFile &); + void operator=(const CMICmnLogMediumFile &); - bool FileWriteEnglish(const CMIUtilString &vData); - bool FileFormFileNamePath(); - CMIUtilString MassagedData(const CMIUtilString &vData, const CMICmnLog::ELogVerbosity veType); - bool FileWriteHeader(); - char ConvertLogVerbosityTypeToId(const CMICmnLog::ELogVerbosity veType) const; - CMIUtilString ConvertCr(const CMIUtilString &vData) const; + bool FileWriteEnglish(const CMIUtilString &vData); + bool FileFormFileNamePath(); + CMIUtilString MassagedData(const CMIUtilString &vData, + const CMICmnLog::ELogVerbosity veType); + bool FileWriteHeader(); + char ConvertLogVerbosityTypeToId(const CMICmnLog::ELogVerbosity veType) const; + CMIUtilString ConvertCr(const CMIUtilString &vData) const; - // Attributes: - private: - const CMIUtilString m_constThisMediumName; - const CMIUtilString m_constMediumFileNameFormat; - // - CMIUtilString m_strMediumFileName; - CMIUtilString m_strMediumFileDirectory; - CMIUtilString m_fileNamePath; - MIuint m_eVerbosityType; - CMIUtilString m_strDate; - CMIUtilString m_fileHeaderTxt; - CMIUtilFileStd m_file; - CMIUtilDateTimeStd m_dateTime; + // Attributes: +private: + const CMIUtilString m_constThisMediumName; + const CMIUtilString m_constMediumFileNameFormat; + // + CMIUtilString m_strMediumFileName; + CMIUtilString m_strMediumFileDirectory; + CMIUtilString m_fileNamePath; + MIuint m_eVerbosityType; + CMIUtilString m_strDate; + CMIUtilString m_fileHeaderTxt; + CMIUtilFileStd m_file; + CMIUtilDateTimeStd m_dateTime; }; diff --git a/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp b/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp index e633e5a61fa..66a44e6084b 100644 --- a/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp +++ b/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.cpp @@ -16,99 +16,98 @@ // Instantiations: static const char * -MapOutOfBandToText(CMICmnMIOutOfBandRecord::OutOfBand_e veType) -{ - switch (veType) - { - case CMICmnMIOutOfBandRecord::eOutOfBand_Running: - return "running"; - case CMICmnMIOutOfBandRecord::eOutOfBand_Stopped: - return "stopped"; - case CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated: - return "breakpoint-created"; - case CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified: - return "breakpoint-modified"; - case CMICmnMIOutOfBandRecord::eOutOfBand_Thread: - return ""; // "" Meant to be empty - case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupAdded: - return "thread-group-added"; - case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited: - return "thread-group-exited"; - case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupRemoved: - return "thread-group-removed"; - case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted: - return "thread-group-started"; - case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated: - return "thread-created"; - case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited: - return "thread-exited"; - case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected: - return "thread-selected"; - case CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleLoaded: - return "library-loaded"; - case CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleUnloaded: - return "library-unloaded"; - case CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput: - return ""; - } - assert(false && "unknown CMICmnMIOutofBandRecord::OutOfBand_e"); - return NULL; +MapOutOfBandToText(CMICmnMIOutOfBandRecord::OutOfBand_e veType) { + switch (veType) { + case CMICmnMIOutOfBandRecord::eOutOfBand_Running: + return "running"; + case CMICmnMIOutOfBandRecord::eOutOfBand_Stopped: + return "stopped"; + case CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated: + return "breakpoint-created"; + case CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified: + return "breakpoint-modified"; + case CMICmnMIOutOfBandRecord::eOutOfBand_Thread: + return ""; // "" Meant to be empty + case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupAdded: + return "thread-group-added"; + case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited: + return "thread-group-exited"; + case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupRemoved: + return "thread-group-removed"; + case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted: + return "thread-group-started"; + case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated: + return "thread-created"; + case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited: + return "thread-exited"; + case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected: + return "thread-selected"; + case CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleLoaded: + return "library-loaded"; + case CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleUnloaded: + return "library-unloaded"; + case CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput: + return ""; + } + assert(false && "unknown CMICmnMIOutofBandRecord::OutOfBand_e"); + return NULL; } static const char * -MapOutOfBandToToken(CMICmnMIOutOfBandRecord::OutOfBand_e veType) -{ - switch (veType) - { - case CMICmnMIOutOfBandRecord::eOutOfBand_Running: - return "*"; - case CMICmnMIOutOfBandRecord::eOutOfBand_Stopped: - return "*"; - case CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated: - return "="; - case CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified: - return "="; - case CMICmnMIOutOfBandRecord::eOutOfBand_Thread: - return "@"; - case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupAdded: - return "="; - case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited: - return "="; - case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupRemoved: - return "="; - case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted: - return "="; - case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated: - return "="; - case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited: - return "="; - case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected: - return "="; - case CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleLoaded: - return "="; - case CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleUnloaded: - return "="; - case CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput: - return "@"; - } - assert(false && "unknown CMICmnMIOutofBandRecord::OutOfBand_e"); - return NULL; +MapOutOfBandToToken(CMICmnMIOutOfBandRecord::OutOfBand_e veType) { + switch (veType) { + case CMICmnMIOutOfBandRecord::eOutOfBand_Running: + return "*"; + case CMICmnMIOutOfBandRecord::eOutOfBand_Stopped: + return "*"; + case CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated: + return "="; + case CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified: + return "="; + case CMICmnMIOutOfBandRecord::eOutOfBand_Thread: + return "@"; + case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupAdded: + return "="; + case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited: + return "="; + case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupRemoved: + return "="; + case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted: + return "="; + case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated: + return "="; + case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited: + return "="; + case CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected: + return "="; + case CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleLoaded: + return "="; + case CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleUnloaded: + return "="; + case CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput: + return "@"; + } + assert(false && "unknown CMICmnMIOutofBandRecord::OutOfBand_e"); + return NULL; } -//++ ------------------------------------------------------------------------------------ -// Details: Build the Out-of-band record's mandatory data part. The part up to the first +//++ +//------------------------------------------------------------------------------------ +// Details: Build the Out-of-band record's mandatory data part. The part up to +// the first // (additional) result i.e. async-record ==> "*" type. // Args: veType - (R) A MI Out-of-Band enumeration. // Return: CMIUtilString - The async record text. // Throws: None. //-- static CMIUtilString -BuildAsyncRecord(CMICmnMIOutOfBandRecord::OutOfBand_e veType) -{ - return CMIUtilString::Format("%s%s", MapOutOfBandToToken(veType), MapOutOfBandToText(veType)); +BuildAsyncRecord(CMICmnMIOutOfBandRecord::OutOfBand_e veType) { + return CMIUtilString::Format("%s%s", MapOutOfBandToToken(veType), + MapOutOfBandToText(veType)); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIOutOfBandRecord constructor. // Type: Method. // Args: None. @@ -116,11 +115,10 @@ BuildAsyncRecord(CMICmnMIOutOfBandRecord::OutOfBand_e veType) // Throws: None. //-- CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord() - : m_strAsyncRecord(MIRSRC(IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION)) -{ -} + : m_strAsyncRecord(MIRSRC(IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION)) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIOutOfBandRecord constructor. // Type: Method. // Args: veType - (R) A MI Out-of-Bound enumeration. @@ -128,11 +126,10 @@ CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord() // Throws: None. //-- CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord(OutOfBand_e veType) - : m_strAsyncRecord(BuildAsyncRecord(veType)) -{ -} + : m_strAsyncRecord(BuildAsyncRecord(veType)) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIOutOfBandRecord constructor. // Type: Method. // Args: veType - (R) A MI Out-of-Bound enumeration. @@ -140,13 +137,14 @@ CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord(OutOfBand_e veType) // Return: None. // Throws: None. //-- -CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord(OutOfBand_e veType, const CMICmnMIValueConst &vConst) - : m_strAsyncRecord(BuildAsyncRecord(veType)) -{ - m_strAsyncRecord += vConst.GetString(); +CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord( + OutOfBand_e veType, const CMICmnMIValueConst &vConst) + : m_strAsyncRecord(BuildAsyncRecord(veType)) { + m_strAsyncRecord += vConst.GetString(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIOutOfBandRecord constructor. // Type: Method. // Args: veType - (R) A MI Out-of-Bound enumeration. @@ -154,49 +152,50 @@ CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord(OutOfBand_e veType, const CMICm // Return: None. // Throws: None. //-- -CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord(OutOfBand_e veType, const CMICmnMIValueResult &vResult) - : m_strAsyncRecord(BuildAsyncRecord(veType)) -{ - Add(vResult); +CMICmnMIOutOfBandRecord::CMICmnMIOutOfBandRecord( + OutOfBand_e veType, const CMICmnMIValueResult &vResult) + : m_strAsyncRecord(BuildAsyncRecord(veType)) { + Add(vResult); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIOutOfBandRecord destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmnMIOutOfBandRecord::~CMICmnMIOutOfBandRecord() -{ -} +CMICmnMIOutOfBandRecord::~CMICmnMIOutOfBandRecord() {} -//++ ------------------------------------------------------------------------------------ -// Details: Return the MI Out-of-band record as a string. The string is a direct result of -// work done on *this Out-of-band record so if not enough data is added then it is -// possible to return a malformed Out-of-band record. If nothing has been set or -// added to *this MI Out-of-band record object then text "<Invalid>" will be returned. +//++ +//------------------------------------------------------------------------------------ +// Details: Return the MI Out-of-band record as a string. The string is a direct +// result of +// work done on *this Out-of-band record so if not enough data is added +// then it is +// possible to return a malformed Out-of-band record. If nothing has +// been set or +// added to *this MI Out-of-band record object then text "<Invalid>" +// will be returned. // Type: Method. // Args: None. // Return: CMIUtilString & - MI output text. // Throws: None. //-- -const CMIUtilString & -CMICmnMIOutOfBandRecord::GetString() const -{ - return m_strAsyncRecord; +const CMIUtilString &CMICmnMIOutOfBandRecord::GetString() const { + return m_strAsyncRecord; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Add to *this Out-of-band record additional information. // Type: Method. // Args: vResult - (R) A MI result object. // Return: None. // Throws: None. //-- -void -CMICmnMIOutOfBandRecord::Add(const CMICmnMIValueResult &vResult) -{ - m_strAsyncRecord += ","; - m_strAsyncRecord += vResult.GetString(); +void CMICmnMIOutOfBandRecord::Add(const CMICmnMIValueResult &vResult) { + m_strAsyncRecord += ","; + m_strAsyncRecord += vResult.GetString(); } diff --git a/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.h b/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.h index ad18e6ccac9..f81c114e668 100644 --- a/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.h +++ b/lldb/tools/lldb-mi/MICmnMIOutOfBandRecord.h @@ -11,72 +11,82 @@ // In-house headers: #include "MICmnBase.h" -#include "MIUtilString.h" #include "MICmnMIValueConst.h" #include "MICmnMIValueResult.h" +#include "MIUtilString.h" -//++ ============================================================================ -// Details: MI common code MI Out-of-band (Async) Record class. A class that encapsulates +//++ +//============================================================================ +// Details: MI common code MI Out-of-band (Async) Record class. A class that +// encapsulates // MI result record data and the forming/format of data added to it. -// Out-of-band records are used to notify the GDB/MI client of additional -// changes that have occurred. Those changes can either be a consequence -// of GDB/MI (e.g., a breakpoint modified) or a result of target activity +// Out-of-band records are used to notify the GDB/MI client of +// additional +// changes that have occurred. Those changes can either be a +// consequence +// of GDB/MI (e.g., a breakpoint modified) or a result of target +// activity // (e.g., target stopped). // The syntax is as follows: // "*" type ( "," result )* // type ==> running | stopped // // The Out-of-band record can be retrieve at any time *this object is -// instantiated so unless work is done on *this Out-of-band record then it is -// possible to return a malformed Out-of-band record. If nothing has been set -// or added to *this MI Out-of-band record object then text "<Invalid>" will +// instantiated so unless work is done on *this Out-of-band record then +// it is +// possible to return a malformed Out-of-band record. If nothing has +// been set +// or added to *this MI Out-of-band record object then text "<Invalid>" +// will // be returned. // // More information see: // http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html// //-- -class CMICmnMIOutOfBandRecord : public CMICmnBase -{ - // Enumerations: - public: - //++ - // Details: Enumeration of the type of Out-of-band for *this Out-of-band record - //-- - enum OutOfBand_e - { - eOutOfBand_Running = 0, - eOutOfBand_Stopped, - eOutOfBand_BreakPointCreated, - eOutOfBand_BreakPointModified, - eOutOfBand_Thread, - eOutOfBand_ThreadGroupAdded, - eOutOfBand_ThreadGroupExited, - eOutOfBand_ThreadGroupRemoved, - eOutOfBand_ThreadGroupStarted, - eOutOfBand_ThreadCreated, - eOutOfBand_ThreadExited, - eOutOfBand_ThreadSelected, - eOutOfBand_TargetModuleLoaded, - eOutOfBand_TargetModuleUnloaded, - eOutOfBand_TargetStreamOutput - }; +class CMICmnMIOutOfBandRecord : public CMICmnBase { + // Enumerations: +public: + //++ + // Details: Enumeration of the type of Out-of-band for *this Out-of-band + // record + //-- + enum OutOfBand_e { + eOutOfBand_Running = 0, + eOutOfBand_Stopped, + eOutOfBand_BreakPointCreated, + eOutOfBand_BreakPointModified, + eOutOfBand_Thread, + eOutOfBand_ThreadGroupAdded, + eOutOfBand_ThreadGroupExited, + eOutOfBand_ThreadGroupRemoved, + eOutOfBand_ThreadGroupStarted, + eOutOfBand_ThreadCreated, + eOutOfBand_ThreadExited, + eOutOfBand_ThreadSelected, + eOutOfBand_TargetModuleLoaded, + eOutOfBand_TargetModuleUnloaded, + eOutOfBand_TargetStreamOutput + }; - // Methods: - public: - /* ctor */ CMICmnMIOutOfBandRecord(); - /* ctor */ CMICmnMIOutOfBandRecord(OutOfBand_e veType); - /* ctor */ CMICmnMIOutOfBandRecord(OutOfBand_e veType, const CMICmnMIValueConst &vConst); - /* ctor */ CMICmnMIOutOfBandRecord(OutOfBand_e veType, const CMICmnMIValueResult &vResult); - // - const CMIUtilString &GetString() const; - void Add(const CMICmnMIValueResult &vResult); + // Methods: +public: + /* ctor */ CMICmnMIOutOfBandRecord(); + /* ctor */ CMICmnMIOutOfBandRecord(OutOfBand_e veType); + /* ctor */ CMICmnMIOutOfBandRecord(OutOfBand_e veType, + const CMICmnMIValueConst &vConst); + /* ctor */ CMICmnMIOutOfBandRecord(OutOfBand_e veType, + const CMICmnMIValueResult &vResult); + // + const CMIUtilString &GetString() const; + void Add(const CMICmnMIValueResult &vResult); - // Overridden: - public: - // From CMICmnBase - /* dtor */ ~CMICmnMIOutOfBandRecord() override; + // Overridden: +public: + // From CMICmnBase + /* dtor */ ~CMICmnMIOutOfBandRecord() override; - // Attributes: - private: - CMIUtilString m_strAsyncRecord; // Holds the text version of the result record to date + // Attributes: +private: + CMIUtilString + m_strAsyncRecord; // Holds the text version of the result record to date }; diff --git a/lldb/tools/lldb-mi/MICmnMIResultRecord.cpp b/lldb/tools/lldb-mi/MICmnMIResultRecord.cpp index 0348f894131..ea6fcf8fc59 100644 --- a/lldb/tools/lldb-mi/MICmnMIResultRecord.cpp +++ b/lldb/tools/lldb-mi/MICmnMIResultRecord.cpp @@ -14,48 +14,51 @@ #include "MICmnMIResultRecord.h" #include "MICmnResources.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Map a result class to the corresponding string. // Args: veType - (R) A MI result class enumeration. // Return: const char* - The string corresponding to the result class. // Throws: None. //-- -static const char* -MapResultClassToResultClassText(CMICmnMIResultRecord::ResultClass_e veType) -{ - switch (veType) - { - case CMICmnMIResultRecord::eResultClass_Done: - return "done"; - case CMICmnMIResultRecord::eResultClass_Running: - return "running"; - case CMICmnMIResultRecord::eResultClass_Connected: - return "connected"; - case CMICmnMIResultRecord::eResultClass_Error: - return "error"; - case CMICmnMIResultRecord::eResultClass_Exit: - return "exit"; - } - assert(false && "unknown CMICmnMIResultRecord::ResultClass_e"); - return NULL; +static const char * +MapResultClassToResultClassText(CMICmnMIResultRecord::ResultClass_e veType) { + switch (veType) { + case CMICmnMIResultRecord::eResultClass_Done: + return "done"; + case CMICmnMIResultRecord::eResultClass_Running: + return "running"; + case CMICmnMIResultRecord::eResultClass_Connected: + return "connected"; + case CMICmnMIResultRecord::eResultClass_Error: + return "error"; + case CMICmnMIResultRecord::eResultClass_Exit: + return "exit"; + } + assert(false && "unknown CMICmnMIResultRecord::ResultClass_e"); + return NULL; } -//++ ------------------------------------------------------------------------------------ -// Details: Build the result record's mandatory data part. The part up to the first -// (additional) result i.e. result-record ==> [ token ] "^" result-class. +//++ +//------------------------------------------------------------------------------------ +// Details: Build the result record's mandatory data part. The part up to the +// first +// (additional) result i.e. result-record ==> [ token ] "^" +// result-class. // Args: vrToken - (R) The command's transaction ID or token. // veType - (R) A MI result class enumeration. // Return: CMIUtilString & - MI result record mandatory data // Throws: None. //-- static const CMIUtilString -BuildResultRecord(const CMIUtilString &vrToken, CMICmnMIResultRecord::ResultClass_e veType) -{ - const char *pStrResultRecord = MapResultClassToResultClassText(veType); - return CMIUtilString::Format("%s^%s", vrToken.c_str(), pStrResultRecord); +BuildResultRecord(const CMIUtilString &vrToken, + CMICmnMIResultRecord::ResultClass_e veType) { + const char *pStrResultRecord = MapResultClassToResultClassText(veType); + return CMIUtilString::Format("%s^%s", vrToken.c_str(), pStrResultRecord); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIResultRecord constructor. // Type: Method. // Args: None. @@ -63,11 +66,10 @@ BuildResultRecord(const CMIUtilString &vrToken, CMICmnMIResultRecord::ResultClas // Throws: None. //-- CMICmnMIResultRecord::CMICmnMIResultRecord() - : m_strResultRecord(MIRSRC(IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION)) -{ -} + : m_strResultRecord(MIRSRC(IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION)) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIResultRecord constructor. // Type: Method. // Args: vrToken - (R) The command's transaction ID or token. @@ -75,12 +77,12 @@ CMICmnMIResultRecord::CMICmnMIResultRecord() // Return: None. // Throws: None. //-- -CMICmnMIResultRecord::CMICmnMIResultRecord(const CMIUtilString &vrToken, ResultClass_e veType) - : m_strResultRecord(BuildResultRecord(vrToken, veType)) -{ -} +CMICmnMIResultRecord::CMICmnMIResultRecord(const CMIUtilString &vrToken, + ResultClass_e veType) + : m_strResultRecord(BuildResultRecord(vrToken, veType)) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIResultRecord constructor. // Type: Method. // Args: vrToken - (R) The command's transaction ID or token. @@ -89,49 +91,51 @@ CMICmnMIResultRecord::CMICmnMIResultRecord(const CMIUtilString &vrToken, ResultC // Return: None. // Throws: None. //-- -CMICmnMIResultRecord::CMICmnMIResultRecord(const CMIUtilString &vrToken, ResultClass_e veType, const CMICmnMIValueResult &vValue) - : m_strResultRecord(BuildResultRecord(vrToken, veType)) -{ - Add(vValue); +CMICmnMIResultRecord::CMICmnMIResultRecord(const CMIUtilString &vrToken, + ResultClass_e veType, + const CMICmnMIValueResult &vValue) + : m_strResultRecord(BuildResultRecord(vrToken, veType)) { + Add(vValue); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIResultRecord destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmnMIResultRecord::~CMICmnMIResultRecord() -{ -} +CMICmnMIResultRecord::~CMICmnMIResultRecord() {} -//++ ------------------------------------------------------------------------------------ -// Details: Return the MI result record as a string. The string is a direct result of -// work done on *this result record so if not enough data is added then it is -// possible to return a malformed result record. If nothing has been set or -// added to *this MI result record object then text "<Invalid>" will be returned. +//++ +//------------------------------------------------------------------------------------ +// Details: Return the MI result record as a string. The string is a direct +// result of +// work done on *this result record so if not enough data is added then +// it is +// possible to return a malformed result record. If nothing has been +// set or +// added to *this MI result record object then text "<Invalid>" will be +// returned. // Type: Method. // Args: None. // Return: CMIUtilString & - MI output text. // Throws: None. //-- -const CMIUtilString & -CMICmnMIResultRecord::GetString() const -{ - return m_strResultRecord; +const CMIUtilString &CMICmnMIResultRecord::GetString() const { + return m_strResultRecord; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Add to *this result record additional information. // Type: Method. // Args: vMIValue - (R) A MI value derived object. // Return: None. // Throws: None. //-- -void -CMICmnMIResultRecord::Add(const CMICmnMIValue &vMIValue) -{ - m_strResultRecord += ","; - m_strResultRecord += vMIValue.GetString(); +void CMICmnMIResultRecord::Add(const CMICmnMIValue &vMIValue) { + m_strResultRecord += ","; + m_strResultRecord += vMIValue.GetString(); } diff --git a/lldb/tools/lldb-mi/MICmnMIResultRecord.h b/lldb/tools/lldb-mi/MICmnMIResultRecord.h index 4408324a370..2018ad58e17 100644 --- a/lldb/tools/lldb-mi/MICmnMIResultRecord.h +++ b/lldb/tools/lldb-mi/MICmnMIResultRecord.h @@ -11,10 +11,11 @@ // In-house headers: #include "MICmnBase.h" -#include "MIUtilString.h" #include "MICmnMIValueResult.h" +#include "MIUtilString.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code MI Result Record class. A class that encapsulates // MI result record data and the forming/format of data added to it. // The syntax is as follows: @@ -25,49 +26,55 @@ // result-class ==> "done" | "running" | "connected" | "error" | "exit" // result ==> variable "=" value // value ==> const | tuple | list -// const ==> c-string (7 bit iso c string content) i.e. "all" inc quotes +// const ==> c-string (7 bit iso c string content) i.e. "all" inc +// quotes // tuple ==> "{}" | "{" result ( "," result )* "}" -// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]" +// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," +// result )* "]" // // The result record can be retrieve at any time *this object is -// instantiated so unless work is done on *this result record then it is -// possible to return a malformed result record. If nothing has been set +// instantiated so unless work is done on *this result record then it +// is +// possible to return a malformed result record. If nothing has been +// set // or added to *this MI result record object then text "<Invalid>" will // be returned. // More information see: // http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html //-- -class CMICmnMIResultRecord : public CMICmnBase -{ - // Enumerations: - public: - //++ - // Details: Enumeration of the result class for *this result record - //-- - enum ResultClass_e - { - eResultClass_Done = 0, - eResultClass_Running, - eResultClass_Connected, - eResultClass_Error, - eResultClass_Exit - }; +class CMICmnMIResultRecord : public CMICmnBase { + // Enumerations: +public: + //++ + // Details: Enumeration of the result class for *this result record + //-- + enum ResultClass_e { + eResultClass_Done = 0, + eResultClass_Running, + eResultClass_Connected, + eResultClass_Error, + eResultClass_Exit + }; - // Methods: - public: - /* ctor */ CMICmnMIResultRecord(); - /* ctor */ CMICmnMIResultRecord(const CMIUtilString &vrToken, ResultClass_e veType); - /* ctor */ CMICmnMIResultRecord(const CMIUtilString &vrToken, ResultClass_e veType, const CMICmnMIValueResult &vValue); - // - const CMIUtilString &GetString() const; - void Add(const CMICmnMIValue &vMIValue); + // Methods: +public: + /* ctor */ CMICmnMIResultRecord(); + /* ctor */ CMICmnMIResultRecord(const CMIUtilString &vrToken, + ResultClass_e veType); + /* ctor */ CMICmnMIResultRecord(const CMIUtilString &vrToken, + ResultClass_e veType, + const CMICmnMIValueResult &vValue); + // + const CMIUtilString &GetString() const; + void Add(const CMICmnMIValue &vMIValue); - // Overridden: - public: - // From CMICmnBase - /* dtor */ ~CMICmnMIResultRecord() override; + // Overridden: +public: + // From CMICmnBase + /* dtor */ ~CMICmnMIResultRecord() override; - // Attributes: - private: - CMIUtilString m_strResultRecord; // Holds the text version of the result record to date + // Attributes: +private: + CMIUtilString + m_strResultRecord; // Holds the text version of the result record to date }; diff --git a/lldb/tools/lldb-mi/MICmnMIValue.cpp b/lldb/tools/lldb-mi/MICmnMIValue.cpp index d5895d70099..6907b9e19ad 100644 --- a/lldb/tools/lldb-mi/MICmnMIValue.cpp +++ b/lldb/tools/lldb-mi/MICmnMIValue.cpp @@ -11,7 +11,8 @@ #include "MICmnMIValue.h" #include "MICmnResources.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIValue constructor. // Type: Method. // Args: None. @@ -19,34 +20,28 @@ // Throws: None. //-- CMICmnMIValue::CMICmnMIValue() - : m_strValue(MIRSRC(IDS_WORD_INVALIDBRKTS)) - , m_bJustConstructed(true) -{ -} + : m_strValue(MIRSRC(IDS_WORD_INVALIDBRKTS)), m_bJustConstructed(true) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIValue destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmnMIValue::~CMICmnMIValue() -{ -} +CMICmnMIValue::~CMICmnMIValue() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Return the MI value as a string. The string is a direct result of // work done on *this value so if not enough data is added then it is // possible to return a malformed value. If nothing has been set or -// added to *this MI value object then text "<Invalid>" will be returned. +// added to *this MI value object then text "<Invalid>" will be +// returned. // Type: Method. // Args: None. // Return: CMIUtilString & - MI output text. // Throws: None. //-- -const CMIUtilString & -CMICmnMIValue::GetString() const -{ - return m_strValue; -} +const CMIUtilString &CMICmnMIValue::GetString() const { return m_strValue; } diff --git a/lldb/tools/lldb-mi/MICmnMIValue.h b/lldb/tools/lldb-mi/MICmnMIValue.h index dd11d6a8d11..484a818e7f4 100644 --- a/lldb/tools/lldb-mi/MICmnMIValue.h +++ b/lldb/tools/lldb-mi/MICmnMIValue.h @@ -12,7 +12,8 @@ // In-house headers: #include "MICmnBase.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code MI Result class. Part of the CMICmnMIValueRecord // set of objects. // The syntax is as follows: @@ -25,25 +26,26 @@ // value ==> const | tuple | list // const ==> c-string (7 bit iso c string content) // tuple ==> "{}" | "{" result ( "," result )* "}" -// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]" +// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," +// result )* "]" // More information see: // http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html //-- -class CMICmnMIValue : public CMICmnBase -{ - // Methods: - public: - /* ctor */ CMICmnMIValue(); - // - const CMIUtilString &GetString() const; +class CMICmnMIValue : public CMICmnBase { + // Methods: +public: + /* ctor */ CMICmnMIValue(); + // + const CMIUtilString &GetString() const; - // Overridden: - public: - // From CMICmnBase - /* dtor */ ~CMICmnMIValue() override; + // Overridden: +public: + // From CMICmnBase + /* dtor */ ~CMICmnMIValue() override; - // Attributes: - protected: - CMIUtilString m_strValue; - bool m_bJustConstructed; // True = *this just constructed with no value, false = *this has had value added to it + // Attributes: +protected: + CMIUtilString m_strValue; + bool m_bJustConstructed; // True = *this just constructed with no value, false + // = *this has had value added to it }; diff --git a/lldb/tools/lldb-mi/MICmnMIValueConst.cpp b/lldb/tools/lldb-mi/MICmnMIValueConst.cpp index d8b11e9cb06..6fe16ab8cca 100644 --- a/lldb/tools/lldb-mi/MICmnMIValueConst.cpp +++ b/lldb/tools/lldb-mi/MICmnMIValueConst.cpp @@ -13,7 +13,8 @@ // Instantiations: const CMIUtilString CMICmnMIValueConst::ms_constStrDblQuote("\""); -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIValueConst constructor. // Type: Method. // Args: vString - (R) MI Const c-string value. @@ -21,39 +22,38 @@ const CMIUtilString CMICmnMIValueConst::ms_constStrDblQuote("\""); // Throws: None. //-- CMICmnMIValueConst::CMICmnMIValueConst(const CMIUtilString &vString) - : m_strPartConst(vString) - , m_bNoQuotes(false) -{ - BuildConst(); + : m_strPartConst(vString), m_bNoQuotes(false) { + BuildConst(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIValueConst constructor. // Type: Method. // Args: vString - (R) MI Const c-string value. -// vbNoQuotes - (R) True = return string not surrounded with quotes, false = use quotes. +// vbNoQuotes - (R) True = return string not surrounded with quotes, +// false = use quotes. // Return: None. // Throws: None. //-- -CMICmnMIValueConst::CMICmnMIValueConst(const CMIUtilString &vString, const bool vbNoQuotes) - : m_strPartConst(vString) - , m_bNoQuotes(vbNoQuotes) -{ - BuildConst(); +CMICmnMIValueConst::CMICmnMIValueConst(const CMIUtilString &vString, + const bool vbNoQuotes) + : m_strPartConst(vString), m_bNoQuotes(vbNoQuotes) { + BuildConst(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIValueConst destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmnMIValueConst::~CMICmnMIValueConst() -{ -} +CMICmnMIValueConst::~CMICmnMIValueConst() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Build the Value Const data. // Type: Method. // Args: None. @@ -61,27 +61,22 @@ CMICmnMIValueConst::~CMICmnMIValueConst() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnMIValueConst::BuildConst() -{ - if (m_strPartConst.length() != 0) - { - const CMIUtilString strValue(m_strPartConst.StripCREndOfLine()); - if (m_bNoQuotes) - { - m_strValue = strValue; - } - else - { - const char *pFormat = "%s%s%s"; - m_strValue = CMIUtilString::Format(pFormat, ms_constStrDblQuote.c_str(), strValue.c_str(), ms_constStrDblQuote.c_str()); - } - } - else - { - const char *pFormat = "%s%s"; - m_strValue = CMIUtilString::Format(pFormat, ms_constStrDblQuote.c_str(), ms_constStrDblQuote.c_str()); +bool CMICmnMIValueConst::BuildConst() { + if (m_strPartConst.length() != 0) { + const CMIUtilString strValue(m_strPartConst.StripCREndOfLine()); + if (m_bNoQuotes) { + m_strValue = strValue; + } else { + const char *pFormat = "%s%s%s"; + m_strValue = + CMIUtilString::Format(pFormat, ms_constStrDblQuote.c_str(), + strValue.c_str(), ms_constStrDblQuote.c_str()); } + } else { + const char *pFormat = "%s%s"; + m_strValue = CMIUtilString::Format(pFormat, ms_constStrDblQuote.c_str(), + ms_constStrDblQuote.c_str()); + } - return MIstatus::success; + return MIstatus::success; } diff --git a/lldb/tools/lldb-mi/MICmnMIValueConst.h b/lldb/tools/lldb-mi/MICmnMIValueConst.h index 7f6333e12f4..6b2862d5f25 100644 --- a/lldb/tools/lldb-mi/MICmnMIValueConst.h +++ b/lldb/tools/lldb-mi/MICmnMIValueConst.h @@ -12,7 +12,8 @@ // In-house headers: #include "MICmnMIValue.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code MI Result class. Part of the CMICmnMIValueConstRecord // set of objects. // The syntax is as follows: @@ -25,32 +26,35 @@ // value ==> const | tuple | list // const ==> c-string (7 bit iso c string content) // tuple ==> "{}" | "{" result ( "," result )* "}" -// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]" +// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," +// result )* "]" // More information see: // http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html // -// The text formed in *this Result class is stripped of any '\n' characters. +// The text formed in *this Result class is stripped of any '\n' +// characters. //-- -class CMICmnMIValueConst : public CMICmnMIValue -{ - // Methods: - public: - /* ctor */ CMICmnMIValueConst(const CMIUtilString &vString); - /* ctor */ CMICmnMIValueConst(const CMIUtilString &vString, const bool vbNoQuotes); +class CMICmnMIValueConst : public CMICmnMIValue { + // Methods: +public: + /* ctor */ CMICmnMIValueConst(const CMIUtilString &vString); + /* ctor */ CMICmnMIValueConst(const CMIUtilString &vString, + const bool vbNoQuotes); - // Overridden: - public: - // From CMICmnBase - /* dtor */ ~CMICmnMIValueConst() override; + // Overridden: +public: + // From CMICmnBase + /* dtor */ ~CMICmnMIValueConst() override; - // Methods: - private: - bool BuildConst(); + // Methods: +private: + bool BuildConst(); - // Attributes: - private: - static const CMIUtilString ms_constStrDblQuote; - // - CMIUtilString m_strPartConst; - bool m_bNoQuotes; // True = return string not surrounded with quotes, false = use quotes + // Attributes: +private: + static const CMIUtilString ms_constStrDblQuote; + // + CMIUtilString m_strPartConst; + bool m_bNoQuotes; // True = return string not surrounded with quotes, false = + // use quotes }; diff --git a/lldb/tools/lldb-mi/MICmnMIValueList.cpp b/lldb/tools/lldb-mi/MICmnMIValueList.cpp index e4d3f408422..28d21dbf3fb 100644 --- a/lldb/tools/lldb-mi/MICmnMIValueList.cpp +++ b/lldb/tools/lldb-mi/MICmnMIValueList.cpp @@ -11,19 +11,21 @@ #include "MICmnMIValueList.h" #include "MICmnResources.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIValueList constructor. // Type: Method. -// Args: vbValueTypeList - (R) True = yes value type list, false = result type list. +// Args: vbValueTypeList - (R) True = yes value type list, false = result +// type list. // Return: None. // Throws: None. //-- -CMICmnMIValueList::CMICmnMIValueList(const bool vbValueTypeList) -{ - m_strValue = "[]"; +CMICmnMIValueList::CMICmnMIValueList(const bool vbValueTypeList) { + m_strValue = "[]"; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIValueList constructor. // Construct a results only list. // return MIstatus::failure. @@ -32,14 +34,14 @@ CMICmnMIValueList::CMICmnMIValueList(const bool vbValueTypeList) // Return: None. // Throws: None. //-- -CMICmnMIValueList::CMICmnMIValueList(const CMICmnMIValueResult &vResult) -{ - m_strValue = vResult.GetString(); - BuildList(); - m_bJustConstructed = false; +CMICmnMIValueList::CMICmnMIValueList(const CMICmnMIValueResult &vResult) { + m_strValue = vResult.GetString(); + BuildList(); + m_bJustConstructed = false; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIValueList constructor. // Construct a value only list. // Type: Method. @@ -47,145 +49,140 @@ CMICmnMIValueList::CMICmnMIValueList(const CMICmnMIValueResult &vResult) // Return: None. // Throws: None. //-- -CMICmnMIValueList::CMICmnMIValueList(const CMICmnMIValue &vValue) -{ - m_strValue = vValue.GetString(); - BuildList(); - m_bJustConstructed = false; +CMICmnMIValueList::CMICmnMIValueList(const CMICmnMIValue &vValue) { + m_strValue = vValue.GetString(); + BuildList(); + m_bJustConstructed = false; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIValueList destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmnMIValueList::~CMICmnMIValueList() -{ -} +CMICmnMIValueList::~CMICmnMIValueList() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Build the result value's mandatory data part, one tuple // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -void -CMICmnMIValueList::BuildList() -{ - const char *pFormat = "[%s]"; - m_strValue = CMIUtilString::Format(pFormat, m_strValue.c_str()); +void CMICmnMIValueList::BuildList() { + const char *pFormat = "[%s]"; + m_strValue = CMIUtilString::Format(pFormat, m_strValue.c_str()); } -//++ ------------------------------------------------------------------------------------ -// Details: Add another MI result object to the value list's of list is results. -// Only result objects can be added to a list of result otherwise this function +//++ +//------------------------------------------------------------------------------------ +// Details: Add another MI result object to the value list's of list is +// results. +// Only result objects can be added to a list of result otherwise this +// function // will return MIstatus::failure. // Type: Method. // Args: vResult - (R) The MI result object. // Return: None. // Throws: None. //-- -void -CMICmnMIValueList::Add(const CMICmnMIValueResult &vResult) -{ - BuildList(vResult); +void CMICmnMIValueList::Add(const CMICmnMIValueResult &vResult) { + BuildList(vResult); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Add another MI value object to the value list's of list is values. -// Only values objects can be added to a list of values otherwise this function +// Only values objects can be added to a list of values otherwise this +// function // will return MIstatus::failure. // Type: Method. // Args: vValue - (R) The MI value object. // Return: None. // Throws: None. //-- -void -CMICmnMIValueList::Add(const CMICmnMIValue &vValue) -{ - BuildList(vValue); -} +void CMICmnMIValueList::Add(const CMICmnMIValue &vValue) { BuildList(vValue); } -//++ ------------------------------------------------------------------------------------ -// Details: Add another MI result object to the value list's of list is results. -// Only result objects can be added to a list of result otherwise this function +//++ +//------------------------------------------------------------------------------------ +// Details: Add another MI result object to the value list's of list is +// results. +// Only result objects can be added to a list of result otherwise this +// function // will return MIstatus::failure. // Type: Method. // Args: vResult - (R) The MI result object. // Return: None. // Throws: None. //-- -void -CMICmnMIValueList::BuildList(const CMICmnMIValueResult &vResult) -{ - // Clear out the default "<Invalid>" text - if (m_bJustConstructed) - { - m_bJustConstructed = false; - m_strValue = vResult.GetString(); - BuildList(); - return; - } +void CMICmnMIValueList::BuildList(const CMICmnMIValueResult &vResult) { + // Clear out the default "<Invalid>" text + if (m_bJustConstructed) { + m_bJustConstructed = false; + m_strValue = vResult.GetString(); + BuildList(); + return; + } - const CMIUtilString data(ExtractContentNoBrackets()); - const char *pFormat = "[%s,%s]"; - m_strValue = CMIUtilString::Format(pFormat, data.c_str(), vResult.GetString().c_str()); + const CMIUtilString data(ExtractContentNoBrackets()); + const char *pFormat = "[%s,%s]"; + m_strValue = + CMIUtilString::Format(pFormat, data.c_str(), vResult.GetString().c_str()); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Add another MI value object to the value list's of list is values. -// Only values objects can be added to a list of values otherwise this function +// Only values objects can be added to a list of values otherwise this +// function // will return MIstatus::failure. // Type: Method. // Args: vValue - (R) The MI value object. // Return: None. // Throws: None. //-- -void -CMICmnMIValueList::BuildList(const CMICmnMIValue &vValue) -{ - // Clear out the default "<Invalid>" text - if (m_bJustConstructed) - { - m_bJustConstructed = false; - m_strValue = vValue.GetString(); - BuildList(); - return; - } +void CMICmnMIValueList::BuildList(const CMICmnMIValue &vValue) { + // Clear out the default "<Invalid>" text + if (m_bJustConstructed) { + m_bJustConstructed = false; + m_strValue = vValue.GetString(); + BuildList(); + return; + } - // Remove already present '[' and ']' from the start and end - m_strValue = m_strValue.Trim(); - size_t len = m_strValue.size(); - if ( (len > 1) && (m_strValue[0] == '[') && (m_strValue[len - 1] == ']') ) - m_strValue = m_strValue.substr(1, len - 2); - const char *pFormat = "[%s,%s]"; - m_strValue = CMIUtilString::Format(pFormat, m_strValue.c_str(), vValue.GetString().c_str()); + // Remove already present '[' and ']' from the start and end + m_strValue = m_strValue.Trim(); + size_t len = m_strValue.size(); + if ((len > 1) && (m_strValue[0] == '[') && (m_strValue[len - 1] == ']')) + m_strValue = m_strValue.substr(1, len - 2); + const char *pFormat = "[%s,%s]"; + m_strValue = CMIUtilString::Format(pFormat, m_strValue.c_str(), + vValue.GetString().c_str()); } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the contents of *this value object but without the outer most +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the contents of *this value object but without the outer +// most // brackets. // Type: Method. // Args: None. // Return: CMIUtilString - Data within the object. // Throws: None. //-- -CMIUtilString -CMICmnMIValueList::ExtractContentNoBrackets() const -{ - CMIUtilString data(m_strValue); +CMIUtilString CMICmnMIValueList::ExtractContentNoBrackets() const { + CMIUtilString data(m_strValue); - if (data[0] == '[') - { - data = data.substr(1, data.length() - 1); - } - if (data[data.size() - 1] == ']') - { - data = data.substr(0, data.length() - 1); - } + if (data[0] == '[') { + data = data.substr(1, data.length() - 1); + } + if (data[data.size() - 1] == ']') { + data = data.substr(0, data.length() - 1); + } - return data; + return data; } diff --git a/lldb/tools/lldb-mi/MICmnMIValueList.h b/lldb/tools/lldb-mi/MICmnMIValueList.h index 0796cbe575c..8cf2c38aede 100644 --- a/lldb/tools/lldb-mi/MICmnMIValueList.h +++ b/lldb/tools/lldb-mi/MICmnMIValueList.h @@ -13,7 +13,8 @@ #include "MICmnMIValue.h" #include "MICmnMIValueResult.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code MI Result class. Part of the CMICmnMIValueListRecord // set of objects. // The syntax is as follows: @@ -26,30 +27,30 @@ // value ==> const | tuple | list // const ==> c-string (7 bit iso c string content) // tuple ==> "{}" | "{" result ( "," result )* "}" -// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]" +// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," +// result )* "]" // More information see: // http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html //-- -class CMICmnMIValueList : public CMICmnMIValue -{ - // Methods: - public: - /* ctor */ CMICmnMIValueList(const bool vbValueTypeList); - /* ctor */ CMICmnMIValueList(const CMICmnMIValueResult &vResult); - /* ctor */ CMICmnMIValueList(const CMICmnMIValue &vValue); - // - void Add(const CMICmnMIValueResult &vResult); - void Add(const CMICmnMIValue &vValue); - CMIUtilString ExtractContentNoBrackets() const; +class CMICmnMIValueList : public CMICmnMIValue { + // Methods: +public: + /* ctor */ CMICmnMIValueList(const bool vbValueTypeList); + /* ctor */ CMICmnMIValueList(const CMICmnMIValueResult &vResult); + /* ctor */ CMICmnMIValueList(const CMICmnMIValue &vValue); + // + void Add(const CMICmnMIValueResult &vResult); + void Add(const CMICmnMIValue &vValue); + CMIUtilString ExtractContentNoBrackets() const; - // Overridden: - public: - // From CMICmnBase - /* dtor */ ~CMICmnMIValueList() override; + // Overridden: +public: + // From CMICmnBase + /* dtor */ ~CMICmnMIValueList() override; - // Methods: - private: - void BuildList(); - void BuildList(const CMICmnMIValueResult &vResult); - void BuildList(const CMICmnMIValue &vResult); + // Methods: +private: + void BuildList(); + void BuildList(const CMICmnMIValueResult &vResult); + void BuildList(const CMICmnMIValue &vResult); }; diff --git a/lldb/tools/lldb-mi/MICmnMIValueResult.cpp b/lldb/tools/lldb-mi/MICmnMIValueResult.cpp index d86f724b7cf..efbf0ddbbfb 100644 --- a/lldb/tools/lldb-mi/MICmnMIValueResult.cpp +++ b/lldb/tools/lldb-mi/MICmnMIValueResult.cpp @@ -14,19 +14,18 @@ // Instantiations: const CMIUtilString CMICmnMIValueResult::ms_constStrEqual("="); -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIValueResult constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmnMIValueResult::CMICmnMIValueResult() - : m_bEmptyConstruction(true) -{ -} +CMICmnMIValueResult::CMICmnMIValueResult() : m_bEmptyConstruction(true) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIValueResult constructor. // Type: Method. // Args: vrVariable - (R) MI value's name. @@ -34,59 +33,59 @@ CMICmnMIValueResult::CMICmnMIValueResult() // Return: None. // Throws: None. //-- -CMICmnMIValueResult::CMICmnMIValueResult(const CMIUtilString &vrVariable, const CMICmnMIValue &vrValue) - : m_strPartVariable(vrVariable) - , m_partMIValue(vrValue) - , m_bEmptyConstruction(false) - , m_bUseSpacing(false) -{ - BuildResult(); +CMICmnMIValueResult::CMICmnMIValueResult(const CMIUtilString &vrVariable, + const CMICmnMIValue &vrValue) + : m_strPartVariable(vrVariable), m_partMIValue(vrValue), + m_bEmptyConstruction(false), m_bUseSpacing(false) { + BuildResult(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIValueResult constructor. // Type: Method. // Args: vrVariable - (R) MI value's name. // vrValue - (R) The MI value. -// vbUseSpacing - (R) True = put space separators into the string, false = no spaces used. +// vbUseSpacing - (R) True = put space separators into the string, +// false = no spaces used. // Return: None. // Throws: None. //-- -CMICmnMIValueResult::CMICmnMIValueResult(const CMIUtilString &vrVariable, const CMICmnMIValue &vrValue, const bool vbUseSpacing) - : m_strPartVariable(vrVariable) - , m_partMIValue(vrValue) - , m_bEmptyConstruction(false) - , m_bUseSpacing(vbUseSpacing) -{ - BuildResult(); +CMICmnMIValueResult::CMICmnMIValueResult(const CMIUtilString &vrVariable, + const CMICmnMIValue &vrValue, + const bool vbUseSpacing) + : m_strPartVariable(vrVariable), m_partMIValue(vrValue), + m_bEmptyConstruction(false), m_bUseSpacing(vbUseSpacing) { + BuildResult(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIValueResult destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmnMIValueResult::~CMICmnMIValueResult() -{ -} +CMICmnMIValueResult::~CMICmnMIValueResult() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Build the MI value result string. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -void -CMICmnMIValueResult::BuildResult() -{ - const char *pFormat = m_bUseSpacing ? "%s %s %s" : "%s%s%s"; - m_strValue = CMIUtilString::Format(pFormat, m_strPartVariable.c_str(), ms_constStrEqual.c_str(), m_partMIValue.GetString().c_str()); +void CMICmnMIValueResult::BuildResult() { + const char *pFormat = m_bUseSpacing ? "%s %s %s" : "%s%s%s"; + m_strValue = CMIUtilString::Format(pFormat, m_strPartVariable.c_str(), + ms_constStrEqual.c_str(), + m_partMIValue.GetString().c_str()); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Build the MI value result string. // Type: Method. // Args: vrVariable - (R) MI value's name. @@ -94,15 +93,16 @@ CMICmnMIValueResult::BuildResult() // Return: None. // Throws: None. //-- -void -CMICmnMIValueResult::BuildResult(const CMIUtilString &vVariable, const CMICmnMIValue &vValue) -{ - const char *pFormat = m_bUseSpacing ? "%s, %s %s %s" : "%s,%s%s%s"; - m_strValue = - CMIUtilString::Format(pFormat, m_strValue.c_str(), vVariable.c_str(), ms_constStrEqual.c_str(), vValue.GetString().c_str()); +void CMICmnMIValueResult::BuildResult(const CMIUtilString &vVariable, + const CMICmnMIValue &vValue) { + const char *pFormat = m_bUseSpacing ? "%s, %s %s %s" : "%s,%s%s%s"; + m_strValue = CMIUtilString::Format( + pFormat, m_strValue.c_str(), vVariable.c_str(), ms_constStrEqual.c_str(), + vValue.GetString().c_str()); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Append another MI value object to *this MI value result. // Type: Method. // Args: vrVariable - (R) MI value's name. @@ -111,16 +111,14 @@ CMICmnMIValueResult::BuildResult(const CMIUtilString &vVariable, const CMICmnMIV // MIstatus::failure - Functional failed. // Throws: None. //-- -void -CMICmnMIValueResult::Add(const CMIUtilString &vrVariable, const CMICmnMIValue &vrValue) -{ - if (!m_bEmptyConstruction) - BuildResult(vrVariable, vrValue); - else - { - m_bEmptyConstruction = false; - m_strPartVariable = vrVariable; - m_partMIValue = vrValue; - BuildResult(); - } +void CMICmnMIValueResult::Add(const CMIUtilString &vrVariable, + const CMICmnMIValue &vrValue) { + if (!m_bEmptyConstruction) + BuildResult(vrVariable, vrValue); + else { + m_bEmptyConstruction = false; + m_strPartVariable = vrVariable; + m_partMIValue = vrValue; + BuildResult(); + } } diff --git a/lldb/tools/lldb-mi/MICmnMIValueResult.h b/lldb/tools/lldb-mi/MICmnMIValueResult.h index cd96520b98f..8a285a99d83 100644 --- a/lldb/tools/lldb-mi/MICmnMIValueResult.h +++ b/lldb/tools/lldb-mi/MICmnMIValueResult.h @@ -12,8 +12,10 @@ // In-house headers: #include "MICmnMIValue.h" -//++ ============================================================================ -// Details: MI common code MI Result class. Part of the CMICmnMIValueResultRecord +//++ +//============================================================================ +// Details: MI common code MI Result class. Part of the +// CMICmnMIValueResultRecord // set of objects. // The syntax is as follows: // result-record ==> [ token ] "^" result-class ( "," result )* nl @@ -25,36 +27,41 @@ // value ==> const | tuple | list // const ==> c-string (7 bit iso c string content) // tuple ==> "{}" | "{" result ( "," result )* "}" -// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]" +// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," +// result )* "]" // More information see: // http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html //-- -class CMICmnMIValueResult : public CMICmnMIValue -{ - // Methods: - public: - /* ctor */ CMICmnMIValueResult(); - /* ctor */ CMICmnMIValueResult(const CMIUtilString &vVariable, const CMICmnMIValue &vValue); - /* ctor */ CMICmnMIValueResult(const CMIUtilString &vVariable, const CMICmnMIValue &vValue, const bool vbUseSpacing); - // - void Add(const CMIUtilString &vVariable, const CMICmnMIValue &vValue); +class CMICmnMIValueResult : public CMICmnMIValue { + // Methods: +public: + /* ctor */ CMICmnMIValueResult(); + /* ctor */ CMICmnMIValueResult(const CMIUtilString &vVariable, + const CMICmnMIValue &vValue); + /* ctor */ CMICmnMIValueResult(const CMIUtilString &vVariable, + const CMICmnMIValue &vValue, + const bool vbUseSpacing); + // + void Add(const CMIUtilString &vVariable, const CMICmnMIValue &vValue); - // Overridden: - public: - // From CMICmnBase - /* dtor */ ~CMICmnMIValueResult() override; + // Overridden: +public: + // From CMICmnBase + /* dtor */ ~CMICmnMIValueResult() override; - // Methods: - private: - void BuildResult(); - void BuildResult(const CMIUtilString &vVariable, const CMICmnMIValue &vValue); + // Methods: +private: + void BuildResult(); + void BuildResult(const CMIUtilString &vVariable, const CMICmnMIValue &vValue); - // Attributes: - private: - static const CMIUtilString ms_constStrEqual; - // - CMIUtilString m_strPartVariable; - CMICmnMIValue m_partMIValue; - bool m_bEmptyConstruction; // True = *this object used constructor with no parameters, false = constructor with parameters - bool m_bUseSpacing; // True = put space separators into the string, false = no spaces used + // Attributes: +private: + static const CMIUtilString ms_constStrEqual; + // + CMIUtilString m_strPartVariable; + CMICmnMIValue m_partMIValue; + bool m_bEmptyConstruction; // True = *this object used constructor with no + // parameters, false = constructor with parameters + bool m_bUseSpacing; // True = put space separators into the string, false = no + // spaces used }; diff --git a/lldb/tools/lldb-mi/MICmnMIValueTuple.cpp b/lldb/tools/lldb-mi/MICmnMIValueTuple.cpp index 4ff1d6ce1fa..375ce50416c 100644 --- a/lldb/tools/lldb-mi/MICmnMIValueTuple.cpp +++ b/lldb/tools/lldb-mi/MICmnMIValueTuple.cpp @@ -10,20 +10,20 @@ // In-house headers: #include "MICmnMIValueTuple.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIValueTuple constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmnMIValueTuple::CMICmnMIValueTuple() - : m_bSpaceAfterComma(false) -{ - m_strValue = "{}"; +CMICmnMIValueTuple::CMICmnMIValueTuple() : m_bSpaceAfterComma(false) { + m_strValue = "{}"; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIValueTuple constructor. // Type: Method. // Args: vResult - (R) MI result object. @@ -31,180 +31,176 @@ CMICmnMIValueTuple::CMICmnMIValueTuple() // Throws: None. //-- CMICmnMIValueTuple::CMICmnMIValueTuple(const CMICmnMIValueResult &vResult) - : m_bSpaceAfterComma(false) -{ - m_strValue = vResult.GetString(); - BuildTuple(); - m_bJustConstructed = false; + : m_bSpaceAfterComma(false) { + m_strValue = vResult.GetString(); + BuildTuple(); + m_bJustConstructed = false; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIValueTuple constructor. // Type: Method. // Args: vResult - (R) MI result object. -// vbUseSpacing - (R) True = put space separators into the string, false = no spaces used. +// vbUseSpacing - (R) True = put space separators into the string, +// false = no spaces used. // Return: None. // Throws: None. //-- -CMICmnMIValueTuple::CMICmnMIValueTuple(const CMICmnMIValueResult &vResult, const bool vbUseSpacing) - : m_bSpaceAfterComma(vbUseSpacing) -{ - m_strValue = vResult.GetString(); - BuildTuple(); - m_bJustConstructed = false; +CMICmnMIValueTuple::CMICmnMIValueTuple(const CMICmnMIValueResult &vResult, + const bool vbUseSpacing) + : m_bSpaceAfterComma(vbUseSpacing) { + m_strValue = vResult.GetString(); + BuildTuple(); + m_bJustConstructed = false; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnMIValueTuple destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMICmnMIValueTuple::~CMICmnMIValueTuple() -{ -} +CMICmnMIValueTuple::~CMICmnMIValueTuple() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Build the result value's mandatory data part, one tuple // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -void -CMICmnMIValueTuple::BuildTuple() -{ - const char *pFormat = "{%s}"; - m_strValue = CMIUtilString::Format(pFormat, m_strValue.c_str()); +void CMICmnMIValueTuple::BuildTuple() { + const char *pFormat = "{%s}"; + m_strValue = CMIUtilString::Format(pFormat, m_strValue.c_str()); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Add another MI result object to the value's list of tuples. // Type: Method. // Args: vResult - (R) The MI result object. // Return: None. // Throws: None. //-- -void -CMICmnMIValueTuple::BuildTuple(const CMICmnMIValueResult &vResult) -{ - // Clear out the default "<Invalid>" text - if (m_bJustConstructed) - { - m_bJustConstructed = false; - m_strValue = vResult.GetString(); - BuildTuple(); - return; - } - - if (m_strValue[0] == '{') - { - m_strValue = m_strValue.substr(1, m_strValue.size() - 1); - } - if (m_strValue[m_strValue.size() - 1] == '}') - { - m_strValue = m_strValue.substr(0, m_strValue.size() - 1); - } - - const char *pFormat = m_bSpaceAfterComma ? "{%s, %s}" : "{%s,%s}"; - m_strValue = CMIUtilString::Format(pFormat, m_strValue.c_str(), vResult.GetString().c_str()); +void CMICmnMIValueTuple::BuildTuple(const CMICmnMIValueResult &vResult) { + // Clear out the default "<Invalid>" text + if (m_bJustConstructed) { + m_bJustConstructed = false; + m_strValue = vResult.GetString(); + BuildTuple(); + return; + } + + if (m_strValue[0] == '{') { + m_strValue = m_strValue.substr(1, m_strValue.size() - 1); + } + if (m_strValue[m_strValue.size() - 1] == '}') { + m_strValue = m_strValue.substr(0, m_strValue.size() - 1); + } + + const char *pFormat = m_bSpaceAfterComma ? "{%s, %s}" : "{%s,%s}"; + m_strValue = CMIUtilString::Format(pFormat, m_strValue.c_str(), + vResult.GetString().c_str()); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Add string value to the value's list of tuples. // Type: Method. // Args: vValue - (R) The string object. // Return: None. // Throws: None. //-- -void -CMICmnMIValueTuple::BuildTuple(const CMIUtilString &vValue) -{ - // Clear out the default "<Invalid>" text - if (m_bJustConstructed) - { - m_bJustConstructed = false; - m_strValue = vValue; - BuildTuple(); - return; - } - - const CMIUtilString data(ExtractContentNoBrackets()); - const char *pFormat = m_bSpaceAfterComma ? "{%s, %s}" : "{%s,%s}"; - m_strValue = CMIUtilString::Format(pFormat, data.c_str(), vValue.c_str()); +void CMICmnMIValueTuple::BuildTuple(const CMIUtilString &vValue) { + // Clear out the default "<Invalid>" text + if (m_bJustConstructed) { + m_bJustConstructed = false; + m_strValue = vValue; + BuildTuple(); + return; + } + + const CMIUtilString data(ExtractContentNoBrackets()); + const char *pFormat = m_bSpaceAfterComma ? "{%s, %s}" : "{%s,%s}"; + m_strValue = CMIUtilString::Format(pFormat, data.c_str(), vValue.c_str()); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Add another MI value object to the value list's of list is values. -// Only values objects can be added to a list of values otherwise this function +// Only values objects can be added to a list of values otherwise this +// function // will return MIstatus::failure. // Type: Method. // Args: vValue - (R) The MI value object. // Return: None. // Throws: None. //-- -void -CMICmnMIValueTuple::Add(const CMICmnMIValueResult &vResult) -{ - BuildTuple(vResult); +void CMICmnMIValueTuple::Add(const CMICmnMIValueResult &vResult) { + BuildTuple(vResult); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Add another MI value object to the value list's of list is values. -// Only values objects can be added to a list of values otherwise this function +// Only values objects can be added to a list of values otherwise this +// function // will return MIstatus::failure. // Type: Method. // Args: vValue - (R) The MI value object. -// vbUseSpacing - (R) True = put space separators into the string, false = no spaces used. +// vbUseSpacing - (R) True = put space separators into the string, +// false = no spaces used. // Return: None. // Throws: None. //-- -void -CMICmnMIValueTuple::Add(const CMICmnMIValueResult &vResult, const bool vbUseSpacing) -{ - m_bSpaceAfterComma = vbUseSpacing; - BuildTuple(vResult); +void CMICmnMIValueTuple::Add(const CMICmnMIValueResult &vResult, + const bool vbUseSpacing) { + m_bSpaceAfterComma = vbUseSpacing; + BuildTuple(vResult); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Add another MI value object to the value list's of list is values. -// Only values objects can be added to a list of values otherwise this function +// Only values objects can be added to a list of values otherwise this +// function // will return MIstatus::failure. // Type: Method. // Args: vValue - (R) The MI value object. -// vbUseSpacing - (R) True = put space separators into the string, false = no spaces used. +// vbUseSpacing - (R) True = put space separators into the string, +// false = no spaces used. // Return: None. // Throws: None. //-- -void -CMICmnMIValueTuple::Add(const CMICmnMIValueConst &vValue, const bool vbUseSpacing) -{ - m_bSpaceAfterComma = vbUseSpacing; - BuildTuple(vValue.GetString()); +void CMICmnMIValueTuple::Add(const CMICmnMIValueConst &vValue, + const bool vbUseSpacing) { + m_bSpaceAfterComma = vbUseSpacing; + BuildTuple(vValue.GetString()); } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the contents of *this value object but without the outer most +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the contents of *this value object but without the outer +// most // brackets. // Type: Method. // Args: None. // Return: CMIUtilString - Data within the object. // Throws: None. //-- -CMIUtilString -CMICmnMIValueTuple::ExtractContentNoBrackets() const -{ - CMIUtilString data(m_strValue); - - if (data[0] == '{') - { - data = data.substr(1, data.length() - 1); - } - if (data[data.size() - 1] == '}') - { - data = data.substr(0, data.length() - 1); - } - - return data; +CMIUtilString CMICmnMIValueTuple::ExtractContentNoBrackets() const { + CMIUtilString data(m_strValue); + + if (data[0] == '{') { + data = data.substr(1, data.length() - 1); + } + if (data[data.size() - 1] == '}') { + data = data.substr(0, data.length() - 1); + } + + return data; } diff --git a/lldb/tools/lldb-mi/MICmnMIValueTuple.h b/lldb/tools/lldb-mi/MICmnMIValueTuple.h index 8f36b4f69d0..095de23139b 100644 --- a/lldb/tools/lldb-mi/MICmnMIValueTuple.h +++ b/lldb/tools/lldb-mi/MICmnMIValueTuple.h @@ -11,10 +11,11 @@ // In-house headers: #include "MICmnMIValue.h" -#include "MICmnMIValueResult.h" #include "MICmnMIValueConst.h" +#include "MICmnMIValueResult.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code MI Result class. Part of the CMICmnMIValueTupleRecord // set of objects. // The syntax is as follows: @@ -27,35 +28,37 @@ // value ==> const | tuple | list // const ==> c-string (7 bit iso c string content) // tuple ==> "{}" | "{" result ( "," result )* "}" -// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]" +// list ==> "[]" | "[" value ( "," value )* "]" | "[" result ( "," +// result )* "]" // More information see: // http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_chapter/gdb_22.html //-- -class CMICmnMIValueTuple : public CMICmnMIValue -{ - // Methods: - public: - /* ctor */ CMICmnMIValueTuple(); - /* ctor */ CMICmnMIValueTuple(const CMICmnMIValueResult &vResult); - /* ctor */ CMICmnMIValueTuple(const CMICmnMIValueResult &vResult, const bool vbUseSpacing); - // - void Add(const CMICmnMIValueResult &vResult); - void Add(const CMICmnMIValueResult &vResult, const bool vbUseSpacing); - void Add(const CMICmnMIValueConst &vValue, const bool vbUseSpacing); - CMIUtilString ExtractContentNoBrackets() const; +class CMICmnMIValueTuple : public CMICmnMIValue { + // Methods: +public: + /* ctor */ CMICmnMIValueTuple(); + /* ctor */ CMICmnMIValueTuple(const CMICmnMIValueResult &vResult); + /* ctor */ CMICmnMIValueTuple(const CMICmnMIValueResult &vResult, + const bool vbUseSpacing); + // + void Add(const CMICmnMIValueResult &vResult); + void Add(const CMICmnMIValueResult &vResult, const bool vbUseSpacing); + void Add(const CMICmnMIValueConst &vValue, const bool vbUseSpacing); + CMIUtilString ExtractContentNoBrackets() const; - // Overridden: - public: - // From CMICmnBase - /* dtor */ ~CMICmnMIValueTuple() override; + // Overridden: +public: + // From CMICmnBase + /* dtor */ ~CMICmnMIValueTuple() override; - // Methods: - private: - void BuildTuple(); - void BuildTuple(const CMICmnMIValueResult &vResult); - void BuildTuple(const CMIUtilString &vValue); + // Methods: +private: + void BuildTuple(); + void BuildTuple(const CMICmnMIValueResult &vResult); + void BuildTuple(const CMIUtilString &vValue); - // Attributes: - private: - bool m_bSpaceAfterComma; // True = put space separators into the string, false = no spaces used + // Attributes: +private: + bool m_bSpaceAfterComma; // True = put space separators into the string, false + // = no spaces used }; diff --git a/lldb/tools/lldb-mi/MICmnResources.cpp b/lldb/tools/lldb-mi/MICmnResources.cpp index 50d6b795def..f96f01b65f0 100644 --- a/lldb/tools/lldb-mi/MICmnResources.cpp +++ b/lldb/tools/lldb-mi/MICmnResources.cpp @@ -8,279 +8,477 @@ //===----------------------------------------------------------------------===// // Third party headers -#include <inttypes.h> // For PRIx64 #include "assert.h" +#include <inttypes.h> // For PRIx64 // In-house headers: #include "MICmnResources.h" // Instantiations: -const CMICmnResources::SRsrcTextData CMICmnResources::ms_pResourceId2TextData[] = { - {IDS_PROJNAME, "LLDB Machine Interface Driver (MI) All rights reserved"}, - {IDS_MI_VERSION_DESCRIPTION_DEBUG, "Version: 1.0.0.9 (Debug)"}, // See version history in MIDriverMain.cpp - {IDS_MI_VERSION_DESCRIPTION, "Version: 1.0.0.9"}, - {IDS_MI_APPNAME_SHORT, "MI"}, - {IDS_MI_APPNAME_LONG, "Machine Interface Driver"}, - {IDS_MI_APP_FILEPATHNAME, "Application: %s"}, - {IDS_MI_APP_ARGS, "Command line args: "}, - {IDE_MI_VERSION_GDB, - "Version: GNU gdb (GDB) 7.4 \n(This is a MI stub on top of LLDB and not GDB)\nAll rights reserved.\n"}, // *** Eclipse needs this - // exactly!! - {IDS_UTIL_FILE_ERR_INVALID_PATHNAME, "File Handler. Invalid file name path"}, - {IDS_UTIL_FILE_ERR_OPENING_FILE, "File Handler. Error %s opening '%s'"}, - {IDS_UTIL_FILE_ERR_OPENING_FILE_UNKNOWN, "File Handler. Unknown error opening '%s'"}, - {IDE_UTIL_FILE_ERR_WRITING_FILE, "File Handler. Error %s writing '%s'"}, - {IDE_UTIL_FILE_ERR_WRITING_NOTOPEN, "File Handler. File '%s' not open for write"}, - {IDS_RESOURCES_ERR_STRING_NOT_FOUND, "Resources. String (%d) not found in resources"}, - {IDS_RESOURCES_ERR_STRING_TABLE_INVALID, "Resources. String resource table is not set up"}, - {IDS_MI_CLIENT_MSG, "Client message: \"%s\""}, - {IDS_LOG_MSG_CREATION_DATE, "Creation date %s time %s%s"}, - {IDS_LOG_MSG_FILE_LOGGER_PATH, "File logger path: %s%s"}, - {IDS_LOG_MSG_VERSION, "Version: %s%s"}, - {IDS_LOG_ERR_FILE_LOGGER_DISABLED, "Log. File logger temporarily disabled due to file error '%s'"}, - {IDS_LOG_MEDIUM_ERR_INIT, "Log. Medium '%s' initialise failed. %s"}, - {IDS_LOG_MEDIUM_ERR_WRITE_ANY, "Log. Failed to write log data to any medium."}, - {IDS_LOG_MEDIUM_ERR_WRITE_MEDIUMFAIL, "Log. One or mediums failed writing log data."}, - {IDS_MEDIUMFILE_NAME, "File"}, - {IDS_MEDIUMFILE_ERR_INVALID_PATH, "<Invalid - not set>"}, - {IDS_MEDIUMFILE_ERR_FILE_HEADER, "<Invalid - header not set>"}, - {IDS_MEDIUMFILE_NAME_LOG, "File medium. %s"}, - {IDE_OS_ERR_UNKNOWN, "Unknown OS error"}, - {IDE_OS_ERR_RETRIEVING, "Unabled to retrieve OS error message"}, - {IDS_DRIVERMGR_DRIVER_ERR_INIT, "Driver Manager. Driver '%s' (ID:'%s') initialise failed. %s"}, - {IDE_MEDIUMSTDERR_NAME, "Stderr"}, - {IDE_MEDIUMSTDOUT_NAME, "Stdout"}, - {IDE_MI_APP_DESCRIPTION, "Description:\nThe Machine Interface Driver (MI Driver) is a stand alone executable\nthat either be used via " - "a client i.e. Eclipse or directly from the command\nline. It processes MI commands, actions those commands " - "using the internal\ndebugger then forms MI response formatted text which is returned to the\nclient."}, - {IDE_MI_APP_INFORMATION, "Information:\nCurrent limitations. The MI Driver currently only handles remote target\ndebugging. Local " - "debugging has not been implemented. The MI Driver has\nbeen designed primarily to be used with Eclipse Juno " - "and a custom plugin.\nThe custom plugin is not necessary to operate the MI Driver."}, - {IDE_MI_APP_ARG_USAGE, "\nMI driver usage:\n\n\tlldb-mi [--longOption] [-s hortOption] [executeable]\n\n[] = optional argument."}, - {IDE_MI_APP_ARG_HELP, "-h\n--help\n\tPrints out usage information for the MI debugger. Exit the MI\n\tDriver immediately."}, - {IDE_MI_APP_ARG_VERSION, "--version\n\tPrints out GNU (gdb) version information. Exit the MI Driver\n\timmediately."}, - {IDE_MI_APP_ARG_VERSION_LONG, "--versionLong\n\tPrints out MI Driver version information. Exit the MI Driver\n\timmediately."}, - {IDE_MI_APP_ARG_INTERPRETER, "--interpreter\n\t This option is kept for backward compatibility. This executable always run in MI mode"}, - {IDE_MI_APP_ARG_EXECUTEABLE, "--executable\n\tUse the MI Driver in MI mode for the debugging the specified executable." }, - {IDE_MI_APP_ARG_SOURCE, "-s <filename>\n--source <filename>\n\t" - "Tells the debugger to read in and execute the lldb commands in the\n\t" - "given file, after any file provided on the command line has been\n\tloaded."}, - {IDE_MI_APP_ARG_APP_LOG, "--log\n\tUse this argument to tell the MI Driver to update it's log\n\tfile '%s'."}, - {IDE_MI_APP_ARG_APP_LOG_DIR, "--log-dir\n\tUse this argument to specify the directory the MI Driver\n\twill place the log file in, i.e --log-dir=/tmp." }, - {IDE_MI_APP_ARG_EXAMPLE, "Example MI command:\n\t3-info-gdb-mi-command gdb-set\n\t3^done,command={exists=\"true\"}"}, - {IDE_MI_APP_ARG_EXECUTABLE, "executable (NOT IMPLEMENTED)\n\tThe file path to the executable i.e. '\"C:\\My Dev\\foo.exe\"'."}, - {IDS_STDIN_ERR_INVALID_PROMPT, "Stdin. Invalid prompt description '%s'"}, - {IDS_STDIN_ERR_THREAD_CREATION_FAILED, "Stdin. Thread creation failed '%s'"}, - {IDS_STDIN_ERR_THREAD_DELETE, "Stdin. Thread failed to delete '%s'"}, - {IDS_STDIN_ERR_CHKING_BYTE_AVAILABLE, "Stdin. Peeking on stdin stream '%s'"}, - {IDS_STDIN_INPUT_CTRL_CHARS, "Stdin. Receive characters not handled as a command: "}, - {IDS_CMD_QUIT_HELP, "MI Driver Command: quit\n\tExit the MI Driver application."}, - {IDS_THREADMGR_ERR_THREAD_ID_INVALID, "Thread Mgr. Thread ID '%s' is not valid"}, - {IDS_THREADMGR_ERR_THREAD_FAIL_CREATE, "Thread Mgr: Failed to create thread '%s'"}, - {IDS_THREADMGR_ERR_THREAD_ID_NOT_FOUND, "Thread Mgr: Thread with ID '%s' not found"}, - {IDS_THREADMGR_ERR_THREAD_STILL_ALIVE, "Thread Mgr: The thread(s) are still alive at Thread Mgr shutdown: %s"}, - {IDS_FALLTHRU_DRIVER_CMD_RECEIVED, "Fall Thru Driver. Received command '%s'. Is was %shandled"}, - {IDS_CMDFACTORY_ERR_INVALID_CMD_NAME, "Command factory. MI command name '%s' is invalid"}, - {IDS_CMDFACTORY_ERR_INVALID_CMD_CR8FN, - "Command factory. Command creation function invalid for command '%s'. Does function exist? Pointer assigned to it?"}, - {IDS_CMDFACTORY_ERR_CMD_NOT_REGISTERED, "Command factory. Command '%s' not registered"}, - {IDS_CMDFACTORY_ERR_CMD_ALREADY_REGED, "Command factory. Command '%s' by that name already registered"}, - {IDS_CMDMGR_ERR_CMD_FAILED_CREATE, "Command manager. Command creation failed. %s"}, - {IDS_CMDMGR_ERR_CMD_INVOKER, "Command manager. %s "}, - {IDS_MI_INIT_ERR_LOG, "Log. Error occurred during initialisation %s"}, - {IDS_MI_INIT_ERR_RESOURCES, "Resources. Error occurred during initialisation %s"}, - {IDS_MI_INIT_ERR_INIT, "Driver. Error occurred during initialisation %s"}, - {IDS_MI_INIT_ERR_STREAMSTDIN, "Stdin. Error occurred during initialisation %s"}, - {IDS_MI_INIT_ERR_STREAMSTDIN_OSHANDLER, "Stdin. The OS specific stdin stream handler has not been specified for this OS"}, - {IDS_MI_INIT_ERR_OS_STDIN_HANDLER, "Stdin handler. Error occurred during initialisation %s"}, - {IDS_MI_INIT_ERR_STREAMSTDOUT, "Stdout. Error occurred during initialisation %s"}, - {IDS_MI_INIT_ERR_STREAMSTDERR, "Stderr. Error occurred during initialisation %s"}, - {IDS_MI_INIT_ERR_FALLTHRUDRIVER, "Fall Through Driver. Error occurred during initialisation %s"}, - {IDS_MI_INIT_ERR_THREADMGR, "Thread Mgr. Error occurred during initialisation %s"}, - {IDS_MI_INIT_ERR_CMDINTERPRETER, "Command interpreter. %s"}, - {IDS_MI_INIT_ERR_CMDMGR, "Command manager. %s"}, - {IDS_MI_INIT_ERR_CMDFACTORY, "Command factory. %s"}, - {IDS_MI_INIT_ERR_CMDINVOKER, "Command invoker. %s"}, - {IDS_MI_INIT_ERR_CMDMONITOR, "Command monitor. %s"}, - {IDS_MI_INIT_ERR_LLDBDEBUGGER, "LLDB Debugger. %s"}, - {IDS_MI_INIT_ERR_DRIVERMGR, "Driver manager. %s"}, - {IDS_MI_INIT_ERR_DRIVER, "Driver. %s"}, - {IDS_MI_INIT_ERR_OUTOFBANDHANDLER, "Out-of-band handler. %s "}, - {IDS_MI_INIT_ERR_DEBUGSESSIONINFO, "LLDB debug session info. %s "}, - {IDS_MI_INIT_ERR_THREADMANAGER, "Unable to init thread manager."}, - {IDS_MI_INIT_ERR_CLIENT_USING_DRIVER, "Initialising the client to this driver failed."}, - {IDS_MI_INIT_ERR_LOCAL_DEBUG_SESSION, "Initialising a local debug session failed."}, - {IDS_CODE_ERR_INVALID_PARAMETER_VALUE, "Code. Invalid parameter passed to function '%s'"}, - {IDS_CODE_ERR_INVALID_PARAM_NULL_POINTER, "Code. NULL pointer passes as a parameter to function '%s'"}, - {IDS_CODE_ERR_INVALID_ENUMERATION_VALUE, "Code. Invalid enumeration value encountered in function '%s'"}, - { - IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER, "LLDB Debugger. LLDB Listener is not valid", - }, - { - IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER, "LLDB Debugger. LLDB Debugger is not valid", - }, - {IDS_LLDBDEBUGGER_ERR_CLIENTDRIVER, - "LLDB Debugger. CMIDriverBase derived driver needs to be set prior to CMICmnLLDBDDebugger initialisation"}, - {IDS_LLDBDEBUGGER_ERR_STARTLISTENER, "LLDB Debugger. Starting listening events for '%s' failed"}, - {IDS_LLDBDEBUGGER_ERR_THREADCREATIONFAIL, "LLDB Debugger. Thread creation failed '%s'"}, - {IDS_LLDBDEBUGGER_ERR_THREAD_DELETE, "LLDB Debugger. Thread failed to delete '%s'"}, - {IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER, "LLDB Debugger. Invalid SB broadcaster class name '%s' "}, - {IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME, "LLDB Debugger. Invalid client name '%s' "}, - {IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERED, "LLDB Debugger. Client name '%s' not registered for listening events"}, - {IDS_LLDBDEBUGGER_ERR_STOPLISTENER, "LLDB Debugger. Failure occurred stopping event for client '%s' SBBroadcaster '%s'"}, - {IDS_LLDBDEBUGGER_ERR_BROADCASTER_NAME, "LLDB Debugger. Broadcaster's name '%s' is not valid"}, - {IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT, "LLDB Debugger. Unhandled event '%s'"}, - {IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT, "LLDB Out-of-band. Handling event for '%s', an event enumeration '%d' not recognised"}, - {IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID, "LLDB Out-of-band. Invalid '%s' in '%s'"}, - {IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND, "LLDB Out-of-band. %s. Breakpoint information for breakpoint ID %d not found"}, - {IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET, "LLDB Out-of-band. %s. Failed to retrieve breakpoint information for for breakpoint ID %d"}, - {IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET, "LLDB Out-of-band. %s. Failed to set breakpoint information for for breakpoint ID %d"}, - {IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE, "LLDB Out-of-band. %s. Failed to form the MI Out-of-band response"}, - {IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET, "LLDB Out-of-band. %s. Failed to retrieve frame information"}, - {IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE, - "LLDB Out-of-band. %s. Event handler tried to set new MI Driver running state and failed. %s"}, - {IDS_LLDBOUTOFBAND_ERR_BRKPT_CNT_EXCEEDED, - "LLDB Out-of-band. '%s'. Number of valid breakpoint exceeded %d. Cannot create new breakpoint with ID %d"}, - {IDS_DBGSESSION_ERR_SHARED_DATA_ADD, "LLDB debug session info. Failed to add '%s' data to the shared data command container"}, - {IDS_MI_SHTDWN_ERR_LOG, "Log. Error occurred during shutdown. %s"}, - {IDS_MI_SHUTDOWN_ERR, "Server shutdown failure. %s"}, - {IDE_MI_SHTDWN_ERR_RESOURCES, "Resources. Error occurred during shutdown. %s"}, - {IDE_MI_SHTDWN_ERR_STREAMSTDIN, "Stdin. Error occurred during shutdown. %s"}, - {IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER, "Stdin handler. Error occurred during shutdown. %s"}, - {IDS_MI_SHTDWN_ERR_STREAMSTDOUT, "Stdout. Error occurred during shutdown. %s"}, - {IDS_MI_SHTDWN_ERR_STREAMSTDERR, "Stderr. Error occurred during shutdown. %s"}, - {IDS_MI_SHTDWN_ERR_THREADMGR, "Thread Mgr. Error occurred during shutdown. %s"}, - {IDS_MI_SHTDWN_ERR_CMDINTERPRETER, "Command interpreter. Error occurred during shutdown. %s"}, - {IDS_MI_SHTDWN_ERR_CMDMGR, "Command manager. Error occurred during shutdown. %s"}, - {IDS_MI_SHTDWN_ERR_CMDFACTORY, "Command factory. Error occurred during shutdown. %s"}, - {IDS_MI_SHTDWN_ERR_CMDMONITOR, "Command invoker. Error occurred during shutdown. %s"}, - {IDS_MI_SHTDWN_ERR_CMDINVOKER, "Command monitor. Error occurred during shutdown. %s"}, - {IDS_MI_SHTDWN_ERR_LLDBDEBUGGER, "LLDB Debugger. Error occurred during shutdown. %s"}, - {IDS_MI_SHTDWN_ERR_DRIVERMGR, "Driver manager. Error occurred during shutdown. %s"}, - {IDS_MI_SHTDWN_ERR_DRIVER, "Driver. Error occurred during shutdown. %s"}, - {IDS_MI_SHTDWN_ERR_OUTOFBANDHANDLER, "Out-of-band handler. Error occurred during shutdown. %s"}, - {IDS_MI_SHTDWN_ERR_DEBUGSESSIONINFO, "LLDB debug session info. Error occurred during shutdown. %s"}, - {IDE_MI_SHTDWN_ERR_THREADMANAGER, "Unable to shutdown thread manager"}, - {IDS_DRIVER_ERR_PARSE_ARGS, "Driver. Driver '%s'. Parse args error '%s'"}, - {IDS_DRIVER_ERR_PARSE_ARGS_UNKNOWN, "Driver. Driver '%s'. Parse args error unknown"}, - {IDS_DRIVER_ERR_CURRENT_NOT_SET, "Driver. Current working driver has not been set. Call CMIDriverMgr::SetUseThisDriverToDoWork()"}, - {IDS_DRIVER_ERR_NON_REGISTERED, "Driver. No suitable drivers registered with the CMIDriverMgr to do work"}, - {IDS_DRIVER_SAY_DRIVER_USING, "Driver. Using driver '%s' internally"}, - {IDS_DRIVER_ERR_ID_INVALID, "Driver. Driver '%s' invalid ID '%s'"}, - {IDS_DRIVER_ERR_FALLTHRU_DRIVER_ERR, "Driver. Fall through driver '%s' (ID:'%s') error '%s'"}, - {IDS_DRIVER_CMD_RECEIVED, "Driver. Received command '%s'. It was %shandled%s"}, - {IDS_DRIVER_CMD_NOT_IN_FACTORY, ". Command '%s' not in Command Factory"}, - { - IDS_DRIVER_ERR_DRIVER_STATE_ERROR, "Driver. Driver running state error. Cannot go to next state from present state as not allowed", - }, - {IDS_DRIVER_WAITING_STDIN_DATA, "Driver. Main thread suspended waiting on Stdin Monitor to resume main thread"}, - {IDS_DRIVER_ERR_MAINLOOP, "Driver. Error in do main loop. %s"}, - {IDS_DRIVER_ERR_LOCAL_DEBUG_NOT_IMPL, "Driver. --executable argument given. Local debugging is not implemented."}, - {IDS_DRIVER_ERR_LOCAL_DEBUG_INIT, "Driver. --executable argument given. Initialising local debugging failed."}, - {IDS_STDERR_ERR_NOT_ALL_DATA_WRITTEN, "Stderr. Not all data was written to stream. The data '%s'"}, - {IDS_CMD_ARGS_ERR_OPTION_NOT_FOUND, "Command Args. Option '%s' not found"}, - {IDS_CMD_ARGS_ERR_VALIDATION_MANDATORY, "Mandatory args not found: %s"}, - {IDS_CMD_ARGS_ERR_VALIDATION_INVALID, "Invalid args: %s"}, - {IDS_CMD_ARGS_ERR_VALIDATION_MAN_INVALID, "Mandatory args not found: %s. Invalid args: %s"}, - {IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF, "Args missing additional information: %s"}, - {IDS_CMD_ARGS_ERR_CONTEXT_NOT_ALL_EATTEN, "Not all arguments or options were recognised: %s"}, - {IDS_CMD_ARGS_ERR_PREFIX_MSG, "Command Args. Validation failed. "}, - {IDS_VARIANT_ERR_USED_BASECLASS, "Variant container: Variant object used the base class. See CMIUtilVariant"}, - {IDS_VARIANT_ERR_MAP_KEY_INVALID, "Variant container: Invalid ID '%s'"}, - {IDS_WORD_INVALIDBRKTS, "<Invalid>"}, - {IDS_WORD_NONE, "None"}, - {IDS_WORD_NOT, "not"}, - {IDS_WORD_INVALIDEMPTY, "<empty>"}, - {IDS_WORD_INVALIDNULLPTR, "<NULL ptr>"}, - {IDS_WORD_UNKNOWNBRKTS, "<unknown>"}, - {IDS_WORD_NOT_IMPLEMENTED, "Not implemented"}, - {IDS_WORD_NOT_IMPLEMENTED_BRKTS, "<not implemented>"}, - {IDS_WORD_UNKNOWNTYPE_BRKTS, "<unknowntype>"}, - {IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS, "<error message not implemented>"}, - {IDS_CMD_ERR_N_OPTIONS_REQUIRED, "Command '%s'. Missing options, %d required"}, - {IDS_CMD_ERR_OPTION_NOT_FOUND, "Command '%s'. Option '%s' not found"}, - {IDS_CMD_ERR_ARGS, "Command '%s'. %s"}, - {IDS_CMD_WRN_ARGS_NOT_HANDLED, "Command '%s'. Warning the following options not handled by the command: %s"}, - {IDS_CMD_ERR_FNFAILED, "Command '%s'. Fn '%s' failed"}, - {IDS_CMD_ERR_SHARED_DATA_NOT_FOUND, "Command '%s'. Shared data '%s' not found"}, - {IDS_CMD_ERR_LLDBPROCESS_DETACH, "Command '%s'. Process detach failed. '%s'"}, - {IDS_CMD_ERR_LLDBPROCESS_DESTROY, "Command '%s'. Process destroy failed. '%s'"}, - {IDS_CMD_ERR_SETWKDIR, "Command '%s'. Failed to set working directory '%s'"}, - {IDS_CMD_ERR_INVALID_TARGET, "Command '%s'. Target binary '%s' is invalid. %s"}, - {IDS_CMD_ERR_INVALID_TARGET_CURRENT, "Command '%s'. Current SBTarget is invalid"}, - {IDS_CMD_ERR_INVALID_TARGET_TYPE, "Command '%s'. Target type '%s' is not recognised"}, - {IDS_CMD_ERR_INVALID_TARGET_PLUGIN, "Command '%s'. Target plugin is invalid. %s"}, - {IDS_CMD_ERR_CONNECT_TO_TARGET, "Command '%s'. Error connecting to target: '%s'"}, - {IDS_CMD_ERR_INVALID_TARGETPLUGINCURRENT, "Command '%s'. Current target plugin is invalid"}, - {IDS_CMD_ERR_NOT_IMPLEMENTED, "Command '%s'. Command not implemented"}, - {IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED, "Command '%s'. Command not implemented as it has been deprecated"}, - {IDS_CMD_ERR_CREATE_TARGET, "Command '%s'. Create target failed: %s"}, - {IDS_CMD_ERR_BRKPT_LOCATION_FORMAT, "Command '%s'. Incorrect format for breakpoint location '%s'"}, - {IDS_CMD_ERR_BRKPT_LOCATION_NOT_FOUND, "Command '%s'. Breakpoint location '%s' not found"}, - {IDS_CMD_ERR_BRKPT_INVALID, "Command '%s'. Breakpoint '%s' invalid"}, - {IDS_CMD_ERR_BRKPT_CNT_EXCEEDED, "Command '%s'. Number of valid breakpoint exceeded %d. Cannot create new breakpoint '%s'"}, - {IDS_CMD_ERR_SOME_ERROR, "Command '%s'. Error: %s"}, - {IDS_CMD_ERR_THREAD_INVALID, "Command '%s'. Thread ID invalid"}, - {IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID, "Command '%s'. Thread frame range invalid"}, - {IDS_CMD_ERR_FRAME_INVALID, "Command '%s'. Frame ID invalid"}, - {IDS_CMD_ERR_VARIABLE_DOESNOTEXIST, "Command '%s'. Variable '%s' does not exist"}, - {IDS_CMD_ERR_VARIABLE_ENUM_INVALID, "Command '%s'. Invalid enumeration for variable '%s' formatted string '%s'"}, - {IDS_CMD_ERR_VARIABLE_EXPRESSIONPATH, "Command '%s'. Failed to get expression for variable '%s'"}, - {IDS_CMD_ERR_VARIABLE_CREATION_FAILED, "Failed to create variable object for '%s'"}, - {IDS_CMD_ERR_VARIABLE_CHILD_RANGE_INVALID, "Command '%s'. Variable children range invalid"}, - {IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION, "<Error: Command run but command did not do anything useful. No MI response formed>"}, - {IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION, "<Error: Command run and event caught, did nothing useful. No MI Out-of-Bound formed>"}, - {IDS_CMD_ERR_DISASM_ADDR_START_INVALID, "Command '%s'. Invalid start value '%s'"}, - {IDS_CMD_ERR_DISASM_ADDR_END_INVALID, "Command '%s'. Invalid end value '%s'"}, - {IDS_CMD_ERR_MEMORY_ALLOC_FAILURE, "Command '%s'. Failed to allocate memory %d bytes"}, - {IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK, "Command '%s'. LLDB unable to read entire memory block of %u bytes at address 0x%016" PRIx64 }, - {IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES, "Command '%s'. Unable to read memory block of %u bytes at address 0x%016" PRIx64 ": %s "}, - {IDS_CMD_ERR_INVALID_PROCESS, "Command '%s'. Invalid process during debug session"}, - {IDS_CMD_ERR_INVALID_PRINT_VALUES, "Command '%s'. Unknown value for PRINT_VALUES: must be: 0 or \"--no-values\", 1 or \"--all-values\", 2 or \"--simple-values\""}, - {IDS_CMD_ERR_INVALID_LOCATION_FORMAT, "Command '%s'. Invalid location format '%s'"}, - {IDS_CMD_ERR_INVALID_FORMAT_TYPE, "Command '%s'. Invalid var format type '%s'"}, - {IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND, "Command '%s'. Breakpoint information for breakpoint ID %d not found"}, - {IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES, "Command '%s'. Unable to write memory block of %u bytes at address 0x%016" PRIx64 ": %s "}, - {IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK, "Command '%s'. LLDB unable to write entire memory block of %u bytes at address 0x%016" PRIX64}, - {IDS_CMD_ERR_SET_NEW_DRIVER_STATE, "Command '%s'. Command tried to set new MI Driver running state and failed. %s"}, - {IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND, "The request '%s' was not recognised, not implemented"}, - {IDS_CMD_ERR_INFO_PRINTFN_FAILED, "The request '%s' failed."}, - {IDS_CMD_ERR_GDBSET_OPT_TARGETASYNC, "'target-async' expects \"on\" or \"off\""}, - {IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH, "'solib-search-path' requires at least one argument"}, - {IDS_CMD_ERR_GDBSET_OPT_PRINT_BAD_ARGS, "'print' expects option-name and \"on\" or \"off\""}, - {IDS_CMD_ERR_GDBSET_OPT_PRINT_UNKNOWN_OPTION, "'print' error. The option '%s' not found"}, - {IDS_CMD_ERR_GDBSHOW_OPT_PRINT_BAD_ARGS, "'print' expects option-name and \"on\" or \"off\""}, - {IDS_CMD_ERR_GDBSHOW_OPT_PRINT_UNKNOWN_OPTION, "'print' error. The option '%s' not found"}, - {IDS_CMD_ERR_EXPR_INVALID, "Failed to evaluate expression: %s"}, - {IDS_CMD_ERR_ATTACH_FAILED, "Command '%s'. Attach to processs failed: %s"}, - {IDS_CMD_ERR_ATTACH_BAD_ARGS, "Command '%s'. Must specify either a PID or a Name"}}; +const CMICmnResources::SRsrcTextData + CMICmnResources::ms_pResourceId2TextData[] = { + {IDS_PROJNAME, + "LLDB Machine Interface Driver (MI) All rights reserved"}, + {IDS_MI_VERSION_DESCRIPTION_DEBUG, + "Version: 1.0.0.9 (Debug)"}, // See version history in MIDriverMain.cpp + {IDS_MI_VERSION_DESCRIPTION, "Version: 1.0.0.9"}, + {IDS_MI_APPNAME_SHORT, "MI"}, + {IDS_MI_APPNAME_LONG, "Machine Interface Driver"}, + {IDS_MI_APP_FILEPATHNAME, "Application: %s"}, + {IDS_MI_APP_ARGS, "Command line args: "}, + {IDE_MI_VERSION_GDB, "Version: GNU gdb (GDB) 7.4 \n(This is a MI stub " + "on top of LLDB and not GDB)\nAll rights " + "reserved.\n"}, // *** Eclipse needs this + // exactly!! + {IDS_UTIL_FILE_ERR_INVALID_PATHNAME, + "File Handler. Invalid file name path"}, + {IDS_UTIL_FILE_ERR_OPENING_FILE, "File Handler. Error %s opening '%s'"}, + {IDS_UTIL_FILE_ERR_OPENING_FILE_UNKNOWN, + "File Handler. Unknown error opening '%s'"}, + {IDE_UTIL_FILE_ERR_WRITING_FILE, "File Handler. Error %s writing '%s'"}, + {IDE_UTIL_FILE_ERR_WRITING_NOTOPEN, + "File Handler. File '%s' not open for write"}, + {IDS_RESOURCES_ERR_STRING_NOT_FOUND, + "Resources. String (%d) not found in resources"}, + {IDS_RESOURCES_ERR_STRING_TABLE_INVALID, + "Resources. String resource table is not set up"}, + {IDS_MI_CLIENT_MSG, "Client message: \"%s\""}, + {IDS_LOG_MSG_CREATION_DATE, "Creation date %s time %s%s"}, + {IDS_LOG_MSG_FILE_LOGGER_PATH, "File logger path: %s%s"}, + {IDS_LOG_MSG_VERSION, "Version: %s%s"}, + {IDS_LOG_ERR_FILE_LOGGER_DISABLED, + "Log. File logger temporarily disabled due to file error '%s'"}, + {IDS_LOG_MEDIUM_ERR_INIT, "Log. Medium '%s' initialise failed. %s"}, + {IDS_LOG_MEDIUM_ERR_WRITE_ANY, + "Log. Failed to write log data to any medium."}, + {IDS_LOG_MEDIUM_ERR_WRITE_MEDIUMFAIL, + "Log. One or mediums failed writing log data."}, + {IDS_MEDIUMFILE_NAME, "File"}, + {IDS_MEDIUMFILE_ERR_INVALID_PATH, "<Invalid - not set>"}, + {IDS_MEDIUMFILE_ERR_FILE_HEADER, "<Invalid - header not set>"}, + {IDS_MEDIUMFILE_NAME_LOG, "File medium. %s"}, + {IDE_OS_ERR_UNKNOWN, "Unknown OS error"}, + {IDE_OS_ERR_RETRIEVING, "Unabled to retrieve OS error message"}, + {IDS_DRIVERMGR_DRIVER_ERR_INIT, + "Driver Manager. Driver '%s' (ID:'%s') initialise failed. %s"}, + {IDE_MEDIUMSTDERR_NAME, "Stderr"}, + {IDE_MEDIUMSTDOUT_NAME, "Stdout"}, + {IDE_MI_APP_DESCRIPTION, + "Description:\nThe Machine Interface Driver (MI Driver) is a stand " + "alone executable\nthat either be used via " + "a client i.e. Eclipse or directly from the command\nline. It " + "processes MI commands, actions those commands " + "using the internal\ndebugger then forms MI response formatted text " + "which is returned to the\nclient."}, + {IDE_MI_APP_INFORMATION, + "Information:\nCurrent limitations. The MI Driver currently only " + "handles remote target\ndebugging. Local " + "debugging has not been implemented. The MI Driver has\nbeen designed " + "primarily to be used with Eclipse Juno " + "and a custom plugin.\nThe custom plugin is not necessary to operate " + "the MI Driver."}, + {IDE_MI_APP_ARG_USAGE, "\nMI driver usage:\n\n\tlldb-mi [--longOption] " + "[-s hortOption] [executeable]\n\n[] = optional " + "argument."}, + {IDE_MI_APP_ARG_HELP, "-h\n--help\n\tPrints out usage information for " + "the MI debugger. Exit the MI\n\tDriver " + "immediately."}, + {IDE_MI_APP_ARG_VERSION, "--version\n\tPrints out GNU (gdb) version " + "information. Exit the MI " + "Driver\n\timmediately."}, + {IDE_MI_APP_ARG_VERSION_LONG, "--versionLong\n\tPrints out MI Driver " + "version information. Exit the MI " + "Driver\n\timmediately."}, + {IDE_MI_APP_ARG_INTERPRETER, "--interpreter\n\t This option is kept " + "for backward compatibility. This " + "executable always run in MI mode"}, + {IDE_MI_APP_ARG_EXECUTEABLE, "--executable\n\tUse the MI Driver in MI " + "mode for the debugging the specified " + "executable."}, + {IDE_MI_APP_ARG_SOURCE, "-s <filename>\n--source <filename>\n\t" + "Tells the debugger to read in and execute the " + "lldb commands in the\n\t" + "given file, after any file provided on the " + "command line has been\n\tloaded."}, + {IDE_MI_APP_ARG_APP_LOG, "--log\n\tUse this argument to tell the MI " + "Driver to update it's log\n\tfile '%s'."}, + {IDE_MI_APP_ARG_APP_LOG_DIR, + "--log-dir\n\tUse this argument to specify the directory the MI " + "Driver\n\twill place the log file in, i.e --log-dir=/tmp."}, + {IDE_MI_APP_ARG_EXAMPLE, "Example MI command:\n\t3-info-gdb-mi-command " + "gdb-set\n\t3^done,command={exists=\"true\"}"}, + {IDE_MI_APP_ARG_EXECUTABLE, "executable (NOT IMPLEMENTED)\n\tThe file " + "path to the executable i.e. '\"C:\\My " + "Dev\\foo.exe\"'."}, + {IDS_STDIN_ERR_INVALID_PROMPT, + "Stdin. Invalid prompt description '%s'"}, + {IDS_STDIN_ERR_THREAD_CREATION_FAILED, + "Stdin. Thread creation failed '%s'"}, + {IDS_STDIN_ERR_THREAD_DELETE, "Stdin. Thread failed to delete '%s'"}, + {IDS_STDIN_ERR_CHKING_BYTE_AVAILABLE, + "Stdin. Peeking on stdin stream '%s'"}, + {IDS_STDIN_INPUT_CTRL_CHARS, + "Stdin. Receive characters not handled as a command: "}, + {IDS_CMD_QUIT_HELP, + "MI Driver Command: quit\n\tExit the MI Driver application."}, + {IDS_THREADMGR_ERR_THREAD_ID_INVALID, + "Thread Mgr. Thread ID '%s' is not valid"}, + {IDS_THREADMGR_ERR_THREAD_FAIL_CREATE, + "Thread Mgr: Failed to create thread '%s'"}, + {IDS_THREADMGR_ERR_THREAD_ID_NOT_FOUND, + "Thread Mgr: Thread with ID '%s' not found"}, + {IDS_THREADMGR_ERR_THREAD_STILL_ALIVE, "Thread Mgr: The thread(s) are " + "still alive at Thread Mgr " + "shutdown: %s"}, + {IDS_FALLTHRU_DRIVER_CMD_RECEIVED, + "Fall Thru Driver. Received command '%s'. Is was %shandled"}, + {IDS_CMDFACTORY_ERR_INVALID_CMD_NAME, + "Command factory. MI command name '%s' is invalid"}, + {IDS_CMDFACTORY_ERR_INVALID_CMD_CR8FN, + "Command factory. Command creation function invalid for command '%s'. " + "Does function exist? Pointer assigned to it?"}, + {IDS_CMDFACTORY_ERR_CMD_NOT_REGISTERED, + "Command factory. Command '%s' not registered"}, + {IDS_CMDFACTORY_ERR_CMD_ALREADY_REGED, + "Command factory. Command '%s' by that name already registered"}, + {IDS_CMDMGR_ERR_CMD_FAILED_CREATE, + "Command manager. Command creation failed. %s"}, + {IDS_CMDMGR_ERR_CMD_INVOKER, "Command manager. %s "}, + {IDS_MI_INIT_ERR_LOG, "Log. Error occurred during initialisation %s"}, + {IDS_MI_INIT_ERR_RESOURCES, + "Resources. Error occurred during initialisation %s"}, + {IDS_MI_INIT_ERR_INIT, + "Driver. Error occurred during initialisation %s"}, + {IDS_MI_INIT_ERR_STREAMSTDIN, + "Stdin. Error occurred during initialisation %s"}, + {IDS_MI_INIT_ERR_STREAMSTDIN_OSHANDLER, "Stdin. The OS specific stdin " + "stream handler has not been " + "specified for this OS"}, + {IDS_MI_INIT_ERR_OS_STDIN_HANDLER, + "Stdin handler. Error occurred during initialisation %s"}, + {IDS_MI_INIT_ERR_STREAMSTDOUT, + "Stdout. Error occurred during initialisation %s"}, + {IDS_MI_INIT_ERR_STREAMSTDERR, + "Stderr. Error occurred during initialisation %s"}, + {IDS_MI_INIT_ERR_FALLTHRUDRIVER, + "Fall Through Driver. Error occurred during initialisation %s"}, + {IDS_MI_INIT_ERR_THREADMGR, + "Thread Mgr. Error occurred during initialisation %s"}, + {IDS_MI_INIT_ERR_CMDINTERPRETER, "Command interpreter. %s"}, + {IDS_MI_INIT_ERR_CMDMGR, "Command manager. %s"}, + {IDS_MI_INIT_ERR_CMDFACTORY, "Command factory. %s"}, + {IDS_MI_INIT_ERR_CMDINVOKER, "Command invoker. %s"}, + {IDS_MI_INIT_ERR_CMDMONITOR, "Command monitor. %s"}, + {IDS_MI_INIT_ERR_LLDBDEBUGGER, "LLDB Debugger. %s"}, + {IDS_MI_INIT_ERR_DRIVERMGR, "Driver manager. %s"}, + {IDS_MI_INIT_ERR_DRIVER, "Driver. %s"}, + {IDS_MI_INIT_ERR_OUTOFBANDHANDLER, "Out-of-band handler. %s "}, + {IDS_MI_INIT_ERR_DEBUGSESSIONINFO, "LLDB debug session info. %s "}, + {IDS_MI_INIT_ERR_THREADMANAGER, "Unable to init thread manager."}, + {IDS_MI_INIT_ERR_CLIENT_USING_DRIVER, + "Initialising the client to this driver failed."}, + {IDS_MI_INIT_ERR_LOCAL_DEBUG_SESSION, + "Initialising a local debug session failed."}, + {IDS_CODE_ERR_INVALID_PARAMETER_VALUE, + "Code. Invalid parameter passed to function '%s'"}, + {IDS_CODE_ERR_INVALID_PARAM_NULL_POINTER, + "Code. NULL pointer passes as a parameter to function '%s'"}, + {IDS_CODE_ERR_INVALID_ENUMERATION_VALUE, + "Code. Invalid enumeration value encountered in function '%s'"}, + { + IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER, + "LLDB Debugger. LLDB Listener is not valid", + }, + { + IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER, + "LLDB Debugger. LLDB Debugger is not valid", + }, + {IDS_LLDBDEBUGGER_ERR_CLIENTDRIVER, + "LLDB Debugger. CMIDriverBase derived driver needs to be set prior to " + "CMICmnLLDBDDebugger initialisation"}, + {IDS_LLDBDEBUGGER_ERR_STARTLISTENER, + "LLDB Debugger. Starting listening events for '%s' failed"}, + {IDS_LLDBDEBUGGER_ERR_THREADCREATIONFAIL, + "LLDB Debugger. Thread creation failed '%s'"}, + {IDS_LLDBDEBUGGER_ERR_THREAD_DELETE, + "LLDB Debugger. Thread failed to delete '%s'"}, + {IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER, + "LLDB Debugger. Invalid SB broadcaster class name '%s' "}, + {IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME, + "LLDB Debugger. Invalid client name '%s' "}, + {IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERED, + "LLDB Debugger. Client name '%s' not registered for listening events"}, + {IDS_LLDBDEBUGGER_ERR_STOPLISTENER, "LLDB Debugger. Failure occurred " + "stopping event for client '%s' " + "SBBroadcaster '%s'"}, + {IDS_LLDBDEBUGGER_ERR_BROADCASTER_NAME, + "LLDB Debugger. Broadcaster's name '%s' is not valid"}, + {IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT, + "LLDB Debugger. Unhandled event '%s'"}, + {IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT, + "LLDB Out-of-band. Handling event for '%s', an event enumeration '%d' " + "not recognised"}, + {IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID, + "LLDB Out-of-band. Invalid '%s' in '%s'"}, + {IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND, "LLDB Out-of-band. %s. " + "Breakpoint information for " + "breakpoint ID %d not found"}, + {IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET, + "LLDB Out-of-band. %s. Failed to retrieve breakpoint information for " + "for breakpoint ID %d"}, + {IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET, "LLDB Out-of-band. %s. Failed " + "to set breakpoint information " + "for for breakpoint ID %d"}, + {IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE, + "LLDB Out-of-band. %s. Failed to form the MI Out-of-band response"}, + {IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET, + "LLDB Out-of-band. %s. Failed to retrieve frame information"}, + {IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE, + "LLDB Out-of-band. %s. Event handler tried to set new MI Driver " + "running state and failed. %s"}, + {IDS_LLDBOUTOFBAND_ERR_BRKPT_CNT_EXCEEDED, + "LLDB Out-of-band. '%s'. Number of valid breakpoint exceeded %d. " + "Cannot create new breakpoint with ID %d"}, + {IDS_DBGSESSION_ERR_SHARED_DATA_ADD, "LLDB debug session info. Failed " + "to add '%s' data to the shared " + "data command container"}, + {IDS_MI_SHTDWN_ERR_LOG, "Log. Error occurred during shutdown. %s"}, + {IDS_MI_SHUTDOWN_ERR, "Server shutdown failure. %s"}, + {IDE_MI_SHTDWN_ERR_RESOURCES, + "Resources. Error occurred during shutdown. %s"}, + {IDE_MI_SHTDWN_ERR_STREAMSTDIN, + "Stdin. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER, + "Stdin handler. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_STREAMSTDOUT, + "Stdout. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_STREAMSTDERR, + "Stderr. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_THREADMGR, + "Thread Mgr. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_CMDINTERPRETER, + "Command interpreter. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_CMDMGR, + "Command manager. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_CMDFACTORY, + "Command factory. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_CMDMONITOR, + "Command invoker. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_CMDINVOKER, + "Command monitor. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_LLDBDEBUGGER, + "LLDB Debugger. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_DRIVERMGR, + "Driver manager. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_DRIVER, + "Driver. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_OUTOFBANDHANDLER, + "Out-of-band handler. Error occurred during shutdown. %s"}, + {IDS_MI_SHTDWN_ERR_DEBUGSESSIONINFO, + "LLDB debug session info. Error occurred during shutdown. %s"}, + {IDE_MI_SHTDWN_ERR_THREADMANAGER, "Unable to shutdown thread manager"}, + {IDS_DRIVER_ERR_PARSE_ARGS, + "Driver. Driver '%s'. Parse args error '%s'"}, + {IDS_DRIVER_ERR_PARSE_ARGS_UNKNOWN, + "Driver. Driver '%s'. Parse args error unknown"}, + {IDS_DRIVER_ERR_CURRENT_NOT_SET, + "Driver. Current working driver has not been set. Call " + "CMIDriverMgr::SetUseThisDriverToDoWork()"}, + {IDS_DRIVER_ERR_NON_REGISTERED, "Driver. No suitable drivers " + "registered with the CMIDriverMgr to " + "do work"}, + {IDS_DRIVER_SAY_DRIVER_USING, "Driver. Using driver '%s' internally"}, + {IDS_DRIVER_ERR_ID_INVALID, "Driver. Driver '%s' invalid ID '%s'"}, + {IDS_DRIVER_ERR_FALLTHRU_DRIVER_ERR, + "Driver. Fall through driver '%s' (ID:'%s') error '%s'"}, + {IDS_DRIVER_CMD_RECEIVED, + "Driver. Received command '%s'. It was %shandled%s"}, + {IDS_DRIVER_CMD_NOT_IN_FACTORY, + ". Command '%s' not in Command Factory"}, + { + IDS_DRIVER_ERR_DRIVER_STATE_ERROR, + "Driver. Driver running state error. Cannot go to next state from " + "present state as not allowed", + }, + {IDS_DRIVER_WAITING_STDIN_DATA, "Driver. Main thread suspended waiting " + "on Stdin Monitor to resume main " + "thread"}, + {IDS_DRIVER_ERR_MAINLOOP, "Driver. Error in do main loop. %s"}, + {IDS_DRIVER_ERR_LOCAL_DEBUG_NOT_IMPL, "Driver. --executable argument " + "given. Local debugging is not " + "implemented."}, + {IDS_DRIVER_ERR_LOCAL_DEBUG_INIT, "Driver. --executable argument " + "given. Initialising local debugging " + "failed."}, + {IDS_STDERR_ERR_NOT_ALL_DATA_WRITTEN, + "Stderr. Not all data was written to stream. The data '%s'"}, + {IDS_CMD_ARGS_ERR_OPTION_NOT_FOUND, + "Command Args. Option '%s' not found"}, + {IDS_CMD_ARGS_ERR_VALIDATION_MANDATORY, "Mandatory args not found: %s"}, + {IDS_CMD_ARGS_ERR_VALIDATION_INVALID, "Invalid args: %s"}, + {IDS_CMD_ARGS_ERR_VALIDATION_MAN_INVALID, + "Mandatory args not found: %s. Invalid args: %s"}, + {IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF, + "Args missing additional information: %s"}, + {IDS_CMD_ARGS_ERR_CONTEXT_NOT_ALL_EATTEN, + "Not all arguments or options were recognised: %s"}, + {IDS_CMD_ARGS_ERR_PREFIX_MSG, "Command Args. Validation failed. "}, + {IDS_VARIANT_ERR_USED_BASECLASS, "Variant container: Variant object " + "used the base class. See " + "CMIUtilVariant"}, + {IDS_VARIANT_ERR_MAP_KEY_INVALID, "Variant container: Invalid ID '%s'"}, + {IDS_WORD_INVALIDBRKTS, "<Invalid>"}, + {IDS_WORD_NONE, "None"}, + {IDS_WORD_NOT, "not"}, + {IDS_WORD_INVALIDEMPTY, "<empty>"}, + {IDS_WORD_INVALIDNULLPTR, "<NULL ptr>"}, + {IDS_WORD_UNKNOWNBRKTS, "<unknown>"}, + {IDS_WORD_NOT_IMPLEMENTED, "Not implemented"}, + {IDS_WORD_NOT_IMPLEMENTED_BRKTS, "<not implemented>"}, + {IDS_WORD_UNKNOWNTYPE_BRKTS, "<unknowntype>"}, + {IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS, + "<error message not implemented>"}, + {IDS_CMD_ERR_N_OPTIONS_REQUIRED, + "Command '%s'. Missing options, %d required"}, + {IDS_CMD_ERR_OPTION_NOT_FOUND, "Command '%s'. Option '%s' not found"}, + {IDS_CMD_ERR_ARGS, "Command '%s'. %s"}, + {IDS_CMD_WRN_ARGS_NOT_HANDLED, "Command '%s'. Warning the following " + "options not handled by the command: " + "%s"}, + {IDS_CMD_ERR_FNFAILED, "Command '%s'. Fn '%s' failed"}, + {IDS_CMD_ERR_SHARED_DATA_NOT_FOUND, + "Command '%s'. Shared data '%s' not found"}, + {IDS_CMD_ERR_LLDBPROCESS_DETACH, + "Command '%s'. Process detach failed. '%s'"}, + {IDS_CMD_ERR_LLDBPROCESS_DESTROY, + "Command '%s'. Process destroy failed. '%s'"}, + {IDS_CMD_ERR_SETWKDIR, + "Command '%s'. Failed to set working directory '%s'"}, + {IDS_CMD_ERR_INVALID_TARGET, + "Command '%s'. Target binary '%s' is invalid. %s"}, + {IDS_CMD_ERR_INVALID_TARGET_CURRENT, + "Command '%s'. Current SBTarget is invalid"}, + {IDS_CMD_ERR_INVALID_TARGET_TYPE, + "Command '%s'. Target type '%s' is not recognised"}, + {IDS_CMD_ERR_INVALID_TARGET_PLUGIN, + "Command '%s'. Target plugin is invalid. %s"}, + {IDS_CMD_ERR_CONNECT_TO_TARGET, + "Command '%s'. Error connecting to target: '%s'"}, + {IDS_CMD_ERR_INVALID_TARGETPLUGINCURRENT, + "Command '%s'. Current target plugin is invalid"}, + {IDS_CMD_ERR_NOT_IMPLEMENTED, "Command '%s'. Command not implemented"}, + {IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED, + "Command '%s'. Command not implemented as it has been deprecated"}, + {IDS_CMD_ERR_CREATE_TARGET, "Command '%s'. Create target failed: %s"}, + {IDS_CMD_ERR_BRKPT_LOCATION_FORMAT, + "Command '%s'. Incorrect format for breakpoint location '%s'"}, + {IDS_CMD_ERR_BRKPT_LOCATION_NOT_FOUND, + "Command '%s'. Breakpoint location '%s' not found"}, + {IDS_CMD_ERR_BRKPT_INVALID, "Command '%s'. Breakpoint '%s' invalid"}, + {IDS_CMD_ERR_BRKPT_CNT_EXCEEDED, "Command '%s'. Number of valid " + "breakpoint exceeded %d. Cannot " + "create new breakpoint '%s'"}, + {IDS_CMD_ERR_SOME_ERROR, "Command '%s'. Error: %s"}, + {IDS_CMD_ERR_THREAD_INVALID, "Command '%s'. Thread ID invalid"}, + {IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID, + "Command '%s'. Thread frame range invalid"}, + {IDS_CMD_ERR_FRAME_INVALID, "Command '%s'. Frame ID invalid"}, + {IDS_CMD_ERR_VARIABLE_DOESNOTEXIST, + "Command '%s'. Variable '%s' does not exist"}, + {IDS_CMD_ERR_VARIABLE_ENUM_INVALID, "Command '%s'. Invalid enumeration " + "for variable '%s' formatted " + "string '%s'"}, + {IDS_CMD_ERR_VARIABLE_EXPRESSIONPATH, + "Command '%s'. Failed to get expression for variable '%s'"}, + {IDS_CMD_ERR_VARIABLE_CREATION_FAILED, + "Failed to create variable object for '%s'"}, + {IDS_CMD_ERR_VARIABLE_CHILD_RANGE_INVALID, + "Command '%s'. Variable children range invalid"}, + {IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION, "<Error: Command run but command " + "did not do anything useful. No MI " + "response formed>"}, + {IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION, + "<Error: Command run and event caught, did nothing useful. No MI " + "Out-of-Bound formed>"}, + {IDS_CMD_ERR_DISASM_ADDR_START_INVALID, + "Command '%s'. Invalid start value '%s'"}, + {IDS_CMD_ERR_DISASM_ADDR_END_INVALID, + "Command '%s'. Invalid end value '%s'"}, + {IDS_CMD_ERR_MEMORY_ALLOC_FAILURE, + "Command '%s'. Failed to allocate memory %d bytes"}, + {IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK, + "Command '%s'. LLDB unable to read entire memory block of %u bytes at " + "address 0x%016" PRIx64}, + {IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES, "Command '%s'. Unable to read " + "memory block of %u bytes at " + "address 0x%016" PRIx64 ": %s "}, + {IDS_CMD_ERR_INVALID_PROCESS, + "Command '%s'. Invalid process during debug session"}, + {IDS_CMD_ERR_INVALID_PRINT_VALUES, + "Command '%s'. Unknown value for PRINT_VALUES: must be: 0 or " + "\"--no-values\", 1 or \"--all-values\", 2 or \"--simple-values\""}, + {IDS_CMD_ERR_INVALID_LOCATION_FORMAT, + "Command '%s'. Invalid location format '%s'"}, + {IDS_CMD_ERR_INVALID_FORMAT_TYPE, + "Command '%s'. Invalid var format type '%s'"}, + {IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND, + "Command '%s'. Breakpoint information for breakpoint ID %d not found"}, + {IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES, "Command '%s'. Unable to write " + "memory block of %u bytes at " + "address 0x%016" PRIx64 ": %s "}, + {IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK, + "Command '%s'. LLDB unable to write entire memory block of %u bytes " + "at address 0x%016" PRIX64}, + {IDS_CMD_ERR_SET_NEW_DRIVER_STATE, "Command '%s'. Command tried to set " + "new MI Driver running state and " + "failed. %s"}, + {IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND, + "The request '%s' was not recognised, not implemented"}, + {IDS_CMD_ERR_INFO_PRINTFN_FAILED, "The request '%s' failed."}, + {IDS_CMD_ERR_GDBSET_OPT_TARGETASYNC, + "'target-async' expects \"on\" or \"off\""}, + {IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH, + "'solib-search-path' requires at least one argument"}, + {IDS_CMD_ERR_GDBSET_OPT_PRINT_BAD_ARGS, + "'print' expects option-name and \"on\" or \"off\""}, + {IDS_CMD_ERR_GDBSET_OPT_PRINT_UNKNOWN_OPTION, + "'print' error. The option '%s' not found"}, + {IDS_CMD_ERR_GDBSHOW_OPT_PRINT_BAD_ARGS, + "'print' expects option-name and \"on\" or \"off\""}, + {IDS_CMD_ERR_GDBSHOW_OPT_PRINT_UNKNOWN_OPTION, + "'print' error. The option '%s' not found"}, + {IDS_CMD_ERR_EXPR_INVALID, "Failed to evaluate expression: %s"}, + {IDS_CMD_ERR_ATTACH_FAILED, + "Command '%s'. Attach to processs failed: %s"}, + {IDS_CMD_ERR_ATTACH_BAD_ARGS, + "Command '%s'. Must specify either a PID or a Name"}}; -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnResources constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmnResources::CMICmnResources() - : m_nResourceId2TextDataSize(0) -{ - // Do not use this constructor, use Initialize() +CMICmnResources::CMICmnResources() : m_nResourceId2TextDataSize(0) { + // Do not use this constructor, use Initialize() } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnResources destructor. // Type: Overridden. // Args: None. // Return: None. // Throws: None. //-- -CMICmnResources::~CMICmnResources() -{ - // Do not use this destructor, use Shutdown() +CMICmnResources::~CMICmnResources() { + // Do not use this destructor, use Shutdown() } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Initialize the resources and set locality for the server. // Type: Method. // Args: None. @@ -288,20 +486,19 @@ CMICmnResources::~CMICmnResources() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnResources::Initialize() -{ - m_clientUsageRefCnt++; +bool CMICmnResources::Initialize() { + m_clientUsageRefCnt++; - if (m_bInitialized) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - m_bInitialized = ReadResourceStringData(); + m_bInitialized = ReadResourceStringData(); - return m_bInitialized; + return m_bInitialized; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release resources for *this object. // Type: Method. // Args: None. @@ -309,24 +506,23 @@ CMICmnResources::Initialize() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnResources::Shutdown() -{ - if (--m_clientUsageRefCnt > 0) - return MIstatus::success; +bool CMICmnResources::Shutdown() { + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - if (!m_bInitialized) - return MIstatus::success; + if (!m_bInitialized) + return MIstatus::success; - // Tear down resource explicitly - m_mapRscrIdToTextData.clear(); + // Tear down resource explicitly + m_mapRscrIdToTextData.clear(); - m_bInitialized = false; + m_bInitialized = false; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Initialize the resources and set locality for the server. // Type: Method. // Args: None. @@ -334,39 +530,37 @@ CMICmnResources::Shutdown() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnResources::ReadResourceStringData() -{ - m_nResourceId2TextDataSize = sizeof ms_pResourceId2TextData / sizeof ms_pResourceId2TextData[0]; - for (MIuint i = 0; i < m_nResourceId2TextDataSize; i++) - { - const SRsrcTextData *pRscrData = &ms_pResourceId2TextData[i]; - MapPairRscrIdToTextData_t pr(pRscrData->id, pRscrData->pTextData); - m_mapRscrIdToTextData.insert(pr); - } +bool CMICmnResources::ReadResourceStringData() { + m_nResourceId2TextDataSize = + sizeof ms_pResourceId2TextData / sizeof ms_pResourceId2TextData[0]; + for (MIuint i = 0; i < m_nResourceId2TextDataSize; i++) { + const SRsrcTextData *pRscrData = &ms_pResourceId2TextData[i]; + MapPairRscrIdToTextData_t pr(pRscrData->id, pRscrData->pTextData); + m_mapRscrIdToTextData.insert(pr); + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the corresponding text assigned to the resource ID. // Type: Method. // Args: vResourceId - (R) MI resource ID. // Return: CMIUtilString - Resource text. // Throws: None. //-- -CMIUtilString -CMICmnResources::GetString(const MIuint vResourceId) const -{ - CMIUtilString str; - const bool bFound = GetStringFromResource(vResourceId, str); - MIunused(bFound); - assert(bFound); +CMIUtilString CMICmnResources::GetString(const MIuint vResourceId) const { + CMIUtilString str; + const bool bFound = GetStringFromResource(vResourceId, str); + MIunused(bFound); + assert(bFound); - return str; + return str; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Determine the MI resource ID existings. // Type: Method. // Args: vResourceId - (R) MI resource ID. @@ -374,16 +568,17 @@ CMICmnResources::GetString(const MIuint vResourceId) const // False - Not found. // Throws: None. //-- -bool -CMICmnResources::HasString(const MIuint vResourceId) const -{ - CMIUtilString str; - return GetStringFromResource(vResourceId, str); +bool CMICmnResources::HasString(const MIuint vResourceId) const { + CMIUtilString str; + return GetStringFromResource(vResourceId, str); } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the resource text data for the given resource ID. If a resource ID -// cannot be found and error is given returning the ID of the resource that +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the resource text data for the given resource ID. If a +// resource ID +// cannot be found and error is given returning the ID of the resource +// that // cannot be located. // Type: Method. // Args: vResourceId - (R) MI resource ID. @@ -392,37 +587,34 @@ CMICmnResources::HasString(const MIuint vResourceId) const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnResources::GetStringFromResource(const MIuint vResourceId, CMIUtilString &vrwResourceString) const -{ - MapRscrIdToTextData_t::const_iterator it = m_mapRscrIdToTextData.find(vResourceId); - if (it == m_mapRscrIdToTextData.end()) - { - // Check this is a static variable init that needs this before we are ready - if (!m_bInitialized) - { - (const_cast<CMICmnResources *>(this))->Initialize(); - it = m_mapRscrIdToTextData.find(vResourceId); - if (it == m_mapRscrIdToTextData.end()) - { - vrwResourceString = MIRSRC(IDS_RESOURCES_ERR_STRING_TABLE_INVALID); - return MIstatus::failure; - } - } +bool CMICmnResources::GetStringFromResource( + const MIuint vResourceId, CMIUtilString &vrwResourceString) const { + MapRscrIdToTextData_t::const_iterator it = + m_mapRscrIdToTextData.find(vResourceId); + if (it == m_mapRscrIdToTextData.end()) { + // Check this is a static variable init that needs this before we are ready + if (!m_bInitialized) { + (const_cast<CMICmnResources *>(this))->Initialize(); + it = m_mapRscrIdToTextData.find(vResourceId); + if (it == m_mapRscrIdToTextData.end()) { + vrwResourceString = MIRSRC(IDS_RESOURCES_ERR_STRING_TABLE_INVALID); + return MIstatus::failure; + } + } - if (it == m_mapRscrIdToTextData.end()) - { - vrwResourceString = CMIUtilString::Format(MIRSRC(IDS_RESOURCES_ERR_STRING_NOT_FOUND), vResourceId); - return MIstatus::failure; - } + if (it == m_mapRscrIdToTextData.end()) { + vrwResourceString = CMIUtilString::Format( + MIRSRC(IDS_RESOURCES_ERR_STRING_NOT_FOUND), vResourceId); + return MIstatus::failure; } + } - const MIuint nRsrcId((*it).first); - MIunused(nRsrcId); - const char *pRsrcData((*it).second); + const MIuint nRsrcId((*it).first); + MIunused(nRsrcId); + const char *pRsrcData((*it).second); - // Return result - vrwResourceString = pRsrcData; + // Return result + vrwResourceString = pRsrcData; - return MIstatus::success; + return MIstatus::success; } diff --git a/lldb/tools/lldb-mi/MICmnResources.h b/lldb/tools/lldb-mi/MICmnResources.h index dc9c52c6df6..e9ebe792810 100644 --- a/lldb/tools/lldb-mi/MICmnResources.h +++ b/lldb/tools/lldb-mi/MICmnResources.h @@ -13,323 +13,321 @@ #include <map> // In-house headers: +#include "MICmnBase.h" #include "MIUtilSingletonBase.h" #include "MIUtilString.h" -#include "MICmnBase.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI string test data resource definitions. These IDs match up with // actual string data in a map internal to CMICmnResources. // *** Be sure to update ms_pResourceId2TextData[] array **** -enum -{ - IDS_PROJNAME = 1, - IDS_MI_VERSION_DESCRIPTION_DEBUG, - IDS_MI_VERSION_DESCRIPTION, - IDS_MI_APPNAME_SHORT, - IDS_MI_APPNAME_LONG, - IDS_MI_APP_FILEPATHNAME, - IDS_MI_APP_ARGS, - IDE_MI_VERSION_GDB, - - IDS_UTIL_FILE_ERR_INVALID_PATHNAME, - IDS_UTIL_FILE_ERR_OPENING_FILE, - IDS_UTIL_FILE_ERR_OPENING_FILE_UNKNOWN, - IDE_UTIL_FILE_ERR_WRITING_FILE, - IDE_UTIL_FILE_ERR_WRITING_NOTOPEN, - - IDS_RESOURCES_ERR_STRING_NOT_FOUND, - IDS_RESOURCES_ERR_STRING_TABLE_INVALID, - - IDS_MI_CLIENT_MSG, - - IDS_LOG_MSG_CREATION_DATE, - IDS_LOG_MSG_FILE_LOGGER_PATH, - IDS_LOG_MSG_VERSION, - IDS_LOG_ERR_FILE_LOGGER_DISABLED, - IDS_LOG_MEDIUM_ERR_INIT, - IDS_LOG_MEDIUM_ERR_WRITE_ANY, - IDS_LOG_MEDIUM_ERR_WRITE_MEDIUMFAIL, - - IDS_MEDIUMFILE_NAME, - IDS_MEDIUMFILE_ERR_INVALID_PATH, - IDS_MEDIUMFILE_ERR_FILE_HEADER, - IDS_MEDIUMFILE_NAME_LOG, - - IDE_OS_ERR_UNKNOWN, - IDE_OS_ERR_RETRIEVING, - - IDS_DRIVERMGR_DRIVER_ERR_INIT, - - IDE_MEDIUMSTDERR_NAME, - IDE_MEDIUMSTDOUT_NAME, - - IDE_MI_APP_DESCRIPTION, - IDE_MI_APP_INFORMATION, - IDE_MI_APP_ARG_USAGE, - IDE_MI_APP_ARG_HELP, - IDE_MI_APP_ARG_VERSION, - IDE_MI_APP_ARG_VERSION_LONG, - IDE_MI_APP_ARG_INTERPRETER, - IDE_MI_APP_ARG_EXECUTEABLE, - IDE_MI_APP_ARG_SOURCE, - IDE_MI_APP_ARG_APP_LOG, - IDE_MI_APP_ARG_APP_LOG_DIR, - IDE_MI_APP_ARG_EXAMPLE, - IDE_MI_APP_ARG_EXECUTABLE, - - IDS_STDIN_ERR_INVALID_PROMPT, - IDS_STDIN_ERR_THREAD_CREATION_FAILED, - IDS_STDIN_ERR_THREAD_DELETE, - IDS_STDIN_ERR_CHKING_BYTE_AVAILABLE, - IDS_STDIN_INPUT_CTRL_CHARS, - - IDS_CMD_QUIT_HELP, - - IDS_THREADMGR_ERR_THREAD_ID_INVALID, - IDS_THREADMGR_ERR_THREAD_FAIL_CREATE, - IDS_THREADMGR_ERR_THREAD_ID_NOT_FOUND, - IDS_THREADMGR_ERR_THREAD_STILL_ALIVE, - - IDS_FALLTHRU_DRIVER_CMD_RECEIVED, - - IDS_CMDFACTORY_ERR_INVALID_CMD_NAME, - IDS_CMDFACTORY_ERR_INVALID_CMD_CR8FN, - IDS_CMDFACTORY_ERR_CMD_NOT_REGISTERED, - IDS_CMDFACTORY_ERR_CMD_ALREADY_REGED, - - IDS_CMDMGR_ERR_CMD_FAILED_CREATE, - IDS_CMDMGR_ERR_CMD_INVOKER, - - IDS_MI_INIT_ERR_LOG, - IDS_MI_INIT_ERR_RESOURCES, - IDS_MI_INIT_ERR_INIT, - IDS_MI_INIT_ERR_STREAMSTDIN, - IDS_MI_INIT_ERR_STREAMSTDIN_OSHANDLER, - IDS_MI_INIT_ERR_OS_STDIN_HANDLER, - IDS_MI_INIT_ERR_STREAMSTDOUT, - IDS_MI_INIT_ERR_STREAMSTDERR, - IDS_MI_INIT_ERR_FALLTHRUDRIVER, - IDS_MI_INIT_ERR_THREADMGR, - IDS_MI_INIT_ERR_CMDINTERPRETER, - IDS_MI_INIT_ERR_CMDMGR, - IDS_MI_INIT_ERR_CMDFACTORY, - IDS_MI_INIT_ERR_CMDINVOKER, - IDS_MI_INIT_ERR_CMDMONITOR, - IDS_MI_INIT_ERR_LLDBDEBUGGER, - IDS_MI_INIT_ERR_DRIVERMGR, - IDS_MI_INIT_ERR_DRIVER, - IDS_MI_INIT_ERR_OUTOFBANDHANDLER, - IDS_MI_INIT_ERR_DEBUGSESSIONINFO, - IDS_MI_INIT_ERR_THREADMANAGER, - IDS_MI_INIT_ERR_CLIENT_USING_DRIVER, - IDS_MI_INIT_ERR_LOCAL_DEBUG_SESSION, - - IDS_CODE_ERR_INVALID_PARAMETER_VALUE, - IDS_CODE_ERR_INVALID_PARAM_NULL_POINTER, - IDS_CODE_ERR_INVALID_ENUMERATION_VALUE, - - IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER, - IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER, - IDS_LLDBDEBUGGER_ERR_CLIENTDRIVER, - IDS_LLDBDEBUGGER_ERR_STARTLISTENER, - IDS_LLDBDEBUGGER_ERR_THREADCREATIONFAIL, - IDS_LLDBDEBUGGER_ERR_THREAD_DELETE, - IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER, - IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME, - IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERED, - IDS_LLDBDEBUGGER_ERR_STOPLISTENER, - IDS_LLDBDEBUGGER_ERR_BROADCASTER_NAME, - IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT, - - IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT, - IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID, - IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND, - IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET, - IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET, - IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE, - IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET, - IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE, - IDS_LLDBOUTOFBAND_ERR_BRKPT_CNT_EXCEEDED, - - IDS_DBGSESSION_ERR_SHARED_DATA_ADD, - - IDS_MI_SHTDWN_ERR_LOG, - IDS_MI_SHUTDOWN_ERR, - IDE_MI_SHTDWN_ERR_RESOURCES, - IDE_MI_SHTDWN_ERR_STREAMSTDIN, - IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER, - IDS_MI_SHTDWN_ERR_STREAMSTDOUT, - IDS_MI_SHTDWN_ERR_STREAMSTDERR, - IDS_MI_SHTDWN_ERR_THREADMGR, - IDS_MI_SHTDWN_ERR_CMDINTERPRETER, - IDS_MI_SHTDWN_ERR_CMDMGR, - IDS_MI_SHTDWN_ERR_CMDFACTORY, - IDS_MI_SHTDWN_ERR_CMDINVOKER, - IDS_MI_SHTDWN_ERR_CMDMONITOR, - IDS_MI_SHTDWN_ERR_LLDBDEBUGGER, - IDS_MI_SHTDWN_ERR_DRIVERMGR, - IDS_MI_SHTDWN_ERR_DRIVER, - IDS_MI_SHTDWN_ERR_OUTOFBANDHANDLER, - IDS_MI_SHTDWN_ERR_DEBUGSESSIONINFO, - IDE_MI_SHTDWN_ERR_THREADMANAGER, - - IDS_DRIVER_ERR_PARSE_ARGS, - IDS_DRIVER_ERR_PARSE_ARGS_UNKNOWN, - IDS_DRIVER_ERR_CURRENT_NOT_SET, - IDS_DRIVER_ERR_NON_REGISTERED, - IDS_DRIVER_SAY_DRIVER_USING, - IDS_DRIVER_ERR_ID_INVALID, - IDS_DRIVER_ERR_FALLTHRU_DRIVER_ERR, - IDS_DRIVER_CMD_RECEIVED, - IDS_DRIVER_CMD_NOT_IN_FACTORY, - IDS_DRIVER_ERR_DRIVER_STATE_ERROR, - IDS_DRIVER_ERR_MAINLOOP, - IDS_DRIVER_ERR_LOCAL_DEBUG_NOT_IMPL, - IDS_DRIVER_ERR_LOCAL_DEBUG_INIT, - - IDS_DRIVER_WAITING_STDIN_DATA, - - IDS_STDERR_ERR_NOT_ALL_DATA_WRITTEN, - - IDS_CMD_ARGS_ERR_OPTION_NOT_FOUND, - IDS_CMD_ARGS_ERR_VALIDATION_MANDATORY, - IDS_CMD_ARGS_ERR_VALIDATION_INVALID, - IDS_CMD_ARGS_ERR_VALIDATION_MAN_INVALID, - IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF, - IDS_CMD_ARGS_ERR_CONTEXT_NOT_ALL_EATTEN, - IDS_CMD_ARGS_ERR_PREFIX_MSG, - - IDS_VARIANT_ERR_USED_BASECLASS, - IDS_VARIANT_ERR_MAP_KEY_INVALID, - - IDS_WORD_INVALIDBRKTS, - IDS_WORD_NONE, - IDS_WORD_NOT, - IDS_WORD_INVALIDEMPTY, - IDS_WORD_INVALIDNULLPTR, - IDS_WORD_UNKNOWNBRKTS, - IDS_WORD_NOT_IMPLEMENTED, - IDS_WORD_NOT_IMPLEMENTED_BRKTS, - IDS_WORD_UNKNOWNTYPE_BRKTS, - IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS, - - IDS_CMD_ERR_N_OPTIONS_REQUIRED, - IDS_CMD_ERR_OPTION_NOT_FOUND, - IDS_CMD_ERR_ARGS, - IDS_CMD_WRN_ARGS_NOT_HANDLED, - IDS_CMD_ERR_FNFAILED, - IDS_CMD_ERR_SHARED_DATA_NOT_FOUND, - IDS_CMD_ERR_LLDBPROCESS_DETACH, - IDS_CMD_ERR_LLDBPROCESS_DESTROY, - IDS_CMD_ERR_SETWKDIR, - IDS_CMD_ERR_INVALID_TARGET, - IDS_CMD_ERR_INVALID_TARGET_CURRENT, - IDS_CMD_ERR_INVALID_TARGET_TYPE, - IDS_CMD_ERR_INVALID_TARGET_PLUGIN, - IDS_CMD_ERR_CONNECT_TO_TARGET, - IDS_CMD_ERR_INVALID_TARGETPLUGINCURRENT, - IDS_CMD_ERR_NOT_IMPLEMENTED, - IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED, - IDS_CMD_ERR_CREATE_TARGET, - IDS_CMD_ERR_BRKPT_LOCATION_FORMAT, - IDS_CMD_ERR_BRKPT_LOCATION_NOT_FOUND, - IDS_CMD_ERR_BRKPT_INVALID, - IDS_CMD_ERR_BRKPT_CNT_EXCEEDED, - IDS_CMD_ERR_SOME_ERROR, - IDS_CMD_ERR_THREAD_INVALID, - IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID, - IDS_CMD_ERR_FRAME_INVALID, - IDS_CMD_ERR_VARIABLE_DOESNOTEXIST, - IDS_CMD_ERR_VARIABLE_ENUM_INVALID, - IDS_CMD_ERR_VARIABLE_EXPRESSIONPATH, - IDS_CMD_ERR_VARIABLE_CREATION_FAILED, - IDS_CMD_ERR_VARIABLE_CHILD_RANGE_INVALID, - IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION, - IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION, - IDS_CMD_ERR_DISASM_ADDR_START_INVALID, - IDS_CMD_ERR_DISASM_ADDR_END_INVALID, - IDS_CMD_ERR_MEMORY_ALLOC_FAILURE, - IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK, - IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES, - IDS_CMD_ERR_INVALID_PROCESS, - IDS_CMD_ERR_INVALID_PRINT_VALUES, - IDS_CMD_ERR_INVALID_LOCATION_FORMAT, - IDS_CMD_ERR_INVALID_FORMAT_TYPE, - IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND, - IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES, - IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK, - IDS_CMD_ERR_SET_NEW_DRIVER_STATE, - IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND, - IDS_CMD_ERR_INFO_PRINTFN_FAILED, - IDS_CMD_ERR_GDBSET_OPT_TARGETASYNC, - IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH, - IDS_CMD_ERR_GDBSET_OPT_PRINT_BAD_ARGS, - IDS_CMD_ERR_GDBSET_OPT_PRINT_UNKNOWN_OPTION, - IDS_CMD_ERR_GDBSHOW_OPT_PRINT_BAD_ARGS, - IDS_CMD_ERR_GDBSHOW_OPT_PRINT_UNKNOWN_OPTION, - IDS_CMD_ERR_EXPR_INVALID, - IDS_CMD_ERR_ATTACH_FAILED, - IDS_CMD_ERR_ATTACH_BAD_ARGS +enum { + IDS_PROJNAME = 1, + IDS_MI_VERSION_DESCRIPTION_DEBUG, + IDS_MI_VERSION_DESCRIPTION, + IDS_MI_APPNAME_SHORT, + IDS_MI_APPNAME_LONG, + IDS_MI_APP_FILEPATHNAME, + IDS_MI_APP_ARGS, + IDE_MI_VERSION_GDB, + + IDS_UTIL_FILE_ERR_INVALID_PATHNAME, + IDS_UTIL_FILE_ERR_OPENING_FILE, + IDS_UTIL_FILE_ERR_OPENING_FILE_UNKNOWN, + IDE_UTIL_FILE_ERR_WRITING_FILE, + IDE_UTIL_FILE_ERR_WRITING_NOTOPEN, + + IDS_RESOURCES_ERR_STRING_NOT_FOUND, + IDS_RESOURCES_ERR_STRING_TABLE_INVALID, + + IDS_MI_CLIENT_MSG, + + IDS_LOG_MSG_CREATION_DATE, + IDS_LOG_MSG_FILE_LOGGER_PATH, + IDS_LOG_MSG_VERSION, + IDS_LOG_ERR_FILE_LOGGER_DISABLED, + IDS_LOG_MEDIUM_ERR_INIT, + IDS_LOG_MEDIUM_ERR_WRITE_ANY, + IDS_LOG_MEDIUM_ERR_WRITE_MEDIUMFAIL, + + IDS_MEDIUMFILE_NAME, + IDS_MEDIUMFILE_ERR_INVALID_PATH, + IDS_MEDIUMFILE_ERR_FILE_HEADER, + IDS_MEDIUMFILE_NAME_LOG, + + IDE_OS_ERR_UNKNOWN, + IDE_OS_ERR_RETRIEVING, + + IDS_DRIVERMGR_DRIVER_ERR_INIT, + + IDE_MEDIUMSTDERR_NAME, + IDE_MEDIUMSTDOUT_NAME, + + IDE_MI_APP_DESCRIPTION, + IDE_MI_APP_INFORMATION, + IDE_MI_APP_ARG_USAGE, + IDE_MI_APP_ARG_HELP, + IDE_MI_APP_ARG_VERSION, + IDE_MI_APP_ARG_VERSION_LONG, + IDE_MI_APP_ARG_INTERPRETER, + IDE_MI_APP_ARG_EXECUTEABLE, + IDE_MI_APP_ARG_SOURCE, + IDE_MI_APP_ARG_APP_LOG, + IDE_MI_APP_ARG_APP_LOG_DIR, + IDE_MI_APP_ARG_EXAMPLE, + IDE_MI_APP_ARG_EXECUTABLE, + + IDS_STDIN_ERR_INVALID_PROMPT, + IDS_STDIN_ERR_THREAD_CREATION_FAILED, + IDS_STDIN_ERR_THREAD_DELETE, + IDS_STDIN_ERR_CHKING_BYTE_AVAILABLE, + IDS_STDIN_INPUT_CTRL_CHARS, + + IDS_CMD_QUIT_HELP, + + IDS_THREADMGR_ERR_THREAD_ID_INVALID, + IDS_THREADMGR_ERR_THREAD_FAIL_CREATE, + IDS_THREADMGR_ERR_THREAD_ID_NOT_FOUND, + IDS_THREADMGR_ERR_THREAD_STILL_ALIVE, + + IDS_FALLTHRU_DRIVER_CMD_RECEIVED, + + IDS_CMDFACTORY_ERR_INVALID_CMD_NAME, + IDS_CMDFACTORY_ERR_INVALID_CMD_CR8FN, + IDS_CMDFACTORY_ERR_CMD_NOT_REGISTERED, + IDS_CMDFACTORY_ERR_CMD_ALREADY_REGED, + + IDS_CMDMGR_ERR_CMD_FAILED_CREATE, + IDS_CMDMGR_ERR_CMD_INVOKER, + + IDS_MI_INIT_ERR_LOG, + IDS_MI_INIT_ERR_RESOURCES, + IDS_MI_INIT_ERR_INIT, + IDS_MI_INIT_ERR_STREAMSTDIN, + IDS_MI_INIT_ERR_STREAMSTDIN_OSHANDLER, + IDS_MI_INIT_ERR_OS_STDIN_HANDLER, + IDS_MI_INIT_ERR_STREAMSTDOUT, + IDS_MI_INIT_ERR_STREAMSTDERR, + IDS_MI_INIT_ERR_FALLTHRUDRIVER, + IDS_MI_INIT_ERR_THREADMGR, + IDS_MI_INIT_ERR_CMDINTERPRETER, + IDS_MI_INIT_ERR_CMDMGR, + IDS_MI_INIT_ERR_CMDFACTORY, + IDS_MI_INIT_ERR_CMDINVOKER, + IDS_MI_INIT_ERR_CMDMONITOR, + IDS_MI_INIT_ERR_LLDBDEBUGGER, + IDS_MI_INIT_ERR_DRIVERMGR, + IDS_MI_INIT_ERR_DRIVER, + IDS_MI_INIT_ERR_OUTOFBANDHANDLER, + IDS_MI_INIT_ERR_DEBUGSESSIONINFO, + IDS_MI_INIT_ERR_THREADMANAGER, + IDS_MI_INIT_ERR_CLIENT_USING_DRIVER, + IDS_MI_INIT_ERR_LOCAL_DEBUG_SESSION, + + IDS_CODE_ERR_INVALID_PARAMETER_VALUE, + IDS_CODE_ERR_INVALID_PARAM_NULL_POINTER, + IDS_CODE_ERR_INVALID_ENUMERATION_VALUE, + + IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER, + IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER, + IDS_LLDBDEBUGGER_ERR_CLIENTDRIVER, + IDS_LLDBDEBUGGER_ERR_STARTLISTENER, + IDS_LLDBDEBUGGER_ERR_THREADCREATIONFAIL, + IDS_LLDBDEBUGGER_ERR_THREAD_DELETE, + IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER, + IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME, + IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERED, + IDS_LLDBDEBUGGER_ERR_STOPLISTENER, + IDS_LLDBDEBUGGER_ERR_BROADCASTER_NAME, + IDS_LLDBDEBUGGER_WRN_UNKNOWN_EVENT, + + IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT, + IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID, + IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND, + IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET, + IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET, + IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE, + IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET, + IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE, + IDS_LLDBOUTOFBAND_ERR_BRKPT_CNT_EXCEEDED, + + IDS_DBGSESSION_ERR_SHARED_DATA_ADD, + + IDS_MI_SHTDWN_ERR_LOG, + IDS_MI_SHUTDOWN_ERR, + IDE_MI_SHTDWN_ERR_RESOURCES, + IDE_MI_SHTDWN_ERR_STREAMSTDIN, + IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER, + IDS_MI_SHTDWN_ERR_STREAMSTDOUT, + IDS_MI_SHTDWN_ERR_STREAMSTDERR, + IDS_MI_SHTDWN_ERR_THREADMGR, + IDS_MI_SHTDWN_ERR_CMDINTERPRETER, + IDS_MI_SHTDWN_ERR_CMDMGR, + IDS_MI_SHTDWN_ERR_CMDFACTORY, + IDS_MI_SHTDWN_ERR_CMDINVOKER, + IDS_MI_SHTDWN_ERR_CMDMONITOR, + IDS_MI_SHTDWN_ERR_LLDBDEBUGGER, + IDS_MI_SHTDWN_ERR_DRIVERMGR, + IDS_MI_SHTDWN_ERR_DRIVER, + IDS_MI_SHTDWN_ERR_OUTOFBANDHANDLER, + IDS_MI_SHTDWN_ERR_DEBUGSESSIONINFO, + IDE_MI_SHTDWN_ERR_THREADMANAGER, + + IDS_DRIVER_ERR_PARSE_ARGS, + IDS_DRIVER_ERR_PARSE_ARGS_UNKNOWN, + IDS_DRIVER_ERR_CURRENT_NOT_SET, + IDS_DRIVER_ERR_NON_REGISTERED, + IDS_DRIVER_SAY_DRIVER_USING, + IDS_DRIVER_ERR_ID_INVALID, + IDS_DRIVER_ERR_FALLTHRU_DRIVER_ERR, + IDS_DRIVER_CMD_RECEIVED, + IDS_DRIVER_CMD_NOT_IN_FACTORY, + IDS_DRIVER_ERR_DRIVER_STATE_ERROR, + IDS_DRIVER_ERR_MAINLOOP, + IDS_DRIVER_ERR_LOCAL_DEBUG_NOT_IMPL, + IDS_DRIVER_ERR_LOCAL_DEBUG_INIT, + + IDS_DRIVER_WAITING_STDIN_DATA, + + IDS_STDERR_ERR_NOT_ALL_DATA_WRITTEN, + + IDS_CMD_ARGS_ERR_OPTION_NOT_FOUND, + IDS_CMD_ARGS_ERR_VALIDATION_MANDATORY, + IDS_CMD_ARGS_ERR_VALIDATION_INVALID, + IDS_CMD_ARGS_ERR_VALIDATION_MAN_INVALID, + IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF, + IDS_CMD_ARGS_ERR_CONTEXT_NOT_ALL_EATTEN, + IDS_CMD_ARGS_ERR_PREFIX_MSG, + + IDS_VARIANT_ERR_USED_BASECLASS, + IDS_VARIANT_ERR_MAP_KEY_INVALID, + + IDS_WORD_INVALIDBRKTS, + IDS_WORD_NONE, + IDS_WORD_NOT, + IDS_WORD_INVALIDEMPTY, + IDS_WORD_INVALIDNULLPTR, + IDS_WORD_UNKNOWNBRKTS, + IDS_WORD_NOT_IMPLEMENTED, + IDS_WORD_NOT_IMPLEMENTED_BRKTS, + IDS_WORD_UNKNOWNTYPE_BRKTS, + IDS_WORD_ERR_MSG_NOT_IMPLEMENTED_BRKTS, + + IDS_CMD_ERR_N_OPTIONS_REQUIRED, + IDS_CMD_ERR_OPTION_NOT_FOUND, + IDS_CMD_ERR_ARGS, + IDS_CMD_WRN_ARGS_NOT_HANDLED, + IDS_CMD_ERR_FNFAILED, + IDS_CMD_ERR_SHARED_DATA_NOT_FOUND, + IDS_CMD_ERR_LLDBPROCESS_DETACH, + IDS_CMD_ERR_LLDBPROCESS_DESTROY, + IDS_CMD_ERR_SETWKDIR, + IDS_CMD_ERR_INVALID_TARGET, + IDS_CMD_ERR_INVALID_TARGET_CURRENT, + IDS_CMD_ERR_INVALID_TARGET_TYPE, + IDS_CMD_ERR_INVALID_TARGET_PLUGIN, + IDS_CMD_ERR_CONNECT_TO_TARGET, + IDS_CMD_ERR_INVALID_TARGETPLUGINCURRENT, + IDS_CMD_ERR_NOT_IMPLEMENTED, + IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED, + IDS_CMD_ERR_CREATE_TARGET, + IDS_CMD_ERR_BRKPT_LOCATION_FORMAT, + IDS_CMD_ERR_BRKPT_LOCATION_NOT_FOUND, + IDS_CMD_ERR_BRKPT_INVALID, + IDS_CMD_ERR_BRKPT_CNT_EXCEEDED, + IDS_CMD_ERR_SOME_ERROR, + IDS_CMD_ERR_THREAD_INVALID, + IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID, + IDS_CMD_ERR_FRAME_INVALID, + IDS_CMD_ERR_VARIABLE_DOESNOTEXIST, + IDS_CMD_ERR_VARIABLE_ENUM_INVALID, + IDS_CMD_ERR_VARIABLE_EXPRESSIONPATH, + IDS_CMD_ERR_VARIABLE_CREATION_FAILED, + IDS_CMD_ERR_VARIABLE_CHILD_RANGE_INVALID, + IDS_CMD_ERR_CMD_RUN_BUT_NO_ACTION, + IDS_CMD_ERR_EVENT_HANDLED_BUT_NO_ACTION, + IDS_CMD_ERR_DISASM_ADDR_START_INVALID, + IDS_CMD_ERR_DISASM_ADDR_END_INVALID, + IDS_CMD_ERR_MEMORY_ALLOC_FAILURE, + IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK, + IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES, + IDS_CMD_ERR_INVALID_PROCESS, + IDS_CMD_ERR_INVALID_PRINT_VALUES, + IDS_CMD_ERR_INVALID_LOCATION_FORMAT, + IDS_CMD_ERR_INVALID_FORMAT_TYPE, + IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND, + IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES, + IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK, + IDS_CMD_ERR_SET_NEW_DRIVER_STATE, + IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND, + IDS_CMD_ERR_INFO_PRINTFN_FAILED, + IDS_CMD_ERR_GDBSET_OPT_TARGETASYNC, + IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH, + IDS_CMD_ERR_GDBSET_OPT_PRINT_BAD_ARGS, + IDS_CMD_ERR_GDBSET_OPT_PRINT_UNKNOWN_OPTION, + IDS_CMD_ERR_GDBSHOW_OPT_PRINT_BAD_ARGS, + IDS_CMD_ERR_GDBSHOW_OPT_PRINT_UNKNOWN_OPTION, + IDS_CMD_ERR_EXPR_INVALID, + IDS_CMD_ERR_ATTACH_FAILED, + IDS_CMD_ERR_ATTACH_BAD_ARGS }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code implementation class. Handle application resources // and locality. // Singleton class. //-- -class CMICmnResources : public CMICmnBase, public MI::ISingleton<CMICmnResources> -{ - friend class MI::ISingleton<CMICmnResources>; - - // Methods: - public: - bool Initialize() override; - bool Shutdown() override; - - CMIUtilString GetString(const MIuint vResourceId) const; - bool HasString(const MIuint vResourceId) const; - - // Typedef: - private: - typedef std::map<MIuint, const char *> MapRscrIdToTextData_t; - typedef std::pair<MIuint, const char *> MapPairRscrIdToTextData_t; - - // Enumerations: - private: - enum Buffer_e - { - eBufferSize = 2048 - }; - - // Structs: - private: - struct SRsrcTextData - { - MIuint id; - const char *pTextData; - }; - - // Methods: - private: - /* ctor */ CMICmnResources(); - /* ctor */ CMICmnResources(const CMICmnResources &); - void operator=(const CMICmnResources &); - - bool GetStringFromResource(const MIuint vResourceId, CMIUtilString &vrwResourceString) const; - bool ReadResourceStringData(); - - // Overridden: - private: - // From CMICmnBase - /* dtor */ ~CMICmnResources() override; - - // Attributes: - private: - static const SRsrcTextData ms_pResourceId2TextData[]; - // - MIuint m_nResourceId2TextDataSize; - MapRscrIdToTextData_t m_mapRscrIdToTextData; +class CMICmnResources : public CMICmnBase, + public MI::ISingleton<CMICmnResources> { + friend class MI::ISingleton<CMICmnResources>; + + // Methods: +public: + bool Initialize() override; + bool Shutdown() override; + + CMIUtilString GetString(const MIuint vResourceId) const; + bool HasString(const MIuint vResourceId) const; + + // Typedef: +private: + typedef std::map<MIuint, const char *> MapRscrIdToTextData_t; + typedef std::pair<MIuint, const char *> MapPairRscrIdToTextData_t; + + // Enumerations: +private: + enum Buffer_e { eBufferSize = 2048 }; + + // Structs: +private: + struct SRsrcTextData { + MIuint id; + const char *pTextData; + }; + + // Methods: +private: + /* ctor */ CMICmnResources(); + /* ctor */ CMICmnResources(const CMICmnResources &); + void operator=(const CMICmnResources &); + + bool GetStringFromResource(const MIuint vResourceId, + CMIUtilString &vrwResourceString) const; + bool ReadResourceStringData(); + + // Overridden: +private: + // From CMICmnBase + /* dtor */ ~CMICmnResources() override; + + // Attributes: +private: + static const SRsrcTextData ms_pResourceId2TextData[]; + // + MIuint m_nResourceId2TextDataSize; + MapRscrIdToTextData_t m_mapRscrIdToTextData; }; //++ ========================================================================= diff --git a/lldb/tools/lldb-mi/MICmnStreamStderr.cpp b/lldb/tools/lldb-mi/MICmnStreamStderr.cpp index e5c494ba38f..2bbbd4b5058 100644 --- a/lldb/tools/lldb-mi/MICmnStreamStderr.cpp +++ b/lldb/tools/lldb-mi/MICmnStreamStderr.cpp @@ -1,4 +1,5 @@ -//===-- MICmnStreamStderr.cpp ------------------------------------*- C++ -*-===// +//===-- MICmnStreamStderr.cpp ------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -13,30 +14,28 @@ #include "MICmnResources.h" #include "MIDriver.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnStreamStderr constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmnStreamStderr::CMICmnStreamStderr() -{ -} +CMICmnStreamStderr::CMICmnStreamStderr() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnStreamStderr destructor. // Type: Overridable. // Args: None. // Return: None. // Throws: None. //-- -CMICmnStreamStderr::~CMICmnStreamStderr() -{ - Shutdown(); -} +CMICmnStreamStderr::~CMICmnStreamStderr() { Shutdown(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Initialize resources for *this stderr stream. // Type: Method. // Args: None. @@ -44,15 +43,13 @@ CMICmnStreamStderr::~CMICmnStreamStderr() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnStreamStderr::Initialize() -{ - m_clientUsageRefCnt++; +bool CMICmnStreamStderr::Initialize() { + m_clientUsageRefCnt++; - if (m_bInitialized) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - bool bOk = MIstatus::success; + bool bOk = MIstatus::success; #ifdef _MSC_VER // Debugging / I/O issues with client. @@ -62,12 +59,13 @@ CMICmnStreamStderr::Initialize() //::setbuf( stderr, NULL ); #endif // _MSC_VER - m_bInitialized = bOk; + m_bInitialized = bOk; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release resources for *this stderr stream. // Type: Method. // Args: None. @@ -75,114 +73,125 @@ CMICmnStreamStderr::Initialize() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnStreamStderr::Shutdown() -{ - if (--m_clientUsageRefCnt > 0) - return MIstatus::success; +bool CMICmnStreamStderr::Shutdown() { + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - if (!m_bInitialized) - return MIstatus::success; + if (!m_bInitialized) + return MIstatus::success; - ClrErrorDescription(); + ClrErrorDescription(); - m_bInitialized = false; + m_bInitialized = false; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Write text data to stderr. Prefix the message with "MI:". The text data does -// not need to include a carriage line return as this is added to the text. The +//++ +//------------------------------------------------------------------------------------ +// Details: Write text data to stderr. Prefix the message with "MI:". The text +// data does +// not need to include a carriage line return as this is added to the +// text. The // function also then passes the text data into the CMICmnLog logger. // Type: Method. // Args: vText - (R) Text data. -// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) +// vbSendToLog - (R) True = Yes send to the Log file too, false = do +// not. (Dflt = true) // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnStreamStderr::Write(const CMIUtilString &vText, const bool vbSendToLog /* = true */) -{ - if (vText.length() == 0) - return MIstatus::failure; +bool CMICmnStreamStderr::Write(const CMIUtilString &vText, + const bool vbSendToLog /* = true */) { + if (vText.length() == 0) + return MIstatus::failure; - const CMIUtilString strPrefixed(CMIUtilString::Format("%s: %s", CMIDriver::Instance().GetAppNameShort().c_str(), vText.c_str())); + const CMIUtilString strPrefixed(CMIUtilString::Format( + "%s: %s", CMIDriver::Instance().GetAppNameShort().c_str(), + vText.c_str())); - return WritePriv(strPrefixed, vText, vbSendToLog); + return WritePriv(strPrefixed, vText, vbSendToLog); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Write an LLDB text message to stderr. -// The text data does not need to include a carriage line return as this is added -// to the text. The function also then passes the text data into the CMICmnLog +// The text data does not need to include a carriage line return as +// this is added +// to the text. The function also then passes the text data into the +// CMICmnLog // logger. // Type: Method. // Args: vText - (R) Text data. -// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) +// vbSendToLog - (R) True = Yes send to the Log file too, false = do +// not. (Dflt = true) // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnStreamStderr::WriteLLDBMsg(const CMIUtilString &vText, const bool vbSendToLog /* = true */) -{ - if (vText.length() == 0) - return MIstatus::failure; +bool CMICmnStreamStderr::WriteLLDBMsg(const CMIUtilString &vText, + const bool vbSendToLog /* = true */) { + if (vText.length() == 0) + return MIstatus::failure; - const CMIUtilString strPrefixed(CMIUtilString::Format("LLDB: %s", vText.c_str())); + const CMIUtilString strPrefixed( + CMIUtilString::Format("LLDB: %s", vText.c_str())); - return WritePriv(vText, strPrefixed, vbSendToLog); + return WritePriv(vText, strPrefixed, vbSendToLog); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Write text data to stderr. The text data does not need to -// include a carriage line return as this is added to the text. The function also +// include a carriage line return as this is added to the text. The +// function also // then passes the text data into the CMICmnLog logger. // Type: Method. -// Args: vText - (R) Text data. May be prefixed with MI app's short name. +// Args: vText - (R) Text data. May be prefixed with MI app's short +// name. // vTxtForLogFile - (R) Text data. -// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) +// vbSendToLog - (R) True = Yes send to the Log file too, false = +// do not. (Dflt = true) // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnStreamStderr::WritePriv(const CMIUtilString &vText, const CMIUtilString &vTxtForLogFile, const bool vbSendToLog /* = true */) -{ - if (vText.length() == 0) - return MIstatus::failure; - - bool bOk = MIstatus::success; - { - // Grab the stderr thread lock while we print - CMIUtilThreadLock _lock(m_mutex); - - // Send this text to stderr - const MIint status = ::fputs(vText.c_str(), stderr); - if (status == EOF) - { - const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_STDERR_ERR_NOT_ALL_DATA_WRITTEN), vText.c_str())); - SetErrorDescription(errMsg); - bOk = MIstatus::failure; - } - else - { - ::fprintf(stderr, "\n"); - ::fflush(stderr); - } - - // Send this text to the log - if (bOk && vbSendToLog) - bOk &= m_pLog->WriteLog(vTxtForLogFile); +bool CMICmnStreamStderr::WritePriv(const CMIUtilString &vText, + const CMIUtilString &vTxtForLogFile, + const bool vbSendToLog /* = true */) { + if (vText.length() == 0) + return MIstatus::failure; + + bool bOk = MIstatus::success; + { + // Grab the stderr thread lock while we print + CMIUtilThreadLock _lock(m_mutex); + + // Send this text to stderr + const MIint status = ::fputs(vText.c_str(), stderr); + if (status == EOF) { + const CMIUtilString errMsg(CMIUtilString::Format( + MIRSRC(IDS_STDERR_ERR_NOT_ALL_DATA_WRITTEN), vText.c_str())); + SetErrorDescription(errMsg); + bOk = MIstatus::failure; + } else { + ::fprintf(stderr, "\n"); + ::fflush(stderr); } - return bOk; + // Send this text to the log + if (bOk && vbSendToLog) + bOk &= m_pLog->WriteLog(vTxtForLogFile); + } + + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Lock the availability of the stream stderr. Other users of *this stream will +//++ +//------------------------------------------------------------------------------------ +// Details: Lock the availability of the stream stderr. Other users of *this +// stream will // be stalled until it is available (Unlock()). // Type: Method. // Args: None. @@ -190,14 +199,13 @@ CMICmnStreamStderr::WritePriv(const CMIUtilString &vText, const CMIUtilString &v // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnStreamStderr::Lock() -{ - m_mutex.Lock(); - return MIstatus::success; +bool CMICmnStreamStderr::Lock() { + m_mutex.Lock(); + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release a previously locked stderr. // Type: Method. // Args: None. @@ -205,15 +213,15 @@ CMICmnStreamStderr::Lock() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnStreamStderr::Unlock() -{ - m_mutex.Unlock(); - return MIstatus::success; +bool CMICmnStreamStderr::Unlock() { + m_mutex.Unlock(); + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Take MI Driver text message and send to the stderr stream. Also output to the +//++ +//------------------------------------------------------------------------------------ +// Details: Take MI Driver text message and send to the stderr stream. Also +// output to the // MI Log file. // Type: Static method. // Args: vrTxt - (R) Text. @@ -221,20 +229,22 @@ CMICmnStreamStderr::Unlock() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnStreamStderr::TextToStderr(const CMIUtilString &vrTxt) -{ - const bool bLock = CMICmnStreamStderr::Instance().Lock(); - const bool bOk = bLock && CMICmnStreamStderr::Instance().Write(vrTxt); - bLock &&CMICmnStreamStderr::Instance().Unlock(); - - return bOk; +bool CMICmnStreamStderr::TextToStderr(const CMIUtilString &vrTxt) { + const bool bLock = CMICmnStreamStderr::Instance().Lock(); + const bool bOk = bLock && CMICmnStreamStderr::Instance().Write(vrTxt); + bLock &&CMICmnStreamStderr::Instance().Unlock(); + + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Take an LLDB message and send to the stderr stream. The message is not always -// an error message. The user has typed a command in to the Eclipse console (by- -// passing Eclipse) and this is the result message from LLDB back to the user. +//++ +//------------------------------------------------------------------------------------ +// Details: Take an LLDB message and send to the stderr stream. The message is +// not always +// an error message. The user has typed a command in to the Eclipse +// console (by- +// passing Eclipse) and this is the result message from LLDB back to +// the user. // Also output to the MI Log file. // Type: Static method. // Args: vrTxt - (R) Text. @@ -242,12 +252,10 @@ CMICmnStreamStderr::TextToStderr(const CMIUtilString &vrTxt) // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnStreamStderr::LLDBMsgToConsole(const CMIUtilString &vrTxt) -{ - const bool bLock = CMICmnStreamStderr::Instance().Lock(); - const bool bOk = bLock && CMICmnStreamStderr::Instance().WriteLLDBMsg(vrTxt); - bLock &&CMICmnStreamStderr::Instance().Unlock(); - - return bOk; +bool CMICmnStreamStderr::LLDBMsgToConsole(const CMIUtilString &vrTxt) { + const bool bLock = CMICmnStreamStderr::Instance().Lock(); + const bool bOk = bLock && CMICmnStreamStderr::Instance().WriteLLDBMsg(vrTxt); + bLock &&CMICmnStreamStderr::Instance().Unlock(); + + return bOk; } diff --git a/lldb/tools/lldb-mi/MICmnStreamStderr.h b/lldb/tools/lldb-mi/MICmnStreamStderr.h index 95085a2a327..07943d02c4d 100644 --- a/lldb/tools/lldb-mi/MICmnStreamStderr.h +++ b/lldb/tools/lldb-mi/MICmnStreamStderr.h @@ -10,50 +10,53 @@ #pragma once // In-house headers: -#include "MIUtilString.h" #include "MICmnBase.h" #include "MIUtilSingletonBase.h" +#include "MIUtilString.h" #include "MIUtilThreadBaseStd.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code class. The MI driver requires this object. // CMICmnStreamStderr sets up and tears downs stderr for the driver. // // Singleton class. //-- -class CMICmnStreamStderr : public CMICmnBase, public MI::ISingleton<CMICmnStreamStderr> -{ - friend class MI::ISingleton<CMICmnStreamStderr>; - - // Statics: - public: - static bool TextToStderr(const CMIUtilString &vrTxt); - static bool LLDBMsgToConsole(const CMIUtilString &vrTxt); - - // Methods: - public: - bool Initialize() override; - bool Shutdown() override; - // - bool Lock(); - bool Unlock(); - bool Write(const CMIUtilString &vText, const bool vbSendToLog = true); - bool WriteLLDBMsg(const CMIUtilString &vText, const bool vbSendToLog = true); - - // Methods: - private: - /* ctor */ CMICmnStreamStderr(); - /* ctor */ CMICmnStreamStderr(const CMICmnStreamStderr &); - void operator=(const CMICmnStreamStderr &); - // - bool WritePriv(const CMIUtilString &vText, const CMIUtilString &vTxtForLogFile, const bool vbSendToLog = true); - - // Overridden: - private: - // From CMICmnBase - /* dtor */ ~CMICmnStreamStderr() override; - - // Attributes: - private: - CMIUtilThreadMutex m_mutex; // Mutex object for sync during Write() +class CMICmnStreamStderr : public CMICmnBase, + public MI::ISingleton<CMICmnStreamStderr> { + friend class MI::ISingleton<CMICmnStreamStderr>; + + // Statics: +public: + static bool TextToStderr(const CMIUtilString &vrTxt); + static bool LLDBMsgToConsole(const CMIUtilString &vrTxt); + + // Methods: +public: + bool Initialize() override; + bool Shutdown() override; + // + bool Lock(); + bool Unlock(); + bool Write(const CMIUtilString &vText, const bool vbSendToLog = true); + bool WriteLLDBMsg(const CMIUtilString &vText, const bool vbSendToLog = true); + + // Methods: +private: + /* ctor */ CMICmnStreamStderr(); + /* ctor */ CMICmnStreamStderr(const CMICmnStreamStderr &); + void operator=(const CMICmnStreamStderr &); + // + bool WritePriv(const CMIUtilString &vText, + const CMIUtilString &vTxtForLogFile, + const bool vbSendToLog = true); + + // Overridden: +private: + // From CMICmnBase + /* dtor */ ~CMICmnStreamStderr() override; + + // Attributes: +private: + CMIUtilThreadMutex m_mutex; // Mutex object for sync during Write() }; diff --git a/lldb/tools/lldb-mi/MICmnStreamStdin.cpp b/lldb/tools/lldb-mi/MICmnStreamStdin.cpp index 60fa49c4988..f560ecea667 100644 --- a/lldb/tools/lldb-mi/MICmnStreamStdin.cpp +++ b/lldb/tools/lldb-mi/MICmnStreamStdin.cpp @@ -14,14 +14,15 @@ #include <string.h> // For std::strerror() // In-house headers: +#include "MICmnLog.h" +#include "MICmnResources.h" #include "MICmnStreamStdin.h" #include "MICmnStreamStdout.h" -#include "MICmnResources.h" -#include "MICmnLog.h" #include "MIDriver.h" #include "MIUtilSingletonHelper.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnStreamStdin constructor. // Type: Method. // Args: None. @@ -29,25 +30,20 @@ // Throws: None. //-- CMICmnStreamStdin::CMICmnStreamStdin() - : m_strPromptCurrent("(gdb)") - , m_bShowPrompt(true) - , m_pCmdBuffer(nullptr) -{ -} + : m_strPromptCurrent("(gdb)"), m_bShowPrompt(true), m_pCmdBuffer(nullptr) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnStreamStdin destructor. // Type: Overridable. // Args: None. // Return: None. // Throws: None. //-- -CMICmnStreamStdin::~CMICmnStreamStdin() -{ - Shutdown(); -} +CMICmnStreamStdin::~CMICmnStreamStdin() { Shutdown(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Initialize resources for *this Stdin stream. // Type: Method. // Args: None. @@ -55,38 +51,36 @@ CMICmnStreamStdin::~CMICmnStreamStdin() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnStreamStdin::Initialize() -{ - m_clientUsageRefCnt++; +bool CMICmnStreamStdin::Initialize() { + m_clientUsageRefCnt++; - if (m_bInitialized) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - bool bOk = MIstatus::success; - CMIUtilString errMsg; + bool bOk = MIstatus::success; + CMIUtilString errMsg; - // Note initialisation order is important here as some resources depend on previous - MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); - MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + // Note initialisation order is important here as some resources depend on + // previous + MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); - if (bOk) - { - m_pCmdBuffer = new char[m_constBufferSize]; - } - else - { - CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_STREAMSTDIN), errMsg.c_str())); - SetErrorDescription(strInitError); + if (bOk) { + m_pCmdBuffer = new char[m_constBufferSize]; + } else { + CMIUtilString strInitError(CMIUtilString::Format( + MIRSRC(IDS_MI_INIT_ERR_STREAMSTDIN), errMsg.c_str())); + SetErrorDescription(strInitError); - return MIstatus::failure; - } - m_bInitialized = bOk; + return MIstatus::failure; + } + m_bInitialized = bOk; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release resources for *this Stdin stream. // Type: Method. // Args: None. @@ -94,40 +88,37 @@ CMICmnStreamStdin::Initialize() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnStreamStdin::Shutdown() -{ - if (--m_clientUsageRefCnt > 0) - return MIstatus::success; +bool CMICmnStreamStdin::Shutdown() { + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - if (!m_bInitialized) - return MIstatus::success; + if (!m_bInitialized) + return MIstatus::success; - m_bInitialized = false; + m_bInitialized = false; - ClrErrorDescription(); + ClrErrorDescription(); - if (m_pCmdBuffer != nullptr) - { - delete[] m_pCmdBuffer; - m_pCmdBuffer = nullptr; - } + if (m_pCmdBuffer != nullptr) { + delete[] m_pCmdBuffer; + m_pCmdBuffer = nullptr; + } - bool bOk = MIstatus::success; - CMIUtilString errMsg; + bool bOk = MIstatus::success; + CMIUtilString errMsg; - MI::ModuleShutdown<CMICmnResources>(IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg); - MI::ModuleShutdown<CMICmnLog>(IDS_MI_SHTDWN_ERR_LOG, bOk, errMsg); + MI::ModuleShutdown<CMICmnResources>(IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg); + MI::ModuleShutdown<CMICmnLog>(IDS_MI_SHTDWN_ERR_LOG, bOk, errMsg); - if (!bOk) - { - SetErrorDescriptionn(MIRSRC(IDE_MI_SHTDWN_ERR_STREAMSTDIN), errMsg.c_str()); - } + if (!bOk) { + SetErrorDescriptionn(MIRSRC(IDE_MI_SHTDWN_ERR_STREAMSTDIN), errMsg.c_str()); + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Validate and set the text that forms the prompt on the command line. // Type: Method. // Args: vNewPrompt - (R) Text description. @@ -135,107 +126,103 @@ CMICmnStreamStdin::Shutdown() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnStreamStdin::SetPrompt(const CMIUtilString &vNewPrompt) -{ - if (vNewPrompt.empty()) - { - const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_STDIN_ERR_INVALID_PROMPT), vNewPrompt.c_str())); - CMICmnStreamStdout::Instance().Write(msg); - return MIstatus::failure; - } +bool CMICmnStreamStdin::SetPrompt(const CMIUtilString &vNewPrompt) { + if (vNewPrompt.empty()) { + const CMIUtilString msg(CMIUtilString::Format( + MIRSRC(IDS_STDIN_ERR_INVALID_PROMPT), vNewPrompt.c_str())); + CMICmnStreamStdout::Instance().Write(msg); + return MIstatus::failure; + } - m_strPromptCurrent = vNewPrompt; + m_strPromptCurrent = vNewPrompt; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the command line prompt text currently being used. // Type: Method. // Args: None. // Return: const CMIUtilString & - Functional failed. // Throws: None. //-- -const CMIUtilString & -CMICmnStreamStdin::GetPrompt() const -{ - return m_strPromptCurrent; +const CMIUtilString &CMICmnStreamStdin::GetPrompt() const { + return m_strPromptCurrent; } -//++ ------------------------------------------------------------------------------------ -// Details: Set whether to display optional command line prompt. The prompt is output to -// stdout. Disable it when this may interfere with the client reading stdout as +//++ +//------------------------------------------------------------------------------------ +// Details: Set whether to display optional command line prompt. The prompt is +// output to +// stdout. Disable it when this may interfere with the client reading +// stdout as // input and it tries to interpret the prompt text to. // Type: Method. -// Args: vbYes - (R) True = Yes prompt is shown/output to the user (stdout), false = no prompt. +// Args: vbYes - (R) True = Yes prompt is shown/output to the user +// (stdout), false = no prompt. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -void -CMICmnStreamStdin::SetEnablePrompt(const bool vbYes) -{ - m_bShowPrompt = vbYes; +void CMICmnStreamStdin::SetEnablePrompt(const bool vbYes) { + m_bShowPrompt = vbYes; } -//++ ------------------------------------------------------------------------------------ -// Details: Get whether to display optional command line prompt. The prompt is output to -// stdout. Disable it when this may interfere with the client reading stdout as +//++ +//------------------------------------------------------------------------------------ +// Details: Get whether to display optional command line prompt. The prompt is +// output to +// stdout. Disable it when this may interfere with the client reading +// stdout as // input and it tries to interpret the prompt text to. // Type: Method. // Args: None. -// Return: bool - True = Yes prompt is shown/output to the user (stdout), false = no prompt. +// Return: bool - True = Yes prompt is shown/output to the user (stdout), false +// = no prompt. // Throws: None. //-- -bool -CMICmnStreamStdin::GetEnablePrompt() const -{ - return m_bShowPrompt; -} +bool CMICmnStreamStdin::GetEnablePrompt() const { return m_bShowPrompt; } -//++ ------------------------------------------------------------------------------------ -// Details: Wait on new line of data from stdin stream (completed by '\n' or '\r'). +//++ +//------------------------------------------------------------------------------------ +// Details: Wait on new line of data from stdin stream (completed by '\n' or +// '\r'). // Type: Method. // Args: vwErrMsg - (W) Empty string ok or error description. // Return: char * - text buffer pointer or NULL on failure. // Throws: None. //-- -const char * -CMICmnStreamStdin::ReadLine(CMIUtilString &vwErrMsg) -{ - vwErrMsg.clear(); - - // Read user input - const char *pText = ::fgets(&m_pCmdBuffer[0], m_constBufferSize, stdin); - if (pText == nullptr) - { +const char *CMICmnStreamStdin::ReadLine(CMIUtilString &vwErrMsg) { + vwErrMsg.clear(); + + // Read user input + const char *pText = ::fgets(&m_pCmdBuffer[0], m_constBufferSize, stdin); + if (pText == nullptr) { #ifdef _MSC_VER - // Was Ctrl-C hit? - // On Windows, Ctrl-C gives an ERROR_OPERATION_ABORTED as error on the command-line. - // The end-of-file indicator is also set, so without this check we will exit next if statement. - if (::GetLastError() == ERROR_OPERATION_ABORTED) - return nullptr; + // Was Ctrl-C hit? + // On Windows, Ctrl-C gives an ERROR_OPERATION_ABORTED as error on the + // command-line. + // The end-of-file indicator is also set, so without this check we will exit + // next if statement. + if (::GetLastError() == ERROR_OPERATION_ABORTED) + return nullptr; #endif - if (::feof(stdin)) - { - const bool bForceExit = true; - CMIDriver::Instance().SetExitApplicationFlag(bForceExit); - } - else if (::ferror(stdin) != 0) - vwErrMsg = ::strerror(errno); - return nullptr; - } - - // Strip off new line characters - for (char *pI = m_pCmdBuffer; *pI != '\0'; pI++) - { - if ((*pI == '\n') || (*pI == '\r')) - { - *pI = '\0'; - break; - } + if (::feof(stdin)) { + const bool bForceExit = true; + CMIDriver::Instance().SetExitApplicationFlag(bForceExit); + } else if (::ferror(stdin) != 0) + vwErrMsg = ::strerror(errno); + return nullptr; + } + + // Strip off new line characters + for (char *pI = m_pCmdBuffer; *pI != '\0'; pI++) { + if ((*pI == '\n') || (*pI == '\r')) { + *pI = '\0'; + break; } + } - return pText; + return pText; } diff --git a/lldb/tools/lldb-mi/MICmnStreamStdin.h b/lldb/tools/lldb-mi/MICmnStreamStdin.h index a4b12a59412..6483e90c6cb 100644 --- a/lldb/tools/lldb-mi/MICmnStreamStdin.h +++ b/lldb/tools/lldb-mi/MICmnStreamStdin.h @@ -10,49 +10,52 @@ #pragma once // In-house headers: -#include "MIUtilString.h" -#include "MIUtilThreadBaseStd.h" #include "MICmnBase.h" #include "MIUtilSingletonBase.h" +#include "MIUtilString.h" +#include "MIUtilThreadBaseStd.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code class. Used to handle stream data from Stdin. -// Singleton class using the Visitor pattern. A driver using the interface +// Singleton class using the Visitor pattern. A driver using the +// interface // provide can receive callbacks when a new line of data is received. // Each line is determined by a carriage return. // A singleton class. //-- -class CMICmnStreamStdin : public CMICmnBase, public MI::ISingleton<CMICmnStreamStdin> -{ - // Give singleton access to private constructors - friend MI::ISingleton<CMICmnStreamStdin>; +class CMICmnStreamStdin : public CMICmnBase, + public MI::ISingleton<CMICmnStreamStdin> { + // Give singleton access to private constructors + friend MI::ISingleton<CMICmnStreamStdin>; - // Methods: - public: - bool Initialize() override; - bool Shutdown() override; - // - const CMIUtilString &GetPrompt() const; - bool SetPrompt(const CMIUtilString &vNewPrompt); - void SetEnablePrompt(const bool vbYes); - bool GetEnablePrompt() const; - const char *ReadLine(CMIUtilString &vwErrMsg); + // Methods: +public: + bool Initialize() override; + bool Shutdown() override; + // + const CMIUtilString &GetPrompt() const; + bool SetPrompt(const CMIUtilString &vNewPrompt); + void SetEnablePrompt(const bool vbYes); + bool GetEnablePrompt() const; + const char *ReadLine(CMIUtilString &vwErrMsg); - // Methods: - private: - /* ctor */ CMICmnStreamStdin(); - /* ctor */ CMICmnStreamStdin(const CMICmnStreamStdin &); - void operator=(const CMICmnStreamStdin &); + // Methods: +private: + /* ctor */ CMICmnStreamStdin(); + /* ctor */ CMICmnStreamStdin(const CMICmnStreamStdin &); + void operator=(const CMICmnStreamStdin &); - // Overridden: - private: - // From CMICmnBase - /* dtor */ ~CMICmnStreamStdin() override; + // Overridden: +private: + // From CMICmnBase + /* dtor */ ~CMICmnStreamStdin() override; - // Attributes: - private: - CMIUtilString m_strPromptCurrent; // Command line prompt as shown to the user - bool m_bShowPrompt; // True = Yes prompt is shown/output to the user (stdout), false = no prompt - static const int m_constBufferSize = 2048; - char *m_pCmdBuffer; + // Attributes: +private: + CMIUtilString m_strPromptCurrent; // Command line prompt as shown to the user + bool m_bShowPrompt; // True = Yes prompt is shown/output to the user (stdout), + // false = no prompt + static const int m_constBufferSize = 2048; + char *m_pCmdBuffer; }; diff --git a/lldb/tools/lldb-mi/MICmnStreamStdout.cpp b/lldb/tools/lldb-mi/MICmnStreamStdout.cpp index 8b65251423b..064c74fab20 100644 --- a/lldb/tools/lldb-mi/MICmnStreamStdout.cpp +++ b/lldb/tools/lldb-mi/MICmnStreamStdout.cpp @@ -13,30 +13,28 @@ #include "MICmnResources.h" #include "MIDriver.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnStreamStdout constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmnStreamStdout::CMICmnStreamStdout() -{ -} +CMICmnStreamStdout::CMICmnStreamStdout() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnStreamStdout destructor. // Type: Overridable. // Args: None. // Return: None. // Throws: None. //-- -CMICmnStreamStdout::~CMICmnStreamStdout() -{ - Shutdown(); -} +CMICmnStreamStdout::~CMICmnStreamStdout() { Shutdown(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Initialize resources for *this Stdout stream. // Type: Method. // Args: None. @@ -44,15 +42,13 @@ CMICmnStreamStdout::~CMICmnStreamStdout() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnStreamStdout::Initialize() -{ - m_clientUsageRefCnt++; +bool CMICmnStreamStdout::Initialize() { + m_clientUsageRefCnt++; - if (m_bInitialized) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - bool bOk = MIstatus::success; + bool bOk = MIstatus::success; #ifdef _MSC_VER // Debugging / I/O issues with client. @@ -62,12 +58,13 @@ CMICmnStreamStdout::Initialize() //::setbuf( stdout, NULL ); #endif // _MSC_VER - m_bInitialized = bOk; + m_bInitialized = bOk; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release resources for *this Stdout stream. // Type: Method. // Args: None. @@ -75,106 +72,117 @@ CMICmnStreamStdout::Initialize() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnStreamStdout::Shutdown() -{ - if (--m_clientUsageRefCnt > 0) - return MIstatus::success; +bool CMICmnStreamStdout::Shutdown() { + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - if (!m_bInitialized) - return MIstatus::success; + if (!m_bInitialized) + return MIstatus::success; - ClrErrorDescription(); + ClrErrorDescription(); - m_bInitialized = false; + m_bInitialized = false; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Write an MI format type response to stdout. The text data does not need to -// include a carriage line return as this is added to the text. The function also +//++ +//------------------------------------------------------------------------------------ +// Details: Write an MI format type response to stdout. The text data does not +// need to +// include a carriage line return as this is added to the text. The +// function also // then passes the text data into the CMICmnLog logger. // Type: Method. // Args: vText - (R) MI formatted text. -// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) +// vbSendToLog - (R) True = Yes send to the Log file too, false = do +// not. (Dflt = true) // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnStreamStdout::WriteMIResponse(const CMIUtilString &vText, const bool vbSendToLog /* = true */) -{ - return WritePriv(vText, vText, vbSendToLog); +bool CMICmnStreamStdout::WriteMIResponse(const CMIUtilString &vText, + const bool vbSendToLog /* = true */) { + return WritePriv(vText, vText, vbSendToLog); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Write text data to stdout. The text data does not need to -// include a carriage line return as this is added to the text. The function also +// include a carriage line return as this is added to the text. The +// function also // then passes the text data into the CMICmnLog logger. // Type: Method. // Args: vText - (R) Text data. -// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) +// vbSendToLog - (R) True = Yes send to the Log file too, false = do +// not. (Dflt = true) // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnStreamStdout::Write(const CMIUtilString &vText, const bool vbSendToLog /* = true */) -{ - if (vText.length() == 0) - return MIstatus::failure; +bool CMICmnStreamStdout::Write(const CMIUtilString &vText, + const bool vbSendToLog /* = true */) { + if (vText.length() == 0) + return MIstatus::failure; - const CMIUtilString strPrefixed(CMIUtilString::Format("%s: %s", CMIDriver::Instance().GetAppNameShort().c_str(), vText.c_str())); + const CMIUtilString strPrefixed(CMIUtilString::Format( + "%s: %s", CMIDriver::Instance().GetAppNameShort().c_str(), + vText.c_str())); - return WritePriv(strPrefixed, vText, vbSendToLog); + return WritePriv(strPrefixed, vText, vbSendToLog); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Write text data to stdout. The text data does not need to -// include a carriage line return as this is added to the text. The function also +// include a carriage line return as this is added to the text. The +// function also // then passes the text data into the CMICmnLog logger. // Type: Method. // Args: vText - (R) Text data prefixed with MI app's short name. // vTxtForLogFile - (R) Text data. -// vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) +// vbSendToLog - (R) True = Yes send to the Log file too, false = +// do not. (Dflt = true) // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnStreamStdout::WritePriv(const CMIUtilString &vText, const CMIUtilString &vTxtForLogFile, const bool vbSendToLog /* = true */) -{ - if (vText.length() == 0) - return MIstatus::failure; - - bool bOk = MIstatus::success; - { - // Grab the stdout thread lock while we print - CMIUtilThreadLock _lock(m_mutex); - - // Send this text to stdout - const MIint status = ::fputs(vText.c_str(), stdout); - if (status == EOF) - // Don't call the CMICmnBase::SetErrorDescription() because it will cause a stack overflow: - // CMICmnBase::SetErrorDescription -> CMICmnStreamStdout::Write -> CMICmnStreamStdout::WritePriv -> CMICmnBase::SetErrorDescription - bOk = MIstatus::failure; - else - { - ::fprintf(stdout, "\n"); - ::fflush(stdout); - } - - // Send this text to the log - if (bOk && vbSendToLog) - bOk &= m_pLog->WriteLog(vTxtForLogFile); +bool CMICmnStreamStdout::WritePriv(const CMIUtilString &vText, + const CMIUtilString &vTxtForLogFile, + const bool vbSendToLog /* = true */) { + if (vText.length() == 0) + return MIstatus::failure; + + bool bOk = MIstatus::success; + { + // Grab the stdout thread lock while we print + CMIUtilThreadLock _lock(m_mutex); + + // Send this text to stdout + const MIint status = ::fputs(vText.c_str(), stdout); + if (status == EOF) + // Don't call the CMICmnBase::SetErrorDescription() because it will cause + // a stack overflow: + // CMICmnBase::SetErrorDescription -> CMICmnStreamStdout::Write -> + // CMICmnStreamStdout::WritePriv -> CMICmnBase::SetErrorDescription + bOk = MIstatus::failure; + else { + ::fprintf(stdout, "\n"); + ::fflush(stdout); } - return bOk; + // Send this text to the log + if (bOk && vbSendToLog) + bOk &= m_pLog->WriteLog(vTxtForLogFile); + } + + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Lock the availability of the stream stdout. Other users of *this stream will +//++ +//------------------------------------------------------------------------------------ +// Details: Lock the availability of the stream stdout. Other users of *this +// stream will // be stalled until it is available (Unlock()). // Type: Method. // Args: None. @@ -182,14 +190,13 @@ CMICmnStreamStdout::WritePriv(const CMIUtilString &vText, const CMIUtilString &v // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnStreamStdout::Lock() -{ - m_mutex.Lock(); - return MIstatus::success; +bool CMICmnStreamStdout::Lock() { + m_mutex.Lock(); + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release a previously locked stdout. // Type: Method. // Args: None. @@ -197,15 +204,15 @@ CMICmnStreamStdout::Lock() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnStreamStdout::Unlock() -{ - m_mutex.Unlock(); - return MIstatus::success; +bool CMICmnStreamStdout::Unlock() { + m_mutex.Unlock(); + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Take a text data and send to the stdout stream. Also output to the MI Log +//++ +//------------------------------------------------------------------------------------ +// Details: Take a text data and send to the stdout stream. Also output to the +// MI Log // file. // Type: Static method. // Args: vrTxt - (R) Text. @@ -213,14 +220,13 @@ CMICmnStreamStdout::Unlock() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMICmnStreamStdout::TextToStdout(const CMIUtilString &vrTxt) -{ - const bool bSendToLog = true; - return CMICmnStreamStdout::Instance().WriteMIResponse(vrTxt, bSendToLog); +bool CMICmnStreamStdout::TextToStdout(const CMIUtilString &vrTxt) { + const bool bSendToLog = true; + return CMICmnStreamStdout::Instance().WriteMIResponse(vrTxt, bSendToLog); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Write prompt to stdout if it's enabled. // Type: Static method. // Args: None. @@ -228,11 +234,9 @@ CMICmnStreamStdout::TextToStdout(const CMIUtilString &vrTxt) // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMICmnStreamStdout::WritePrompt() -{ - const CMICmnStreamStdin &rStdinMan = CMICmnStreamStdin::Instance(); - if (rStdinMan.GetEnablePrompt()) - return TextToStdout(rStdinMan.GetPrompt()); - return MIstatus::success; +bool CMICmnStreamStdout::WritePrompt() { + const CMICmnStreamStdin &rStdinMan = CMICmnStreamStdin::Instance(); + if (rStdinMan.GetEnablePrompt()) + return TextToStdout(rStdinMan.GetPrompt()); + return MIstatus::success; } diff --git a/lldb/tools/lldb-mi/MICmnStreamStdout.h b/lldb/tools/lldb-mi/MICmnStreamStdout.h index 9d7f91a1504..928dcc2c1c4 100644 --- a/lldb/tools/lldb-mi/MICmnStreamStdout.h +++ b/lldb/tools/lldb-mi/MICmnStreamStdout.h @@ -10,50 +10,54 @@ #pragma once // In-house headers: -#include "MIUtilString.h" #include "MICmnBase.h" -#include "MIUtilThreadBaseStd.h" #include "MIUtilSingletonBase.h" +#include "MIUtilString.h" +#include "MIUtilThreadBaseStd.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code class. The MI driver requires this object. // CMICmnStreamStdout sets up and tears downs stdout for the driver. // // Singleton class. //-- -class CMICmnStreamStdout : public CMICmnBase, public MI::ISingleton<CMICmnStreamStdout> -{ - friend class MI::ISingleton<CMICmnStreamStdout>; - - // Statics: - public: - static bool TextToStdout(const CMIUtilString &vrTxt); - static bool WritePrompt(); - - // Methods: - public: - bool Initialize() override; - bool Shutdown() override; - // - bool Lock(); - bool Unlock(); - bool Write(const CMIUtilString &vText, const bool vbSendToLog = true); - bool WriteMIResponse(const CMIUtilString &vText, const bool vbSendToLog = true); - - // Methods: - private: - /* ctor */ CMICmnStreamStdout(); - /* ctor */ CMICmnStreamStdout(const CMICmnStreamStdout &); - void operator=(const CMICmnStreamStdout &); - // - bool WritePriv(const CMIUtilString &vText, const CMIUtilString &vTxtForLogFile, const bool vbSendToLog = true); - - // Overridden: - private: - // From CMICmnBase - /* dtor */ ~CMICmnStreamStdout() override; - - // Attributes: - private: - CMIUtilThreadMutex m_mutex; // Mutex object for sync during writing to stream +class CMICmnStreamStdout : public CMICmnBase, + public MI::ISingleton<CMICmnStreamStdout> { + friend class MI::ISingleton<CMICmnStreamStdout>; + + // Statics: +public: + static bool TextToStdout(const CMIUtilString &vrTxt); + static bool WritePrompt(); + + // Methods: +public: + bool Initialize() override; + bool Shutdown() override; + // + bool Lock(); + bool Unlock(); + bool Write(const CMIUtilString &vText, const bool vbSendToLog = true); + bool WriteMIResponse(const CMIUtilString &vText, + const bool vbSendToLog = true); + + // Methods: +private: + /* ctor */ CMICmnStreamStdout(); + /* ctor */ CMICmnStreamStdout(const CMICmnStreamStdout &); + void operator=(const CMICmnStreamStdout &); + // + bool WritePriv(const CMIUtilString &vText, + const CMIUtilString &vTxtForLogFile, + const bool vbSendToLog = true); + + // Overridden: +private: + // From CMICmnBase + /* dtor */ ~CMICmnStreamStdout() override; + + // Attributes: +private: + CMIUtilThreadMutex m_mutex; // Mutex object for sync during writing to stream }; diff --git a/lldb/tools/lldb-mi/MICmnThreadMgrStd.cpp b/lldb/tools/lldb-mi/MICmnThreadMgrStd.cpp index ec223b802f8..efa24d60250 100644 --- a/lldb/tools/lldb-mi/MICmnThreadMgrStd.cpp +++ b/lldb/tools/lldb-mi/MICmnThreadMgrStd.cpp @@ -13,30 +13,28 @@ #include "MICmnResources.h" #include "MIUtilSingletonHelper.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnThreadMgr constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmnThreadMgrStd::CMICmnThreadMgrStd() -{ -} +CMICmnThreadMgrStd::CMICmnThreadMgrStd() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMICmnThreadMgr destructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMICmnThreadMgrStd::~CMICmnThreadMgrStd() -{ - Shutdown(); -} +CMICmnThreadMgrStd::~CMICmnThreadMgrStd() { Shutdown(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Initialise resources for *this thread manager. // Type: Method. // Args: None. @@ -44,36 +42,36 @@ CMICmnThreadMgrStd::~CMICmnThreadMgrStd() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnThreadMgrStd::Initialize() -{ - m_clientUsageRefCnt++; +bool CMICmnThreadMgrStd::Initialize() { + m_clientUsageRefCnt++; - if (m_bInitialized) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - bool bOk = MIstatus::success; + bool bOk = MIstatus::success; - ClrErrorDescription(); - CMIUtilString errMsg; + ClrErrorDescription(); + CMIUtilString errMsg; - // Note initialisation order is important here as some resources depend on previous - MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); - MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + // Note initialisation order is important here as some resources depend on + // previous + MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); - m_bInitialized = bOk; + m_bInitialized = bOk; - if (!bOk) - { - CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_THREADMGR), errMsg.c_str())); - SetErrorDescription(strInitError); - return MIstatus::failure; - } + if (!bOk) { + CMIUtilString strInitError(CMIUtilString::Format( + MIRSRC(IDS_MI_INIT_ERR_THREADMGR), errMsg.c_str())); + SetErrorDescription(strInitError); + return MIstatus::failure; + } - return bOk; + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release resources for *this thread manager. // Type: Method. // Args: None. @@ -81,68 +79,65 @@ CMICmnThreadMgrStd::Initialize() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnThreadMgrStd::Shutdown() -{ - if (--m_clientUsageRefCnt > 0) - return MIstatus::success; +bool CMICmnThreadMgrStd::Shutdown() { + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - if (!m_bInitialized) - return MIstatus::success; + if (!m_bInitialized) + return MIstatus::success; - m_bInitialized = false; + m_bInitialized = false; - ClrErrorDescription(); + ClrErrorDescription(); - bool bOk = MIstatus::success; - CMIUtilString errMsg; + bool bOk = MIstatus::success; + CMIUtilString errMsg; - // Tidy up - ThreadAllTerminate(); + // Tidy up + ThreadAllTerminate(); - // Note shutdown order is important here - MI::ModuleShutdown<CMICmnResources>(IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg); - MI::ModuleShutdown<CMICmnLog>(IDS_MI_SHTDWN_ERR_LOG, bOk, errMsg); + // Note shutdown order is important here + MI::ModuleShutdown<CMICmnResources>(IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg); + MI::ModuleShutdown<CMICmnLog>(IDS_MI_SHTDWN_ERR_LOG, bOk, errMsg); - if (!bOk) - { - SetErrorDescriptionn(MIRSRC(IDS_MI_SHUTDOWN_ERR), errMsg.c_str()); - } + if (!bOk) { + SetErrorDescriptionn(MIRSRC(IDS_MI_SHUTDOWN_ERR), errMsg.c_str()); + } - return bOk; + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Ask the thread manager to kill all threads and wait until they have died +//++ +//------------------------------------------------------------------------------------ +// Details: Ask the thread manager to kill all threads and wait until they have +// died // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnThreadMgrStd::ThreadAllTerminate() -{ - ThreadList_t::const_iterator it = m_threadList.begin(); - for (; it != m_threadList.end(); ++it) - { - // If the thread is still running - CMIUtilThreadActiveObjBase *pThread = *it; - if (pThread->ThreadIsActive()) - { - // Ask this thread to kill itself - pThread->ThreadKill(); - - // Wait for this thread to die - pThread->ThreadJoin(); - } +bool CMICmnThreadMgrStd::ThreadAllTerminate() { + ThreadList_t::const_iterator it = m_threadList.begin(); + for (; it != m_threadList.end(); ++it) { + // If the thread is still running + CMIUtilThreadActiveObjBase *pThread = *it; + if (pThread->ThreadIsActive()) { + // Ask this thread to kill itself + pThread->ThreadKill(); + + // Wait for this thread to die + pThread->ThreadJoin(); } + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Add a thread object to *this manager's list of thread objects. The list to +//++ +//------------------------------------------------------------------------------------ +// Details: Add a thread object to *this manager's list of thread objects. The +// list to // used to manage thread objects centrally. // Type: Method. // Args: vrObj - (R) A thread object. @@ -150,10 +145,8 @@ CMICmnThreadMgrStd::ThreadAllTerminate() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMICmnThreadMgrStd::AddThread(const CMIUtilThreadActiveObjBase &vrObj) -{ - m_threadList.push_back(const_cast<CMIUtilThreadActiveObjBase *>(&vrObj)); +bool CMICmnThreadMgrStd::AddThread(const CMIUtilThreadActiveObjBase &vrObj) { + m_threadList.push_back(const_cast<CMIUtilThreadActiveObjBase *>(&vrObj)); - return MIstatus::success; + return MIstatus::success; } diff --git a/lldb/tools/lldb-mi/MICmnThreadMgrStd.h b/lldb/tools/lldb-mi/MICmnThreadMgrStd.h index fc0013f9949..86f5bc7373c 100644 --- a/lldb/tools/lldb-mi/MICmnThreadMgrStd.h +++ b/lldb/tools/lldb-mi/MICmnThreadMgrStd.h @@ -14,11 +14,12 @@ // In-house headers: #include "MICmnBase.h" -#include "MIUtilThreadBaseStd.h" #include "MICmnResources.h" #include "MIUtilSingletonBase.h" +#include "MIUtilThreadBaseStd.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI's worker thread (active thread) manager. // The manager creates threads and behalf of clients. Client are // responsible for their threads and can delete them when necessary. @@ -26,98 +27,99 @@ // shutdown. // Singleton class. //-- -class CMICmnThreadMgrStd : public CMICmnBase, public MI::ISingleton<CMICmnThreadMgrStd> -{ - friend MI::ISingleton<CMICmnThreadMgrStd>; - - // Methods: - public: - bool Initialize() override; - bool Shutdown() override; - bool - ThreadAllTerminate(); // Ask all threads to stop (caution) - template <typename T> // Ask the thread manager to start and stop threads on our behalf - bool ThreadStart(T &vrwObject); - - // Typedef: - private: - typedef std::vector<CMIUtilThreadActiveObjBase *> ThreadList_t; - - // Methods: - private: - /* ctor */ CMICmnThreadMgrStd(); - /* ctor */ CMICmnThreadMgrStd(const CMICmnThreadMgrStd &); - void operator=(const CMICmnThreadMgrStd &); - // - bool - AddThread(const CMIUtilThreadActiveObjBase &vrObj); // Add a thread for monitoring by the threadmanager - - // Overridden: - private: - // From CMICmnBase - /* dtor */ ~CMICmnThreadMgrStd() override; - - // Attributes: - private: - CMIUtilThreadMutex m_mutex; - ThreadList_t m_threadList; +class CMICmnThreadMgrStd : public CMICmnBase, + public MI::ISingleton<CMICmnThreadMgrStd> { + friend MI::ISingleton<CMICmnThreadMgrStd>; + + // Methods: +public: + bool Initialize() override; + bool Shutdown() override; + bool ThreadAllTerminate(); // Ask all threads to stop (caution) + template <typename T> // Ask the thread manager to start and stop threads on + // our behalf + bool ThreadStart(T &vrwObject); + + // Typedef: +private: + typedef std::vector<CMIUtilThreadActiveObjBase *> ThreadList_t; + + // Methods: +private: + /* ctor */ CMICmnThreadMgrStd(); + /* ctor */ CMICmnThreadMgrStd(const CMICmnThreadMgrStd &); + void operator=(const CMICmnThreadMgrStd &); + // + bool AddThread(const CMIUtilThreadActiveObjBase & + vrObj); // Add a thread for monitoring by the threadmanager + + // Overridden: +private: + // From CMICmnBase + /* dtor */ ~CMICmnThreadMgrStd() override; + + // Attributes: +private: + CMIUtilThreadMutex m_mutex; + ThreadList_t m_threadList; }; -//++ ------------------------------------------------------------------------------------ -// Details: Given a thread object start its (worker) thread to do work. The object is -// added to the *this manager for housekeeping and deletion of all thread objects. +//++ +//------------------------------------------------------------------------------------ +// Details: Given a thread object start its (worker) thread to do work. The +// object is +// added to the *this manager for housekeeping and deletion of all +// thread objects. // Type: Template method. -// Args: vrwThreadObj - (RW) A CMIUtilThreadActiveObjBase derived object. +// Args: vrwThreadObj - (RW) A CMIUtilThreadActiveObjBase derived +// object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -template <typename T> -bool -CMICmnThreadMgrStd::ThreadStart(T &vrwThreadObj) -{ - bool bOk = MIstatus::success; - - // Grab a reference to the base object type - CMIUtilThreadActiveObjBase &rObj = static_cast<CMIUtilThreadActiveObjBase &>(vrwThreadObj); - - // Add to the thread managers internal database - bOk &= AddThread(rObj); - if (!bOk) - { - const CMIUtilString errMsg( - CMIUtilString::Format(MIRSRC(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE), vrwThreadObj.ThreadGetName().c_str())); - SetErrorDescription(errMsg); - return MIstatus::failure; - } - - // Grab a reference on behalf of the caller - bOk &= vrwThreadObj.Acquire(); - if (!bOk) - { - const CMIUtilString errMsg( - CMIUtilString::Format(MIRSRC(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE), vrwThreadObj.ThreadGetName().c_str())); - SetErrorDescription(errMsg); - return MIstatus::failure; - } - - // Thread is already started - // This call must come after the reference count increment - if (vrwThreadObj.ThreadIsActive()) - { - // Early exit on thread already running condition - return MIstatus::success; - } - - // Start the thread running - bOk &= vrwThreadObj.ThreadExecute(); - if (!bOk) - { - const CMIUtilString errMsg( - CMIUtilString::Format(MIRSRC(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE), vrwThreadObj.ThreadGetName().c_str())); - SetErrorDescription(errMsg); - return MIstatus::failure; - } - +template <typename T> bool CMICmnThreadMgrStd::ThreadStart(T &vrwThreadObj) { + bool bOk = MIstatus::success; + + // Grab a reference to the base object type + CMIUtilThreadActiveObjBase &rObj = + static_cast<CMIUtilThreadActiveObjBase &>(vrwThreadObj); + + // Add to the thread managers internal database + bOk &= AddThread(rObj); + if (!bOk) { + const CMIUtilString errMsg( + CMIUtilString::Format(MIRSRC(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE), + vrwThreadObj.ThreadGetName().c_str())); + SetErrorDescription(errMsg); + return MIstatus::failure; + } + + // Grab a reference on behalf of the caller + bOk &= vrwThreadObj.Acquire(); + if (!bOk) { + const CMIUtilString errMsg( + CMIUtilString::Format(MIRSRC(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE), + vrwThreadObj.ThreadGetName().c_str())); + SetErrorDescription(errMsg); + return MIstatus::failure; + } + + // Thread is already started + // This call must come after the reference count increment + if (vrwThreadObj.ThreadIsActive()) { + // Early exit on thread already running condition return MIstatus::success; + } + + // Start the thread running + bOk &= vrwThreadObj.ThreadExecute(); + if (!bOk) { + const CMIUtilString errMsg( + CMIUtilString::Format(MIRSRC(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE), + vrwThreadObj.ThreadGetName().c_str())); + SetErrorDescription(errMsg); + return MIstatus::failure; + } + + return MIstatus::success; } diff --git a/lldb/tools/lldb-mi/MIDataTypes.h b/lldb/tools/lldb-mi/MIDataTypes.h index d749b0c661a..34fe4575160 100644 --- a/lldb/tools/lldb-mi/MIDataTypes.h +++ b/lldb/tools/lldb-mi/MIDataTypes.h @@ -30,14 +30,13 @@ // Common definitions: // Function return status -namespace MIstatus -{ +namespace MIstatus { const bool success = true; const bool failure = false; } // Use to avoid "unused parameter" compiler warnings: -#define MIunused(x) (void) x; +#define MIunused(x) (void)x; // Portability issues #ifdef _WIN64 diff --git a/lldb/tools/lldb-mi/MIDriver.cpp b/lldb/tools/lldb-mi/MIDriver.cpp index 78172375b3d..dacd39f7da1 100644 --- a/lldb/tools/lldb-mi/MIDriver.cpp +++ b/lldb/tools/lldb-mi/MIDriver.cpp @@ -8,37 +8,41 @@ //===----------------------------------------------------------------------===// // Third party headers: -#include <fstream> #include "lldb/API/SBError.h" +#include <fstream> // In-house headers: -#include "MIDriver.h" -#include "MICmnResources.h" -#include "MICmnLog.h" +#include "MICmdArgValFile.h" +#include "MICmdArgValString.h" #include "MICmdMgr.h" +#include "MICmnConfig.h" +#include "MICmnLLDBDebugSessionInfo.h" #include "MICmnLLDBDebugger.h" +#include "MICmnLog.h" #include "MICmnMIResultRecord.h" #include "MICmnMIValueConst.h" +#include "MICmnResources.h" +#include "MICmnStreamStderr.h" +#include "MICmnStreamStdout.h" #include "MICmnThreadMgrStd.h" +#include "MIDriver.h" #include "MIUtilDebug.h" #include "MIUtilSingletonHelper.h" -#include "MICmnStreamStdout.h" -#include "MICmnStreamStderr.h" -#include "MICmdArgValFile.h" -#include "MICmdArgValString.h" -#include "MICmnConfig.h" -#include "MICmnLLDBDebugSessionInfo.h" // Instantiations: #if _DEBUG -const CMIUtilString CMIDriver::ms_constMIVersion = MIRSRC(IDS_MI_VERSION_DESCRIPTION_DEBUG); +const CMIUtilString CMIDriver::ms_constMIVersion = + MIRSRC(IDS_MI_VERSION_DESCRIPTION_DEBUG); #else -const CMIUtilString CMIDriver::ms_constMIVersion = MIRSRC(IDS_MI_VERSION_DESCRIPTION); // Matches version in resources file +const CMIUtilString CMIDriver::ms_constMIVersion = + MIRSRC(IDS_MI_VERSION_DESCRIPTION); // Matches version in resources file #endif // _DEBUG -const CMIUtilString CMIDriver::ms_constAppNameShort(MIRSRC(IDS_MI_APPNAME_SHORT)); +const CMIUtilString + CMIDriver::ms_constAppNameShort(MIRSRC(IDS_MI_APPNAME_SHORT)); const CMIUtilString CMIDriver::ms_constAppNameLong(MIRSRC(IDS_MI_APPNAME_LONG)); -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIDriver constructor. // Type: Method. // Args: None. @@ -46,102 +50,98 @@ const CMIUtilString CMIDriver::ms_constAppNameLong(MIRSRC(IDS_MI_APPNAME_LONG)); // Throws: None. //-- CMIDriver::CMIDriver() - : m_bFallThruToOtherDriverEnabled(false) - , m_bDriverIsExiting(false) - , m_handleMainThread(0) - , m_rStdin(CMICmnStreamStdin::Instance()) - , m_rLldbDebugger(CMICmnLLDBDebugger::Instance()) - , m_rStdOut(CMICmnStreamStdout::Instance()) - , m_eCurrentDriverState(eDriverState_NotRunning) - , m_bHaveExecutableFileNamePathOnCmdLine(false) - , m_bDriverDebuggingArgExecutable(false) - , m_bHaveCommandFileNamePathOnCmdLine(false) -{ -} - -//++ ------------------------------------------------------------------------------------ + : m_bFallThruToOtherDriverEnabled(false), m_bDriverIsExiting(false), + m_handleMainThread(0), m_rStdin(CMICmnStreamStdin::Instance()), + m_rLldbDebugger(CMICmnLLDBDebugger::Instance()), + m_rStdOut(CMICmnStreamStdout::Instance()), + m_eCurrentDriverState(eDriverState_NotRunning), + m_bHaveExecutableFileNamePathOnCmdLine(false), + m_bDriverDebuggingArgExecutable(false), + m_bHaveCommandFileNamePathOnCmdLine(false) {} + +//++ +//------------------------------------------------------------------------------------ // Details: CMIDriver destructor. // Type: Overridden. // Args: None. // Return: None. // Throws: None. //-- -CMIDriver::~CMIDriver() -{ -} - -//++ ------------------------------------------------------------------------------------ -// Details: Set whether *this driver (the parent) is enabled to pass a command to its -// fall through (child) driver to interpret the command and do work instead +CMIDriver::~CMIDriver() {} + +//++ +//------------------------------------------------------------------------------------ +// Details: Set whether *this driver (the parent) is enabled to pass a command +// to its +// fall through (child) driver to interpret the command and do work +// instead // (if *this driver decides it can't handle the command). // Type: Method. -// Args: vbYes - (R) True = yes fall through, false = do not pass on command. +// Args: vbYes - (R) True = yes fall through, false = do not pass on +// command. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriver::SetEnableFallThru(const bool vbYes) -{ - m_bFallThruToOtherDriverEnabled = vbYes; - return MIstatus::success; +bool CMIDriver::SetEnableFallThru(const bool vbYes) { + m_bFallThruToOtherDriverEnabled = vbYes; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Get whether *this driver (the parent) is enabled to pass a command to its -// fall through (child) driver to interpret the command and do work instead +//++ +//------------------------------------------------------------------------------------ +// Details: Get whether *this driver (the parent) is enabled to pass a command +// to its +// fall through (child) driver to interpret the command and do work +// instead // (if *this driver decides it can't handle the command). // Type: Method. // Args: None. // Return: bool - True = yes fall through, false = do not pass on command. // Throws: None. //-- -bool -CMIDriver::GetEnableFallThru() const -{ - return m_bFallThruToOtherDriverEnabled; +bool CMIDriver::GetEnableFallThru() const { + return m_bFallThruToOtherDriverEnabled; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve MI's application name of itself. // Type: Method. // Args: None. // Return: CMIUtilString & - Text description. // Throws: None. //-- -const CMIUtilString & -CMIDriver::GetAppNameShort() const -{ - return ms_constAppNameShort; +const CMIUtilString &CMIDriver::GetAppNameShort() const { + return ms_constAppNameShort; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve MI's application name of itself. // Type: Method. // Args: None. // Return: CMIUtilString & - Text description. // Throws: None. //-- -const CMIUtilString & -CMIDriver::GetAppNameLong() const -{ - return ms_constAppNameLong; +const CMIUtilString &CMIDriver::GetAppNameLong() const { + return ms_constAppNameLong; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve MI's version description of itself. // Type: Method. // Args: None. // Return: CMIUtilString & - Text description. // Throws: None. //-- -const CMIUtilString & -CMIDriver::GetVersionDescription() const -{ - return ms_constMIVersion; +const CMIUtilString &CMIDriver::GetVersionDescription() const { + return ms_constMIVersion; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Initialize setup *this driver ready for use. // Type: Method. // Args: None. @@ -149,48 +149,48 @@ CMIDriver::GetVersionDescription() const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriver::Initialize() -{ - m_eCurrentDriverState = eDriverState_Initialising; - m_clientUsageRefCnt++; - - ClrErrorDescription(); - - if (m_bInitialized) - return MIstatus::success; - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - - // Initialize all of the modules we depend on - MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); - MI::ModuleInit<CMICmnStreamStdout>(IDS_MI_INIT_ERR_STREAMSTDOUT, bOk, errMsg); - MI::ModuleInit<CMICmnStreamStderr>(IDS_MI_INIT_ERR_STREAMSTDERR, bOk, errMsg); - MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); - MI::ModuleInit<CMICmnThreadMgrStd>(IDS_MI_INIT_ERR_THREADMANAGER, bOk, errMsg); - MI::ModuleInit<CMICmnStreamStdin>(IDS_MI_INIT_ERR_STREAMSTDIN, bOk, errMsg); - MI::ModuleInit<CMICmdMgr>(IDS_MI_INIT_ERR_CMDMGR, bOk, errMsg); - bOk &= m_rLldbDebugger.SetDriver(*this); - MI::ModuleInit<CMICmnLLDBDebugger>(IDS_MI_INIT_ERR_LLDBDEBUGGER, bOk, errMsg); - - m_bExitApp = false; - - m_bInitialized = bOk; - - if (!bOk) - { - const CMIUtilString msg = CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_DRIVER), errMsg.c_str()); - SetErrorDescription(msg); - return MIstatus::failure; - } +bool CMIDriver::Initialize() { + m_eCurrentDriverState = eDriverState_Initialising; + m_clientUsageRefCnt++; - m_eCurrentDriverState = eDriverState_RunningNotDebugging; + ClrErrorDescription(); - return bOk; + if (m_bInitialized) + return MIstatus::success; + + bool bOk = MIstatus::success; + CMIUtilString errMsg; + + // Initialize all of the modules we depend on + MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + MI::ModuleInit<CMICmnStreamStdout>(IDS_MI_INIT_ERR_STREAMSTDOUT, bOk, errMsg); + MI::ModuleInit<CMICmnStreamStderr>(IDS_MI_INIT_ERR_STREAMSTDERR, bOk, errMsg); + MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + MI::ModuleInit<CMICmnThreadMgrStd>(IDS_MI_INIT_ERR_THREADMANAGER, bOk, + errMsg); + MI::ModuleInit<CMICmnStreamStdin>(IDS_MI_INIT_ERR_STREAMSTDIN, bOk, errMsg); + MI::ModuleInit<CMICmdMgr>(IDS_MI_INIT_ERR_CMDMGR, bOk, errMsg); + bOk &= m_rLldbDebugger.SetDriver(*this); + MI::ModuleInit<CMICmnLLDBDebugger>(IDS_MI_INIT_ERR_LLDBDEBUGGER, bOk, errMsg); + + m_bExitApp = false; + + m_bInitialized = bOk; + + if (!bOk) { + const CMIUtilString msg = + CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_DRIVER), errMsg.c_str()); + SetErrorDescription(msg); + return MIstatus::failure; + } + + m_eCurrentDriverState = eDriverState_RunningNotDebugging; + + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Unbind detach or release resources used by *this driver. // Type: Method. // Args: None. @@ -198,44 +198,48 @@ CMIDriver::Initialize() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriver::Shutdown() -{ - if (--m_clientUsageRefCnt > 0) - return MIstatus::success; - - if (!m_bInitialized) - return MIstatus::success; - - m_eCurrentDriverState = eDriverState_ShuttingDown; - - ClrErrorDescription(); - - bool bOk = MIstatus::success; - CMIUtilString errMsg; - - // Shutdown all of the modules we depend on - MI::ModuleShutdown<CMICmnLLDBDebugger>(IDS_MI_INIT_ERR_LLDBDEBUGGER, bOk, errMsg); - MI::ModuleShutdown<CMICmdMgr>(IDS_MI_INIT_ERR_CMDMGR, bOk, errMsg); - MI::ModuleShutdown<CMICmnStreamStdin>(IDS_MI_INIT_ERR_STREAMSTDIN, bOk, errMsg); - MI::ModuleShutdown<CMICmnThreadMgrStd>(IDS_MI_INIT_ERR_THREADMANAGER, bOk, errMsg); - MI::ModuleShutdown<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); - MI::ModuleShutdown<CMICmnStreamStderr>(IDS_MI_INIT_ERR_STREAMSTDERR, bOk, errMsg); - MI::ModuleShutdown<CMICmnStreamStdout>(IDS_MI_INIT_ERR_STREAMSTDOUT, bOk, errMsg); - MI::ModuleShutdown<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); - - if (!bOk) - { - SetErrorDescriptionn(MIRSRC(IDS_MI_SHUTDOWN_ERR), errMsg.c_str()); - } +bool CMIDriver::Shutdown() { + if (--m_clientUsageRefCnt > 0) + return MIstatus::success; - m_eCurrentDriverState = eDriverState_NotRunning; + if (!m_bInitialized) + return MIstatus::success; - return bOk; + m_eCurrentDriverState = eDriverState_ShuttingDown; + + ClrErrorDescription(); + + bool bOk = MIstatus::success; + CMIUtilString errMsg; + + // Shutdown all of the modules we depend on + MI::ModuleShutdown<CMICmnLLDBDebugger>(IDS_MI_INIT_ERR_LLDBDEBUGGER, bOk, + errMsg); + MI::ModuleShutdown<CMICmdMgr>(IDS_MI_INIT_ERR_CMDMGR, bOk, errMsg); + MI::ModuleShutdown<CMICmnStreamStdin>(IDS_MI_INIT_ERR_STREAMSTDIN, bOk, + errMsg); + MI::ModuleShutdown<CMICmnThreadMgrStd>(IDS_MI_INIT_ERR_THREADMANAGER, bOk, + errMsg); + MI::ModuleShutdown<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + MI::ModuleShutdown<CMICmnStreamStderr>(IDS_MI_INIT_ERR_STREAMSTDERR, bOk, + errMsg); + MI::ModuleShutdown<CMICmnStreamStdout>(IDS_MI_INIT_ERR_STREAMSTDOUT, bOk, + errMsg); + MI::ModuleShutdown<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + + if (!bOk) { + SetErrorDescriptionn(MIRSRC(IDS_MI_SHUTDOWN_ERR), errMsg.c_str()); + } + + m_eCurrentDriverState = eDriverState_NotRunning; + + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Work function. Client (the driver's user) is able to append their own message +//++ +//------------------------------------------------------------------------------------ +// Details: Work function. Client (the driver's user) is able to append their +// own message // in to the MI's Log trace file. // Type: Method. // Args: vMessage - (R) Client's text message. @@ -243,15 +247,14 @@ CMIDriver::Shutdown() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriver::WriteMessageToLog(const CMIUtilString &vMessage) -{ - CMIUtilString msg; - msg = CMIUtilString::Format(MIRSRC(IDS_MI_CLIENT_MSG), vMessage.c_str()); - return m_pLog->Write(msg, CMICmnLog::eLogVerbosity_ClientMsg); +bool CMIDriver::WriteMessageToLog(const CMIUtilString &vMessage) { + CMIUtilString msg; + msg = CMIUtilString::Format(MIRSRC(IDS_MI_CLIENT_MSG), vMessage.c_str()); + return m_pLog->Write(msg, CMICmnLog::eLogVerbosity_ClientMsg); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CDriverMgr calls *this driver initialize setup ready for use. // Type: Overridden. // Args: None. @@ -259,14 +262,12 @@ CMIDriver::WriteMessageToLog(const CMIUtilString &vMessage) // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriver::DoInitialize() -{ - return CMIDriver::Instance().Initialize(); -} +bool CMIDriver::DoInitialize() { return CMIDriver::Instance().Initialize(); } -//++ ------------------------------------------------------------------------------------ -// Details: CDriverMgr calls *this driver to unbind detach or release resources used by +//++ +//------------------------------------------------------------------------------------ +// Details: CDriverMgr calls *this driver to unbind detach or release resources +// used by // *this driver. // Type: Overridden. // Args: None. @@ -274,189 +275,211 @@ CMIDriver::DoInitialize() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriver::DoShutdown() -{ - return CMIDriver::Instance().Shutdown(); -} +bool CMIDriver::DoShutdown() { return CMIDriver::Instance().Shutdown(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the name for *this driver. // Type: Overridden. // Args: None. // Return: CMIUtilString & - Driver name. // Throws: None. //-- -const CMIUtilString & -CMIDriver::GetName() const -{ - const CMIUtilString &rName = GetAppNameLong(); - const CMIUtilString &rVsn = GetVersionDescription(); - static CMIUtilString strName = CMIUtilString::Format("%s %s", rName.c_str(), rVsn.c_str()); - - return strName; +const CMIUtilString &CMIDriver::GetName() const { + const CMIUtilString &rName = GetAppNameLong(); + const CMIUtilString &rVsn = GetVersionDescription(); + static CMIUtilString strName = + CMIUtilString::Format("%s %s", rName.c_str(), rVsn.c_str()); + + return strName; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve *this driver's last error condition. // Type: Overridden. // Args: None. // Return: CMIUtilString - Text description. // Throws: None. //-- -CMIUtilString -CMIDriver::GetError() const -{ - return GetErrorDescription(); -} +CMIUtilString CMIDriver::GetError() const { return GetErrorDescription(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Call *this driver to return it's debugger. // Type: Overridden. // Args: None. // Return: lldb::SBDebugger & - LLDB debugger object reference. // Throws: None. //-- -lldb::SBDebugger & -CMIDriver::GetTheDebugger() -{ - return m_rLldbDebugger.GetTheDebugger(); +lldb::SBDebugger &CMIDriver::GetTheDebugger() { + return m_rLldbDebugger.GetTheDebugger(); } -//++ ------------------------------------------------------------------------------------ -// Details: Specify another driver *this driver can call should this driver not be able -// to handle the client data input. DoFallThruToAnotherDriver() makes the call. +//++ +//------------------------------------------------------------------------------------ +// Details: Specify another driver *this driver can call should this driver not +// be able +// to handle the client data input. DoFallThruToAnotherDriver() makes +// the call. // Type: Overridden. // Args: vrOtherDriver - (R) Reference to another driver object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriver::SetDriverToFallThruTo(const CMIDriverBase &vrOtherDriver) -{ - m_pDriverFallThru = const_cast<CMIDriverBase *>(&vrOtherDriver); +bool CMIDriver::SetDriverToFallThruTo(const CMIDriverBase &vrOtherDriver) { + m_pDriverFallThru = const_cast<CMIDriverBase *>(&vrOtherDriver); - return m_pDriverFallThru->SetDriverParent(*this); + return m_pDriverFallThru->SetDriverParent(*this); } -//++ ------------------------------------------------------------------------------------ -// Details: Proxy function CMIDriverMgr IDriver interface implementation. *this driver's -// implementation called from here to match the existing function name of the -// original LLDB driver class (the extra indirection is not necessarily required). -// Check the arguments that were passed to this program to make sure they are +//++ +//------------------------------------------------------------------------------------ +// Details: Proxy function CMIDriverMgr IDriver interface implementation. *this +// driver's +// implementation called from here to match the existing function name +// of the +// original LLDB driver class (the extra indirection is not necessarily +// required). +// Check the arguments that were passed to this program to make sure +// they are // valid and to get their argument values (if any). // Type: Overridden. -// Args: argc - (R) An integer that contains the count of arguments that follow in -// argv. The argc parameter is always greater than or equal to 1. -// argv - (R) An array of null-terminated strings representing command-line -// arguments entered by the user of the program. By convention, -// argv[0] is the command with which the program is invoked. +// Args: argc - (R) An integer that contains the count of arguments +// that follow in +// argv. The argc parameter is always greater than +// or equal to 1. +// argv - (R) An array of null-terminated strings representing +// command-line +// arguments entered by the user of the program. By +// convention, +// argv[0] is the command with which the program is +// invoked. // vpStdOut - (R) Pointer to a standard output stream. -// vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s), +// vwbExiting - (W) True = *this want to exit, Reasons: help, +// invalid arg(s), // version information only. -// False = Continue to work, start debugger i.e. Command +// False = Continue to work, start debugger i.e. +// Command // interpreter. // Return: lldb::SBError - LLDB current error status. // Throws: None. //-- -lldb::SBError -CMIDriver::DoParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting) -{ - return ParseArgs(argc, argv, vpStdOut, vwbExiting); +lldb::SBError CMIDriver::DoParseArgs(const int argc, const char *argv[], + FILE *vpStdOut, bool &vwbExiting) { + return ParseArgs(argc, argv, vpStdOut, vwbExiting); } -//++ ------------------------------------------------------------------------------------ -// Details: Check the arguments that were passed to this program to make sure they are -// valid and to get their argument values (if any). The following are options +//++ +//------------------------------------------------------------------------------------ +// Details: Check the arguments that were passed to this program to make sure +// they are +// valid and to get their argument values (if any). The following are +// options // that are only handled by *this driver: // --executable <file> // --source <file> or -s <file> -// The application's options --interpreter and --executable in code act very similar. -// The --executable is necessary to differentiate whether the MI Driver is being -// used by a client (e.g. Eclipse) or from the command line. Eclipse issues the option -// --interpreter and also passes additional arguments which can be interpreted as an -// executable if called from the command line. Using --executable tells the MI Driver -// it is being called from the command line and to prepare to launch the executable -// argument for a debug session. Using --interpreter on the command line does not +// The application's options --interpreter and --executable in code act +// very similar. +// The --executable is necessary to differentiate whether the MI Driver +// is being +// used by a client (e.g. Eclipse) or from the command line. Eclipse +// issues the option +// --interpreter and also passes additional arguments which can be +// interpreted as an +// executable if called from the command line. Using --executable tells +// the MI Driver +// it is being called from the command line and to prepare to launch +// the executable +// argument for a debug session. Using --interpreter on the command +// line does not // issue additional commands to initialise a debug session. // Type: Overridden. -// Args: argc - (R) An integer that contains the count of arguments that follow in -// argv. The argc parameter is always greater than or equal to 1. -// argv - (R) An array of null-terminated strings representing command-line -// arguments entered by the user of the program. By convention, -// argv[0] is the command with which the program is invoked. +// Args: argc - (R) An integer that contains the count of arguments +// that follow in +// argv. The argc parameter is always greater than +// or equal to 1. +// argv - (R) An array of null-terminated strings representing +// command-line +// arguments entered by the user of the program. By +// convention, +// argv[0] is the command with which the program is +// invoked. // vpStdOut - (R) Pointer to a standard output stream. -// vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s), +// vwbExiting - (W) True = *this want to exit, Reasons: help, +// invalid arg(s), // version information only. -// False = Continue to work, start debugger i.e. Command +// False = Continue to work, start debugger i.e. +// Command // interpreter. // Return: lldb::SBError - LLDB current error status. // Throws: None. //-- -lldb::SBError -CMIDriver::ParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting) -{ - lldb::SBError errStatus; - const bool bHaveArgs(argc >= 2); - - // *** Add any args handled here to GetHelpOnCmdLineArgOptions() *** - - // CODETAG_MIDRIVE_CMD_LINE_ARG_HANDLING - // Look for the command line options - bool bHaveExecutableFileNamePath = false; - bool bHaveExecutableLongOption = false; - - if (bHaveArgs) - { - // Search right to left to look for filenames - for (MIint i = argc - 1; i > 0; i--) - { - const CMIUtilString strArg(argv[i]); - const CMICmdArgValFile argFile; - - // Check for a filename - if (argFile.IsFilePath(strArg) || CMICmdArgValString(true, false, true).IsStringArg(strArg)) - { - // Is this the command file for the '-s' or '--source' options? - const CMIUtilString strPrevArg(argv[i - 1]); - if (strPrevArg.compare("-s") == 0 || strPrevArg.compare("--source") == 0) - { - m_strCmdLineArgCommandFileNamePath = strArg; - m_bHaveCommandFileNamePathOnCmdLine = true; - i--; // skip '-s' on the next loop - continue; - } - // Else, must be the executable - bHaveExecutableFileNamePath = true; - m_strCmdLineArgExecuteableFileNamePath = strArg; - m_bHaveExecutableFileNamePathOnCmdLine = true; - } - // Report error if no command file was specified for the '-s' or '--source' options - else if (strArg.compare("-s") == 0 || strArg.compare("--source") == 0) - { - vwbExiting = true; - const CMIUtilString errMsg = CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF), strArg.c_str()); - errStatus.SetErrorString(errMsg.c_str()); - break; - } - // This argument is also checked for in CMIDriverMgr::ParseArgs() - else if (strArg.compare("--executable") == 0) // Used to specify that there is executable argument also on the command line - { // See fn description. - bHaveExecutableLongOption = true; - } +lldb::SBError CMIDriver::ParseArgs(const int argc, const char *argv[], + FILE *vpStdOut, bool &vwbExiting) { + lldb::SBError errStatus; + const bool bHaveArgs(argc >= 2); + + // *** Add any args handled here to GetHelpOnCmdLineArgOptions() *** + + // CODETAG_MIDRIVE_CMD_LINE_ARG_HANDLING + // Look for the command line options + bool bHaveExecutableFileNamePath = false; + bool bHaveExecutableLongOption = false; + + if (bHaveArgs) { + // Search right to left to look for filenames + for (MIint i = argc - 1; i > 0; i--) { + const CMIUtilString strArg(argv[i]); + const CMICmdArgValFile argFile; + + // Check for a filename + if (argFile.IsFilePath(strArg) || + CMICmdArgValString(true, false, true).IsStringArg(strArg)) { + // Is this the command file for the '-s' or '--source' options? + const CMIUtilString strPrevArg(argv[i - 1]); + if (strPrevArg.compare("-s") == 0 || + strPrevArg.compare("--source") == 0) { + m_strCmdLineArgCommandFileNamePath = strArg; + m_bHaveCommandFileNamePathOnCmdLine = true; + i--; // skip '-s' on the next loop + continue; } + // Else, must be the executable + bHaveExecutableFileNamePath = true; + m_strCmdLineArgExecuteableFileNamePath = strArg; + m_bHaveExecutableFileNamePathOnCmdLine = true; + } + // Report error if no command file was specified for the '-s' or + // '--source' options + else if (strArg.compare("-s") == 0 || strArg.compare("--source") == 0) { + vwbExiting = true; + const CMIUtilString errMsg = CMIUtilString::Format( + MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF), strArg.c_str()); + errStatus.SetErrorString(errMsg.c_str()); + break; + } + // This argument is also checked for in CMIDriverMgr::ParseArgs() + else if (strArg.compare("--executable") == 0) // Used to specify that + // there is executable + // argument also on the + // command line + { // See fn description. + bHaveExecutableLongOption = true; + } } + } - if (bHaveExecutableFileNamePath && bHaveExecutableLongOption) - { - SetDriverDebuggingArgExecutable(); - } + if (bHaveExecutableFileNamePath && bHaveExecutableLongOption) { + SetDriverDebuggingArgExecutable(); + } - return errStatus; + return errStatus; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: A client can ask if *this driver is GDB/MI compatible. // Type: Overridden. // Args: None. @@ -464,13 +487,10 @@ CMIDriver::ParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &v // False - Not GBD/MI compatible LLDB front end. // Throws: None. //-- -bool -CMIDriver::GetDriverIsGDBMICompatibleDriver() const -{ - return true; -} +bool CMIDriver::GetDriverIsGDBMICompatibleDriver() const { return true; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Start worker threads for the driver. // Type: Method. // Args: None. @@ -478,27 +498,26 @@ CMIDriver::GetDriverIsGDBMICompatibleDriver() const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriver::StartWorkerThreads() -{ - bool bOk = MIstatus::success; - - // Grab the thread manager - CMICmnThreadMgrStd &rThreadMgr = CMICmnThreadMgrStd::Instance(); - - // Start the event polling thread - if (bOk && !rThreadMgr.ThreadStart<CMICmnLLDBDebugger>(m_rLldbDebugger)) - { - const CMIUtilString errMsg = CMIUtilString::Format(MIRSRC(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE), - CMICmnThreadMgrStd::Instance().GetErrorDescription().c_str()); - SetErrorDescriptionn(errMsg); - return MIstatus::failure; - } - - return bOk; +bool CMIDriver::StartWorkerThreads() { + bool bOk = MIstatus::success; + + // Grab the thread manager + CMICmnThreadMgrStd &rThreadMgr = CMICmnThreadMgrStd::Instance(); + + // Start the event polling thread + if (bOk && !rThreadMgr.ThreadStart<CMICmnLLDBDebugger>(m_rLldbDebugger)) { + const CMIUtilString errMsg = CMIUtilString::Format( + MIRSRC(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE), + CMICmnThreadMgrStd::Instance().GetErrorDescription().c_str()); + SetErrorDescriptionn(errMsg); + return MIstatus::failure; + } + + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Stop worker threads for the driver. // Type: Method. // Args: None. @@ -506,14 +525,13 @@ CMIDriver::StartWorkerThreads() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriver::StopWorkerThreads() -{ - CMICmnThreadMgrStd &rThreadMgr = CMICmnThreadMgrStd::Instance(); - return rThreadMgr.ThreadAllTerminate(); +bool CMIDriver::StopWorkerThreads() { + CMICmnThreadMgrStd &rThreadMgr = CMICmnThreadMgrStd::Instance(); + return rThreadMgr.ThreadAllTerminate(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Call this function puts *this driver to work. // This function is used by the application's main thread. // Type: Overridden. @@ -522,82 +540,78 @@ CMIDriver::StopWorkerThreads() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriver::DoMainLoop() -{ - if (!InitClientIDEToMIDriver()) // Init Eclipse IDE - { - SetErrorDescriptionn(MIRSRC(IDS_MI_INIT_ERR_CLIENT_USING_DRIVER)); - return MIstatus::failure; +bool CMIDriver::DoMainLoop() { + if (!InitClientIDEToMIDriver()) // Init Eclipse IDE + { + SetErrorDescriptionn(MIRSRC(IDS_MI_INIT_ERR_CLIENT_USING_DRIVER)); + return MIstatus::failure; + } + + if (!StartWorkerThreads()) + return MIstatus::failure; + + bool bOk = MIstatus::success; + + if (HaveExecutableFileNamePathOnCmdLine()) { + if (!LocalDebugSessionStartupExecuteCommands()) { + SetErrorDescription(MIRSRC(IDS_MI_INIT_ERR_LOCAL_DEBUG_SESSION)); + bOk = MIstatus::failure; } + } + + // App is not quitting currently + m_bExitApp = false; + + // Handle source file + if (m_bHaveCommandFileNamePathOnCmdLine) { + const bool bAsyncMode = false; + ExecuteCommandFile(bAsyncMode); + } + + // While the app is active + while (bOk && !m_bExitApp) { + CMIUtilString errorText; + const char *pCmd = m_rStdin.ReadLine(errorText); + if (pCmd != nullptr) { + CMIUtilString lineText(pCmd); + if (!lineText.empty()) { + // Check that the handler thread is alive (otherwise we stuck here) + assert(CMICmnLLDBDebugger::Instance().ThreadIsActive()); - if (!StartWorkerThreads()) - return MIstatus::failure; - - bool bOk = MIstatus::success; - - if (HaveExecutableFileNamePathOnCmdLine()) - { - if (!LocalDebugSessionStartupExecuteCommands()) { - SetErrorDescription(MIRSRC(IDS_MI_INIT_ERR_LOCAL_DEBUG_SESSION)); - bOk = MIstatus::failure; + // Lock Mutex before processing commands so that we don't disturb an + // event + // being processed + CMIUtilThreadLock lock( + CMICmnLLDBDebugSessionInfo::Instance().GetSessionMutex()); + bOk = InterpretCommand(lineText); } - } - // App is not quitting currently - m_bExitApp = false; - - // Handle source file - if (m_bHaveCommandFileNamePathOnCmdLine) - { - const bool bAsyncMode = false; - ExecuteCommandFile(bAsyncMode); - } + // Draw prompt if desired + bOk = bOk && CMICmnStreamStdout::WritePrompt(); - // While the app is active - while (bOk && !m_bExitApp) - { - CMIUtilString errorText; - const char *pCmd = m_rStdin.ReadLine (errorText); - if (pCmd != nullptr) - { - CMIUtilString lineText(pCmd); - if (!lineText.empty ()) - { - // Check that the handler thread is alive (otherwise we stuck here) - assert(CMICmnLLDBDebugger::Instance().ThreadIsActive()); - - { - // Lock Mutex before processing commands so that we don't disturb an event - // being processed - CMIUtilThreadLock lock(CMICmnLLDBDebugSessionInfo::Instance().GetSessionMutex()); - bOk = InterpretCommand(lineText); - } - - // Draw prompt if desired - bOk = bOk && CMICmnStreamStdout::WritePrompt(); - - // Wait while the handler thread handles incoming events - CMICmnLLDBDebugger::Instance().WaitForHandleEvent(); - } - } + // Wait while the handler thread handles incoming events + CMICmnLLDBDebugger::Instance().WaitForHandleEvent(); + } } + } - // Signal that the application is shutting down - DoAppQuit(); + // Signal that the application is shutting down + DoAppQuit(); - // Close and wait for the workers to stop - StopWorkerThreads(); + // Close and wait for the workers to stop + StopWorkerThreads(); - // Ensure that a new line is sent as the last act of the dying driver - m_rStdOut.WriteMIResponse("\n", false); + // Ensure that a new line is sent as the last act of the dying driver + m_rStdOut.WriteMIResponse("\n", false); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Set things in motion, set state etc that brings *this driver (and the +//++ +//------------------------------------------------------------------------------------ +// Details: Set things in motion, set state etc that brings *this driver (and +// the // application) to a tidy shutdown. // This function is used by the application's main thread. // Type: Method. @@ -606,95 +620,94 @@ CMIDriver::DoMainLoop() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriver::DoAppQuit() -{ - bool bYesQuit = true; - - // Shutdown stuff, ready app for exit - { - CMIUtilThreadLock lock(m_threadMutex); - m_bDriverIsExiting = true; - } +bool CMIDriver::DoAppQuit() { + bool bYesQuit = true; - return bYesQuit; + // Shutdown stuff, ready app for exit + { + CMIUtilThreadLock lock(m_threadMutex); + m_bDriverIsExiting = true; + } + + return bYesQuit; } -//++ ------------------------------------------------------------------------------------ -// Details: *this driver passes text commands to a fall through driver is it does not +//++ +//------------------------------------------------------------------------------------ +// Details: *this driver passes text commands to a fall through driver is it +// does not // understand them (the LLDB driver). // This function is used by the application's main thread. // Type: Method. // Args: vTextLine - (R) Text data representing a possible command. -// vwbCmdYesValid - (W) True = Command valid, false = command not handled. +// vwbCmdYesValid - (W) True = Command valid, false = command not +// handled. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriver::InterpretCommandFallThruDriver(const CMIUtilString &vTextLine, bool &vwbCmdYesValid) -{ - MIunused(vTextLine); - MIunused(vwbCmdYesValid); - - // ToDo: Implement when less urgent work to be done or decide remove as not required - // bool bOk = MIstatus::success; - // bool bCmdNotUnderstood = true; - // if( bCmdNotUnderstood && GetEnableFallThru() ) - //{ - // CMIUtilString errMsg; - // bOk = DoFallThruToAnotherDriver( vStdInBuffer, errMsg ); - // if( !bOk ) - // { - // errMsg = errMsg.StripCREndOfLine(); - // errMsg = errMsg.StripCRAll(); - // const CMIDriverBase * pOtherDriver = GetDriverToFallThruTo(); - // const char * pName = pOtherDriver->GetDriverName().c_str(); - // const char * pId = pOtherDriver->GetDriverId().c_str(); - // const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_FALLTHRU_DRIVER_ERR ), pName, pId, errMsg.c_str() ) - //); - // m_pLog->WriteMsg( msg ); - // } - //} - // - // vwbCmdYesValid = bOk; - // CMIUtilString strNot; - // if( vwbCmdYesValid) - // strNot = CMIUtilString::Format( "%s ", MIRSRC( IDS_WORD_NOT ) ); - // const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_FALLTHRU_DRIVER_CMD_RECEIVED ), vTextLine.c_str(), strNot.c_str() ) ); - // m_pLog->WriteLog( msg ); - - return MIstatus::success; +bool CMIDriver::InterpretCommandFallThruDriver(const CMIUtilString &vTextLine, + bool &vwbCmdYesValid) { + MIunused(vTextLine); + MIunused(vwbCmdYesValid); + + // ToDo: Implement when less urgent work to be done or decide remove as not + // required + // bool bOk = MIstatus::success; + // bool bCmdNotUnderstood = true; + // if( bCmdNotUnderstood && GetEnableFallThru() ) + //{ + // CMIUtilString errMsg; + // bOk = DoFallThruToAnotherDriver( vStdInBuffer, errMsg ); + // if( !bOk ) + // { + // errMsg = errMsg.StripCREndOfLine(); + // errMsg = errMsg.StripCRAll(); + // const CMIDriverBase * pOtherDriver = GetDriverToFallThruTo(); + // const char * pName = pOtherDriver->GetDriverName().c_str(); + // const char * pId = pOtherDriver->GetDriverId().c_str(); + // const CMIUtilString msg( CMIUtilString::Format( MIRSRC( + // IDS_DRIVER_ERR_FALLTHRU_DRIVER_ERR ), pName, pId, errMsg.c_str() ) + //); + // m_pLog->WriteMsg( msg ); + // } + //} + // + // vwbCmdYesValid = bOk; + // CMIUtilString strNot; + // if( vwbCmdYesValid) + // strNot = CMIUtilString::Format( "%s ", MIRSRC( IDS_WORD_NOT ) ); + // const CMIUtilString msg( CMIUtilString::Format( MIRSRC( + // IDS_FALLTHRU_DRIVER_CMD_RECEIVED ), vTextLine.c_str(), strNot.c_str() ) ); + // m_pLog->WriteLog( msg ); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the name for *this driver. // Type: Overridden. // Args: None. // Return: CMIUtilString & - Driver name. // Throws: None. //-- -const CMIUtilString & -CMIDriver::GetDriverName() const -{ - return GetName(); -} +const CMIUtilString &CMIDriver::GetDriverName() const { return GetName(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Get the unique ID for *this driver. // Type: Overridden. // Args: None. // Return: CMIUtilString & - Text description. // Throws: None. //-- -const CMIUtilString & -CMIDriver::GetDriverId() const -{ - return GetId(); -} +const CMIUtilString &CMIDriver::GetDriverId() const { return GetId(); } -//++ ------------------------------------------------------------------------------------ -// Details: This function allows *this driver to call on another driver to perform work +//++ +//------------------------------------------------------------------------------------ +// Details: This function allows *this driver to call on another driver to +// perform work // should this driver not be able to handle the client data input. // SetDriverToFallThruTo() specifies the fall through to driver. // Check the error message if the function returns a failure. @@ -705,76 +718,77 @@ CMIDriver::GetDriverId() const // MIstatus::failure - Command failed. // Throws: None. //-- -bool -CMIDriver::DoFallThruToAnotherDriver(const CMIUtilString &vCmd, CMIUtilString &vwErrMsg) -{ - bool bOk = MIstatus::success; +bool CMIDriver::DoFallThruToAnotherDriver(const CMIUtilString &vCmd, + CMIUtilString &vwErrMsg) { + bool bOk = MIstatus::success; - CMIDriverBase *pOtherDriver = GetDriverToFallThruTo(); - if (pOtherDriver == nullptr) - return bOk; + CMIDriverBase *pOtherDriver = GetDriverToFallThruTo(); + if (pOtherDriver == nullptr) + return bOk; - return pOtherDriver->DoFallThruToAnotherDriver(vCmd, vwErrMsg); + return pOtherDriver->DoFallThruToAnotherDriver(vCmd, vwErrMsg); } -//++ ------------------------------------------------------------------------------------ -// Details: *this driver provides a file stream to other drivers on which *this driver -// write's out to and they read as expected input. *this driver is passing +//++ +//------------------------------------------------------------------------------------ +// Details: *this driver provides a file stream to other drivers on which *this +// driver +// write's out to and they read as expected input. *this driver is +// passing // through commands to the (child) pass through assigned driver. // Type: Overrdidden. // Args: None. // Return: FILE * - Pointer to stream. // Throws: None. //-- -FILE * -CMIDriver::GetStdin() const -{ - // Note this fn is called on CMIDriverMgr register driver so stream has to be - // available before *this driver has been initialized! Flaw? - - // This very likely to change later to a stream that the pass thru driver - // will read and we write to give it 'input' - return stdin; +FILE *CMIDriver::GetStdin() const { + // Note this fn is called on CMIDriverMgr register driver so stream has to be + // available before *this driver has been initialized! Flaw? + + // This very likely to change later to a stream that the pass thru driver + // will read and we write to give it 'input' + return stdin; } -//++ ------------------------------------------------------------------------------------ -// Details: *this driver provides a file stream to other pass through assigned drivers +//++ +//------------------------------------------------------------------------------------ +// Details: *this driver provides a file stream to other pass through assigned +// drivers // so they know what to write to. // Type: Overidden. // Args: None. // Return: FILE * - Pointer to stream. // Throws: None. //-- -FILE * -CMIDriver::GetStdout() const -{ - // Note this fn is called on CMIDriverMgr register driver so stream has to be - // available before *this driver has been initialized! Flaw? - - // Do not want to pass through driver to write to stdout - return NULL; +FILE *CMIDriver::GetStdout() const { + // Note this fn is called on CMIDriverMgr register driver so stream has to be + // available before *this driver has been initialized! Flaw? + + // Do not want to pass through driver to write to stdout + return NULL; } -//++ ------------------------------------------------------------------------------------ -// Details: *this driver provides a error file stream to other pass through assigned drivers +//++ +//------------------------------------------------------------------------------------ +// Details: *this driver provides a error file stream to other pass through +// assigned drivers // so they know what to write to. // Type: Overidden. // Args: None. // Return: FILE * - Pointer to stream. // Throws: None. //-- -FILE * -CMIDriver::GetStderr() const -{ - // Note this fn is called on CMIDriverMgr register driver so stream has to be - // available before *this driver has been initialized! Flaw? - - // This very likely to change later to a stream that the pass thru driver - // will write to and *this driver reads from to pass on the CMICmnLog object - return stderr; +FILE *CMIDriver::GetStderr() const { + // Note this fn is called on CMIDriverMgr register driver so stream has to be + // available before *this driver has been initialized! Flaw? + + // This very likely to change later to a stream that the pass thru driver + // will write to and *this driver reads from to pass on the CMICmnLog object + return stderr; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Set a unique ID for *this driver. It cannot be empty. // Type: Overridden. // Args: vId - (R) Text description. @@ -782,36 +796,35 @@ CMIDriver::GetStderr() const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriver::SetId(const CMIUtilString &vId) -{ - if (vId.empty()) - { - SetErrorDescriptionn(MIRSRC(IDS_DRIVER_ERR_ID_INVALID), GetName().c_str(), vId.c_str()); - return MIstatus::failure; - } - - m_strDriverId = vId; - return MIstatus::success; +bool CMIDriver::SetId(const CMIUtilString &vId) { + if (vId.empty()) { + SetErrorDescriptionn(MIRSRC(IDS_DRIVER_ERR_ID_INVALID), GetName().c_str(), + vId.c_str()); + return MIstatus::failure; + } + + m_strDriverId = vId; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Get the unique ID for *this driver. // Type: Overridden. // Args: None. // Return: CMIUtilString & - Text description. // Throws: None. //-- -const CMIUtilString & -CMIDriver::GetId() const -{ - return m_strDriverId; -} - -//++ ------------------------------------------------------------------------------------ -// Details: Interpret the text data and match against current commands to see if there -// is a match. If a match then the command is issued and actioned on. The -// text data if not understood by *this driver is past on to the Fall Thru +const CMIUtilString &CMIDriver::GetId() const { return m_strDriverId; } + +//++ +//------------------------------------------------------------------------------------ +// Details: Interpret the text data and match against current commands to see if +// there +// is a match. If a match then the command is issued and actioned on. +// The +// text data if not understood by *this driver is past on to the Fall +// Thru // driver. // This function is used by the application's main thread. // Type: Method. @@ -820,22 +833,22 @@ CMIDriver::GetId() const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriver::InterpretCommand(const CMIUtilString &vTextLine) -{ - const bool bNeedToRebroadcastStopEvent = m_rLldbDebugger.CheckIfNeedToRebroadcastStopEvent(); - bool bCmdYesValid = false; - bool bOk = InterpretCommandThisDriver(vTextLine, bCmdYesValid); - if (bOk && !bCmdYesValid) - bOk = InterpretCommandFallThruDriver(vTextLine, bCmdYesValid); - - if (bNeedToRebroadcastStopEvent) - m_rLldbDebugger.RebroadcastStopEvent(); - - return bOk; +bool CMIDriver::InterpretCommand(const CMIUtilString &vTextLine) { + const bool bNeedToRebroadcastStopEvent = + m_rLldbDebugger.CheckIfNeedToRebroadcastStopEvent(); + bool bCmdYesValid = false; + bool bOk = InterpretCommandThisDriver(vTextLine, bCmdYesValid); + if (bOk && !bCmdYesValid) + bOk = InterpretCommandFallThruDriver(vTextLine, bCmdYesValid); + + if (bNeedToRebroadcastStopEvent) + m_rLldbDebugger.RebroadcastStopEvent(); + + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Helper function for CMIDriver::InterpretCommandThisDriver. // Convert a CLI command to MI command (just wrap any CLI command // into "<tokens>-interpreter-exec command \"<CLI command>\""). @@ -846,135 +859,147 @@ CMIDriver::InterpretCommand(const CMIUtilString &vTextLine) // Throws: None. //-- CMIUtilString -CMIDriver::WrapCLICommandIntoMICommand(const CMIUtilString &vTextLine) const -{ - // Tokens contain following digits - static const CMIUtilString digits("0123456789"); - - // Consider an algorithm on the following example: - // 001-file-exec-and-symbols "/path/to/file" - // - // 1. Skip a command token - // For example: - // 001-file-exec-and-symbols "/path/to/file" - // 001target create "/path/to/file" - // ^ -- command starts here (in both cases) - // Also possible case when command not found: - // 001 - // ^ -- i.e. only tokens are present (or empty string at all) - const size_t nCommandOffset = vTextLine.find_first_not_of(digits); - - // 2. Check if command is empty - // For example: - // 001-file-exec-and-symbols "/path/to/file" - // 001target create "/path/to/file" - // ^ -- command not empty (in both cases) - // or: - // 001 - // ^ -- command wasn't found - const bool bIsEmptyCommand = (nCommandOffset == CMIUtilString::npos); - - // 3. Check and exit if it isn't a CLI command - // For example: - // 001-file-exec-and-symbols "/path/to/file" - // 001 - // ^ -- it isn't CLI command (in both cases) - // or: - // 001target create "/path/to/file" - // ^ -- it's CLI command - const bool bIsCliCommand = !bIsEmptyCommand && (vTextLine.at(nCommandOffset) != '-'); - if (!bIsCliCommand) - return vTextLine; - - // 4. Wrap CLI command to make it MI-compatible - // - // 001target create "/path/to/file" - // ^^^ -- token - const std::string vToken(vTextLine.begin(), vTextLine.begin() + nCommandOffset); - // 001target create "/path/to/file" - // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- CLI command - const CMIUtilString vCliCommand(std::string(vTextLine, nCommandOffset)); - - // 5. Escape special characters and embed the command in a string - // Result: it looks like -- target create \"/path/to/file\". - const std::string vShieldedCliCommand(vCliCommand.AddSlashes()); - - // 6. Turn the CLI command into an MI command, as in: - // 001-interpreter-exec command "target create \"/path/to/file\"" - // ^^^ -- token - // ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ -- wrapper - // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- shielded CLI command - return CMIUtilString::Format("%s-interpreter-exec command \"%s\"", - vToken.c_str(), vShieldedCliCommand.c_str()); +CMIDriver::WrapCLICommandIntoMICommand(const CMIUtilString &vTextLine) const { + // Tokens contain following digits + static const CMIUtilString digits("0123456789"); + + // Consider an algorithm on the following example: + // 001-file-exec-and-symbols "/path/to/file" + // + // 1. Skip a command token + // For example: + // 001-file-exec-and-symbols "/path/to/file" + // 001target create "/path/to/file" + // ^ -- command starts here (in both cases) + // Also possible case when command not found: + // 001 + // ^ -- i.e. only tokens are present (or empty string at all) + const size_t nCommandOffset = vTextLine.find_first_not_of(digits); + + // 2. Check if command is empty + // For example: + // 001-file-exec-and-symbols "/path/to/file" + // 001target create "/path/to/file" + // ^ -- command not empty (in both cases) + // or: + // 001 + // ^ -- command wasn't found + const bool bIsEmptyCommand = (nCommandOffset == CMIUtilString::npos); + + // 3. Check and exit if it isn't a CLI command + // For example: + // 001-file-exec-and-symbols "/path/to/file" + // 001 + // ^ -- it isn't CLI command (in both cases) + // or: + // 001target create "/path/to/file" + // ^ -- it's CLI command + const bool bIsCliCommand = + !bIsEmptyCommand && (vTextLine.at(nCommandOffset) != '-'); + if (!bIsCliCommand) + return vTextLine; + + // 4. Wrap CLI command to make it MI-compatible + // + // 001target create "/path/to/file" + // ^^^ -- token + const std::string vToken(vTextLine.begin(), + vTextLine.begin() + nCommandOffset); + // 001target create "/path/to/file" + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- CLI command + const CMIUtilString vCliCommand(std::string(vTextLine, nCommandOffset)); + + // 5. Escape special characters and embed the command in a string + // Result: it looks like -- target create \"/path/to/file\". + const std::string vShieldedCliCommand(vCliCommand.AddSlashes()); + + // 6. Turn the CLI command into an MI command, as in: + // 001-interpreter-exec command "target create \"/path/to/file\"" + // ^^^ -- token + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ -- wrapper + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- shielded + // CLI command + return CMIUtilString::Format("%s-interpreter-exec command \"%s\"", + vToken.c_str(), vShieldedCliCommand.c_str()); } -//++ ------------------------------------------------------------------------------------ -// Details: Interpret the text data and match against current commands to see if there -// is a match. If a match then the command is issued and actioned on. If a -// command cannot be found to match then vwbCmdYesValid is set to false and +//++ +//------------------------------------------------------------------------------------ +// Details: Interpret the text data and match against current commands to see if +// there +// is a match. If a match then the command is issued and actioned on. +// If a +// command cannot be found to match then vwbCmdYesValid is set to false +// and // nothing else is done here. // This function is used by the application's main thread. // Type: Method. // Args: vTextLine - (R) Text data representing a possible command. -// vwbCmdYesValid - (W) True = Command valid, false = command not handled. +// vwbCmdYesValid - (W) True = Command valid, false = command not +// handled. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriver::InterpretCommandThisDriver(const CMIUtilString &vTextLine, bool &vwbCmdYesValid) -{ - // Convert any CLI commands into MI commands - const CMIUtilString vMITextLine(WrapCLICommandIntoMICommand(vTextLine)); - - vwbCmdYesValid = false; - bool bCmdNotInCmdFactor = false; - SMICmdData cmdData; - CMICmdMgr &rCmdMgr = CMICmdMgr::Instance(); - if (!rCmdMgr.CmdInterpret(vMITextLine, vwbCmdYesValid, bCmdNotInCmdFactor, cmdData)) - return MIstatus::failure; - - if (vwbCmdYesValid) - { - // For debugging only - // m_pLog->WriteLog( cmdData.strMiCmdAll.c_str() ); - - return ExecuteCommand(cmdData); +bool CMIDriver::InterpretCommandThisDriver(const CMIUtilString &vTextLine, + bool &vwbCmdYesValid) { + // Convert any CLI commands into MI commands + const CMIUtilString vMITextLine(WrapCLICommandIntoMICommand(vTextLine)); + + vwbCmdYesValid = false; + bool bCmdNotInCmdFactor = false; + SMICmdData cmdData; + CMICmdMgr &rCmdMgr = CMICmdMgr::Instance(); + if (!rCmdMgr.CmdInterpret(vMITextLine, vwbCmdYesValid, bCmdNotInCmdFactor, + cmdData)) + return MIstatus::failure; + + if (vwbCmdYesValid) { + // For debugging only + // m_pLog->WriteLog( cmdData.strMiCmdAll.c_str() ); + + return ExecuteCommand(cmdData); + } + + // Check for escape character, may be cursor control characters + // This code is not necessary for application operation, just want to keep + // tabs on what + // has been given to the driver to try and interpret. + if (vMITextLine.at(0) == 27) { + CMIUtilString logInput(MIRSRC(IDS_STDIN_INPUT_CTRL_CHARS)); + for (MIuint i = 0; i < vMITextLine.length(); i++) { + logInput += CMIUtilString::Format("%d ", vMITextLine.at(i)); } - - // Check for escape character, may be cursor control characters - // This code is not necessary for application operation, just want to keep tabs on what - // has been given to the driver to try and interpret. - if (vMITextLine.at(0) == 27) - { - CMIUtilString logInput(MIRSRC(IDS_STDIN_INPUT_CTRL_CHARS)); - for (MIuint i = 0; i < vMITextLine.length(); i++) - { - logInput += CMIUtilString::Format("%d ", vMITextLine.at(i)); - } - m_pLog->WriteLog(logInput); - return MIstatus::success; - } - - // Write to the Log that a 'command' was not valid. - // Report back to the MI client via MI result record. - CMIUtilString strNotInCmdFactory; - if (bCmdNotInCmdFactor) - strNotInCmdFactory = CMIUtilString::Format(MIRSRC(IDS_DRIVER_CMD_NOT_IN_FACTORY), cmdData.strMiCmd.c_str()); - const CMIUtilString strNot(CMIUtilString::Format("%s ", MIRSRC(IDS_WORD_NOT))); - const CMIUtilString msg( - CMIUtilString::Format(MIRSRC(IDS_DRIVER_CMD_RECEIVED), vMITextLine.c_str(), strNot.c_str(), strNotInCmdFactory.c_str())); - const CMICmnMIValueConst vconst = CMICmnMIValueConst(msg); - const CMICmnMIValueResult valueResult("msg", vconst); - const CMICmnMIResultRecord miResultRecord(cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, valueResult); - const bool bOk = m_rStdOut.WriteMIResponse(miResultRecord.GetString()); - - // Proceed to wait for or execute next command - return bOk; + m_pLog->WriteLog(logInput); + return MIstatus::success; + } + + // Write to the Log that a 'command' was not valid. + // Report back to the MI client via MI result record. + CMIUtilString strNotInCmdFactory; + if (bCmdNotInCmdFactor) + strNotInCmdFactory = CMIUtilString::Format( + MIRSRC(IDS_DRIVER_CMD_NOT_IN_FACTORY), cmdData.strMiCmd.c_str()); + const CMIUtilString strNot( + CMIUtilString::Format("%s ", MIRSRC(IDS_WORD_NOT))); + const CMIUtilString msg(CMIUtilString::Format( + MIRSRC(IDS_DRIVER_CMD_RECEIVED), vMITextLine.c_str(), strNot.c_str(), + strNotInCmdFactory.c_str())); + const CMICmnMIValueConst vconst = CMICmnMIValueConst(msg); + const CMICmnMIValueResult valueResult("msg", vconst); + const CMICmnMIResultRecord miResultRecord( + cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, + valueResult); + const bool bOk = m_rStdOut.WriteMIResponse(miResultRecord.GetString()); + + // Proceed to wait for or execute next command + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Having previously had the potential command validated and found valid now +//++ +//------------------------------------------------------------------------------------ +// Details: Having previously had the potential command validated and found +// valid now // get the command executed. // This function is used by the application's main thread. // Type: Method. @@ -983,17 +1008,18 @@ CMIDriver::InterpretCommandThisDriver(const CMIUtilString &vTextLine, bool &vwbC // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriver::ExecuteCommand(const SMICmdData &vCmdData) -{ - CMICmdMgr &rCmdMgr = CMICmdMgr::Instance(); - return rCmdMgr.CmdExecute(vCmdData); +bool CMIDriver::ExecuteCommand(const SMICmdData &vCmdData) { + CMICmdMgr &rCmdMgr = CMICmdMgr::Instance(); + return rCmdMgr.CmdExecute(vCmdData); } -//++ ------------------------------------------------------------------------------------ -// Details: Set the MI Driver's exit application flag. The application checks this flag +//++ +//------------------------------------------------------------------------------------ +// Details: Set the MI Driver's exit application flag. The application checks +// this flag // after every stdin line is read so the exit may not be instantaneous. -// If vbForceExit is false the MI Driver queries its state and determines if is +// If vbForceExit is false the MI Driver queries its state and +// determines if is // should exit or continue operating depending on that running state. // This is related to the running state of the MI driver. // Type: Overridden. @@ -1001,58 +1027,53 @@ CMIDriver::ExecuteCommand(const SMICmdData &vCmdData) // Return: None. // Throws: None. //-- -void -CMIDriver::SetExitApplicationFlag(const bool vbForceExit) -{ - if (vbForceExit) - { - CMIUtilThreadLock lock(m_threadMutex); - m_bExitApp = true; - return; - } - - // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM - // Did we receive a SIGINT from the client during a running debug program, if - // so then SIGINT is not to be taken as meaning kill the MI driver application - // but halt the inferior program being debugged instead - if (m_eCurrentDriverState == eDriverState_RunningDebugging) - { - InterpretCommand("-exec-interrupt"); - return; - } - +void CMIDriver::SetExitApplicationFlag(const bool vbForceExit) { + if (vbForceExit) { + CMIUtilThreadLock lock(m_threadMutex); m_bExitApp = true; + return; + } + + // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM + // Did we receive a SIGINT from the client during a running debug program, if + // so then SIGINT is not to be taken as meaning kill the MI driver application + // but halt the inferior program being debugged instead + if (m_eCurrentDriverState == eDriverState_RunningDebugging) { + InterpretCommand("-exec-interrupt"); + return; + } + + m_bExitApp = true; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Get the MI Driver's exit exit application flag. // This is related to the running state of the MI driver. // Type: Method. // Args: None. -// Return: bool - True = MI Driver is shutting down, false = MI driver is running. +// Return: bool - True = MI Driver is shutting down, false = MI driver is +// running. // Throws: None. //-- -bool -CMIDriver::GetExitApplicationFlag() const -{ - return m_bExitApp; -} +bool CMIDriver::GetExitApplicationFlag() const { return m_bExitApp; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Get the current running state of the MI Driver. // Type: Method. // Args: None. // Return: DriverState_e - The current running state of the application. // Throws: None. //-- -CMIDriver::DriverState_e -CMIDriver::GetCurrentDriverState() const -{ - return m_eCurrentDriverState; +CMIDriver::DriverState_e CMIDriver::GetCurrentDriverState() const { + return m_eCurrentDriverState; } -//++ ------------------------------------------------------------------------------------ -// Details: Set the current running state of the MI Driver to running and currently not in +//++ +//------------------------------------------------------------------------------------ +// Details: Set the current running state of the MI Driver to running and +// currently not in // a debug session. // Type: Method. // Return: MIstatus::success - Functionality succeeded. @@ -1060,48 +1081,48 @@ CMIDriver::GetCurrentDriverState() const // Return: DriverState_e - The current running state of the application. // Throws: None. //-- -bool -CMIDriver::SetDriverStateRunningNotDebugging() -{ - // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM - - if (m_eCurrentDriverState == eDriverState_RunningNotDebugging) - return MIstatus::success; - - // Driver cannot be in the following states to set eDriverState_RunningNotDebugging - switch (m_eCurrentDriverState) - { - case eDriverState_NotRunning: - case eDriverState_Initialising: - case eDriverState_ShuttingDown: - { - SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR)); - return MIstatus::failure; - } - case eDriverState_RunningDebugging: - case eDriverState_RunningNotDebugging: - break; - case eDriverState_count: - SetErrorDescription( - CMIUtilString::Format(MIRSRC(IDS_CODE_ERR_INVALID_ENUMERATION_VALUE), "SetDriverStateRunningNotDebugging()")); - return MIstatus::failure; - } - - // Driver must be in this state to set eDriverState_RunningNotDebugging - if (m_eCurrentDriverState != eDriverState_RunningDebugging) - { - SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR)); - return MIstatus::failure; - } - - m_eCurrentDriverState = eDriverState_RunningNotDebugging; +bool CMIDriver::SetDriverStateRunningNotDebugging() { + // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM + if (m_eCurrentDriverState == eDriverState_RunningNotDebugging) return MIstatus::success; + + // Driver cannot be in the following states to set + // eDriverState_RunningNotDebugging + switch (m_eCurrentDriverState) { + case eDriverState_NotRunning: + case eDriverState_Initialising: + case eDriverState_ShuttingDown: { + SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR)); + return MIstatus::failure; + } + case eDriverState_RunningDebugging: + case eDriverState_RunningNotDebugging: + break; + case eDriverState_count: + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_CODE_ERR_INVALID_ENUMERATION_VALUE), + "SetDriverStateRunningNotDebugging()")); + return MIstatus::failure; + } + + // Driver must be in this state to set eDriverState_RunningNotDebugging + if (m_eCurrentDriverState != eDriverState_RunningDebugging) { + SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR)); + return MIstatus::failure; + } + + m_eCurrentDriverState = eDriverState_RunningNotDebugging; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Set the current running state of the MI Driver to running and currently not in -// a debug session. The driver's state must in the state running and in a +//++ +//------------------------------------------------------------------------------------ +// Details: Set the current running state of the MI Driver to running and +// currently not in +// a debug session. The driver's state must in the state running and in +// a // debug session to set this new state. // Type: Method. // Return: MIstatus::success - Functionality succeeded. @@ -1109,46 +1130,46 @@ CMIDriver::SetDriverStateRunningNotDebugging() // Return: DriverState_e - The current running state of the application. // Throws: None. //-- -bool -CMIDriver::SetDriverStateRunningDebugging() -{ - // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM - - if (m_eCurrentDriverState == eDriverState_RunningDebugging) - return MIstatus::success; - - // Driver cannot be in the following states to set eDriverState_RunningDebugging - switch (m_eCurrentDriverState) - { - case eDriverState_NotRunning: - case eDriverState_Initialising: - case eDriverState_ShuttingDown: - { - SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR)); - return MIstatus::failure; - } - case eDriverState_RunningDebugging: - case eDriverState_RunningNotDebugging: - break; - case eDriverState_count: - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CODE_ERR_INVALID_ENUMERATION_VALUE), "SetDriverStateRunningDebugging()")); - return MIstatus::failure; - } - - // Driver must be in this state to set eDriverState_RunningDebugging - if (m_eCurrentDriverState != eDriverState_RunningNotDebugging) - { - SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR)); - return MIstatus::failure; - } - - m_eCurrentDriverState = eDriverState_RunningDebugging; +bool CMIDriver::SetDriverStateRunningDebugging() { + // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM + if (m_eCurrentDriverState == eDriverState_RunningDebugging) return MIstatus::success; + + // Driver cannot be in the following states to set + // eDriverState_RunningDebugging + switch (m_eCurrentDriverState) { + case eDriverState_NotRunning: + case eDriverState_Initialising: + case eDriverState_ShuttingDown: { + SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR)); + return MIstatus::failure; + } + case eDriverState_RunningDebugging: + case eDriverState_RunningNotDebugging: + break; + case eDriverState_count: + SetErrorDescription( + CMIUtilString::Format(MIRSRC(IDS_CODE_ERR_INVALID_ENUMERATION_VALUE), + "SetDriverStateRunningDebugging()")); + return MIstatus::failure; + } + + // Driver must be in this state to set eDriverState_RunningDebugging + if (m_eCurrentDriverState != eDriverState_RunningNotDebugging) { + SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR)); + return MIstatus::failure; + } + + m_eCurrentDriverState = eDriverState_RunningDebugging; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Prepare the client IDE so it will start working/communicating with *this MI +//++ +//------------------------------------------------------------------------------------ +// Details: Prepare the client IDE so it will start working/communicating with +// *this MI // driver. // Type: Method. // Args: None. @@ -1156,16 +1177,16 @@ CMIDriver::SetDriverStateRunningDebugging() // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMIDriver::InitClientIDEToMIDriver() const -{ - // Put other IDE init functions here - return InitClientIDEEclipse(); +bool CMIDriver::InitClientIDEToMIDriver() const { + // Put other IDE init functions here + return InitClientIDEEclipse(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: The IDE Eclipse when debugging locally expects "(gdb)\n" character -// sequence otherwise it refuses to communicate and times out. This should be +// sequence otherwise it refuses to communicate and times out. This +// should be // sent to Eclipse before anything else. // Type: Method. // Args: None. @@ -1173,46 +1194,49 @@ CMIDriver::InitClientIDEToMIDriver() const // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMIDriver::InitClientIDEEclipse() const -{ - return CMICmnStreamStdout::WritePrompt(); +bool CMIDriver::InitClientIDEEclipse() const { + return CMICmnStreamStdout::WritePrompt(); } -//++ ------------------------------------------------------------------------------------ -// Details: Ask *this driver whether it found an executable in the MI Driver's list of -// arguments which to open and debug. If so instigate commands to set up a debug +//++ +//------------------------------------------------------------------------------------ +// Details: Ask *this driver whether it found an executable in the MI Driver's +// list of +// arguments which to open and debug. If so instigate commands to set +// up a debug // session for that executable. // Type: Method. // Args: None. -// Return: bool - True = True = Yes executable given as one of the parameters to the MI +// Return: bool - True = True = Yes executable given as one of the parameters +// to the MI // Driver. // False = not found. // Throws: None. //-- -bool -CMIDriver::HaveExecutableFileNamePathOnCmdLine() const -{ - return m_bHaveExecutableFileNamePathOnCmdLine; +bool CMIDriver::HaveExecutableFileNamePathOnCmdLine() const { + return m_bHaveExecutableFileNamePathOnCmdLine; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve from *this driver executable file name path to start a debug session +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve from *this driver executable file name path to start a +// debug session // with (if present see HaveExecutableFileNamePathOnCmdLine()). // Type: Method. // Args: None. // Return: CMIUtilString & - Executeable file name path or empty string. // Throws: None. //-- -const CMIUtilString & -CMIDriver::GetExecutableFileNamePathOnCmdLine() const -{ - return m_strCmdLineArgExecuteableFileNamePath; +const CMIUtilString &CMIDriver::GetExecutableFileNamePathOnCmdLine() const { + return m_strCmdLineArgExecuteableFileNamePath; } -//++ ------------------------------------------------------------------------------------ -// Details: Execute commands (by injecting them into the stdin line queue container) and -// other code to set up the MI Driver such that is can take the executable +//++ +//------------------------------------------------------------------------------------ +// Details: Execute commands (by injecting them into the stdin line queue +// container) and +// other code to set up the MI Driver such that is can take the +// executable // argument passed on the command and create a debug session for it. // Type: Method. // Args: None. @@ -1220,124 +1244,124 @@ CMIDriver::GetExecutableFileNamePathOnCmdLine() const // MIstatus::failure - Functionality failed. // Throws: None. //-- -bool -CMIDriver::LocalDebugSessionStartupExecuteCommands() -{ - const CMIUtilString strCmd(CMIUtilString::Format("-file-exec-and-symbols \"%s\"", m_strCmdLineArgExecuteableFileNamePath.AddSlashes().c_str())); - bool bOk = CMICmnStreamStdout::TextToStdout(strCmd); - bOk = bOk && InterpretCommand(strCmd); - bOk = bOk && CMICmnStreamStdout::WritePrompt(); - return bOk; +bool CMIDriver::LocalDebugSessionStartupExecuteCommands() { + const CMIUtilString strCmd(CMIUtilString::Format( + "-file-exec-and-symbols \"%s\"", + m_strCmdLineArgExecuteableFileNamePath.AddSlashes().c_str())); + bool bOk = CMICmnStreamStdout::TextToStdout(strCmd); + bOk = bOk && InterpretCommand(strCmd); + bOk = bOk && CMICmnStreamStdout::WritePrompt(); + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Set the MI Driver into "its debugging an executable passed as an argument" +//++ +//------------------------------------------------------------------------------------ +// Details: Set the MI Driver into "its debugging an executable passed as an +// argument" // mode as against running via a client like Eclipse. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -void -CMIDriver::SetDriverDebuggingArgExecutable() -{ - m_bDriverDebuggingArgExecutable = true; +void CMIDriver::SetDriverDebuggingArgExecutable() { + m_bDriverDebuggingArgExecutable = true; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the MI Driver state indicating if it is operating in "its debugging -// an executable passed as an argument" mode as against running via a client +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the MI Driver state indicating if it is operating in "its +// debugging +// an executable passed as an argument" mode as against running via a +// client // like Eclipse. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -bool -CMIDriver::IsDriverDebuggingArgExecutable() const -{ - return m_bDriverDebuggingArgExecutable; +bool CMIDriver::IsDriverDebuggingArgExecutable() const { + return m_bDriverDebuggingArgExecutable; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Execute commands from command source file in specified mode, and // set exit-flag if needed. // Type: Method. -// Args: vbAsyncMode - (R) True = execute commands in asynchronous mode, false = otherwise. +// Args: vbAsyncMode - (R) True = execute commands in asynchronous +// mode, false = otherwise. // Return: MIstatus::success - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- -bool -CMIDriver::ExecuteCommandFile(const bool vbAsyncMode) -{ - std::ifstream ifsStartScript(m_strCmdLineArgCommandFileNamePath.c_str()); - if (!ifsStartScript.is_open()) - { - const CMIUtilString errMsg( - CMIUtilString::Format(MIRSRC(IDS_UTIL_FILE_ERR_OPENING_FILE_UNKNOWN), m_strCmdLineArgCommandFileNamePath.c_str())); - SetErrorDescription(errMsg.c_str()); - const bool bForceExit = true; - SetExitApplicationFlag(bForceExit); - return MIstatus::failure; +bool CMIDriver::ExecuteCommandFile(const bool vbAsyncMode) { + std::ifstream ifsStartScript(m_strCmdLineArgCommandFileNamePath.c_str()); + if (!ifsStartScript.is_open()) { + const CMIUtilString errMsg( + CMIUtilString::Format(MIRSRC(IDS_UTIL_FILE_ERR_OPENING_FILE_UNKNOWN), + m_strCmdLineArgCommandFileNamePath.c_str())); + SetErrorDescription(errMsg.c_str()); + const bool bForceExit = true; + SetExitApplicationFlag(bForceExit); + return MIstatus::failure; + } + + // Switch lldb to synchronous mode + CMICmnLLDBDebugSessionInfo &rSessionInfo( + CMICmnLLDBDebugSessionInfo::Instance()); + const bool bAsyncSetting = rSessionInfo.GetDebugger().GetAsync(); + rSessionInfo.GetDebugger().SetAsync(vbAsyncMode); + + // Execute commands from file + bool bOk = MIstatus::success; + CMIUtilString strCommand; + while (!m_bExitApp && std::getline(ifsStartScript, strCommand)) { + // Print command + bOk = CMICmnStreamStdout::TextToStdout(strCommand); + + // Skip if it's a comment or empty line + if (strCommand.empty() || strCommand[0] == '#') + continue; + + // Execute if no error + if (bOk) { + CMIUtilThreadLock lock(rSessionInfo.GetSessionMutex()); + bOk = InterpretCommand(strCommand); } - // Switch lldb to synchronous mode - CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); - const bool bAsyncSetting = rSessionInfo.GetDebugger().GetAsync(); - rSessionInfo.GetDebugger().SetAsync(vbAsyncMode); - - // Execute commands from file - bool bOk = MIstatus::success; - CMIUtilString strCommand; - while (!m_bExitApp && std::getline(ifsStartScript, strCommand)) - { - // Print command - bOk = CMICmnStreamStdout::TextToStdout(strCommand); - - // Skip if it's a comment or empty line - if (strCommand.empty() || strCommand[0] == '#') - continue; - - // Execute if no error - if (bOk) - { - CMIUtilThreadLock lock(rSessionInfo.GetSessionMutex()); - bOk = InterpretCommand(strCommand); - } - - // Draw the prompt after command will be executed (if enabled) - bOk = bOk && CMICmnStreamStdout::WritePrompt(); - - // Exit if there is an error - if (!bOk) - { - const bool bForceExit = true; - SetExitApplicationFlag(bForceExit); - break; - } + // Draw the prompt after command will be executed (if enabled) + bOk = bOk && CMICmnStreamStdout::WritePrompt(); - // Wait while the handler thread handles incoming events - CMICmnLLDBDebugger::Instance().WaitForHandleEvent(); + // Exit if there is an error + if (!bOk) { + const bool bForceExit = true; + SetExitApplicationFlag(bForceExit); + break; } - // Switch lldb back to initial mode - rSessionInfo.GetDebugger().SetAsync(bAsyncSetting); + // Wait while the handler thread handles incoming events + CMICmnLLDBDebugger::Instance().WaitForHandleEvent(); + } - return bOk; + // Switch lldb back to initial mode + rSessionInfo.GetDebugger().SetAsync(bAsyncSetting); + + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Gets called when lldb-mi gets a signal. Stops the process if it was SIGINT. +//++ +//------------------------------------------------------------------------------------ +// Details: Gets called when lldb-mi gets a signal. Stops the process if it was +// SIGINT. // // Type: Method. // Args: signal that was delivered // Return: None. // Throws: None. //-- -void -CMIDriver::DeliverSignal(int signal) -{ - if (signal == SIGINT && (m_eCurrentDriverState == eDriverState_RunningDebugging)) - InterpretCommand("-exec-interrupt"); +void CMIDriver::DeliverSignal(int signal) { + if (signal == SIGINT && + (m_eCurrentDriverState == eDriverState_RunningDebugging)) + InterpretCommand("-exec-interrupt"); } diff --git a/lldb/tools/lldb-mi/MIDriver.h b/lldb/tools/lldb-mi/MIDriver.h index a90c31fbc75..1b5865697da 100644 --- a/lldb/tools/lldb-mi/MIDriver.h +++ b/lldb/tools/lldb-mi/MIDriver.h @@ -13,19 +13,20 @@ #include <queue> // In-house headers: -#include "MICmnConfig.h" +#include "MICmdData.h" #include "MICmnBase.h" +#include "MICmnConfig.h" +#include "MICmnStreamStdin.h" #include "MIDriverBase.h" #include "MIDriverMgr.h" -#include "MICmnStreamStdin.h" -#include "MICmdData.h" #include "MIUtilSingletonBase.h" // Declarations: class CMICmnLLDBDebugger; class CMICmnStreamStdout; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI driver implementation class. A singleton class derived from // LLDB SBBroadcaster class. Register the instance of *this class with // the CMIDriverMgr. The CMIDriverMgr sets the driver(s) of to start @@ -36,129 +37,145 @@ class CMICmnStreamStdout; class CMIDriver : public CMICmnBase, public CMIDriverMgr::IDriver, public CMIDriverBase, - public MI::ISingleton<CMIDriver> -{ - friend class MI::ISingleton<CMIDriver>; - - // Enumerations: - public: - //++ ---------------------------------------------------------------------- - // Details: The MI Driver has a running state which is used to help determine - // which specific action(s) it should take or not allow. - // The driver when operational and not shutting down alternates - // between eDriverState_RunningNotDebugging and - // eDriverState_RunningDebugging. eDriverState_RunningNotDebugging - // is normally set when a breakpoint is hit or halted. - // eDriverState_RunningDebugging is normally set when "exec-continue" - // or "exec-run" is issued. - //-- - enum DriverState_e - { - eDriverState_NotRunning = 0, // The MI Driver is not operating - eDriverState_Initialising, // The MI Driver is setting itself up - eDriverState_RunningNotDebugging, // The MI Driver is operational acting on any MI commands sent to it - eDriverState_RunningDebugging, // The MI Driver is currently overseeing an inferior program that is running - eDriverState_ShuttingDown, // The MI Driver is tearing down resources and about exit - eDriverState_count // Always last - }; - - // Methods: - public: - // MI system - bool Initialize() override; - bool Shutdown() override; - - // MI state - bool GetExitApplicationFlag() const; - DriverState_e GetCurrentDriverState() const; - bool SetDriverStateRunningNotDebugging(); - bool SetDriverStateRunningDebugging(); - void SetDriverDebuggingArgExecutable(); - bool IsDriverDebuggingArgExecutable() const; - - // MI information about itself - const CMIUtilString &GetAppNameShort() const; - const CMIUtilString &GetAppNameLong() const; - const CMIUtilString &GetVersionDescription() const; - - // MI do work - bool WriteMessageToLog(const CMIUtilString &vMessage); - bool SetEnableFallThru(const bool vbYes); - bool GetEnableFallThru() const; - bool HaveExecutableFileNamePathOnCmdLine() const; - const CMIUtilString &GetExecutableFileNamePathOnCmdLine() const; - - // Overridden: - public: - // From CMIDriverMgr::IDriver - bool DoInitialize() override; - bool DoShutdown() override; - bool DoMainLoop() override; - lldb::SBError DoParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting) override; - CMIUtilString GetError() const override; - const CMIUtilString &GetName() const override; - lldb::SBDebugger &GetTheDebugger() override; - bool GetDriverIsGDBMICompatibleDriver() const override; - bool SetId(const CMIUtilString &vId) override; - const CMIUtilString &GetId() const override; - // From CMIDriverBase - void SetExitApplicationFlag(const bool vbForceExit) override; - bool DoFallThruToAnotherDriver(const CMIUtilString &vCmd, CMIUtilString &vwErrMsg) override; - bool SetDriverToFallThruTo(const CMIDriverBase &vrOtherDriver) override; - FILE *GetStdin() const override; - FILE *GetStdout() const override; - FILE *GetStderr() const override; - const CMIUtilString &GetDriverName() const override; - const CMIUtilString &GetDriverId() const override; - void DeliverSignal(int signal) override; - - // Typedefs: - private: - typedef std::queue<CMIUtilString> QueueStdinLine_t; - - // Methods: - private: - /* ctor */ CMIDriver(); - /* ctor */ CMIDriver(const CMIDriver &); - void operator=(const CMIDriver &); - - lldb::SBError ParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting); - bool DoAppQuit(); - bool InterpretCommand(const CMIUtilString &vTextLine); - bool InterpretCommandThisDriver(const CMIUtilString &vTextLine, bool &vwbCmdYesValid); - CMIUtilString WrapCLICommandIntoMICommand(const CMIUtilString &vTextLine) const; - bool InterpretCommandFallThruDriver(const CMIUtilString &vTextLine, bool &vwbCmdYesValid); - bool ExecuteCommand(const SMICmdData &vCmdData); - bool StartWorkerThreads(); - bool StopWorkerThreads(); - bool InitClientIDEToMIDriver() const; - bool InitClientIDEEclipse() const; - bool LocalDebugSessionStartupExecuteCommands(); - bool ExecuteCommandFile(const bool vbAsyncMode); - - // Overridden: - private: - // From CMICmnBase - /* dtor */ ~CMIDriver() override; - - // Attributes: - private: - static const CMIUtilString ms_constAppNameShort; - static const CMIUtilString ms_constAppNameLong; - static const CMIUtilString ms_constMIVersion; - // - bool m_bFallThruToOtherDriverEnabled; // True = yes fall through, false = do not pass on command - CMIUtilThreadMutex m_threadMutex; - bool m_bDriverIsExiting; // True = yes, driver told to quit, false = continue working - void *m_handleMainThread; // *this driver is run by the main thread - CMICmnStreamStdin &m_rStdin; - CMICmnLLDBDebugger &m_rLldbDebugger; - CMICmnStreamStdout &m_rStdOut; - DriverState_e m_eCurrentDriverState; - bool m_bHaveExecutableFileNamePathOnCmdLine; // True = yes, executable given as one of the parameters to the MI Driver, false = not found - CMIUtilString m_strCmdLineArgExecuteableFileNamePath; - bool m_bDriverDebuggingArgExecutable; // True = the MI Driver (MI mode) is debugging executable passed as argument, - // false = running via a client (e.g. Eclipse) - bool m_bHaveCommandFileNamePathOnCmdLine; // True = file with initial commands given as one of the parameters to the MI Driver, false = not found - CMIUtilString m_strCmdLineArgCommandFileNamePath; + public MI::ISingleton<CMIDriver> { + friend class MI::ISingleton<CMIDriver>; + + // Enumerations: +public: + //++ ---------------------------------------------------------------------- + // Details: The MI Driver has a running state which is used to help determine + // which specific action(s) it should take or not allow. + // The driver when operational and not shutting down alternates + // between eDriverState_RunningNotDebugging and + // eDriverState_RunningDebugging. eDriverState_RunningNotDebugging + // is normally set when a breakpoint is hit or halted. + // eDriverState_RunningDebugging is normally set when "exec-continue" + // or "exec-run" is issued. + //-- + enum DriverState_e { + eDriverState_NotRunning = 0, // The MI Driver is not operating + eDriverState_Initialising, // The MI Driver is setting itself up + eDriverState_RunningNotDebugging, // The MI Driver is operational acting on + // any MI commands sent to it + eDriverState_RunningDebugging, // The MI Driver is currently overseeing an + // inferior program that is running + eDriverState_ShuttingDown, // The MI Driver is tearing down resources and + // about exit + eDriverState_count // Always last + }; + + // Methods: +public: + // MI system + bool Initialize() override; + bool Shutdown() override; + + // MI state + bool GetExitApplicationFlag() const; + DriverState_e GetCurrentDriverState() const; + bool SetDriverStateRunningNotDebugging(); + bool SetDriverStateRunningDebugging(); + void SetDriverDebuggingArgExecutable(); + bool IsDriverDebuggingArgExecutable() const; + + // MI information about itself + const CMIUtilString &GetAppNameShort() const; + const CMIUtilString &GetAppNameLong() const; + const CMIUtilString &GetVersionDescription() const; + + // MI do work + bool WriteMessageToLog(const CMIUtilString &vMessage); + bool SetEnableFallThru(const bool vbYes); + bool GetEnableFallThru() const; + bool HaveExecutableFileNamePathOnCmdLine() const; + const CMIUtilString &GetExecutableFileNamePathOnCmdLine() const; + + // Overridden: +public: + // From CMIDriverMgr::IDriver + bool DoInitialize() override; + bool DoShutdown() override; + bool DoMainLoop() override; + lldb::SBError DoParseArgs(const int argc, const char *argv[], FILE *vpStdOut, + bool &vwbExiting) override; + CMIUtilString GetError() const override; + const CMIUtilString &GetName() const override; + lldb::SBDebugger &GetTheDebugger() override; + bool GetDriverIsGDBMICompatibleDriver() const override; + bool SetId(const CMIUtilString &vId) override; + const CMIUtilString &GetId() const override; + // From CMIDriverBase + void SetExitApplicationFlag(const bool vbForceExit) override; + bool DoFallThruToAnotherDriver(const CMIUtilString &vCmd, + CMIUtilString &vwErrMsg) override; + bool SetDriverToFallThruTo(const CMIDriverBase &vrOtherDriver) override; + FILE *GetStdin() const override; + FILE *GetStdout() const override; + FILE *GetStderr() const override; + const CMIUtilString &GetDriverName() const override; + const CMIUtilString &GetDriverId() const override; + void DeliverSignal(int signal) override; + + // Typedefs: +private: + typedef std::queue<CMIUtilString> QueueStdinLine_t; + + // Methods: +private: + /* ctor */ CMIDriver(); + /* ctor */ CMIDriver(const CMIDriver &); + void operator=(const CMIDriver &); + + lldb::SBError ParseArgs(const int argc, const char *argv[], FILE *vpStdOut, + bool &vwbExiting); + bool DoAppQuit(); + bool InterpretCommand(const CMIUtilString &vTextLine); + bool InterpretCommandThisDriver(const CMIUtilString &vTextLine, + bool &vwbCmdYesValid); + CMIUtilString + WrapCLICommandIntoMICommand(const CMIUtilString &vTextLine) const; + bool InterpretCommandFallThruDriver(const CMIUtilString &vTextLine, + bool &vwbCmdYesValid); + bool ExecuteCommand(const SMICmdData &vCmdData); + bool StartWorkerThreads(); + bool StopWorkerThreads(); + bool InitClientIDEToMIDriver() const; + bool InitClientIDEEclipse() const; + bool LocalDebugSessionStartupExecuteCommands(); + bool ExecuteCommandFile(const bool vbAsyncMode); + + // Overridden: +private: + // From CMICmnBase + /* dtor */ ~CMIDriver() override; + + // Attributes: +private: + static const CMIUtilString ms_constAppNameShort; + static const CMIUtilString ms_constAppNameLong; + static const CMIUtilString ms_constMIVersion; + // + bool m_bFallThruToOtherDriverEnabled; // True = yes fall through, false = do + // not pass on command + CMIUtilThreadMutex m_threadMutex; + bool m_bDriverIsExiting; // True = yes, driver told to quit, false = continue + // working + void *m_handleMainThread; // *this driver is run by the main thread + CMICmnStreamStdin &m_rStdin; + CMICmnLLDBDebugger &m_rLldbDebugger; + CMICmnStreamStdout &m_rStdOut; + DriverState_e m_eCurrentDriverState; + bool m_bHaveExecutableFileNamePathOnCmdLine; // True = yes, executable given + // as one of the parameters to + // the MI Driver, false = not + // found + CMIUtilString m_strCmdLineArgExecuteableFileNamePath; + bool m_bDriverDebuggingArgExecutable; // True = the MI Driver (MI mode) is + // debugging executable passed as + // argument, + // false = running via a client (e.g. Eclipse) + bool m_bHaveCommandFileNamePathOnCmdLine; // True = file with initial commands + // given as one of the parameters to + // the MI Driver, false = not found + CMIUtilString m_strCmdLineArgCommandFileNamePath; }; diff --git a/lldb/tools/lldb-mi/MIDriverBase.cpp b/lldb/tools/lldb-mi/MIDriverBase.cpp index 6738497de75..0620b6154b1 100644 --- a/lldb/tools/lldb-mi/MIDriverBase.cpp +++ b/lldb/tools/lldb-mi/MIDriverBase.cpp @@ -8,13 +8,14 @@ //===----------------------------------------------------------------------===// // Third party headers: -#include "lldb/API/SBEvent.h" #include "lldb/API/SBBroadcaster.h" +#include "lldb/API/SBEvent.h" // In-house headers: #include "MIDriverBase.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIDriverBase constructor. // Type: Method. // Args: None. @@ -22,26 +23,22 @@ // Throws: None. //-- CMIDriverBase::CMIDriverBase() - : m_pDriverFallThru(nullptr) - , m_pDriverParent(nullptr) - , m_bExitApp(false) -{ -} + : m_pDriverFallThru(nullptr), m_pDriverParent(nullptr), m_bExitApp(false) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIDriverBase destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMIDriverBase::~CMIDriverBase() -{ - m_pDriverFallThru = NULL; -} +CMIDriverBase::~CMIDriverBase() { m_pDriverFallThru = NULL; } -//++ ------------------------------------------------------------------------------------ -// Details: This function allows *this driver to call on another driver to perform work +//++ +//------------------------------------------------------------------------------------ +// Details: This function allows *this driver to call on another driver to +// perform work // should this driver not be able to handle the client data input. // Type: Overrideable. // Check the error message if the function returns a failure. @@ -52,15 +49,16 @@ CMIDriverBase::~CMIDriverBase() // MIstatus::failure - Command failed. // Throws: None. //-- -bool -CMIDriverBase::DoFallThruToAnotherDriver(const CMIUtilString &vCmd, CMIUtilString &vwErrMsg) -{ - // Do nothing - override and implement. Use m_pDriverFallThru. - return MIstatus::success; +bool CMIDriverBase::DoFallThruToAnotherDriver(const CMIUtilString &vCmd, + CMIUtilString &vwErrMsg) { + // Do nothing - override and implement. Use m_pDriverFallThru. + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: This function allows *this driver to call on another driver to perform work +//++ +//------------------------------------------------------------------------------------ +// Details: This function allows *this driver to call on another driver to +// perform work // should this driver not be able to handle the client data input. // Type: Overrideable. // Args: vrOtherDriver - (R) Reference to another driver object. @@ -68,18 +66,18 @@ CMIDriverBase::DoFallThruToAnotherDriver(const CMIUtilString &vCmd, CMIUtilStrin // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriverBase::SetDriverToFallThruTo(const CMIDriverBase &vrOtherDriver) -{ - MIunused(vrOtherDriver); +bool CMIDriverBase::SetDriverToFallThruTo(const CMIDriverBase &vrOtherDriver) { + MIunused(vrOtherDriver); - // Do nothing - override and implement. Set m_pDriverFallThru. + // Do nothing - override and implement. Set m_pDriverFallThru. - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: This function allows *this driver to call functionality on the parent driver +//++ +//------------------------------------------------------------------------------------ +// Details: This function allows *this driver to call functionality on the +// parent driver // ask for information for example. // Type: Overrideable. // Args: vrOtherDriver - (R) Reference to another driver object. @@ -87,18 +85,18 @@ CMIDriverBase::SetDriverToFallThruTo(const CMIDriverBase &vrOtherDriver) // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriverBase::SetDriverParent(const CMIDriverBase &vrOtherDriver) -{ - MIunused(vrOtherDriver); +bool CMIDriverBase::SetDriverParent(const CMIDriverBase &vrOtherDriver) { + MIunused(vrOtherDriver); - // Do nothing - override and implement. Set m_pDriverParent. + // Do nothing - override and implement. Set m_pDriverParent. - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the parent driver to *this driver if one assigned. If assigned *this +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the parent driver to *this driver if one assigned. If +// assigned *this // is the pass through driver that the parent driver passes work to. // Type: Method. // Args: None. @@ -106,14 +104,14 @@ CMIDriverBase::SetDriverParent(const CMIDriverBase &vrOtherDriver) // - NULL = there is not parent to *this driver. // Throws: None. //-- -CMIDriverBase * -CMIDriverBase::GetDriversParent() const -{ - return m_pDriverParent; +CMIDriverBase *CMIDriverBase::GetDriversParent() const { + return m_pDriverParent; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve the pointer to the other fall through driver *this driver is using +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve the pointer to the other fall through driver *this driver +// is using // (or not using). // Type: Method. // Args: None. @@ -121,72 +119,73 @@ CMIDriverBase::GetDriversParent() const // - NULL if no driver set. // Throws: None. //-- -CMIDriverBase * -CMIDriverBase::GetDriverToFallThruTo() const -{ - return m_pDriverFallThru; +CMIDriverBase *CMIDriverBase::GetDriverToFallThruTo() const { + return m_pDriverFallThru; } -//++ ------------------------------------------------------------------------------------ -// Details: *this driver provides a file stream to other drivers on which *this driver -// write's out to and they read as expected input. *this driver is passing +//++ +//------------------------------------------------------------------------------------ +// Details: *this driver provides a file stream to other drivers on which *this +// driver +// write's out to and they read as expected input. *this driver is +// passing // through commands to the (child) pass through assigned driver. // Type: Overrideable. // Args: None. // Return: FILE * - Pointer to stream. // Throws: None. //-- -FILE * -CMIDriverBase::GetStdin() const -{ - // Do nothing - override and implement - return nullptr; +FILE *CMIDriverBase::GetStdin() const { + // Do nothing - override and implement + return nullptr; } -//++ ------------------------------------------------------------------------------------ -// Details: *this driver provides a file stream to other pass through assigned drivers +//++ +//------------------------------------------------------------------------------------ +// Details: *this driver provides a file stream to other pass through assigned +// drivers // so they know what to write to. // Type: Overrideable. // Args: None. // Return: FILE * - Pointer to stream. // Throws: None. //-- -FILE * -CMIDriverBase::GetStdout() const -{ - // Do nothing - override and implement - return nullptr; +FILE *CMIDriverBase::GetStdout() const { + // Do nothing - override and implement + return nullptr; } -//++ ------------------------------------------------------------------------------------ -// Details: *this driver provides a error file stream to other pass through assigned drivers +//++ +//------------------------------------------------------------------------------------ +// Details: *this driver provides a error file stream to other pass through +// assigned drivers // so they know what to write to. // Type: Overrideable. // Args: None. // Return: FILE * - Pointer to stream. // Throws: None. //-- -FILE * -CMIDriverBase::GetStderr() const -{ - // Do nothing - override and implement - return nullptr; +FILE *CMIDriverBase::GetStderr() const { + // Do nothing - override and implement + return nullptr; } -//++ ------------------------------------------------------------------------------------ -// Details: Set the MI Driver's exit application flag. The application checks this flag +//++ +//------------------------------------------------------------------------------------ +// Details: Set the MI Driver's exit application flag. The application checks +// this flag // after every stdin line is read so the exit may not be instantaneous. -// If vbForceExit is false the MI Driver queries its state and determines if is +// If vbForceExit is false the MI Driver queries its state and +// determines if is // should exit or continue operating depending on that running state. // Type: Overrideable. -// Args: vbForceExit - (R) True = Do not query, set state to exit, false = query if can/should exit right now. +// Args: vbForceExit - (R) True = Do not query, set state to exit, false = +// query if can/should exit right now. // Return: None. // Throws: None. //-- -void -CMIDriverBase::SetExitApplicationFlag(const bool vbForceExit) -{ - MIunused(vbForceExit); +void CMIDriverBase::SetExitApplicationFlag(const bool vbForceExit) { + MIunused(vbForceExit); - // Do nothing - override and implement + // Do nothing - override and implement } diff --git a/lldb/tools/lldb-mi/MIDriverBase.h b/lldb/tools/lldb-mi/MIDriverBase.h index 9be407e0c14..8ac49ecd88d 100644 --- a/lldb/tools/lldb-mi/MIDriverBase.h +++ b/lldb/tools/lldb-mi/MIDriverBase.h @@ -10,19 +10,19 @@ #pragma once // Third party headers: -#include "lldb/API/SBDebugger.h" #include "lldb/API/SBBroadcaster.h" +#include "lldb/API/SBDebugger.h" // In-house headers: #include "MIUtilString.h" // Declarations: -namespace lldb -{ +namespace lldb { class SBBroadcaster; } -//++ ============================================================================ +//++ +//============================================================================ // Details: MI driver base implementation class. This class has been created so // not have to edit the lldb::SBBroadcaster class code. Functionality // and attributes need to be common to the LLDB Driver class and the @@ -32,35 +32,37 @@ class SBBroadcaster; // Each driver instance (the CMIDriver, LLDB::Driver) has its own // LLDB::SBDebugger object. //-- -class CMIDriverBase -{ - // Methods: - public: - /* ctor */ CMIDriverBase(); +class CMIDriverBase { + // Methods: +public: + /* ctor */ CMIDriverBase(); - CMIDriverBase *GetDriverToFallThruTo() const; - CMIDriverBase *GetDriversParent() const; + CMIDriverBase *GetDriverToFallThruTo() const; + CMIDriverBase *GetDriversParent() const; - // Overrideable: - public: - /* dtor */ virtual ~CMIDriverBase(); + // Overrideable: +public: + /* dtor */ virtual ~CMIDriverBase(); - virtual bool DoFallThruToAnotherDriver(const CMIUtilString &vCmd, CMIUtilString &vwErrMsg); - virtual bool SetDriverToFallThruTo(const CMIDriverBase &vrOtherDriver); - virtual bool SetDriverParent(const CMIDriverBase &vrOtherDriver); - virtual const CMIUtilString &GetDriverName() const = 0; - virtual const CMIUtilString &GetDriverId() const = 0; - virtual void SetExitApplicationFlag(const bool vbForceExit); + virtual bool DoFallThruToAnotherDriver(const CMIUtilString &vCmd, + CMIUtilString &vwErrMsg); + virtual bool SetDriverToFallThruTo(const CMIDriverBase &vrOtherDriver); + virtual bool SetDriverParent(const CMIDriverBase &vrOtherDriver); + virtual const CMIUtilString &GetDriverName() const = 0; + virtual const CMIUtilString &GetDriverId() const = 0; + virtual void SetExitApplicationFlag(const bool vbForceExit); - // MI provide information for the pass through (child) assigned driver - virtual FILE *GetStdin() const; - virtual FILE *GetStdout() const; - virtual FILE *GetStderr() const; + // MI provide information for the pass through (child) assigned driver + virtual FILE *GetStdin() const; + virtual FILE *GetStdout() const; + virtual FILE *GetStderr() const; - // Attributes: - protected: - CMIDriverBase *m_pDriverFallThru; // Child driver to use should *this driver not be able to handle client input - CMIDriverBase *m_pDriverParent; // The parent driver who passes work to *this driver to do work - CMIUtilString m_strDriverId; - bool m_bExitApp; // True = Yes, exit application, false = continue execution + // Attributes: +protected: + CMIDriverBase *m_pDriverFallThru; // Child driver to use should *this driver + // not be able to handle client input + CMIDriverBase *m_pDriverParent; // The parent driver who passes work to *this + // driver to do work + CMIUtilString m_strDriverId; + bool m_bExitApp; // True = Yes, exit application, false = continue execution }; diff --git a/lldb/tools/lldb-mi/MIDriverMain.cpp b/lldb/tools/lldb-mi/MIDriverMain.cpp index ccbaf77f09e..fdced8dd4ea 100644 --- a/lldb/tools/lldb-mi/MIDriverMain.cpp +++ b/lldb/tools/lldb-mi/MIDriverMain.cpp @@ -9,78 +9,87 @@ // Overview: Defines the entry point for the console application. // The MI application (project name MI) runs in two modes: -// An LLDB native driver mode where it acts no different from the LLDB driver. +// An LLDB native driver mode where it acts no different from the +// LLDB driver. // The other mode is the MI when it finds on the command line -// the --interpreter option. Command line argument --help on its own will give -// help for the LLDB driver. If entered with --interpreter then MI help will +// the --interpreter option. Command line argument --help on its +// own will give +// help for the LLDB driver. If entered with --interpreter then MI +// help will // provided. -// To implement new MI commands derive a new command class from the command base -// class. To enable the new command for interpretation add the new command class +// To implement new MI commands derive a new command class from the +// command base +// class. To enable the new command for interpretation add the new +// command class // to the command factory. The files of relevance are: // MICmdCommands.cpp // MICmdBase.h / .cpp // MICmdCmd.h / .cpp - #if defined(_MSC_VER) -#define _INC_SIGNAL // Stop window's signal.h being included - CODETAG_IOR_SIGNALS +#define _INC_SIGNAL // Stop window's signal.h being included - + // CODETAG_IOR_SIGNALS #endif // _MSC_VER // Third party headers: -#include <stdio.h> #include "lldb/API/SBHostOS.h" +#include <stdio.h> // In house headers: #include "MICmnConfig.h" -#include "Platform.h" // Define signals - CODETAG_IOR_SIGNALS -#include "MIDriverMgr.h" -#include "MIDriver.h" #include "MICmnResources.h" #include "MICmnStreamStdin.h" +#include "MIDriver.h" +#include "MIDriverMgr.h" #include "MIUtilDebug.h" - +#include "Platform.h" // Define signals - CODETAG_IOR_SIGNALS #if defined(_MSC_VER) -#pragma warning(once : 4530) // Warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc -#endif // _MSC_VER +#pragma warning( \ + once : 4530) // Warning C4530: C++ exception handler used, but unwind + // semantics are not enabled. Specify /EHsc +#endif // _MSC_VER // CODETAG_IOR_SIGNALS -//++ ------------------------------------------------------------------------------------ -// Details: The SIGINT signal is sent to a process by its controlling terminal when a -// user wishes to interrupt the process. This is typically initiated by pressing -// Control-C, but on some systems, the "delete" character or "break" key can be +//++ +//------------------------------------------------------------------------------------ +// Details: The SIGINT signal is sent to a process by its controlling terminal +// when a +// user wishes to interrupt the process. This is typically initiated by +// pressing +// Control-C, but on some systems, the "delete" character or "break" +// key can be // used. -// Be aware this function may be called on another thread besides the main thread. +// Be aware this function may be called on another thread besides the +// main thread. // Type: Function. // Args: vSigno - (R) Signal number. // Return: None. // Throws: None. //-- -void -sigint_handler(int vSigno) -{ +void sigint_handler(int vSigno) { #ifdef _WIN32 // Restore handler as it is not persistent on Windows - signal(SIGINT, sigint_handler); + signal(SIGINT, sigint_handler); #endif - static bool g_interrupt_sent = false; - CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance(); - lldb::SBDebugger *pDebugger = rDriverMgr.DriverGetTheDebugger(); - if (pDebugger != nullptr) - { - if (!g_interrupt_sent) - { - g_interrupt_sent = true; - pDebugger->DispatchInputInterrupt(); - g_interrupt_sent = false; - } + static bool g_interrupt_sent = false; + CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance(); + lldb::SBDebugger *pDebugger = rDriverMgr.DriverGetTheDebugger(); + if (pDebugger != nullptr) { + if (!g_interrupt_sent) { + g_interrupt_sent = true; + pDebugger->DispatchInputInterrupt(); + g_interrupt_sent = false; } + } - // Send signal to driver so that it can take suitable action - rDriverMgr.DeliverSignal (vSigno); + // Send signal to driver so that it can take suitable action + rDriverMgr.DeliverSignal(vSigno); } -//++ ------------------------------------------------------------------------------------ -// Details: Init the MI driver system. Initialize the whole driver system which includes +//++ +//------------------------------------------------------------------------------------ +// Details: Init the MI driver system. Initialize the whole driver system which +// includes // both the original LLDB driver and the MI driver. // Type: Function. // Args: None. @@ -88,95 +97,104 @@ sigint_handler(int vSigno) // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -DriverSystemInit() -{ - bool bOk = MIstatus::success; - CMIDriver &rMIDriver = CMIDriver::Instance(); - CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance(); - bOk = rDriverMgr.Initialize(); - - // Register MIDriver first as it needs to initialize and be ready - // for the Driver to get information from MIDriver when it initializes - // (LLDB Driver is registered with the Driver Manager in MI's Initialize()) - bOk = bOk && rDriverMgr.RegisterDriver(rMIDriver, "MIDriver"); // Will be main driver - - return bOk; +bool DriverSystemInit() { + bool bOk = MIstatus::success; + CMIDriver &rMIDriver = CMIDriver::Instance(); + CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance(); + bOk = rDriverMgr.Initialize(); + + // Register MIDriver first as it needs to initialize and be ready + // for the Driver to get information from MIDriver when it initializes + // (LLDB Driver is registered with the Driver Manager in MI's Initialize()) + bOk = bOk && + rDriverMgr.RegisterDriver(rMIDriver, "MIDriver"); // Will be main driver + + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Shutdown the debugger system. Release / terminate resources external to +//++ +//------------------------------------------------------------------------------------ +// Details: Shutdown the debugger system. Release / terminate resources external +// to // specifically the MI driver. // Type: Function. -// Args: vbAppExitOk - (R) True = No problems, false = App exiting with problems (investigate!). +// Args: vbAppExitOk - (R) True = No problems, false = App exiting with +// problems (investigate!). // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -DriverSystemShutdown(const bool vbAppExitOk) -{ - bool bOk = MIstatus::success; - - // *** Order is important here *** - CMIDriverMgr::Instance().Shutdown(); - return bOk; +bool DriverSystemShutdown(const bool vbAppExitOk) { + bool bOk = MIstatus::success; + + // *** Order is important here *** + CMIDriverMgr::Instance().Shutdown(); + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: MI's application start point of execution. The application runs in two modes. -// An LLDB native driver mode where it acts no different from the LLDB driver. +//++ +//------------------------------------------------------------------------------------ +// Details: MI's application start point of execution. The application runs in +// two modes. +// An LLDB native driver mode where it acts no different from the LLDB +// driver. // The other mode is the MI when it finds on the command line -// the --interpreter option. Command line argument --help on its own will give -// help for the LLDB driver. If entered with --interpreter then application +// the --interpreter option. Command line argument --help on its own +// will give +// help for the LLDB driver. If entered with --interpreter then +// application // help will provided. // Type: Method. -// Args: argc - (R) An integer that contains the count of arguments that follow in -// argv. The argc parameter is always greater than or equal to 1. -// argv - (R) An array of null-terminated strings representing command-line -// arguments entered by the user of the program. By convention, -// argv[0] is the command with which the program is invoked. +// Args: argc - (R) An integer that contains the count of arguments that +// follow in +// argv. The argc parameter is always greater than or +// equal to 1. +// argv - (R) An array of null-terminated strings representing +// command-line +// arguments entered by the user of the program. By +// convention, +// argv[0] is the command with which the program is +// invoked. // Return: int - 0 = Normal exit, program success. -// >0 = Program success with status i.e. Control-C signal status +// >0 = Program success with status i.e. Control-C signal +// status // <0 = Program failed. -// -1 = Program failed reason not specified here, see MI log file. +// -1 = Program failed reason not specified here, see MI log +// file. // -1000 = Program failed did not initialize successfully. // Throws: None. //-- -int -main(int argc, char const *argv[]) -{ +int main(int argc, char const *argv[]) { #if MICONFIG_DEBUG_SHOW_ATTACH_DBG_DLG #ifdef _WIN32 - CMIUtilDebug::ShowDlgWaitForDbgAttach(); + CMIUtilDebug::ShowDlgWaitForDbgAttach(); #else - CMIUtilDebug::WaitForDbgAttachInfinteLoop(); + CMIUtilDebug::WaitForDbgAttachInfinteLoop(); #endif // _WIN32 #endif // MICONFIG_DEBUG_SHOW_ATTACH_DBG_DLG - // *** Order is important here *** - bool bOk = DriverSystemInit(); - if (!bOk) - { - DriverSystemShutdown(bOk); - return -1000; - } + // *** Order is important here *** + bool bOk = DriverSystemInit(); + if (!bOk) { + DriverSystemShutdown(bOk); + return -1000; + } - // CODETAG_IOR_SIGNALS - signal(SIGINT, sigint_handler); + // CODETAG_IOR_SIGNALS + signal(SIGINT, sigint_handler); - bool bExiting = false; - CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance(); - bOk = bOk && rDriverMgr.ParseArgs(argc, argv, bExiting); - if (bOk && !bExiting) - bOk = rDriverMgr.DriverParseArgs(argc, argv, stdout, bExiting); - if (bOk && !bExiting) - bOk = rDriverMgr.DriverMainLoop(); + bool bExiting = false; + CMIDriverMgr &rDriverMgr = CMIDriverMgr::Instance(); + bOk = bOk && rDriverMgr.ParseArgs(argc, argv, bExiting); + if (bOk && !bExiting) + bOk = rDriverMgr.DriverParseArgs(argc, argv, stdout, bExiting); + if (bOk && !bExiting) + bOk = rDriverMgr.DriverMainLoop(); - // Logger and other resources shutdown now - DriverSystemShutdown(bOk); + // Logger and other resources shutdown now + DriverSystemShutdown(bOk); - const int appResult = bOk ? 0 : -1; + const int appResult = bOk ? 0 : -1; - return appResult; + return appResult; } diff --git a/lldb/tools/lldb-mi/MIDriverMgr.cpp b/lldb/tools/lldb-mi/MIDriverMgr.cpp index 472fc60f643..1ce7febc1b3 100644 --- a/lldb/tools/lldb-mi/MIDriverMgr.cpp +++ b/lldb/tools/lldb-mi/MIDriverMgr.cpp @@ -11,40 +11,36 @@ #include "lldb/API/SBError.h" // In-house headers: -#include "MIDriverMgr.h" -#include "MICmnResources.h" #include "MICmnLog.h" #include "MICmnLogMediumFile.h" -#include "MIDriver.h" +#include "MICmnResources.h" #include "MICmnStreamStdout.h" +#include "MIDriver.h" +#include "MIDriverMgr.h" #include "MIUtilSingletonHelper.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIDriverMgr constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMIDriverMgr::CMIDriverMgr() - : m_pDriverCurrent(nullptr) - , m_bInMi2Mode(false) -{ -} +CMIDriverMgr::CMIDriverMgr() : m_pDriverCurrent(nullptr), m_bInMi2Mode(false) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIDriverMgr destructor. // Type: Overridden. // Args: None. // Return: None. // Throws: None. //-- -CMIDriverMgr::~CMIDriverMgr() -{ - Shutdown(); -} +CMIDriverMgr::~CMIDriverMgr() { Shutdown(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Initialize *this manager. // Type: Method. // Args: None. @@ -52,78 +48,81 @@ CMIDriverMgr::~CMIDriverMgr() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriverMgr::Initialize() -{ - m_clientUsageRefCnt++; +bool CMIDriverMgr::Initialize() { + m_clientUsageRefCnt++; - ClrErrorDescription(); + ClrErrorDescription(); - if (m_bInitialized) - return MIstatus::success; + if (m_bInitialized) + return MIstatus::success; - bool bOk = MIstatus::success; - CMIUtilString errMsg; + bool bOk = MIstatus::success; + CMIUtilString errMsg; - // Note initialisation order is important here as some resources depend on previous - MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); - MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); + // Note initialisation order is important here as some resources depend on + // previous + MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); + MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); - m_bInitialized = bOk; + m_bInitialized = bOk; - if (!bOk) - { - CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_DRIVERMGR), errMsg.c_str())); - SetErrorDescription(strInitError); - return MIstatus::failure; - } + if (!bOk) { + CMIUtilString strInitError(CMIUtilString::Format( + MIRSRC(IDS_MI_INIT_ERR_DRIVERMGR), errMsg.c_str())); + SetErrorDescription(strInitError); + return MIstatus::failure; + } - return bOk; + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Unbind detach or release resources used by this server in general common -// functionality shared between versions of any server interfaces implemented. +//++ +//------------------------------------------------------------------------------------ +// Details: Unbind detach or release resources used by this server in general +// common +// functionality shared between versions of any server interfaces +// implemented. // Type: Method. -// Args: vbAppExitOk - (R) True = No problems, false = App exiting with problems (investigate!). +// Args: vbAppExitOk - (R) True = No problems, false = App exiting with +// problems (investigate!). // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriverMgr::Shutdown() -{ - // Do not want a ref counter because this function needs to be called how ever this - // application stops running - // if( --m_clientUsageRefCnt > 0 ) - // return MIstatus::success; +bool CMIDriverMgr::Shutdown() { + // Do not want a ref counter because this function needs to be called how ever + // this + // application stops running + // if( --m_clientUsageRefCnt > 0 ) + // return MIstatus::success; - ClrErrorDescription(); + ClrErrorDescription(); - if (!m_bInitialized) - return MIstatus::success; + if (!m_bInitialized) + return MIstatus::success; - m_bInitialized = false; + m_bInitialized = false; - bool bOk = MIstatus::success; - CMIUtilString errMsg; + bool bOk = MIstatus::success; + CMIUtilString errMsg; - // Tidy up - UnregisterDriverAll(); + // Tidy up + UnregisterDriverAll(); - // Note shutdown order is important here - MI::ModuleShutdown<CMICmnResources>(IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg); - MI::ModuleShutdown<CMICmnLog>(IDS_MI_SHTDWN_ERR_LOG, bOk, errMsg); + // Note shutdown order is important here + MI::ModuleShutdown<CMICmnResources>(IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg); + MI::ModuleShutdown<CMICmnLog>(IDS_MI_SHTDWN_ERR_LOG, bOk, errMsg); - if (!bOk) - { - SetErrorDescriptionn(MIRSRC(IDS_MI_SHTDWN_ERR_DRIVERMGR), errMsg.c_str()); - } + if (!bOk) { + SetErrorDescriptionn(MIRSRC(IDS_MI_SHTDWN_ERR_DRIVERMGR), errMsg.c_str()); + } - return bOk; + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Unregister all the Driver registered with *this manager. The manager also +//++ +//------------------------------------------------------------------------------------ +// Details: Unregister all the Driver registered with *this manager. The manager +// also // deletes // Type: Method. // Args: None. @@ -131,29 +130,30 @@ CMIDriverMgr::Shutdown() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriverMgr::UnregisterDriverAll() -{ - MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); - while (it != m_mapDriverIdToDriver.end()) - { - IDriver *pDriver = (*it).second; - pDriver->DoShutdown(); - - // Next - ++it; - } +bool CMIDriverMgr::UnregisterDriverAll() { + MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); + while (it != m_mapDriverIdToDriver.end()) { + IDriver *pDriver = (*it).second; + pDriver->DoShutdown(); - m_mapDriverIdToDriver.clear(); - m_pDriverCurrent = NULL; + // Next + ++it; + } - return MIstatus::success; + m_mapDriverIdToDriver.clear(); + m_pDriverCurrent = NULL; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Register a driver with *this Driver Manager. Call SetUseThisDriverToDoWork() -// inform the manager which driver is the one to the work. The manager calls -// the driver's init function which must be successful in order to complete the +//++ +//------------------------------------------------------------------------------------ +// Details: Register a driver with *this Driver Manager. Call +// SetUseThisDriverToDoWork() +// inform the manager which driver is the one to the work. The manager +// calls +// the driver's init function which must be successful in order to +// complete the // registration. // Type: Method. // Args: vrDriver - (R) The driver to register. @@ -162,30 +162,31 @@ CMIDriverMgr::UnregisterDriverAll() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriverMgr::RegisterDriver(const IDriver &vrDriver, const CMIUtilString &vrDriverID) -{ - if (HaveDriverAlready(vrDriver)) - return MIstatus::success; - - IDriver *pDriver = const_cast<IDriver *>(&vrDriver); - if (!pDriver->SetId(vrDriverID)) - return MIstatus::failure; - if (!pDriver->DoInitialize()) - { - SetErrorDescriptionn(MIRSRC(IDS_DRIVERMGR_DRIVER_ERR_INIT), pDriver->GetName().c_str(), vrDriverID.c_str(), - pDriver->GetError().c_str()); - return MIstatus::failure; - } +bool CMIDriverMgr::RegisterDriver(const IDriver &vrDriver, + const CMIUtilString &vrDriverID) { + if (HaveDriverAlready(vrDriver)) + return MIstatus::success; - MapPairDriverIdToDriver_t pr(vrDriverID, pDriver); - m_mapDriverIdToDriver.insert(pr); + IDriver *pDriver = const_cast<IDriver *>(&vrDriver); + if (!pDriver->SetId(vrDriverID)) + return MIstatus::failure; + if (!pDriver->DoInitialize()) { + SetErrorDescriptionn(MIRSRC(IDS_DRIVERMGR_DRIVER_ERR_INIT), + pDriver->GetName().c_str(), vrDriverID.c_str(), + pDriver->GetError().c_str()); + return MIstatus::failure; + } - return MIstatus::success; + MapPairDriverIdToDriver_t pr(vrDriverID, pDriver); + m_mapDriverIdToDriver.insert(pr); + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Query the Driver Manager to see if *this manager has the driver already +//++ +//------------------------------------------------------------------------------------ +// Details: Query the Driver Manager to see if *this manager has the driver +// already // registered. // Type: Method. // Args: vrDriver - (R) The driver to query. @@ -193,26 +194,26 @@ CMIDriverMgr::RegisterDriver(const IDriver &vrDriver, const CMIUtilString &vrDri // False - not registered. // Throws: None. //-- -bool -CMIDriverMgr::HaveDriverAlready(const IDriver &vrDriver) const -{ - MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); - while (it != m_mapDriverIdToDriver.end()) - { - const IDriver *pDrvr = (*it).second; - if (pDrvr == &vrDriver) - return true; - - // Next - ++it; - } - - return false; +bool CMIDriverMgr::HaveDriverAlready(const IDriver &vrDriver) const { + MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); + while (it != m_mapDriverIdToDriver.end()) { + const IDriver *pDrvr = (*it).second; + if (pDrvr == &vrDriver) + return true; + + // Next + ++it; + } + + return false; } -//++ ------------------------------------------------------------------------------------ -// Details: Unregister a driver from the Driver Manager. Call the SetUseThisDriverToDoWork() -// function to define another driver to do work if the one being unregistered did +//++ +//------------------------------------------------------------------------------------ +// Details: Unregister a driver from the Driver Manager. Call the +// SetUseThisDriverToDoWork() +// function to define another driver to do work if the one being +// unregistered did // the work previously. // Type: Method. // Args: vrDriver - (R) The driver to unregister. @@ -220,31 +221,31 @@ CMIDriverMgr::HaveDriverAlready(const IDriver &vrDriver) const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriverMgr::UnregisterDriver(const IDriver &vrDriver) -{ - const IDriver *pDrvr = nullptr; - MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); - while (it != m_mapDriverIdToDriver.end()) - { - pDrvr = (*it).second; - if (pDrvr == &vrDriver) - break; - - // Next - ++it; - } - m_mapDriverIdToDriver.erase(it); - - if (m_pDriverCurrent == pDrvr) - m_pDriverCurrent = nullptr; - - return MIstatus::success; +bool CMIDriverMgr::UnregisterDriver(const IDriver &vrDriver) { + const IDriver *pDrvr = nullptr; + MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); + while (it != m_mapDriverIdToDriver.end()) { + pDrvr = (*it).second; + if (pDrvr == &vrDriver) + break; + + // Next + ++it; + } + m_mapDriverIdToDriver.erase(it); + + if (m_pDriverCurrent == pDrvr) + m_pDriverCurrent = nullptr; + + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Specify the driver to do work. The Driver Manager drives this driver. Any -// previous driver doing work is not called anymore (so be sure the previous +//++ +//------------------------------------------------------------------------------------ +// Details: Specify the driver to do work. The Driver Manager drives this +// driver. Any +// previous driver doing work is not called anymore (so be sure the +// previous // driver is in a tidy state before stopping it working). // Type: Method. // Args: vrADriver - (R) A lldb::SBBroadcaster/IDriver derived object. @@ -252,33 +253,34 @@ CMIDriverMgr::UnregisterDriver(const IDriver &vrDriver) // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriverMgr::SetUseThisDriverToDoWork(const IDriver &vrADriver) -{ - m_pDriverCurrent = const_cast<IDriver *>(&vrADriver); +bool CMIDriverMgr::SetUseThisDriverToDoWork(const IDriver &vrADriver) { + m_pDriverCurrent = const_cast<IDriver *>(&vrADriver); - const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_SAY_DRIVER_USING), m_pDriverCurrent->GetName().c_str())); - m_pLog->Write(msg, CMICmnLog::eLogVerbosity_Log); + const CMIUtilString msg( + CMIUtilString::Format(MIRSRC(IDS_DRIVER_SAY_DRIVER_USING), + m_pDriverCurrent->GetName().c_str())); + m_pLog->Write(msg, CMICmnLog::eLogVerbosity_Log); - m_bInMi2Mode = m_pDriverCurrent->GetDriverIsGDBMICompatibleDriver(); + m_bInMi2Mode = m_pDriverCurrent->GetDriverIsGDBMICompatibleDriver(); - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Ask *this manager which driver is currently doing the work. // Type: Method. // Args: None. -// Return: IDriver * - Pointer to a driver, NULL if there is no current working driver. +// Return: IDriver * - Pointer to a driver, NULL if there is no current working +// driver. // Throws: None. //-- -CMIDriverMgr::IDriver * -CMIDriverMgr::GetUseThisDriverToDoWork() const -{ - return m_pDriverCurrent; +CMIDriverMgr::IDriver *CMIDriverMgr::GetUseThisDriverToDoWork() const { + return m_pDriverCurrent; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Call this function puts *this driver to work. // Type: Method. // Args: None. @@ -286,91 +288,95 @@ CMIDriverMgr::GetUseThisDriverToDoWork() const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriverMgr::DriverMainLoop() -{ - if (m_pDriverCurrent != nullptr) - { - if (!m_pDriverCurrent->DoMainLoop()) - { - const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_MAINLOOP), m_pDriverCurrent->GetError().c_str())); - CMICmnStreamStdout::Instance().Write(errMsg, true); - return MIstatus::failure; - } - } - else - { - const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)); - CMICmnStreamStdout::Instance().Write(errMsg, true); - return MIstatus::failure; +bool CMIDriverMgr::DriverMainLoop() { + if (m_pDriverCurrent != nullptr) { + if (!m_pDriverCurrent->DoMainLoop()) { + const CMIUtilString errMsg( + CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_MAINLOOP), + m_pDriverCurrent->GetError().c_str())); + CMICmnStreamStdout::Instance().Write(errMsg, true); + return MIstatus::failure; } + } else { + const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)); + CMICmnStreamStdout::Instance().Write(errMsg, true); + return MIstatus::failure; + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ -// Details: Get the current driver to validate executable command line arguments. +//++ +//------------------------------------------------------------------------------------ +// Details: Get the current driver to validate executable command line +// arguments. // Type: Method. -// Args: argc - (R) An integer that contains the count of arguments that follow in -// argv. The argc parameter is always greater than or equal to 1. -// argv - (R) An array of null-terminated strings representing command-line -// arguments entered by the user of the program. By convention, -// argv[0] is the command with which the program is invoked. +// Args: argc - (R) An integer that contains the count of arguments +// that follow in +// argv. The argc parameter is always greater than +// or equal to 1. +// argv - (R) An array of null-terminated strings representing +// command-line +// arguments entered by the user of the program. By +// convention, +// argv[0] is the command with which the program is +// invoked. // vpStdOut - (R) Point to a standard output stream. -// vwbExiting - (W) True = *this want to exit, false = continue to work. +// vwbExiting - (W) True = *this want to exit, false = continue to +// work. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIDriverMgr::DriverParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting) -{ - if (m_pDriverCurrent == nullptr) - { - const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)); - CMICmnStreamStdout::Instance().Write(errMsg, true); - return MIstatus::failure; - } +bool CMIDriverMgr::DriverParseArgs(const int argc, const char *argv[], + FILE *vpStdOut, bool &vwbExiting) { + if (m_pDriverCurrent == nullptr) { + const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)); + CMICmnStreamStdout::Instance().Write(errMsg, true); + return MIstatus::failure; + } + + const lldb::SBError error( + m_pDriverCurrent->DoParseArgs(argc, argv, vpStdOut, vwbExiting)); + bool bOk = !error.Fail(); + if (!bOk) { + CMIUtilString errMsg; + const char *pErrorCstr = error.GetCString(); + if (pErrorCstr != nullptr) + errMsg = CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_PARSE_ARGS), + m_pDriverCurrent->GetName().c_str(), + pErrorCstr); + else + errMsg = CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_PARSE_ARGS_UNKNOWN), + m_pDriverCurrent->GetName().c_str()); - const lldb::SBError error(m_pDriverCurrent->DoParseArgs(argc, argv, vpStdOut, vwbExiting)); - bool bOk = !error.Fail(); - if (!bOk) - { - CMIUtilString errMsg; - const char *pErrorCstr = error.GetCString(); - if (pErrorCstr != nullptr) - errMsg = CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_PARSE_ARGS), m_pDriverCurrent->GetName().c_str(), pErrorCstr); - else - errMsg = CMIUtilString::Format(MIRSRC(IDS_DRIVER_ERR_PARSE_ARGS_UNKNOWN), m_pDriverCurrent->GetName().c_str()); - - bOk = CMICmnStreamStdout::Instance().Write(errMsg, true); - } + bOk = CMICmnStreamStdout::Instance().Write(errMsg, true); + } - return bOk; + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the current driver's last error condition. // Type: Method. // Args: None. // Return: CMIUtilString - Text description. // Throws: None. //-- -CMIUtilString -CMIDriverMgr::DriverGetError() const -{ - if (m_pDriverCurrent != nullptr) - return m_pDriverCurrent->GetError(); - else - { - const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)); - CMICmnStreamStdout::Instance().Write(errMsg, true); - } - - return CMIUtilString(); +CMIUtilString CMIDriverMgr::DriverGetError() const { + if (m_pDriverCurrent != nullptr) + return m_pDriverCurrent->GetError(); + else { + const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)); + CMICmnStreamStdout::Instance().Write(errMsg, true); + } + + return CMIUtilString(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the current driver's name. // Type: Method. // Args: None. @@ -378,21 +384,19 @@ CMIDriverMgr::DriverGetError() const // Empty string = no current working driver specified. // Throws: None. //-- -CMIUtilString -CMIDriverMgr::DriverGetName() const -{ - if (m_pDriverCurrent != nullptr) - return m_pDriverCurrent->GetName(); - else - { - const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)); - CMICmnStreamStdout::Instance().Write(errMsg, true); - } - - return CMIUtilString(); +CMIUtilString CMIDriverMgr::DriverGetName() const { + if (m_pDriverCurrent != nullptr) + return m_pDriverCurrent->GetName(); + else { + const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)); + CMICmnStreamStdout::Instance().Write(errMsg, true); + } + + return CMIUtilString(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the current driver's debugger object. // Type: Method. // Args: None. @@ -400,26 +404,28 @@ CMIDriverMgr::DriverGetName() const // - NULL = no current working driver specified. // Throws: None. //-- -lldb::SBDebugger * -CMIDriverMgr::DriverGetTheDebugger() -{ - lldb::SBDebugger *pDebugger = nullptr; - if (m_pDriverCurrent != nullptr) - pDebugger = &m_pDriverCurrent->GetTheDebugger(); - else - { - const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)); - CMICmnStreamStdout::Instance().Write(errMsg, true); - } - - return pDebugger; +lldb::SBDebugger *CMIDriverMgr::DriverGetTheDebugger() { + lldb::SBDebugger *pDebugger = nullptr; + if (m_pDriverCurrent != nullptr) + pDebugger = &m_pDriverCurrent->GetTheDebugger(); + else { + const CMIUtilString errMsg(MIRSRC(IDS_DRIVER_ERR_CURRENT_NOT_SET)); + CMICmnStreamStdout::Instance().Write(errMsg, true); + } + + return pDebugger; } -//++ ------------------------------------------------------------------------------------ -// Details: Check the arguments given on the command line. The main purpose of this -// function is to check for the presence of the --interpreter option. Having -// this option present tells *this manager to set the CMIDriver to do work. If -// not use the LLDB driver. The following are options that are only handled by +//++ +//------------------------------------------------------------------------------------ +// Details: Check the arguments given on the command line. The main purpose of +// this +// function is to check for the presence of the --interpreter option. +// Having +// this option present tells *this manager to set the CMIDriver to do +// work. If +// not use the LLDB driver. The following are options that are only +// handled by // the CMIDriverMgr are: // --help or -h // --interpreter @@ -428,315 +434,317 @@ CMIDriverMgr::DriverGetTheDebugger() // --log // --executable // --log-dir -// The above arguments are not handled by any driver object except for --executable. -// The options --interpreter and --executable in code act very similar. The -// --executable is necessary to differentiate whither the MI Driver is being using -// by a client i.e. Eclipse or from the command line. Eclipse issues the option -// --interpreter and also passes additional arguments which can be interpreted as an -// executable if called from the command line. Using --executable tells the MI -// Driver is being called the command line and that the executable argument is indeed -// a specified executable an so actions commands to set up the executable for a -// debug session. Using --interpreter on the command line does not action additional -// commands to initialise a debug session and so be able to launch the process. The directory +// The above arguments are not handled by any driver object except for +// --executable. +// The options --interpreter and --executable in code act very similar. +// The +// --executable is necessary to differentiate whither the MI Driver is +// being using +// by a client i.e. Eclipse or from the command line. Eclipse issues +// the option +// --interpreter and also passes additional arguments which can be +// interpreted as an +// executable if called from the command line. Using --executable tells +// the MI +// Driver is being called the command line and that the executable +// argument is indeed +// a specified executable an so actions commands to set up the +// executable for a +// debug session. Using --interpreter on the command line does not +// action additional +// commands to initialise a debug session and so be able to launch the +// process. The directory // where the log file is created is specified using --log-dir. // Type: Method. -// Args: argc - (R) An integer that contains the count of arguments that follow in -// argv. The argc parameter is always greater than or equal to 1. -// argv - (R) An array of null-terminated strings representing command-line -// arguments entered by the user of the program. By convention, -// argv[0] is the command with which the program is invoked. -// vwbExiting - (W) True = *this want to exit, Reasons: help, invalid arg(s), +// Args: argc - (R) An integer that contains the count of arguments +// that follow in +// argv. The argc parameter is always greater than +// or equal to 1. +// argv - (R) An array of null-terminated strings representing +// command-line +// arguments entered by the user of the program. By +// convention, +// argv[0] is the command with which the program is +// invoked. +// vwbExiting - (W) True = *this want to exit, Reasons: help, +// invalid arg(s), // version information only. -// False = Continue to work, start debugger i.e. Command +// False = Continue to work, start debugger i.e. +// Command // interpreter. // Return: lldb::SBError - LLDB current error status. // Throws: None. //-- -bool -CMIDriverMgr::ParseArgs(const int argc, const char *argv[], bool &vwbExiting) -{ - bool bOk = MIstatus::success; - - vwbExiting = false; - - // Print MI application path to the Log file - const CMIUtilString appPath(CMIUtilString::Format(MIRSRC(IDS_MI_APP_FILEPATHNAME), argv[0])); - bOk = m_pLog->Write(appPath, CMICmnLog::eLogVerbosity_Log); - - // Print application arguments to the Log file - const bool bHaveArgs(argc >= 2); - CMIUtilString strArgs(MIRSRC(IDS_MI_APP_ARGS)); - if (!bHaveArgs) - { - strArgs += MIRSRC(IDS_WORD_NONE); - bOk = bOk && m_pLog->Write(strArgs, CMICmnLog::eLogVerbosity_Log); - } - else - { - for (MIint i = 1; i < argc; i++) - { - strArgs += CMIUtilString::Format("%d:'%s' ", i, argv[i]); - } - bOk = bOk && m_pLog->Write(strArgs, CMICmnLog::eLogVerbosity_Log); - } - - // Look for the command line options - bool bHaveArgInterpret = false; - bool bHaveArgVersion = false; - bool bHaveArgVersionLong = false; - bool bHaveArgLog = false; - bool bHaveArgLogDir = false; - bool bHaveArgHelp = false; - CMIUtilString strLogDir; - - bHaveArgInterpret = true; - if (bHaveArgs) - { - // CODETAG_MIDRIVE_CMD_LINE_ARG_HANDLING - for (MIint i = 1; i < argc; i++) - { - // *** Add args to help in GetHelpOnCmdLineArgOptions() *** - const CMIUtilString strArg(argv[i]); - - // Argument "--executable" is also check for in CMIDriver::ParseArgs() - if ((0 == strArg.compare("--interpreter")) || // Given by the client such as Eclipse - (0 == strArg.compare("--executable"))) // Used to specify that there is executable argument also on the command line - { // See fn description. - bHaveArgInterpret = true; - } - if (0 == strArg.compare("--version")) - { - bHaveArgVersion = true; - } - if (0 == strArg.compare("--versionLong")) - { - bHaveArgVersionLong = true; - } - if (0 == strArg.compare("--log")) - { - bHaveArgLog = true; - } - if (0 == strArg.compare(0,10,"--log-dir=")) - { - strLogDir = strArg.substr(10, CMIUtilString::npos); - bHaveArgLogDir = true; - } - if ((0 == strArg.compare("--help")) || (0 == strArg.compare("-h"))) - { - bHaveArgHelp = true; - } - } - } - - if (bHaveArgLog) - { - CMICmnLog::Instance().SetEnabled(true); - } - - if (bHaveArgLogDir) - { - bOk = bOk && CMICmnLogMediumFile::Instance().SetDirectory(strLogDir); +bool CMIDriverMgr::ParseArgs(const int argc, const char *argv[], + bool &vwbExiting) { + bool bOk = MIstatus::success; + + vwbExiting = false; + + // Print MI application path to the Log file + const CMIUtilString appPath( + CMIUtilString::Format(MIRSRC(IDS_MI_APP_FILEPATHNAME), argv[0])); + bOk = m_pLog->Write(appPath, CMICmnLog::eLogVerbosity_Log); + + // Print application arguments to the Log file + const bool bHaveArgs(argc >= 2); + CMIUtilString strArgs(MIRSRC(IDS_MI_APP_ARGS)); + if (!bHaveArgs) { + strArgs += MIRSRC(IDS_WORD_NONE); + bOk = bOk && m_pLog->Write(strArgs, CMICmnLog::eLogVerbosity_Log); + } else { + for (MIint i = 1; i < argc; i++) { + strArgs += CMIUtilString::Format("%d:'%s' ", i, argv[i]); } - - // Todo: Remove this output when MI is finished. It is temporary to persuade Eclipse plugin to work. - // Eclipse reads this literally and will not work unless it gets this exact version text. - // Handle --version option (ignore the --interpreter option if present) - if (bHaveArgVersion) - { - vwbExiting = true; - bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse(MIRSRC(IDE_MI_VERSION_GDB)); - return bOk; - } - - // Todo: Make this the --version when the above --version version is removed - // Handle --versionlong option (ignore the --interpreter option if present) - if (bHaveArgVersionLong) - { - vwbExiting = true; - bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse(GetAppVersion()); - return bOk; - } - - // Both '--help' and '--interpreter' means give help for MI only. Without - // '--interpreter' help the LLDB driver is working and so help is for that. - if (bHaveArgHelp && bHaveArgInterpret) - { - vwbExiting = true; - bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse(GetHelpOnCmdLineArgOptions()); - return bOk; + bOk = bOk && m_pLog->Write(strArgs, CMICmnLog::eLogVerbosity_Log); + } + + // Look for the command line options + bool bHaveArgInterpret = false; + bool bHaveArgVersion = false; + bool bHaveArgVersionLong = false; + bool bHaveArgLog = false; + bool bHaveArgLogDir = false; + bool bHaveArgHelp = false; + CMIUtilString strLogDir; + + bHaveArgInterpret = true; + if (bHaveArgs) { + // CODETAG_MIDRIVE_CMD_LINE_ARG_HANDLING + for (MIint i = 1; i < argc; i++) { + // *** Add args to help in GetHelpOnCmdLineArgOptions() *** + const CMIUtilString strArg(argv[i]); + + // Argument "--executable" is also check for in CMIDriver::ParseArgs() + if ((0 == + strArg.compare( + "--interpreter")) || // Given by the client such as Eclipse + (0 == strArg.compare("--executable"))) // Used to specify that there + // is executable argument also + // on the command line + { // See fn description. + bHaveArgInterpret = true; + } + if (0 == strArg.compare("--version")) { + bHaveArgVersion = true; + } + if (0 == strArg.compare("--versionLong")) { + bHaveArgVersionLong = true; + } + if (0 == strArg.compare("--log")) { + bHaveArgLog = true; + } + if (0 == strArg.compare(0, 10, "--log-dir=")) { + strLogDir = strArg.substr(10, CMIUtilString::npos); + bHaveArgLogDir = true; + } + if ((0 == strArg.compare("--help")) || (0 == strArg.compare("-h"))) { + bHaveArgHelp = true; + } } - - // This makes the assumption that there is at least one MI compatible - // driver registered and one LLDB driver registered and the CMIDriver - // is the first one found. - // ToDo: Implement a better solution that handle any order, any number - // of drivers. Or this 'feature' may be removed if deemed not required. - IDriver *pLldbDriver = GetFirstNonMIDriver(); - IDriver *pMi2Driver = GetFirstMIDriver(); - if (bHaveArgInterpret && (pMi2Driver != nullptr)) - bOk = bOk && SetUseThisDriverToDoWork(*pMi2Driver); - else if (pLldbDriver != nullptr) - bOk = bOk && SetUseThisDriverToDoWork(*pLldbDriver); - else - { - if (bOk) - { - vwbExiting = true; - const CMIUtilString msg(MIRSRC(IDS_DRIVER_ERR_NON_REGISTERED)); - bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse(msg); - } + } + + if (bHaveArgLog) { + CMICmnLog::Instance().SetEnabled(true); + } + + if (bHaveArgLogDir) { + bOk = bOk && CMICmnLogMediumFile::Instance().SetDirectory(strLogDir); + } + + // Todo: Remove this output when MI is finished. It is temporary to persuade + // Eclipse plugin to work. + // Eclipse reads this literally and will not work unless it gets this + // exact version text. + // Handle --version option (ignore the --interpreter option if present) + if (bHaveArgVersion) { + vwbExiting = true; + bOk = bOk && + CMICmnStreamStdout::Instance().WriteMIResponse( + MIRSRC(IDE_MI_VERSION_GDB)); + return bOk; + } + + // Todo: Make this the --version when the above --version version is removed + // Handle --versionlong option (ignore the --interpreter option if present) + if (bHaveArgVersionLong) { + vwbExiting = true; + bOk = + bOk && CMICmnStreamStdout::Instance().WriteMIResponse(GetAppVersion()); + return bOk; + } + + // Both '--help' and '--interpreter' means give help for MI only. Without + // '--interpreter' help the LLDB driver is working and so help is for that. + if (bHaveArgHelp && bHaveArgInterpret) { + vwbExiting = true; + bOk = bOk && + CMICmnStreamStdout::Instance().WriteMIResponse( + GetHelpOnCmdLineArgOptions()); + return bOk; + } + + // This makes the assumption that there is at least one MI compatible + // driver registered and one LLDB driver registered and the CMIDriver + // is the first one found. + // ToDo: Implement a better solution that handle any order, any number + // of drivers. Or this 'feature' may be removed if deemed not required. + IDriver *pLldbDriver = GetFirstNonMIDriver(); + IDriver *pMi2Driver = GetFirstMIDriver(); + if (bHaveArgInterpret && (pMi2Driver != nullptr)) + bOk = bOk && SetUseThisDriverToDoWork(*pMi2Driver); + else if (pLldbDriver != nullptr) + bOk = bOk && SetUseThisDriverToDoWork(*pLldbDriver); + else { + if (bOk) { + vwbExiting = true; + const CMIUtilString msg(MIRSRC(IDS_DRIVER_ERR_NON_REGISTERED)); + bOk = bOk && CMICmnStreamStdout::Instance().WriteMIResponse(msg); } + } - return bOk; + return bOk; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Return formatted application version and name information. // Type: Method. // Args: None. // Return: CMIUtilString - Text data. // Throws: None. //-- -CMIUtilString -CMIDriverMgr::GetAppVersion() const -{ - const CMIUtilString strProj(MIRSRC(IDS_PROJNAME)); - const CMIUtilString strVsn(CMIDriver::Instance().GetVersionDescription()); - const CMIUtilString strGdb(MIRSRC(IDE_MI_VERSION_GDB)); - const CMIUtilString strVrsnInfo(CMIUtilString::Format("%s\n%s\n%s", strProj.c_str(), strVsn.c_str(), strGdb.c_str())); - - return strVrsnInfo; +CMIUtilString CMIDriverMgr::GetAppVersion() const { + const CMIUtilString strProj(MIRSRC(IDS_PROJNAME)); + const CMIUtilString strVsn(CMIDriver::Instance().GetVersionDescription()); + const CMIUtilString strGdb(MIRSRC(IDE_MI_VERSION_GDB)); + const CMIUtilString strVrsnInfo(CMIUtilString::Format( + "%s\n%s\n%s", strProj.c_str(), strVsn.c_str(), strGdb.c_str())); + + return strVrsnInfo; } -//++ ------------------------------------------------------------------------------------ -// Details: Return formatted help information on all the MI command line options. +//++ +//------------------------------------------------------------------------------------ +// Details: Return formatted help information on all the MI command line +// options. // Type: Method. // Args: None. // Return: CMIUtilString - Text data. // Throws: None. //-- -CMIUtilString -CMIDriverMgr::GetHelpOnCmdLineArgOptions() const -{ - const CMIUtilString pHelp[] = { - MIRSRC(IDE_MI_APP_DESCRIPTION), - MIRSRC(IDE_MI_APP_INFORMATION), - MIRSRC(IDE_MI_APP_ARG_USAGE), - MIRSRC(IDE_MI_APP_ARG_HELP), - MIRSRC(IDE_MI_APP_ARG_VERSION), - MIRSRC(IDE_MI_APP_ARG_VERSION_LONG), - MIRSRC(IDE_MI_APP_ARG_INTERPRETER), - MIRSRC(IDE_MI_APP_ARG_SOURCE), - MIRSRC(IDE_MI_APP_ARG_EXECUTEABLE), - CMIUtilString::Format(MIRSRC(IDE_MI_APP_ARG_APP_LOG), CMICmnLogMediumFile::Instance().GetFileName().c_str()), - MIRSRC(IDE_MI_APP_ARG_APP_LOG_DIR), - MIRSRC(IDE_MI_APP_ARG_EXECUTABLE), - MIRSRC(IDS_CMD_QUIT_HELP), - MIRSRC(IDE_MI_APP_ARG_EXAMPLE)}; - const MIuint nHelpItems = sizeof pHelp / sizeof pHelp[0]; - CMIUtilString strHelp; - for (MIuint i = 0; i < nHelpItems; i++) - { - strHelp += pHelp[i]; - strHelp += "\n\n"; - } - - return strHelp; +CMIUtilString CMIDriverMgr::GetHelpOnCmdLineArgOptions() const { + const CMIUtilString pHelp[] = { + MIRSRC(IDE_MI_APP_DESCRIPTION), MIRSRC(IDE_MI_APP_INFORMATION), + MIRSRC(IDE_MI_APP_ARG_USAGE), MIRSRC(IDE_MI_APP_ARG_HELP), + MIRSRC(IDE_MI_APP_ARG_VERSION), MIRSRC(IDE_MI_APP_ARG_VERSION_LONG), + MIRSRC(IDE_MI_APP_ARG_INTERPRETER), MIRSRC(IDE_MI_APP_ARG_SOURCE), + MIRSRC(IDE_MI_APP_ARG_EXECUTEABLE), + CMIUtilString::Format( + MIRSRC(IDE_MI_APP_ARG_APP_LOG), + CMICmnLogMediumFile::Instance().GetFileName().c_str()), + MIRSRC(IDE_MI_APP_ARG_APP_LOG_DIR), MIRSRC(IDE_MI_APP_ARG_EXECUTABLE), + MIRSRC(IDS_CMD_QUIT_HELP), MIRSRC(IDE_MI_APP_ARG_EXAMPLE)}; + const MIuint nHelpItems = sizeof pHelp / sizeof pHelp[0]; + CMIUtilString strHelp; + for (MIuint i = 0; i < nHelpItems; i++) { + strHelp += pHelp[i]; + strHelp += "\n\n"; + } + + return strHelp; } -//++ ------------------------------------------------------------------------------------ -// Details: Search the registered drivers and return the first driver which says it is +//++ +//------------------------------------------------------------------------------------ +// Details: Search the registered drivers and return the first driver which says +// it is // GDB/MI compatible i.e. the CMIDriver class. // Type: Method. // Args: None. // Return: IDriver * - Ptr to driver, NULL = no driver found. // Throws: None. //-- -CMIDriverMgr::IDriver * -CMIDriverMgr::GetFirstMIDriver() const -{ - IDriver *pDriver = nullptr; - MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); - while (it != m_mapDriverIdToDriver.end()) - { - const CMIUtilString &rDrvId = (*it).first; - MIunused(rDrvId); - IDriver *pDvr = (*it).second; - if (pDvr->GetDriverIsGDBMICompatibleDriver()) - { - pDriver = pDvr; - break; - } - - // Next - ++it; +CMIDriverMgr::IDriver *CMIDriverMgr::GetFirstMIDriver() const { + IDriver *pDriver = nullptr; + MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); + while (it != m_mapDriverIdToDriver.end()) { + const CMIUtilString &rDrvId = (*it).first; + MIunused(rDrvId); + IDriver *pDvr = (*it).second; + if (pDvr->GetDriverIsGDBMICompatibleDriver()) { + pDriver = pDvr; + break; } - return pDriver; + // Next + ++it; + } + + return pDriver; } -//++ ------------------------------------------------------------------------------------ -// Details: Search the registered drivers and return the first driver which says it is +//++ +//------------------------------------------------------------------------------------ +// Details: Search the registered drivers and return the first driver which says +// it is // not GDB/MI compatible i.e. the LLDB Driver class. // Type: Method. // Args: None. // Return: IDriver * - Ptr to driver, NULL = no driver found. // Throws: None. //-- -CMIDriverMgr::IDriver * -CMIDriverMgr::GetFirstNonMIDriver() const -{ - IDriver *pDriver = nullptr; - MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); - while (it != m_mapDriverIdToDriver.end()) - { - const CMIUtilString &rDrvId = (*it).first; - MIunused(rDrvId); - IDriver *pDvr = (*it).second; - if (!pDvr->GetDriverIsGDBMICompatibleDriver()) - { - pDriver = pDvr; - break; - } - - // Next - ++it; +CMIDriverMgr::IDriver *CMIDriverMgr::GetFirstNonMIDriver() const { + IDriver *pDriver = nullptr; + MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); + while (it != m_mapDriverIdToDriver.end()) { + const CMIUtilString &rDrvId = (*it).first; + MIunused(rDrvId); + IDriver *pDvr = (*it).second; + if (!pDvr->GetDriverIsGDBMICompatibleDriver()) { + pDriver = pDvr; + break; } - return pDriver; + // Next + ++it; + } + + return pDriver; } -//++ ------------------------------------------------------------------------------------ -// Details: Search the registered drivers and return driver with the specified ID. +//++ +//------------------------------------------------------------------------------------ +// Details: Search the registered drivers and return driver with the specified +// ID. // Type: Method. // Args: vrDriverId - (R) ID of a driver. // Return: IDriver * - Ptr to driver, NULL = no driver found. // Throws: None. //-- CMIDriverMgr::IDriver * -CMIDriverMgr::GetDriver(const CMIUtilString &vrDriverId) const -{ - MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.find(vrDriverId); - if (it == m_mapDriverIdToDriver.end()) - return nullptr; +CMIDriverMgr::GetDriver(const CMIUtilString &vrDriverId) const { + MapDriverIdToDriver_t::const_iterator it = + m_mapDriverIdToDriver.find(vrDriverId); + if (it == m_mapDriverIdToDriver.end()) + return nullptr; - IDriver *pDriver = (*it).second; + IDriver *pDriver = (*it).second; - return pDriver; + return pDriver; } - -//++ ------------------------------------------------------------------------------------ -// Details: Gets called when lldb-mi gets a signal. Passed signal to current driver. +//++ +//------------------------------------------------------------------------------------ +// Details: Gets called when lldb-mi gets a signal. Passed signal to current +// driver. // // Type: Method. // Args: signal that was delivered // Return: None. // Throws: None. //-- -void -CMIDriverMgr::DeliverSignal(int signal) -{ - if (m_pDriverCurrent != nullptr) - m_pDriverCurrent->DeliverSignal(signal); +void CMIDriverMgr::DeliverSignal(int signal) { + if (m_pDriverCurrent != nullptr) + m_pDriverCurrent->DeliverSignal(signal); } diff --git a/lldb/tools/lldb-mi/MIDriverMgr.h b/lldb/tools/lldb-mi/MIDriverMgr.h index 016e722ed7b..dbdc4194e19 100644 --- a/lldb/tools/lldb-mi/MIDriverMgr.h +++ b/lldb/tools/lldb-mi/MIDriverMgr.h @@ -10,26 +10,30 @@ #pragma once // Third party headers: -#include <map> #include "lldb/API/SBDebugger.h" +#include <map> // In-house headers: #include "MICmnBase.h" -#include "MIUtilString.h" #include "MICmnLog.h" #include "MIUtilSingletonBase.h" +#include "MIUtilString.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI Driver Manager. Register lldb::SBBroadcaster derived Driver type // objects with *this manager. The manager does not own driver objects // registered with it and so will not delete when this manager is -// shutdown. The Driver flagged as "use this one" will be set as current +// shutdown. The Driver flagged as "use this one" will be set as +// current // driver and will be the one that is used. Other drivers are not // operated. A Driver can call another Driver should it not handle a // command. // It also initializes other resources as part it's setup such as the -// Logger and Resources objects (explicit indicate *this object requires -// those objects (modules/components) to support it's own functionality). +// Logger and Resources objects (explicit indicate *this object +// requires +// those objects (modules/components) to support it's own +// functionality). // The Driver manager is the first object instantiated as part of the // MI code base. It is also the first thing to interpret the command // line arguments passed to the executable. Bases on options it @@ -40,83 +44,86 @@ // LLDB::SBDebugger. // Singleton class. //-- -class CMIDriverMgr : public CMICmnBase, public MI::ISingleton<CMIDriverMgr> -{ - friend MI::ISingleton<CMIDriverMgr>; +class CMIDriverMgr : public CMICmnBase, public MI::ISingleton<CMIDriverMgr> { + friend MI::ISingleton<CMIDriverMgr>; - // Class: + // Class: +public: + //++ + // Description: Driver deriver objects need this interface to work with + // *this manager. + //-- + class IDriver { public: - //++ - // Description: Driver deriver objects need this interface to work with - // *this manager. - //-- - class IDriver - { - public: - virtual bool DoInitialize() = 0; - virtual bool DoShutdown() = 0; - virtual bool DoMainLoop() = 0; - virtual lldb::SBError DoParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting) = 0; - virtual CMIUtilString GetError() const = 0; - virtual const CMIUtilString &GetName() const = 0; - virtual lldb::SBDebugger &GetTheDebugger() = 0; - virtual bool GetDriverIsGDBMICompatibleDriver() const = 0; - virtual bool SetId(const CMIUtilString &vId) = 0; - virtual const CMIUtilString &GetId() const = 0; - virtual void DeliverSignal(int signal) = 0; + virtual bool DoInitialize() = 0; + virtual bool DoShutdown() = 0; + virtual bool DoMainLoop() = 0; + virtual lldb::SBError DoParseArgs(const int argc, const char *argv[], + FILE *vpStdOut, bool &vwbExiting) = 0; + virtual CMIUtilString GetError() const = 0; + virtual const CMIUtilString &GetName() const = 0; + virtual lldb::SBDebugger &GetTheDebugger() = 0; + virtual bool GetDriverIsGDBMICompatibleDriver() const = 0; + virtual bool SetId(const CMIUtilString &vId) = 0; + virtual const CMIUtilString &GetId() const = 0; + virtual void DeliverSignal(int signal) = 0; - // Not part of the interface, ignore - /* dtor */ virtual ~IDriver() {} - }; + // Not part of the interface, ignore + /* dtor */ virtual ~IDriver() {} + }; - // Methods: - public: - // MI system - bool Initialize() override; - bool Shutdown() override; - // - CMIUtilString GetAppVersion() const; - bool RegisterDriver(const IDriver &vrADriver, const CMIUtilString &vrDriverID); - bool UnregisterDriver(const IDriver &vrADriver); - bool - SetUseThisDriverToDoWork(const IDriver &vrADriver); // Specify working main driver - IDriver *GetUseThisDriverToDoWork() const; - bool ParseArgs(const int argc, const char *argv[], bool &vwbExiting); - IDriver *GetDriver(const CMIUtilString &vrDriverId) const; - // - // MI Proxy fn to current specified working driver - bool DriverMainLoop(); - bool DriverParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &vwbExiting); - CMIUtilString DriverGetError() const; - CMIUtilString DriverGetName() const; - lldb::SBDebugger *DriverGetTheDebugger(); - void DeliverSignal(int signal); + // Methods: +public: + // MI system + bool Initialize() override; + bool Shutdown() override; + // + CMIUtilString GetAppVersion() const; + bool RegisterDriver(const IDriver &vrADriver, + const CMIUtilString &vrDriverID); + bool UnregisterDriver(const IDriver &vrADriver); + bool SetUseThisDriverToDoWork( + const IDriver &vrADriver); // Specify working main driver + IDriver *GetUseThisDriverToDoWork() const; + bool ParseArgs(const int argc, const char *argv[], bool &vwbExiting); + IDriver *GetDriver(const CMIUtilString &vrDriverId) const; + // + // MI Proxy fn to current specified working driver + bool DriverMainLoop(); + bool DriverParseArgs(const int argc, const char *argv[], FILE *vpStdOut, + bool &vwbExiting); + CMIUtilString DriverGetError() const; + CMIUtilString DriverGetName() const; + lldb::SBDebugger *DriverGetTheDebugger(); + void DeliverSignal(int signal); - // Typedef: - private: - typedef std::map<CMIUtilString, IDriver *> MapDriverIdToDriver_t; - typedef std::pair<CMIUtilString, IDriver *> MapPairDriverIdToDriver_t; + // Typedef: +private: + typedef std::map<CMIUtilString, IDriver *> MapDriverIdToDriver_t; + typedef std::pair<CMIUtilString, IDriver *> MapPairDriverIdToDriver_t; - // Methods: - private: - /* ctor */ CMIDriverMgr(); - /* ctor */ CMIDriverMgr(const CMIDriverMgr &); - void operator=(const CMIDriverMgr &); - // - bool HaveDriverAlready(const IDriver &vrMedium) const; - bool UnregisterDriverAll(); - IDriver *GetFirstMIDriver() const; - IDriver *GetFirstNonMIDriver() const; - CMIUtilString GetHelpOnCmdLineArgOptions() const; + // Methods: +private: + /* ctor */ CMIDriverMgr(); + /* ctor */ CMIDriverMgr(const CMIDriverMgr &); + void operator=(const CMIDriverMgr &); + // + bool HaveDriverAlready(const IDriver &vrMedium) const; + bool UnregisterDriverAll(); + IDriver *GetFirstMIDriver() const; + IDriver *GetFirstNonMIDriver() const; + CMIUtilString GetHelpOnCmdLineArgOptions() const; - // Overridden: - private: - // From CMICmnBase - /* dtor */ ~CMIDriverMgr() override; + // Overridden: +private: + // From CMICmnBase + /* dtor */ ~CMIDriverMgr() override; - // Attributes: - private: - MapDriverIdToDriver_t m_mapDriverIdToDriver; - IDriver *m_pDriverCurrent; // This driver is used by this manager to do work. It is the main driver. - bool m_bInMi2Mode; // True = --interpreter entered on the cmd line, false = operate LLDB driver (non GDB) + // Attributes: +private: + MapDriverIdToDriver_t m_mapDriverIdToDriver; + IDriver *m_pDriverCurrent; // This driver is used by this manager to do work. + // It is the main driver. + bool m_bInMi2Mode; // True = --interpreter entered on the cmd line, false = + // operate LLDB driver (non GDB) }; diff --git a/lldb/tools/lldb-mi/MIUtilDateTimeStd.cpp b/lldb/tools/lldb-mi/MIUtilDateTimeStd.cpp index db730daeefc..e06eadd6b6a 100644 --- a/lldb/tools/lldb-mi/MIUtilDateTimeStd.cpp +++ b/lldb/tools/lldb-mi/MIUtilDateTimeStd.cpp @@ -11,81 +11,80 @@ #include "MIUtilDateTimeStd.h" #include "MICmnResources.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilDateTimeStd constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMIUtilDateTimeStd::CMIUtilDateTimeStd() -{ -} +CMIUtilDateTimeStd::CMIUtilDateTimeStd() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilDateTimeStd destructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMIUtilDateTimeStd::~CMIUtilDateTimeStd() -{ -} +CMIUtilDateTimeStd::~CMIUtilDateTimeStd() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve system local current date. Format is MM/DD/YYYY. // Type: Method. // Args: None. // Return: CMIUtilString - Text description. // Throws: None. //-- -CMIUtilString -CMIUtilDateTimeStd::GetDate() -{ - CMIUtilString strDate(MIRSRC(IDS_WORD_INVALIDBRKTS)); +CMIUtilString CMIUtilDateTimeStd::GetDate() { + CMIUtilString strDate(MIRSRC(IDS_WORD_INVALIDBRKTS)); - std::time(&m_rawTime); - const std::tm *pTi = std::localtime(&m_rawTime); - if (std::strftime(&m_pScratch[0], sizeof(m_pScratch), "%d/%m/%y", pTi) > 0) - strDate = m_pScratch; + std::time(&m_rawTime); + const std::tm *pTi = std::localtime(&m_rawTime); + if (std::strftime(&m_pScratch[0], sizeof(m_pScratch), "%d/%m/%y", pTi) > 0) + strDate = m_pScratch; - return strDate; + return strDate; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve system local current time. Format is HH:MM:SS 24 hour clock. +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve system local current time. Format is HH:MM:SS 24 hour +// clock. // Type: Method. // Args: None. // Return: CMIUtilString - Text description. // Throws: None. //-- -CMIUtilString -CMIUtilDateTimeStd::GetTime() -{ - std::time(&m_rawTime); - const std::tm *pTi = std::localtime(&m_rawTime); - const CMIUtilString seconds(CMIUtilString::Format("%d", pTi->tm_sec)); - const CMIUtilString zero((seconds.length() == 1) ? "0" : ""); - const CMIUtilString strTime(CMIUtilString::Format("%d:%d:%s%s", pTi->tm_hour, pTi->tm_min, zero.c_str(), seconds.c_str())); +CMIUtilString CMIUtilDateTimeStd::GetTime() { + std::time(&m_rawTime); + const std::tm *pTi = std::localtime(&m_rawTime); + const CMIUtilString seconds(CMIUtilString::Format("%d", pTi->tm_sec)); + const CMIUtilString zero((seconds.length() == 1) ? "0" : ""); + const CMIUtilString strTime(CMIUtilString::Format( + "%d:%d:%s%s", pTi->tm_hour, pTi->tm_min, zero.c_str(), seconds.c_str())); - return strTime; + return strTime; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve system local current date and time in yyyy-MM-dd--HH-mm-ss format for log file names. +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve system local current date and time in yyyy-MM-dd--HH-mm-ss +// format for log file names. // Type: Method. // Args: None. // Return: CMIUtilString - Text description. // Throws: None. //-- -CMIUtilString -CMIUtilDateTimeStd::GetDateTimeLogFilename() -{ - std::time(&m_rawTime); - const std::tm *pTi = std::localtime(&m_rawTime); - const CMIUtilString strTime(CMIUtilString::Format("%d%02d%02d%02d%02d%02d", pTi->tm_year + 1900, pTi->tm_mon, - pTi->tm_mday, pTi->tm_hour, pTi->tm_min, pTi->tm_sec)); +CMIUtilString CMIUtilDateTimeStd::GetDateTimeLogFilename() { + std::time(&m_rawTime); + const std::tm *pTi = std::localtime(&m_rawTime); + const CMIUtilString strTime(CMIUtilString::Format( + "%d%02d%02d%02d%02d%02d", pTi->tm_year + 1900, pTi->tm_mon, pTi->tm_mday, + pTi->tm_hour, pTi->tm_min, pTi->tm_sec)); - return strTime; + return strTime; } diff --git a/lldb/tools/lldb-mi/MIUtilDateTimeStd.h b/lldb/tools/lldb-mi/MIUtilDateTimeStd.h index cb5f4988700..7afece807eb 100644 --- a/lldb/tools/lldb-mi/MIUtilDateTimeStd.h +++ b/lldb/tools/lldb-mi/MIUtilDateTimeStd.h @@ -15,27 +15,27 @@ // In-house headers: #include "MIUtilString.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code utility class. Used to retrieve system local date // time. //-- -class CMIUtilDateTimeStd -{ - // Methods: - public: - /* ctor */ CMIUtilDateTimeStd(); +class CMIUtilDateTimeStd { + // Methods: +public: + /* ctor */ CMIUtilDateTimeStd(); - CMIUtilString GetDate(); - CMIUtilString GetTime(); - CMIUtilString GetDateTimeLogFilename(); + CMIUtilString GetDate(); + CMIUtilString GetTime(); + CMIUtilString GetDateTimeLogFilename(); - // Overrideable: - public: - // From CMICmnBase - /* dtor */ virtual ~CMIUtilDateTimeStd(); + // Overrideable: +public: + // From CMICmnBase + /* dtor */ virtual ~CMIUtilDateTimeStd(); - // Attributes: - private: - std::time_t m_rawTime; - char m_pScratch[16]; + // Attributes: +private: + std::time_t m_rawTime; + char m_pScratch[16]; }; diff --git a/lldb/tools/lldb-mi/MIUtilDebug.cpp b/lldb/tools/lldb-mi/MIUtilDebug.cpp index d49aaa20a8f..5a9e480ebcd 100644 --- a/lldb/tools/lldb-mi/MIUtilDebug.cpp +++ b/lldb/tools/lldb-mi/MIUtilDebug.cpp @@ -13,72 +13,72 @@ #endif // In-house headers: -#include "MIUtilDebug.h" -#include "MIDriver.h" #include "MICmnLog.h" +#include "MIDriver.h" +#include "MIUtilDebug.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilDebug constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMIUtilDebug::CMIUtilDebug() -{ -} +CMIUtilDebug::CMIUtilDebug() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilDebug destructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMIUtilDebug::~CMIUtilDebug() -{ -} +CMIUtilDebug::~CMIUtilDebug() {} -//++ ------------------------------------------------------------------------------------ -// Details: Show a dialog to the process/application halts. It gives the opportunity to +//++ +//------------------------------------------------------------------------------------ +// Details: Show a dialog to the process/application halts. It gives the +// opportunity to // attach a debugger. // Type: Static method. // Args: None. // Return: None. // Throws: None. //-- -void -CMIUtilDebug::ShowDlgWaitForDbgAttach() -{ - const CMIUtilString strCaption(CMIDriver::Instance().GetAppNameShort()); +void CMIUtilDebug::ShowDlgWaitForDbgAttach() { + const CMIUtilString strCaption(CMIDriver::Instance().GetAppNameShort()); #ifdef _WIN32 - ::MessageBoxA(NULL, "Attach your debugger now", strCaption.c_str(), MB_OK); + ::MessageBoxA(NULL, "Attach your debugger now", strCaption.c_str(), MB_OK); #else // ToDo: Implement other platform version of an Ok to continue dialog box #endif // _WIN32 } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Temporarily stall the process/application to give the programmer the -// opportunity to attach a debugger. How to use: Put a break in the programmer -// where you want to visit, run the application then attach your debugger to the -// application. Hit the debugger's pause button and the debugger should should -// show this loop. Change the i variable value to break out of the loop and +// opportunity to attach a debugger. How to use: Put a break in the +// programmer +// where you want to visit, run the application then attach your +// debugger to the +// application. Hit the debugger's pause button and the debugger should +// should +// show this loop. Change the i variable value to break out of the loop +// and // visit your break point. // Type: Static method. // Args: None. // Return: None. // Throws: None. //-- -void -CMIUtilDebug::WaitForDbgAttachInfinteLoop() -{ - MIuint i = 0; - while (i == 0) - { - const std::chrono::milliseconds time(100); - std::this_thread::sleep_for(time); - } +void CMIUtilDebug::WaitForDbgAttachInfinteLoop() { + MIuint i = 0; + while (i == 0) { + const std::chrono::milliseconds time(100); + std::this_thread::sleep_for(time); + } } //--------------------------------------------------------------------------------------- @@ -89,7 +89,8 @@ CMIUtilDebug::WaitForDbgAttachInfinteLoop() CMICmnLog &CMIUtilDebugFnTrace::ms_rLog = CMICmnLog::Instance(); MIuint CMIUtilDebugFnTrace::ms_fnDepthCnt = 0; -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilDebugFnTrace constructor. // Type: Method. // Args: vFnName - (R) The text to insert into the log. @@ -97,21 +98,22 @@ MIuint CMIUtilDebugFnTrace::ms_fnDepthCnt = 0; // Throws: None. //-- CMIUtilDebugFnTrace::CMIUtilDebugFnTrace(const CMIUtilString &vFnName) - : m_strFnName(vFnName) -{ - const CMIUtilString txt(CMIUtilString::Format("%d>%s", ++ms_fnDepthCnt, m_strFnName.c_str())); - ms_rLog.Write(txt, CMICmnLog::eLogVerbosity_FnTrace); + : m_strFnName(vFnName) { + const CMIUtilString txt( + CMIUtilString::Format("%d>%s", ++ms_fnDepthCnt, m_strFnName.c_str())); + ms_rLog.Write(txt, CMICmnLog::eLogVerbosity_FnTrace); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilDebugFnTrace destructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMIUtilDebugFnTrace::~CMIUtilDebugFnTrace() -{ - const CMIUtilString txt(CMIUtilString::Format("%d<%s", ms_fnDepthCnt--, m_strFnName.c_str())); - ms_rLog.Write(txt, CMICmnLog::eLogVerbosity_FnTrace); +CMIUtilDebugFnTrace::~CMIUtilDebugFnTrace() { + const CMIUtilString txt( + CMIUtilString::Format("%d<%s", ms_fnDepthCnt--, m_strFnName.c_str())); + ms_rLog.Write(txt, CMICmnLog::eLogVerbosity_FnTrace); } diff --git a/lldb/tools/lldb-mi/MIUtilDebug.h b/lldb/tools/lldb-mi/MIUtilDebug.h index c5383883f52..a49fd9a868e 100644 --- a/lldb/tools/lldb-mi/MIUtilDebug.h +++ b/lldb/tools/lldb-mi/MIUtilDebug.h @@ -17,27 +17,28 @@ // Declarations: class CMICmnLog; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI debugging aid utility class. //-- -class CMIUtilDebug -{ - // Statics: - public: - static void ShowDlgWaitForDbgAttach(); - static void WaitForDbgAttachInfinteLoop(); +class CMIUtilDebug { + // Statics: +public: + static void ShowDlgWaitForDbgAttach(); + static void WaitForDbgAttachInfinteLoop(); - // Methods: - public: - /* ctor */ CMIUtilDebug(); + // Methods: +public: + /* ctor */ CMIUtilDebug(); - // Overrideable: - public: - // From CMICmnBase - /* dtor */ virtual ~CMIUtilDebug(); + // Overrideable: +public: + // From CMICmnBase + /* dtor */ virtual ~CMIUtilDebug(); }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI debug utility class. Used to indicate the current function // depth in the call stack. It uses the CMIlCmnLog logger to output // the current fn trace information. @@ -46,27 +47,29 @@ class CMIUtilDebug // Use preprocessor definition MI_USE_DEBUG_TRACE_FN to turn off or on // tracing code. //-- -class CMIUtilDebugFnTrace -{ - // Methods: - public: - /* ctor */ CMIUtilDebugFnTrace(const CMIUtilString &vFnName); +class CMIUtilDebugFnTrace { + // Methods: +public: + /* ctor */ CMIUtilDebugFnTrace(const CMIUtilString &vFnName); - // Overrideable: - public: - // From CMICmnBase - /* dtor */ virtual ~CMIUtilDebugFnTrace(); + // Overrideable: +public: + // From CMICmnBase + /* dtor */ virtual ~CMIUtilDebugFnTrace(); - // Attributes: - private: - const CMIUtilString m_strFnName; + // Attributes: +private: + const CMIUtilString m_strFnName; - static CMICmnLog &ms_rLog; - static MIuint ms_fnDepthCnt; // Increment count as fn depth increases, decrement count as fn stack pops off + static CMICmnLog &ms_rLog; + static MIuint ms_fnDepthCnt; // Increment count as fn depth increases, + // decrement count as fn stack pops off }; -//++ ============================================================================ -// Details: Take the given text and send it to the server's Logger to output to the +//++ +//============================================================================ +// Details: Take the given text and send it to the server's Logger to output to +// the // trace file. // Type: Compile preprocess. // Args: x - (R) Message (may be seen by user). diff --git a/lldb/tools/lldb-mi/MIUtilFileStd.cpp b/lldb/tools/lldb-mi/MIUtilFileStd.cpp index ed80466b2df..1e76c1c58fe 100644 --- a/lldb/tools/lldb-mi/MIUtilFileStd.cpp +++ b/lldb/tools/lldb-mi/MIUtilFileStd.cpp @@ -8,10 +8,10 @@ //===----------------------------------------------------------------------===// // Third party headers -#include <stdio.h> #include <assert.h> -#include <string.h> // For strerror() #include <cerrno> +#include <stdio.h> +#include <string.h> // For strerror() // In-house headers: #include "MICmnResources.h" @@ -20,7 +20,8 @@ #include "llvm/Support/ConvertUTF.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilFileStd constructor. // Type: Method. // Args: None. @@ -28,87 +29,88 @@ // Throws: None. //-- CMIUtilFileStd::CMIUtilFileStd() - : m_fileNamePath(CMIUtilString()) - , m_pFileHandle(nullptr) + : m_fileNamePath(CMIUtilString()), m_pFileHandle(nullptr) #if defined(_MSC_VER) - , m_constCharNewLine("\r\n") + , + m_constCharNewLine("\r\n") #else - , m_constCharNewLine("\n") + , + m_constCharNewLine("\n") #endif // #if defined( _MSC_VER ) - , m_bFileError(false) -{ + , + m_bFileError(false) { } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilFileStd destructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMIUtilFileStd::~CMIUtilFileStd() -{ - Close(); -} - -//++ ------------------------------------------------------------------------------------ -// Details: Open file for writing. On the first call to this function after *this object -// is created the file is either created or replace, from then on open only opens +CMIUtilFileStd::~CMIUtilFileStd() { Close(); } + +//++ +//------------------------------------------------------------------------------------ +// Details: Open file for writing. On the first call to this function after +// *this object +// is created the file is either created or replace, from then on open +// only opens // an existing file. // Type: Method. // Args: vFileNamePath - (R) File name path. -// vwrbNewCreated - (W) True - file recreated, false - file appended too. +// vwrbNewCreated - (W) True - file recreated, false - file appended +// too. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIUtilFileStd::CreateWrite(const CMIUtilString &vFileNamePath, bool &vwrbNewCreated) -{ - // Reset - m_bFileError = false; - vwrbNewCreated = false; - - if (vFileNamePath.empty()) - { - m_bFileError = true; - SetErrorDescription(MIRSRC(IDS_UTIL_FILE_ERR_INVALID_PATHNAME)); - return MIstatus::failure; - } - - // File is already open so exit - if (m_pFileHandle != nullptr) - return MIstatus::success; +bool CMIUtilFileStd::CreateWrite(const CMIUtilString &vFileNamePath, + bool &vwrbNewCreated) { + // Reset + m_bFileError = false; + vwrbNewCreated = false; + + if (vFileNamePath.empty()) { + m_bFileError = true; + SetErrorDescription(MIRSRC(IDS_UTIL_FILE_ERR_INVALID_PATHNAME)); + return MIstatus::failure; + } + + // File is already open so exit + if (m_pFileHandle != nullptr) + return MIstatus::success; #if !defined(_MSC_VER) - // Open with 'write' and 'binary' mode - m_pFileHandle = ::fopen(vFileNamePath.c_str(), "wb"); + // Open with 'write' and 'binary' mode + m_pFileHandle = ::fopen(vFileNamePath.c_str(), "wb"); #else - // Open a file with exclusive write and shared read permissions - std::wstring path; - if (llvm::ConvertUTF8toWide(vFileNamePath.c_str(), path)) - m_pFileHandle = ::_wfsopen(path.c_str(), L"wb", _SH_DENYWR); - else - { - errno = EINVAL; - m_pFileHandle = nullptr; - } + // Open a file with exclusive write and shared read permissions + std::wstring path; + if (llvm::ConvertUTF8toWide(vFileNamePath.c_str(), path)) + m_pFileHandle = ::_wfsopen(path.c_str(), L"wb", _SH_DENYWR); + else { + errno = EINVAL; + m_pFileHandle = nullptr; + } #endif // !defined( _MSC_VER ) - if (m_pFileHandle == nullptr) - { - m_bFileError = true; - SetErrorDescriptionn(MIRSRC(IDS_UTIL_FILE_ERR_OPENING_FILE), strerror(errno), vFileNamePath.c_str()); - return MIstatus::failure; - } + if (m_pFileHandle == nullptr) { + m_bFileError = true; + SetErrorDescriptionn(MIRSRC(IDS_UTIL_FILE_ERR_OPENING_FILE), + strerror(errno), vFileNamePath.c_str()); + return MIstatus::failure; + } - vwrbNewCreated = true; - m_fileNamePath = vFileNamePath; + vwrbNewCreated = true; + m_fileNamePath = vFileNamePath; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Write data to existing opened file. // Type: Method. // Args: vData - (R) Text data. @@ -116,38 +118,37 @@ CMIUtilFileStd::CreateWrite(const CMIUtilString &vFileNamePath, bool &vwrbNewCre // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIUtilFileStd::Write(const CMIUtilString &vData) -{ - if (vData.size() == 0) - return MIstatus::success; - - if (m_bFileError) - return MIstatus::failure; - - if (m_pFileHandle == nullptr) - { - m_bFileError = true; - SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_NOTOPEN), m_fileNamePath.c_str()); - return MIstatus::failure; - } - - // Get the string size - MIuint size = vData.size(); - if (::fwrite(vData.c_str(), 1, size, m_pFileHandle) == size) - { - // Flush the data to the file - ::fflush(m_pFileHandle); - return MIstatus::success; - } - - // Not all of the data has been transferred +bool CMIUtilFileStd::Write(const CMIUtilString &vData) { + if (vData.size() == 0) + return MIstatus::success; + + if (m_bFileError) + return MIstatus::failure; + + if (m_pFileHandle == nullptr) { m_bFileError = true; - SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_FILE), m_fileNamePath.c_str()); + SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_NOTOPEN), + m_fileNamePath.c_str()); return MIstatus::failure; + } + + // Get the string size + MIuint size = vData.size(); + if (::fwrite(vData.c_str(), 1, size, m_pFileHandle) == size) { + // Flush the data to the file + ::fflush(m_pFileHandle); + return MIstatus::success; + } + + // Not all of the data has been transferred + m_bFileError = true; + SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_FILE), + m_fileNamePath.c_str()); + return MIstatus::failure; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Write data to existing opened file. // Type: Method. // Args: vData - (R) Text data. @@ -156,54 +157,53 @@ CMIUtilFileStd::Write(const CMIUtilString &vData) // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIUtilFileStd::Write(const char *vpData, const MIuint vCharCnt) -{ - if (vCharCnt == 0) - return MIstatus::success; - - if (m_bFileError) - return MIstatus::failure; - - if (m_pFileHandle == nullptr) - { - m_bFileError = true; - SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_NOTOPEN), m_fileNamePath.c_str()); - return MIstatus::failure; - } - - if (::fwrite(vpData, 1, vCharCnt, m_pFileHandle) == vCharCnt) - { - // Flush the data to the file - ::fflush(m_pFileHandle); - return MIstatus::success; - } - - // Not all of the data has been transferred +bool CMIUtilFileStd::Write(const char *vpData, const MIuint vCharCnt) { + if (vCharCnt == 0) + return MIstatus::success; + + if (m_bFileError) + return MIstatus::failure; + + if (m_pFileHandle == nullptr) { m_bFileError = true; - SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_FILE), m_fileNamePath.c_str()); + SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_NOTOPEN), + m_fileNamePath.c_str()); return MIstatus::failure; + } + + if (::fwrite(vpData, 1, vCharCnt, m_pFileHandle) == vCharCnt) { + // Flush the data to the file + ::fflush(m_pFileHandle); + return MIstatus::success; + } + + // Not all of the data has been transferred + m_bFileError = true; + SetErrorDescriptionn(MIRSRC(IDE_UTIL_FILE_ERR_WRITING_FILE), + m_fileNamePath.c_str()); + return MIstatus::failure; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Close existing opened file. Note Close() must must an open! // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -void -CMIUtilFileStd::Close() -{ - if (m_pFileHandle == nullptr) - return; - - ::fclose(m_pFileHandle); - m_pFileHandle = nullptr; - // m_bFileError = false; Do not reset as want to remain until next attempt at open or create +void CMIUtilFileStd::Close() { + if (m_pFileHandle == nullptr) + return; + + ::fclose(m_pFileHandle); + m_pFileHandle = nullptr; + // m_bFileError = false; Do not reset as want to remain until next attempt at + // open or create } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve state of whether the file is ok. // Type: Method. // Args: None. @@ -211,13 +211,10 @@ CMIUtilFileStd::Close() // False - file has a problem. // Throws: None. //-- -bool -CMIUtilFileStd::IsOk() const -{ - return !m_bFileError; -} +bool CMIUtilFileStd::IsOk() const { return !m_bFileError; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Status on a file existing already. // Type: Method. // Args: vFileNamePath. @@ -225,38 +222,36 @@ CMIUtilFileStd::IsOk() const // False - Not found. // Throws: None. //-- -bool -CMIUtilFileStd::IsFileExist(const CMIUtilString &vFileNamePath) const -{ - if (vFileNamePath.empty()) - return false; - - FILE *pTmp = nullptr; - pTmp = ::fopen(vFileNamePath.c_str(), "wb"); - if (pTmp != nullptr) - { - ::fclose(pTmp); - return true; - } - +bool CMIUtilFileStd::IsFileExist(const CMIUtilString &vFileNamePath) const { + if (vFileNamePath.empty()) return false; + + FILE *pTmp = nullptr; + pTmp = ::fopen(vFileNamePath.c_str(), "wb"); + if (pTmp != nullptr) { + ::fclose(pTmp); + return true; + } + + return false; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the file current carriage line return characters used. // Type: Method. // Args: None. // Return: CMIUtilString & - Text. // Throws: None. //-- -const CMIUtilString & -CMIUtilFileStd::GetLineReturn() const -{ - return m_constCharNewLine; +const CMIUtilString &CMIUtilFileStd::GetLineReturn() const { + return m_constCharNewLine; } -//++ ------------------------------------------------------------------------------------ -// Details: Given a file name directory path, strip off the filename and return the path. +//++ +//------------------------------------------------------------------------------------ +// Details: Given a file name directory path, strip off the filename and return +// the path. // It look for either backslash or forward slash. // Type: Method. // Args: vDirectoryPath - (R) Text directory path. @@ -264,34 +259,33 @@ CMIUtilFileStd::GetLineReturn() const // Throws: None. //-- CMIUtilString -CMIUtilFileStd::StripOffFileName(const CMIUtilString &vDirectoryPath) -{ - const size_t nPos = vDirectoryPath.rfind('\\'); - size_t nPos2 = vDirectoryPath.rfind('/'); - if ((nPos == std::string::npos) && (nPos2 == std::string::npos)) - return vDirectoryPath; - - if (nPos > nPos2) - nPos2 = nPos; - - const CMIUtilString strPath(vDirectoryPath.substr(0, nPos2).c_str()); - return strPath; +CMIUtilFileStd::StripOffFileName(const CMIUtilString &vDirectoryPath) { + const size_t nPos = vDirectoryPath.rfind('\\'); + size_t nPos2 = vDirectoryPath.rfind('/'); + if ((nPos == std::string::npos) && (nPos2 == std::string::npos)) + return vDirectoryPath; + + if (nPos > nPos2) + nPos2 = nPos; + + const CMIUtilString strPath(vDirectoryPath.substr(0, nPos2).c_str()); + return strPath; } -//++ ------------------------------------------------------------------------------------ -// Details: Return either backslash or forward slash appropriate to the OS this application +//++ +//------------------------------------------------------------------------------------ +// Details: Return either backslash or forward slash appropriate to the OS this +// application // is running on. // Type: Static method. // Args: None. // Return: char - '/' or '\' character. // Throws: None. //-- -char -CMIUtilFileStd::GetSlash() -{ +char CMIUtilFileStd::GetSlash() { #if !defined(_MSC_VER) - return '/'; + return '/'; #else - return '\\'; + return '\\'; #endif // !defined( _MSC_VER ) } diff --git a/lldb/tools/lldb-mi/MIUtilFileStd.h b/lldb/tools/lldb-mi/MIUtilFileStd.h index 458f64a75df..2120cc25e8a 100644 --- a/lldb/tools/lldb-mi/MIUtilFileStd.h +++ b/lldb/tools/lldb-mi/MIUtilFileStd.h @@ -10,40 +10,40 @@ #pragma once // In-house headers: -#include "MIUtilString.h" #include "MICmnBase.h" +#include "MIUtilString.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code utility class. File handling. //-- -class CMIUtilFileStd : public CMICmnBase -{ - // Static: - public: - static char GetSlash(); +class CMIUtilFileStd : public CMICmnBase { + // Static: +public: + static char GetSlash(); - // Methods: - public: - /* ctor */ CMIUtilFileStd(); - // - bool CreateWrite(const CMIUtilString &vFileNamePath, bool &vwrbNewCreated); - bool Write(const CMIUtilString &vData); - bool Write(const char *vpData, const MIuint vCharCnt); - void Close(); - bool IsOk() const; - bool IsFileExist(const CMIUtilString &vFileNamePath) const; - const CMIUtilString &GetLineReturn() const; - static CMIUtilString StripOffFileName(const CMIUtilString &vDirectoryPath); + // Methods: +public: + /* ctor */ CMIUtilFileStd(); + // + bool CreateWrite(const CMIUtilString &vFileNamePath, bool &vwrbNewCreated); + bool Write(const CMIUtilString &vData); + bool Write(const char *vpData, const MIuint vCharCnt); + void Close(); + bool IsOk() const; + bool IsFileExist(const CMIUtilString &vFileNamePath) const; + const CMIUtilString &GetLineReturn() const; + static CMIUtilString StripOffFileName(const CMIUtilString &vDirectoryPath); - // Overridden: - public: - // From CMICmnBase - /* dtor */ ~CMIUtilFileStd() override; + // Overridden: +public: + // From CMICmnBase + /* dtor */ ~CMIUtilFileStd() override; - // Attributes: - private: - CMIUtilString m_fileNamePath; - FILE *m_pFileHandle; - CMIUtilString m_constCharNewLine; - bool m_bFileError; // True = have a file error ATM, false = all ok + // Attributes: +private: + CMIUtilString m_fileNamePath; + FILE *m_pFileHandle; + CMIUtilString m_constCharNewLine; + bool m_bFileError; // True = have a file error ATM, false = all ok }; diff --git a/lldb/tools/lldb-mi/MIUtilMapIdToVariant.cpp b/lldb/tools/lldb-mi/MIUtilMapIdToVariant.cpp index b35d97a20d1..52bc413a471 100644 --- a/lldb/tools/lldb-mi/MIUtilMapIdToVariant.cpp +++ b/lldb/tools/lldb-mi/MIUtilMapIdToVariant.cpp @@ -10,42 +10,38 @@ // In-house headers: #include "MIUtilMapIdToVariant.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilMapIdToVariant constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMIUtilMapIdToVariant::CMIUtilMapIdToVariant() -{ -} +CMIUtilMapIdToVariant::CMIUtilMapIdToVariant() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilMapIdToVariant destructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMIUtilMapIdToVariant::~CMIUtilMapIdToVariant() -{ -} +CMIUtilMapIdToVariant::~CMIUtilMapIdToVariant() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Remove at the data from *this container. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -void -CMIUtilMapIdToVariant::Clear() -{ - m_mapKeyToVariantValue.clear(); -} +void CMIUtilMapIdToVariant::Clear() { m_mapKeyToVariantValue.clear(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Check an ID is present already in *this container. // Type: Method. // Args: vId - (R) Unique ID i.e. GUID. @@ -53,30 +49,29 @@ CMIUtilMapIdToVariant::Clear() // False - not found. // Throws: None. //-- -bool -CMIUtilMapIdToVariant::HaveAlready(const CMIUtilString &vId) const -{ - const MapKeyToVariantValue_t::const_iterator it = m_mapKeyToVariantValue.find(vId); - if (it != m_mapKeyToVariantValue.end()) - return true; +bool CMIUtilMapIdToVariant::HaveAlready(const CMIUtilString &vId) const { + const MapKeyToVariantValue_t::const_iterator it = + m_mapKeyToVariantValue.find(vId); + if (it != m_mapKeyToVariantValue.end()) + return true; - return false; + return false; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Determine if *this container is currently holding any data. // Type: Method. // Args: None. // Return: bool - True - Yes empty, false - one or more data object present. // Throws: None. //-- -bool -CMIUtilMapIdToVariant::IsEmpty() const -{ - return m_mapKeyToVariantValue.empty(); +bool CMIUtilMapIdToVariant::IsEmpty() const { + return m_mapKeyToVariantValue.empty(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Check the ID is valid to be registered. // Type: Method. // Args: vId - (R) Unique ID i.e. GUID. @@ -84,19 +79,19 @@ CMIUtilMapIdToVariant::IsEmpty() const // False - not valid. // Throws: None. //-- -bool -CMIUtilMapIdToVariant::IsValid(const CMIUtilString &vId) const -{ - bool bValid = true; +bool CMIUtilMapIdToVariant::IsValid(const CMIUtilString &vId) const { + bool bValid = true; - if (vId.empty()) - bValid = false; + if (vId.empty()) + bValid = false; - return bValid; + return bValid; } -//++ ------------------------------------------------------------------------------------ -// Details: Remove from *this contain a data object specified by ID. The data object +//++ +//------------------------------------------------------------------------------------ +// Details: Remove from *this contain a data object specified by ID. The data +// object // when removed also calls its destructor should it have one. // Type: Method. // Args: vId - (R) Unique ID i.e. GUID. @@ -104,14 +99,12 @@ CMIUtilMapIdToVariant::IsValid(const CMIUtilString &vId) const // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIUtilMapIdToVariant::Remove(const CMIUtilString &vId) -{ - const MapKeyToVariantValue_t::const_iterator it = m_mapKeyToVariantValue.find(vId); - if (it != m_mapKeyToVariantValue.end()) - { - m_mapKeyToVariantValue.erase(it); - } +bool CMIUtilMapIdToVariant::Remove(const CMIUtilString &vId) { + const MapKeyToVariantValue_t::const_iterator it = + m_mapKeyToVariantValue.find(vId); + if (it != m_mapKeyToVariantValue.end()) { + m_mapKeyToVariantValue.erase(it); + } - return MIstatus::success; + return MIstatus::success; } diff --git a/lldb/tools/lldb-mi/MIUtilMapIdToVariant.h b/lldb/tools/lldb-mi/MIUtilMapIdToVariant.h index 1a164907dd0..a56477c4dba 100644 --- a/lldb/tools/lldb-mi/MIUtilMapIdToVariant.h +++ b/lldb/tools/lldb-mi/MIUtilMapIdToVariant.h @@ -18,45 +18,49 @@ #include "MIUtilString.h" #include "MIUtilVariant.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code utility class. Map type container that hold general // object types (by being a variant wrapper) // objects by ID. //-- -class CMIUtilMapIdToVariant : public CMICmnBase -{ - // Methods: - public: - /* ctor */ CMIUtilMapIdToVariant(); - - template <typename T> bool Add(const CMIUtilString &vId, const T &vData); - void Clear(); - template <typename T> bool Get(const CMIUtilString &vId, T &vrwData, bool &vrwbFound) const; - bool HaveAlready(const CMIUtilString &vId) const; - bool IsEmpty() const; - bool Remove(const CMIUtilString &vId); - - // Overridden: - public: - // From CMICmnBase - /* dtor */ ~CMIUtilMapIdToVariant() override; - - // Typedefs: - private: - typedef std::map<CMIUtilString, CMIUtilVariant> MapKeyToVariantValue_t; - typedef std::pair<CMIUtilString, CMIUtilVariant> MapPairKeyToVariantValue_t; - - // Methods: - private: - bool IsValid(const CMIUtilString &vId) const; - - // Attributes: - MapKeyToVariantValue_t m_mapKeyToVariantValue; +class CMIUtilMapIdToVariant : public CMICmnBase { + // Methods: +public: + /* ctor */ CMIUtilMapIdToVariant(); + + template <typename T> bool Add(const CMIUtilString &vId, const T &vData); + void Clear(); + template <typename T> + bool Get(const CMIUtilString &vId, T &vrwData, bool &vrwbFound) const; + bool HaveAlready(const CMIUtilString &vId) const; + bool IsEmpty() const; + bool Remove(const CMIUtilString &vId); + + // Overridden: +public: + // From CMICmnBase + /* dtor */ ~CMIUtilMapIdToVariant() override; + + // Typedefs: +private: + typedef std::map<CMIUtilString, CMIUtilVariant> MapKeyToVariantValue_t; + typedef std::pair<CMIUtilString, CMIUtilVariant> MapPairKeyToVariantValue_t; + + // Methods: +private: + bool IsValid(const CMIUtilString &vId) const; + + // Attributes: + MapKeyToVariantValue_t m_mapKeyToVariantValue; }; -//++ ------------------------------------------------------------------------------------ -// Details: Add to *this container a data object of general type identified by an ID. -// If the data with that ID already exists in the container it is replace with +//++ +//------------------------------------------------------------------------------------ +// Details: Add to *this container a data object of general type identified by +// an ID. +// If the data with that ID already exists in the container it is +// replace with // the new data specified. // Type: Method. // Args: T - The data object's variable type. @@ -67,29 +71,28 @@ class CMIUtilMapIdToVariant : public CMICmnBase // Throws: None. //-- template <typename T> -bool -CMIUtilMapIdToVariant::Add(const CMIUtilString &vId, const T &vData) -{ - if (!IsValid(vId)) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_VARIANT_ERR_MAP_KEY_INVALID), vId.c_str())); - return MIstatus::failure; - } - - const bool bOk = HaveAlready(vId) ? Remove(vId) : MIstatus::success; - if (bOk) - { - CMIUtilVariant data; - data.Set<T>(vData); - MapPairKeyToVariantValue_t pr(vId, data); - m_mapKeyToVariantValue.insert(pr); - } - - return bOk; +bool CMIUtilMapIdToVariant::Add(const CMIUtilString &vId, const T &vData) { + if (!IsValid(vId)) { + SetErrorDescription(CMIUtilString::Format( + MIRSRC(IDS_VARIANT_ERR_MAP_KEY_INVALID), vId.c_str())); + return MIstatus::failure; + } + + const bool bOk = HaveAlready(vId) ? Remove(vId) : MIstatus::success; + if (bOk) { + CMIUtilVariant data; + data.Set<T>(vData); + MapPairKeyToVariantValue_t pr(vId, data); + m_mapKeyToVariantValue.insert(pr); + } + + return bOk; } -//++ ------------------------------------------------------------------------------------ -// Details: Retrieve a data object from *this container identified by the specified ID. +//++ +//------------------------------------------------------------------------------------ +// Details: Retrieve a data object from *this container identified by the +// specified ID. // Type: Method. // Args: T - The data object's variable type. // vId - (R) Unique ID i.e. GUID. @@ -100,34 +103,30 @@ CMIUtilMapIdToVariant::Add(const CMIUtilString &vId, const T &vData) // Throws: None. //-- template <typename T> -bool -CMIUtilMapIdToVariant::Get(const CMIUtilString &vId, T &vrwData, bool &vrwbFound) const -{ - vrwbFound = false; - - if (!IsValid(vId)) - { - SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_VARIANT_ERR_MAP_KEY_INVALID), vId.c_str())); - return MIstatus::failure; - } - - const MapKeyToVariantValue_t::const_iterator it = m_mapKeyToVariantValue.find(vId); - if (it != m_mapKeyToVariantValue.end()) - { - const CMIUtilVariant &rData = (*it).second; - const T *pDataObj = rData.Get<T>(); - if (pDataObj != nullptr) - { - vrwbFound = true; - vrwData = *pDataObj; - return MIstatus::success; - } - else - { - SetErrorDescription(MIRSRC(IDS_VARIANT_ERR_USED_BASECLASS)); - return MIstatus::failure; - } +bool CMIUtilMapIdToVariant::Get(const CMIUtilString &vId, T &vrwData, + bool &vrwbFound) const { + vrwbFound = false; + + if (!IsValid(vId)) { + SetErrorDescription(CMIUtilString::Format( + MIRSRC(IDS_VARIANT_ERR_MAP_KEY_INVALID), vId.c_str())); + return MIstatus::failure; + } + + const MapKeyToVariantValue_t::const_iterator it = + m_mapKeyToVariantValue.find(vId); + if (it != m_mapKeyToVariantValue.end()) { + const CMIUtilVariant &rData = (*it).second; + const T *pDataObj = rData.Get<T>(); + if (pDataObj != nullptr) { + vrwbFound = true; + vrwData = *pDataObj; + return MIstatus::success; + } else { + SetErrorDescription(MIRSRC(IDS_VARIANT_ERR_USED_BASECLASS)); + return MIstatus::failure; } + } - return MIstatus::success; + return MIstatus::success; } diff --git a/lldb/tools/lldb-mi/MIUtilParse.cpp b/lldb/tools/lldb-mi/MIUtilParse.cpp index 27e25b8b743..7b039e32131 100644 --- a/lldb/tools/lldb-mi/MIUtilParse.cpp +++ b/lldb/tools/lldb-mi/MIUtilParse.cpp @@ -6,14 +6,15 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// - + // Third party headers: #include <memory> // In-house headers: #include "MIUtilParse.h" - -//++ ------------------------------------------------------------------------------------ + +//++ +//------------------------------------------------------------------------------------ // Details: CRegexParser constructor. // Type: Method. // Args: regexStr - Pointer to the regular expression to compile. @@ -21,25 +22,24 @@ // Throws: None. //-- MIUtilParse::CRegexParser::CRegexParser(const char *regexStr) - : m_isValid(llvm_regcomp(&m_emma, regexStr, REG_EXTENDED) == 0) -{ -} - -//++ ------------------------------------------------------------------------------------ + : m_isValid(llvm_regcomp(&m_emma, regexStr, REG_EXTENDED) == 0) {} + +//++ +//------------------------------------------------------------------------------------ // Details: CRegexParser destructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -MIUtilParse::CRegexParser::~CRegexParser() -{ - // Free up memory held within regex. - if (m_isValid) - llvm_regfree(&m_emma); +MIUtilParse::CRegexParser::~CRegexParser() { + // Free up memory held within regex. + if (m_isValid) + llvm_regfree(&m_emma); } - -//++ ------------------------------------------------------------------------------------ + +//++ +//------------------------------------------------------------------------------------ // Details: CRegexParser regex executer. // Match the input against the regular expression. Return an error // if the number of matches is less than minMatches. If the default @@ -54,22 +54,21 @@ MIUtilParse::CRegexParser::~CRegexParser() // false = minimum matches were not met or regex failed. // Throws: None. //-- -bool -MIUtilParse::CRegexParser::Execute(const char *input, Match& match, size_t minMatches) -{ - if (!m_isValid) - return false; - - std::unique_ptr<llvm_regmatch_t[]> matches(new llvm_regmatch_t[match.m_maxMatches]); // Array of matches - - if (llvm_regexec(&m_emma, input, match.m_maxMatches, matches.get(), 0) != 0) - return false; - - size_t i; - for (i = 0; i < match.m_maxMatches && matches[i].rm_so >= 0; i++) - { - const int n = matches[i].rm_eo - matches[i].rm_so; - match.m_matchStrs[i].assign(input + matches[i].rm_so, n); - } - return i >= minMatches; +bool MIUtilParse::CRegexParser::Execute(const char *input, Match &match, + size_t minMatches) { + if (!m_isValid) + return false; + + std::unique_ptr<llvm_regmatch_t[]> matches( + new llvm_regmatch_t[match.m_maxMatches]); // Array of matches + + if (llvm_regexec(&m_emma, input, match.m_maxMatches, matches.get(), 0) != 0) + return false; + + size_t i; + for (i = 0; i < match.m_maxMatches && matches[i].rm_so >= 0; i++) { + const int n = matches[i].rm_eo - matches[i].rm_so; + match.m_matchStrs[i].assign(input + matches[i].rm_so, n); + } + return i >= minMatches; } diff --git a/lldb/tools/lldb-mi/MIUtilParse.h b/lldb/tools/lldb-mi/MIUtilParse.h index d3569586f81..cb74f4708b4 100644 --- a/lldb/tools/lldb-mi/MIUtilParse.h +++ b/lldb/tools/lldb-mi/MIUtilParse.h @@ -6,88 +6,72 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// - + #pragma once - + // Third party headers: #include "../lib/Support/regex_impl.h" // In-house headers: #include "MIUtilString.h" - -namespace MIUtilParse -{ - -//++ ============================================================================ + +namespace MIUtilParse { + +//++ +//============================================================================ // Details: MI common code utility class. Used to parse the output // returned from lldb commands using regex. //-- -class CRegexParser -{ +class CRegexParser { +public: + // Helper class for keeping track of regex matches. + class Match { + friend CRegexParser; + public: - // Helper class for keeping track of regex matches. - class Match - { - friend CRegexParser; - public: - /* ctor */ explicit Match(size_t nmatches) - : m_matchStrs(nmatches), m_maxMatches(nmatches) - { - } - size_t - GetMatchCount() const - { - return m_matchStrs.size(); - } - CMIUtilString - GetMatchAtIndex(size_t i) const - { - if (m_matchStrs.size() > i) - return m_matchStrs[i]; - return CMIUtilString(); - } - private: - CMIUtilString::VecString_t m_matchStrs; - const size_t m_maxMatches; - }; - - // Methods: - // Compile the regular expression. - /* ctor */ explicit CRegexParser(const char *regexStr); - - // Free the memory used by the regular expression. - /* dtor */ ~CRegexParser(); - - // No copies - CRegexParser(const CRegexParser&) = delete; - void operator=(CRegexParser&) = delete; - - // Return the match at the index. - int - GetMatchCount(const Match& match) const - { - if (m_isValid) - return match.GetMatchCount(); - return 0; - } - - bool - IsValid() const - { - return m_isValid; + /* ctor */ explicit Match(size_t nmatches) + : m_matchStrs(nmatches), m_maxMatches(nmatches) {} + size_t GetMatchCount() const { return m_matchStrs.size(); } + CMIUtilString GetMatchAtIndex(size_t i) const { + if (m_matchStrs.size() > i) + return m_matchStrs[i]; + return CMIUtilString(); } - - // Match the input against the regular expression. Return an error - // if the number of matches is less than minMatches. If the default - // minMatches value of 0 is passed, an error will be returned if - // the number of matches is less than the maxMatches value used to - // initialize Match. - bool - Execute(const char *input, Match& match, size_t minMatches = 0); - + private: - llvm_regex_t m_emma; - const bool m_isValid; -}; + CMIUtilString::VecString_t m_matchStrs; + const size_t m_maxMatches; + }; + // Methods: + // Compile the regular expression. + /* ctor */ explicit CRegexParser(const char *regexStr); + + // Free the memory used by the regular expression. + /* dtor */ ~CRegexParser(); + + // No copies + CRegexParser(const CRegexParser &) = delete; + void operator=(CRegexParser &) = delete; + + // Return the match at the index. + int GetMatchCount(const Match &match) const { + if (m_isValid) + return match.GetMatchCount(); + return 0; + } + + bool IsValid() const { return m_isValid; } + + // Match the input against the regular expression. Return an error + // if the number of matches is less than minMatches. If the default + // minMatches value of 0 is passed, an error will be returned if + // the number of matches is less than the maxMatches value used to + // initialize Match. + bool Execute(const char *input, Match &match, size_t minMatches = 0); + +private: + llvm_regex_t m_emma; + const bool m_isValid; +}; } diff --git a/lldb/tools/lldb-mi/MIUtilSingletonBase.h b/lldb/tools/lldb-mi/MIUtilSingletonBase.h index 03ce8c8aa44..d73627307e5 100644 --- a/lldb/tools/lldb-mi/MIUtilSingletonBase.h +++ b/lldb/tools/lldb-mi/MIUtilSingletonBase.h @@ -9,8 +9,7 @@ #pragma once -namespace MI -{ +namespace MI { // MI::ISingleton base class usage: // @@ -26,31 +25,29 @@ namespace MI // bool Shutdown() override; // }; -//++ ============================================================================ +//++ +//============================================================================ // Details: Base class for the singleton pattern. // Gotchas: Derived class must specify MI::ISingleton<> as a friend class. //-- -template <typename T> class ISingleton -{ - // Statics: - public: - // Return an instance of the derived class - static T & - Instance() - { - // This will fail if the derived class has not - // declared itself to be a friend of MI::ISingleton - static T instance; +template <typename T> class ISingleton { + // Statics: +public: + // Return an instance of the derived class + static T &Instance() { + // This will fail if the derived class has not + // declared itself to be a friend of MI::ISingleton + static T instance; - return instance; - } + return instance; + } - // Overrideable: - public: - virtual bool Initialize() = 0; - virtual bool Shutdown() = 0; - // - /* dtor */ virtual ~ISingleton(){} + // Overrideable: +public: + virtual bool Initialize() = 0; + virtual bool Shutdown() = 0; + // + /* dtor */ virtual ~ISingleton() {} }; } // namespace MI diff --git a/lldb/tools/lldb-mi/MIUtilSingletonHelper.h b/lldb/tools/lldb-mi/MIUtilSingletonHelper.h index 2b9f4c41665..82bed558a7d 100644 --- a/lldb/tools/lldb-mi/MIUtilSingletonHelper.h +++ b/lldb/tools/lldb-mi/MIUtilSingletonHelper.h @@ -9,69 +9,74 @@ #pragma once -namespace MI -{ +namespace MI { // In house headers: -#include "MIUtilString.h" #include "MICmnResources.h" +#include "MIUtilString.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: Short cut helper function to simplify repeated initialisation of // MI components (singletons) required by a client module. // Type: Template method. -// Args: vErrorResrcId - (R) The string resource ID error message identifier to place in errMsg. -// vwrbOk - (RW) On input True = Try to initialize MI driver module. -// On output True = MI driver module initialise successfully. -// vwrErrMsg - (W) MI driver module initialise error description on failure. +// Args: vErrorResrcId - (R) The string resource ID error message +// identifier to place in errMsg. +// vwrbOk - (RW) On input True = Try to initialize MI driver +// module. +// On output True = MI driver module initialise +// successfully. +// vwrErrMsg - (W) MI driver module initialise error description +// on failure. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. //-- template <typename T> -bool -ModuleInit(const MIint vErrorResrcId, bool &vwrbOk, CMIUtilString &vwrErrMsg) -{ - if (vwrbOk && !T::Instance().Initialize()) - { - vwrbOk = MIstatus::failure; - vwrErrMsg = CMIUtilString::Format(MIRSRC(vErrorResrcId), T::Instance().GetErrorDescription().c_str()); - } +bool ModuleInit(const MIint vErrorResrcId, bool &vwrbOk, + CMIUtilString &vwrErrMsg) { + if (vwrbOk && !T::Instance().Initialize()) { + vwrbOk = MIstatus::failure; + vwrErrMsg = CMIUtilString::Format( + MIRSRC(vErrorResrcId), T::Instance().GetErrorDescription().c_str()); + } - return vwrbOk; + return vwrbOk; } -//++ ============================================================================ +//++ +//============================================================================ // Details: Short cut helper function to simplify repeated shutdown of // MI components (singletons) required by a client module. // Type: Template method. -// Args: vErrorResrcId - (R) The string resource ID error message identifier +// Args: vErrorResrcId - (R) The string resource ID error message +// identifier // to place in errMsg. // vwrbOk - (W) If not already false make false on module // shutdown failure. -// vwrErrMsg - (RW) Append to existing error description string MI +// vwrErrMsg - (RW) Append to existing error description string +// MI // driver module initialise error description on // failure. // Return: True - Module shutdown succeeded. // False - Module shutdown failed. //-- template <typename T> -bool -ModuleShutdown(const MIint vErrorResrcId, bool &vwrbOk, CMIUtilString &vwrErrMsg) -{ - bool bOk = MIstatus::success; +bool ModuleShutdown(const MIint vErrorResrcId, bool &vwrbOk, + CMIUtilString &vwrErrMsg) { + bool bOk = MIstatus::success; - if (!T::Instance().Shutdown()) - { - const bool bMoreThanOneError(!vwrErrMsg.empty()); - bOk = MIstatus::failure; - if (bMoreThanOneError) - vwrErrMsg += ", "; - vwrErrMsg += CMIUtilString::Format(MIRSRC(vErrorResrcId), T::Instance().GetErrorDescription().c_str()); - } + if (!T::Instance().Shutdown()) { + const bool bMoreThanOneError(!vwrErrMsg.empty()); + bOk = MIstatus::failure; + if (bMoreThanOneError) + vwrErrMsg += ", "; + vwrErrMsg += CMIUtilString::Format( + MIRSRC(vErrorResrcId), T::Instance().GetErrorDescription().c_str()); + } - vwrbOk = bOk ? vwrbOk : MIstatus::failure; + vwrbOk = bOk ? vwrbOk : MIstatus::failure; - return bOk; + return bOk; } } // namespace MI diff --git a/lldb/tools/lldb-mi/MIUtilString.cpp b/lldb/tools/lldb-mi/MIUtilString.cpp index 176d9a6de74..2ea17fe0840 100644 --- a/lldb/tools/lldb-mi/MIUtilString.cpp +++ b/lldb/tools/lldb-mi/MIUtilString.cpp @@ -18,81 +18,76 @@ // In-house headers: #include "MIUtilString.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilString constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMIUtilString::CMIUtilString() - : std::string() -{ -} +CMIUtilString::CMIUtilString() : std::string() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilString constructor. // Type: Method. // Args: vpData - Pointer to UTF8 text data. // Return: None. // Throws: None. //-- -CMIUtilString::CMIUtilString(const char *vpData) - : std::string(vpData) -{ -} +CMIUtilString::CMIUtilString(const char *vpData) : std::string(vpData) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilString constructor. // Type: Method. // Args: vpStr - Text data. // Return: None. // Throws: None. //-- -CMIUtilString::CMIUtilString(const std::string& vrStr) - : std::string(vrStr) -{ -} +CMIUtilString::CMIUtilString(const std::string &vrStr) : std::string(vrStr) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilString assignment operator. // Type: Method. // Args: vpRhs - Pointer to UTF8 text data. // Return: CMIUtilString & - *this string. // Throws: None. //-- -CMIUtilString &CMIUtilString::operator=(const char *vpRhs) -{ - assign(vpRhs); - return *this; +CMIUtilString &CMIUtilString::operator=(const char *vpRhs) { + assign(vpRhs); + return *this; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilString assignment operator. // Type: Method. // Args: vrRhs - The other string to copy from. // Return: CMIUtilString & - *this string. // Throws: None. //-- -CMIUtilString &CMIUtilString::operator=(const std::string &vrRhs) -{ - assign(vrRhs); - return *this; +CMIUtilString &CMIUtilString::operator=(const std::string &vrRhs) { + assign(vrRhs); + return *this; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilString destructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMIUtilString::~CMIUtilString() -{ -} +CMIUtilString::~CMIUtilString() {} -//++ ------------------------------------------------------------------------------------ -// Details: Perform a snprintf format style on a string data. A new string object is +//++ +//------------------------------------------------------------------------------------ +// Details: Perform a snprintf format style on a string data. A new string +// object is // created and returned. // Type: Static method. // Args: vrFormat - (R) Format string data instruction. @@ -100,57 +95,60 @@ CMIUtilString::~CMIUtilString() // Return: CMIUtilString - Number of splits found in the string data. // Throws: None. //-- -CMIUtilString -CMIUtilString::FormatPriv(const CMIUtilString &vrFormat, va_list vArgs) -{ - CMIUtilString strResult; - MIint nFinal = 0; - MIint n = vrFormat.size(); - - // IOR: mysterious crash in this function on some windows builds not able to duplicate - // but found article which may be related. Crash occurs in vsnprintf() or va_copy() - // Duplicate vArgs va_list argument pointer to ensure that it can be safely used in - // a new frame - // http://julipedia.meroh.net/2011/09/using-vacopy-to-safely-pass-ap.html - va_list argsDup; - va_copy(argsDup, vArgs); - - // Create a copy va_list to reset when we spin - va_list argsCpy; - va_copy(argsCpy, argsDup); - - if (n == 0) - return strResult; - - n = n << 4; // Reserve 16 times as much the length of the vrFormat - - std::unique_ptr<char[]> pFormatted; - while (1) - { - pFormatted.reset(new char[n + 1]); // +1 for safety margin - ::strncpy(&pFormatted[0], vrFormat.c_str(), n); - - // We need to restore the variable argument list pointer to the start again - // before running vsnprintf() more then once - va_copy(argsDup, argsCpy); - - nFinal = ::vsnprintf(&pFormatted[0], n, vrFormat.c_str(), argsDup); - if ((nFinal < 0) || (nFinal >= n)) - n += abs(nFinal - n + 1); - else - break; - } +CMIUtilString CMIUtilString::FormatPriv(const CMIUtilString &vrFormat, + va_list vArgs) { + CMIUtilString strResult; + MIint nFinal = 0; + MIint n = vrFormat.size(); + + // IOR: mysterious crash in this function on some windows builds not able to + // duplicate + // but found article which may be related. Crash occurs in vsnprintf() or + // va_copy() + // Duplicate vArgs va_list argument pointer to ensure that it can be safely + // used in + // a new frame + // http://julipedia.meroh.net/2011/09/using-vacopy-to-safely-pass-ap.html + va_list argsDup; + va_copy(argsDup, vArgs); + + // Create a copy va_list to reset when we spin + va_list argsCpy; + va_copy(argsCpy, argsDup); + + if (n == 0) + return strResult; - va_end(argsCpy); - va_end(argsDup); + n = n << 4; // Reserve 16 times as much the length of the vrFormat - strResult = pFormatted.get(); + std::unique_ptr<char[]> pFormatted; + while (1) { + pFormatted.reset(new char[n + 1]); // +1 for safety margin + ::strncpy(&pFormatted[0], vrFormat.c_str(), n); - return strResult; + // We need to restore the variable argument list pointer to the start again + // before running vsnprintf() more then once + va_copy(argsDup, argsCpy); + + nFinal = ::vsnprintf(&pFormatted[0], n, vrFormat.c_str(), argsDup); + if ((nFinal < 0) || (nFinal >= n)) + n += abs(nFinal - n + 1); + else + break; + } + + va_end(argsCpy); + va_end(argsDup); + + strResult = pFormatted.get(); + + return strResult; } -//++ ------------------------------------------------------------------------------------ -// Details: Perform a snprintf format style on a string data. A new string object is +//++ +//------------------------------------------------------------------------------------ +// Details: Perform a snprintf format style on a string data. A new string +// object is // created and returned. // Type: Static method. // Args: vFormat - (R) Format string data instruction. @@ -158,19 +156,19 @@ CMIUtilString::FormatPriv(const CMIUtilString &vrFormat, va_list vArgs) // Return: CMIUtilString - Number of splits found in the string data. // Throws: None. //-- -CMIUtilString -CMIUtilString::Format(const CMIUtilString vFormating, ...) -{ - va_list args; - va_start(args, vFormating); - CMIUtilString strResult = CMIUtilString::FormatPriv(vFormating, args); - va_end(args); +CMIUtilString CMIUtilString::Format(const CMIUtilString vFormating, ...) { + va_list args; + va_start(args, vFormating); + CMIUtilString strResult = CMIUtilString::FormatPriv(vFormating, args); + va_end(args); - return strResult; + return strResult; } -//++ ------------------------------------------------------------------------------------ -// Details: Perform a snprintf format style on a string data. A new string object is +//++ +//------------------------------------------------------------------------------------ +// Details: Perform a snprintf format style on a string data. A new string +// object is // created and returned. // Type: Static method. // Args: vrFormat - (R) Format string data instruction. @@ -178,14 +176,15 @@ CMIUtilString::Format(const CMIUtilString vFormating, ...) // Return: CMIUtilString - Number of splits found in the string data. // Throws: None. //-- -CMIUtilString -CMIUtilString::FormatValist(const CMIUtilString &vrFormating, va_list vArgs) -{ - return CMIUtilString::FormatPriv(vrFormating, vArgs); +CMIUtilString CMIUtilString::FormatValist(const CMIUtilString &vrFormating, + va_list vArgs) { + return CMIUtilString::FormatPriv(vrFormating, vArgs); } -//++ ------------------------------------------------------------------------------------ -// Details: Splits string into array of strings using delimiter. If multiple delimiter +//++ +//------------------------------------------------------------------------------------ +// Details: Splits string into array of strings using delimiter. If multiple +// delimiter // are found in sequence then they are not added to the list of splits. // Type: Method. // Args: vData - (R) String data to be split up. @@ -194,47 +193,50 @@ CMIUtilString::FormatValist(const CMIUtilString &vrFormating, va_list vArgs) // Return: size_t - Number of splits found in the string data. // Throws: None. //-- -size_t -CMIUtilString::Split(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits) const -{ - vwVecSplits.clear(); - - if (this->empty() || vDelimiter.empty()) - return 0; - - const size_t nLen(length()); - size_t nOffset(0); - do - { - // Find first occurrence which doesn't match to the delimiter - const size_t nSectionPos(FindFirstNot(vDelimiter, nOffset)); - if (nSectionPos == std::string::npos) - break; - - // Find next occurrence of the delimiter after section - size_t nNextDelimiterPos(FindFirst(vDelimiter, nSectionPos)); - if (nNextDelimiterPos == std::string::npos) - nNextDelimiterPos = nLen; - - // Extract string between delimiters - const size_t nSectionLen(nNextDelimiterPos - nSectionPos); - const std::string strSection(substr(nSectionPos, nSectionLen)); - vwVecSplits.push_back(strSection); - - // Next - nOffset = nNextDelimiterPos + 1; - } - while (nOffset < nLen); - - return vwVecSplits.size(); -} - -//++ ------------------------------------------------------------------------------------ -// Details: Splits string into array of strings using delimiter. However the string is -// also considered for text surrounded by quotes. Text with quotes including the -// delimiter is treated as a whole. If multiple delimiter are found in sequence -// then they are not added to the list of splits. Quotes that are embedded in -// the string as string formatted quotes are ignored (proceeded by a '\\') i.e. +size_t CMIUtilString::Split(const CMIUtilString &vDelimiter, + VecString_t &vwVecSplits) const { + vwVecSplits.clear(); + + if (this->empty() || vDelimiter.empty()) + return 0; + + const size_t nLen(length()); + size_t nOffset(0); + do { + // Find first occurrence which doesn't match to the delimiter + const size_t nSectionPos(FindFirstNot(vDelimiter, nOffset)); + if (nSectionPos == std::string::npos) + break; + + // Find next occurrence of the delimiter after section + size_t nNextDelimiterPos(FindFirst(vDelimiter, nSectionPos)); + if (nNextDelimiterPos == std::string::npos) + nNextDelimiterPos = nLen; + + // Extract string between delimiters + const size_t nSectionLen(nNextDelimiterPos - nSectionPos); + const std::string strSection(substr(nSectionPos, nSectionLen)); + vwVecSplits.push_back(strSection); + + // Next + nOffset = nNextDelimiterPos + 1; + } while (nOffset < nLen); + + return vwVecSplits.size(); +} + +//++ +//------------------------------------------------------------------------------------ +// Details: Splits string into array of strings using delimiter. However the +// string is +// also considered for text surrounded by quotes. Text with quotes +// including the +// delimiter is treated as a whole. If multiple delimiter are found in +// sequence +// then they are not added to the list of splits. Quotes that are +// embedded in +// the string as string formatted quotes are ignored (proceeded by a +// '\\') i.e. // "\"MI GDB local C++.cpp\":88". // Type: Method. // Args: vData - (R) String data to be split up. @@ -243,62 +245,59 @@ CMIUtilString::Split(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits) // Return: size_t - Number of splits found in the string data. // Throws: None. //-- -size_t -CMIUtilString::SplitConsiderQuotes(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits) const -{ - vwVecSplits.clear(); - - if (this->empty() || vDelimiter.empty()) - return 0; - - const size_t nLen(length()); - size_t nOffset(0); - do - { - // Find first occurrence which doesn't match to the delimiter - const size_t nSectionPos(FindFirstNot(vDelimiter, nOffset)); - if (nSectionPos == std::string::npos) - break; - - // Find next occurrence of the delimiter after (quoted) section - const bool bSkipQuotedText(true); - bool bUnmatchedQuote(false); - size_t nNextDelimiterPos(FindFirst(vDelimiter, bSkipQuotedText, bUnmatchedQuote, nSectionPos)); - if (bUnmatchedQuote) - { - vwVecSplits.clear(); - return 0; - } - if (nNextDelimiterPos == std::string::npos) - nNextDelimiterPos = nLen; - - // Extract string between delimiters - const size_t nSectionLen(nNextDelimiterPos - nSectionPos); - const std::string strSection(substr(nSectionPos, nSectionLen)); - vwVecSplits.push_back(strSection); - - // Next - nOffset = nNextDelimiterPos + 1; +size_t CMIUtilString::SplitConsiderQuotes(const CMIUtilString &vDelimiter, + VecString_t &vwVecSplits) const { + vwVecSplits.clear(); + + if (this->empty() || vDelimiter.empty()) + return 0; + + const size_t nLen(length()); + size_t nOffset(0); + do { + // Find first occurrence which doesn't match to the delimiter + const size_t nSectionPos(FindFirstNot(vDelimiter, nOffset)); + if (nSectionPos == std::string::npos) + break; + + // Find next occurrence of the delimiter after (quoted) section + const bool bSkipQuotedText(true); + bool bUnmatchedQuote(false); + size_t nNextDelimiterPos( + FindFirst(vDelimiter, bSkipQuotedText, bUnmatchedQuote, nSectionPos)); + if (bUnmatchedQuote) { + vwVecSplits.clear(); + return 0; } - while (nOffset < nLen); + if (nNextDelimiterPos == std::string::npos) + nNextDelimiterPos = nLen; - return vwVecSplits.size(); + // Extract string between delimiters + const size_t nSectionLen(nNextDelimiterPos - nSectionPos); + const std::string strSection(substr(nSectionPos, nSectionLen)); + vwVecSplits.push_back(strSection); + + // Next + nOffset = nNextDelimiterPos + 1; + } while (nOffset < nLen); + + return vwVecSplits.size(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Split string into lines using \n and return an array of strings. // Type: Method. // Args: vwVecSplits - (W) Container of splits found in string data. // Return: size_t - Number of splits found in the string data. // Throws: None. //-- -size_t -CMIUtilString::SplitLines(VecString_t &vwVecSplits) const -{ - return Split("\n", vwVecSplits); +size_t CMIUtilString::SplitLines(VecString_t &vwVecSplits) const { + return Split("\n", vwVecSplits); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Remove '\n' from the end of string if found. It does not alter // *this string. // Type: Method. @@ -306,34 +305,34 @@ CMIUtilString::SplitLines(VecString_t &vwVecSplits) const // Return: CMIUtilString - New version of the string. // Throws: None. //-- -CMIUtilString -CMIUtilString::StripCREndOfLine() const -{ - const size_t nPos = rfind('\n'); - if (nPos == std::string::npos) - return *this; +CMIUtilString CMIUtilString::StripCREndOfLine() const { + const size_t nPos = rfind('\n'); + if (nPos == std::string::npos) + return *this; - const CMIUtilString strNew(substr(0, nPos)); + const CMIUtilString strNew(substr(0, nPos)); - return strNew; + return strNew; } -//++ ------------------------------------------------------------------------------------ -// Details: Remove all '\n' from the string and replace with a space. It does not alter +//++ +//------------------------------------------------------------------------------------ +// Details: Remove all '\n' from the string and replace with a space. It does +// not alter // *this string. // Type: Method. // Args: None. // Return: CMIUtilString - New version of the string. // Throws: None. //-- -CMIUtilString -CMIUtilString::StripCRAll() const -{ - return FindAndReplace("\n", " "); +CMIUtilString CMIUtilString::StripCRAll() const { + return FindAndReplace("\n", " "); } -//++ ------------------------------------------------------------------------------------ -// Details: Find and replace all matches of a sub string with another string. It does not +//++ +//------------------------------------------------------------------------------------ +// Details: Find and replace all matches of a sub string with another string. It +// does not // alter *this string. // Type: Method. // Args: vFind - (R) The string to look for. @@ -342,150 +341,145 @@ CMIUtilString::StripCRAll() const // Throws: None. //-- CMIUtilString -CMIUtilString::FindAndReplace(const CMIUtilString &vFind, const CMIUtilString &vReplaceWith) const -{ - if (vFind.empty() || this->empty()) - return *this; - - size_t nPos = find(vFind); - if (nPos == std::string::npos) - return *this; - - CMIUtilString strNew(*this); - while (nPos != std::string::npos) - { - strNew.replace(nPos, vFind.length(), vReplaceWith); - nPos += vReplaceWith.length(); - nPos = strNew.find(vFind, nPos); - } +CMIUtilString::FindAndReplace(const CMIUtilString &vFind, + const CMIUtilString &vReplaceWith) const { + if (vFind.empty() || this->empty()) + return *this; + + size_t nPos = find(vFind); + if (nPos == std::string::npos) + return *this; + + CMIUtilString strNew(*this); + while (nPos != std::string::npos) { + strNew.replace(nPos, vFind.length(), vReplaceWith); + nPos += vReplaceWith.length(); + nPos = strNew.find(vFind, nPos); + } - return strNew; + return strNew; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Check if *this string is a decimal number. // Type: Method. // Args: None. // Return: bool - True = yes number, false not a number. // Throws: None. //-- -bool -CMIUtilString::IsNumber() const -{ - if (empty()) - return false; +bool CMIUtilString::IsNumber() const { + if (empty()) + return false; - if ((at(0) == '-') && (length() == 1)) - return false; + if ((at(0) == '-') && (length() == 1)) + return false; - const size_t nPos = find_first_not_of("-.0123456789"); - if (nPos != std::string::npos) - return false; + const size_t nPos = find_first_not_of("-.0123456789"); + if (nPos != std::string::npos) + return false; - return true; + return true; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Check if *this string is a hexadecimal number. // Type: Method. // Args: None. // Return: bool - True = yes number, false not a number. // Throws: None. //-- -bool -CMIUtilString::IsHexadecimalNumber() const -{ - // Compare '0x..' prefix - if ((strncmp(c_str(), "0x", 2) != 0) && (strncmp(c_str(), "0X", 2) != 0)) - return false; +bool CMIUtilString::IsHexadecimalNumber() const { + // Compare '0x..' prefix + if ((strncmp(c_str(), "0x", 2) != 0) && (strncmp(c_str(), "0X", 2) != 0)) + return false; - // Skip '0x..' prefix - const size_t nPos = find_first_not_of("01234567890ABCDEFabcedf", 2); - if (nPos != std::string::npos) - return false; + // Skip '0x..' prefix + const size_t nPos = find_first_not_of("01234567890ABCDEFabcedf", 2); + if (nPos != std::string::npos) + return false; - return true; + return true; } -//++ ------------------------------------------------------------------------------------ -// Details: Extract the number from the string. The number can be either a hexadecimal or +//++ +//------------------------------------------------------------------------------------ +// Details: Extract the number from the string. The number can be either a +// hexadecimal or // natural number. It cannot contain other non-numeric characters. // Type: Method. // Args: vwrNumber - (W) Number extracted from the string. // Return: bool - True = yes number, false not a number. // Throws: None. //-- -bool -CMIUtilString::ExtractNumber(MIint64 &vwrNumber) const -{ - vwrNumber = 0; +bool CMIUtilString::ExtractNumber(MIint64 &vwrNumber) const { + vwrNumber = 0; - if (!IsNumber()) - { - if (ExtractNumberFromHexadecimal(vwrNumber)) - return true; + if (!IsNumber()) { + if (ExtractNumberFromHexadecimal(vwrNumber)) + return true; - return false; - } + return false; + } - std::stringstream ss(const_cast<CMIUtilString &>(*this)); - ss >> vwrNumber; + std::stringstream ss(const_cast<CMIUtilString &>(*this)); + ss >> vwrNumber; - return true; + return true; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Extract the number from the hexadecimal string.. // Type: Method. // Args: vwrNumber - (W) Number extracted from the string. // Return: bool - True = yes number, false not a number. // Throws: None. //-- -bool -CMIUtilString::ExtractNumberFromHexadecimal(MIint64 &vwrNumber) const -{ - vwrNumber = 0; +bool CMIUtilString::ExtractNumberFromHexadecimal(MIint64 &vwrNumber) const { + vwrNumber = 0; - const size_t nPos = find_first_not_of("xX01234567890ABCDEFabcedf"); - if (nPos != std::string::npos) - return false; + const size_t nPos = find_first_not_of("xX01234567890ABCDEFabcedf"); + if (nPos != std::string::npos) + return false; - errno = 0; - const MIuint64 nNum = ::strtoull(this->c_str(), nullptr, 16); - if (errno == ERANGE) - return false; + errno = 0; + const MIuint64 nNum = ::strtoull(this->c_str(), nullptr, 16); + if (errno == ERANGE) + return false; - vwrNumber = static_cast<MIint64>(nNum); + vwrNumber = static_cast<MIint64>(nNum); - return true; + return true; } -//++ ------------------------------------------------------------------------------------ -// Details: Determine if the text is all valid alpha numeric characters. Letters can be +//++ +//------------------------------------------------------------------------------------ +// Details: Determine if the text is all valid alpha numeric characters. Letters +// can be // either upper or lower case. // Type: Static method. // Args: vpText - (R) The text data to examine. // Return: bool - True = yes all alpha, false = one or more chars is non alpha. // Throws: None. //-- -bool -CMIUtilString::IsAllValidAlphaAndNumeric(const char *vpText) -{ - const size_t len = ::strlen(vpText); - if (len == 0) - return false; +bool CMIUtilString::IsAllValidAlphaAndNumeric(const char *vpText) { + const size_t len = ::strlen(vpText); + if (len == 0) + return false; - for (size_t i = 0; i < len; i++, vpText++) - { - const char c = *vpText; - if (::isalnum((int)c) == 0) - return false; - } + for (size_t i = 0; i < len; i++, vpText++) { + const char c = *vpText; + if (::isalnum((int)c) == 0) + return false; + } - return true; + return true; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Check if two strings share equal contents. // Type: Method. // Args: vrLhs - (R) String A. @@ -493,491 +487,474 @@ CMIUtilString::IsAllValidAlphaAndNumeric(const char *vpText) // Return: bool - True = yes equal, false - different. // Throws: None. //-- -bool -CMIUtilString::Compare(const CMIUtilString &vrLhs, const CMIUtilString &vrRhs) -{ - // Check the sizes match - if (vrLhs.size() != vrRhs.size()) - return false; +bool CMIUtilString::Compare(const CMIUtilString &vrLhs, + const CMIUtilString &vrRhs) { + // Check the sizes match + if (vrLhs.size() != vrRhs.size()) + return false; - return (::strncmp(vrLhs.c_str(), vrRhs.c_str(), vrLhs.size()) == 0); + return (::strncmp(vrLhs.c_str(), vrRhs.c_str(), vrLhs.size()) == 0); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Remove from either end of *this string the following: " \t\n\v\f\r". // Type: Method. // Args: None. // Return: CMIUtilString - Trimmed string. // Throws: None. //-- -CMIUtilString -CMIUtilString::Trim() const -{ - CMIUtilString strNew(*this); - const char *pWhiteSpace = " \t\n\v\f\r"; - const size_t nPos = find_last_not_of(pWhiteSpace); - if (nPos != std::string::npos) - { - strNew = substr(0, nPos + 1); - } - const size_t nPos2 = strNew.find_first_not_of(pWhiteSpace); - if (nPos2 != std::string::npos) - { - strNew = strNew.substr(nPos2); - } +CMIUtilString CMIUtilString::Trim() const { + CMIUtilString strNew(*this); + const char *pWhiteSpace = " \t\n\v\f\r"; + const size_t nPos = find_last_not_of(pWhiteSpace); + if (nPos != std::string::npos) { + strNew = substr(0, nPos + 1); + } + const size_t nPos2 = strNew.find_first_not_of(pWhiteSpace); + if (nPos2 != std::string::npos) { + strNew = strNew.substr(nPos2); + } - return strNew; + return strNew; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Remove from either end of *this string the specified character. // Type: Method. // Args: None. // Return: CMIUtilString - Trimmed string. // Throws: None. //-- -CMIUtilString -CMIUtilString::Trim(const char vChar) const -{ - CMIUtilString strNew(*this); - const size_t nLen = strNew.length(); - if (nLen > 1) - { - if ((strNew[0] == vChar) && (strNew[nLen - 1] == vChar)) - strNew = strNew.substr(1, nLen - 2); - } +CMIUtilString CMIUtilString::Trim(const char vChar) const { + CMIUtilString strNew(*this); + const size_t nLen = strNew.length(); + if (nLen > 1) { + if ((strNew[0] == vChar) && (strNew[nLen - 1] == vChar)) + strNew = strNew.substr(1, nLen - 2); + } - return strNew; + return strNew; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Do a printf equivalent for printing a number in binary i.e. "b%llB". // Type: Static method. // Args: vnDecimal - (R) The number to represent in binary. // Return: CMIUtilString - Binary number in text. // Throws: None. //-- -CMIUtilString -CMIUtilString::FormatBinary(const MIuint64 vnDecimal) -{ - CMIUtilString strBinaryNumber; - - const MIuint nConstBits = 64; - MIuint nRem[nConstBits + 1]; - MIint i = 0; - MIuint nLen = 0; - MIuint64 nNum = vnDecimal; - while ((nNum > 0) && (nLen < nConstBits)) - { - nRem[i++] = nNum % 2; - nNum = nNum >> 1; - nLen++; - } - char pN[nConstBits + 1]; - MIuint j = 0; - for (i = nLen; i > 0; --i, j++) - { - pN[j] = '0' + nRem[i - 1]; - } - pN[j] = 0; // String NUL termination - - strBinaryNumber = CMIUtilString::Format("0b%s", &pN[0]); - - return strBinaryNumber; -} - -//++ ------------------------------------------------------------------------------------ -// Details: Remove from a string doubled up characters so only one set left. Characters -// are only removed if the previous character is already a same character. +CMIUtilString CMIUtilString::FormatBinary(const MIuint64 vnDecimal) { + CMIUtilString strBinaryNumber; + + const MIuint nConstBits = 64; + MIuint nRem[nConstBits + 1]; + MIint i = 0; + MIuint nLen = 0; + MIuint64 nNum = vnDecimal; + while ((nNum > 0) && (nLen < nConstBits)) { + nRem[i++] = nNum % 2; + nNum = nNum >> 1; + nLen++; + } + char pN[nConstBits + 1]; + MIuint j = 0; + for (i = nLen; i > 0; --i, j++) { + pN[j] = '0' + nRem[i - 1]; + } + pN[j] = 0; // String NUL termination + + strBinaryNumber = CMIUtilString::Format("0b%s", &pN[0]); + + return strBinaryNumber; +} + +//++ +//------------------------------------------------------------------------------------ +// Details: Remove from a string doubled up characters so only one set left. +// Characters +// are only removed if the previous character is already a same +// character. // Type: Method. -// Args: vChar - (R) The character to search for and remove adjacent duplicates. +// Args: vChar - (R) The character to search for and remove adjacent +// duplicates. // Return: CMIUtilString - New version of the string. // Throws: None. //-- -CMIUtilString -CMIUtilString::RemoveRepeatedCharacters(const char vChar) -{ - return RemoveRepeatedCharacters(0, vChar); +CMIUtilString CMIUtilString::RemoveRepeatedCharacters(const char vChar) { + return RemoveRepeatedCharacters(0, vChar); } -//++ ------------------------------------------------------------------------------------ -// Details: Recursively remove from a string doubled up characters so only one set left. -// Characters are only removed if the previous character is already a same +//++ +//------------------------------------------------------------------------------------ +// Details: Recursively remove from a string doubled up characters so only one +// set left. +// Characters are only removed if the previous character is already a +// same // character. // Type: Method. -// Args: vChar - (R) The character to search for and remove adjacent duplicates. +// Args: vChar - (R) The character to search for and remove adjacent +// duplicates. // vnPos - Character position in the string. // Return: CMIUtilString - New version of the string. // Throws: None. //-- -CMIUtilString -CMIUtilString::RemoveRepeatedCharacters(size_t vnPos, const char vChar) -{ - const char cQuote = '"'; - - // Look for first quote of two - const size_t nPos = find(cQuote, vnPos); - if (nPos == std::string::npos) - return *this; - - const size_t nPosNext = nPos + 1; - if (nPosNext > length()) - return *this; - - if (at(nPosNext) == cQuote) - { - *this = substr(0, nPos) + substr(nPosNext, length()); - RemoveRepeatedCharacters(nPosNext, vChar); - } +CMIUtilString CMIUtilString::RemoveRepeatedCharacters(size_t vnPos, + const char vChar) { + const char cQuote = '"'; + + // Look for first quote of two + const size_t nPos = find(cQuote, vnPos); + if (nPos == std::string::npos) + return *this; + const size_t nPosNext = nPos + 1; + if (nPosNext > length()) return *this; + + if (at(nPosNext) == cQuote) { + *this = substr(0, nPos) + substr(nPosNext, length()); + RemoveRepeatedCharacters(nPosNext, vChar); + } + + return *this; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Is the text in *this string surrounded by quotes. // Type: Method. // Args: None. // Return: bool - True = Yes string is quoted, false = no quoted. // Throws: None. //-- -bool -CMIUtilString::IsQuoted() const -{ - const char cQuote = '"'; +bool CMIUtilString::IsQuoted() const { + const char cQuote = '"'; - if (at(0) != cQuote) - return false; + if (at(0) != cQuote) + return false; - const size_t nLen = length(); - if ((nLen > 0) && (at(nLen - 1) != cQuote)) - return false; + const size_t nLen = length(); + if ((nLen > 0) && (at(nLen - 1) != cQuote)) + return false; - return true; + return true; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Find first occurrence in *this string which matches the pattern. // Type: Method. // Args: vrPattern - (R) The pattern to search for. -// vnPos - The starting position at which to start searching. (Dflt = 0) +// vnPos - The starting position at which to start searching. +// (Dflt = 0) // Return: size_t - The position of the first substring that match. // Throws: None. //-- -size_t -CMIUtilString::FindFirst(const CMIUtilString &vrPattern, size_t vnPos /* = 0 */) const -{ - return find(vrPattern, vnPos); +size_t CMIUtilString::FindFirst(const CMIUtilString &vrPattern, + size_t vnPos /* = 0 */) const { + return find(vrPattern, vnPos); } -//++ ------------------------------------------------------------------------------------ -// Details: Find first occurrence in *this string which matches the pattern and isn't surrounded by quotes. +//++ +//------------------------------------------------------------------------------------ +// Details: Find first occurrence in *this string which matches the pattern and +// isn't surrounded by quotes. // Type: Method. // Args: vrPattern - (R) The pattern to search for. -// vbSkipQuotedText - (R) True = don't look at quoted text, false = otherwise. -// vrwbNotFoundClosedQuote - (W) True = parsing error: unmatched quote, false = otherwise. -// vnPos - Position of the first character in the string to be considered in the search. (Dflt = 0) -// Return: size_t - The position of the first substring that matches and isn't quoted. -// Throws: None. -//-- -size_t -CMIUtilString::FindFirst(const CMIUtilString &vrPattern, const bool vbSkipQuotedText, bool &vrwbNotFoundClosedQuote, - size_t vnPos /* = 0 */) const -{ - vrwbNotFoundClosedQuote = false; - - if (!vbSkipQuotedText) - return FindFirst(vrPattern, vnPos); - - const size_t nLen(length()); - - size_t nPos = vnPos; - do - { - const size_t nQuotePos(FindFirstQuote(nPos)); - const size_t nPatternPos(FindFirst(vrPattern, nPos)); - if (nQuotePos == std::string::npos) - return nPatternPos; - - const size_t nQuoteClosedPos = FindFirstQuote(nQuotePos + 1); - if (nQuoteClosedPos == std::string::npos) - { - vrwbNotFoundClosedQuote = true; - return std::string::npos; - } - - if ((nPatternPos == std::string::npos) || (nPatternPos < nQuotePos)) - return nPatternPos; - - nPos = nQuoteClosedPos + 1; +// vbSkipQuotedText - (R) True = don't look at quoted text, +// false = otherwise. +// vrwbNotFoundClosedQuote - (W) True = parsing error: unmatched +// quote, false = otherwise. +// vnPos - Position of the first character in the +// string to be considered in the search. (Dflt = 0) +// Return: size_t - The position of the first substring that matches and isn't +// quoted. +// Throws: None. +//-- +size_t CMIUtilString::FindFirst(const CMIUtilString &vrPattern, + const bool vbSkipQuotedText, + bool &vrwbNotFoundClosedQuote, + size_t vnPos /* = 0 */) const { + vrwbNotFoundClosedQuote = false; + + if (!vbSkipQuotedText) + return FindFirst(vrPattern, vnPos); + + const size_t nLen(length()); + + size_t nPos = vnPos; + do { + const size_t nQuotePos(FindFirstQuote(nPos)); + const size_t nPatternPos(FindFirst(vrPattern, nPos)); + if (nQuotePos == std::string::npos) + return nPatternPos; + + const size_t nQuoteClosedPos = FindFirstQuote(nQuotePos + 1); + if (nQuoteClosedPos == std::string::npos) { + vrwbNotFoundClosedQuote = true; + return std::string::npos; } - while (nPos < nLen); - return std::string::npos; + if ((nPatternPos == std::string::npos) || (nPatternPos < nQuotePos)) + return nPatternPos; + + nPos = nQuoteClosedPos + 1; + } while (nPos < nLen); + + return std::string::npos; } -//++ ------------------------------------------------------------------------------------ -// Details: Find first occurrence in *this string which doesn't match the pattern. +//++ +//------------------------------------------------------------------------------------ +// Details: Find first occurrence in *this string which doesn't match the +// pattern. // Type: Method. // Args: vrPattern - (R) The pattern to search for. -// vnPos - Position of the first character in the string to be considered in the search. (Dflt = 0) +// vnPos - Position of the first character in the string to be +// considered in the search. (Dflt = 0) // Return: size_t - The position of the first character that doesn't match. // Throws: None. //-- -size_t -CMIUtilString::FindFirstNot(const CMIUtilString &vrPattern, size_t vnPos /* = 0 */) const -{ - const size_t nLen(length()); - const size_t nPatternLen(vrPattern.length()); +size_t CMIUtilString::FindFirstNot(const CMIUtilString &vrPattern, + size_t vnPos /* = 0 */) const { + const size_t nLen(length()); + const size_t nPatternLen(vrPattern.length()); - size_t nPatternPos(vnPos); - do - { - const bool bMatchPattern(compare(nPatternPos, nPatternLen, vrPattern) == 0); - if (!bMatchPattern) - return nPatternPos; - nPatternPos += nPatternLen; - } - while (nPatternPos < nLen); + size_t nPatternPos(vnPos); + do { + const bool bMatchPattern(compare(nPatternPos, nPatternLen, vrPattern) == 0); + if (!bMatchPattern) + return nPatternPos; + nPatternPos += nPatternLen; + } while (nPatternPos < nLen); - return std::string::npos; + return std::string::npos; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Find first occurrence of not escaped quotation mark in *this string. // Type: Method. -// Args: vnPos - Position of the first character in the string to be considered in the search. +// Args: vnPos - Position of the first character in the string to be +// considered in the search. // Return: size_t - The position of the quotation mark. // Throws: None. //-- -size_t -CMIUtilString::FindFirstQuote(size_t vnPos) const -{ - const char cBckSlash('\\'); - const char cQuote('"'); - const size_t nLen(length()); +size_t CMIUtilString::FindFirstQuote(size_t vnPos) const { + const char cBckSlash('\\'); + const char cQuote('"'); + const size_t nLen(length()); - size_t nPos = vnPos; - do - { - const size_t nBckSlashPos(find(cBckSlash, nPos)); - const size_t nQuotePos(find(cQuote, nPos)); - if ((nBckSlashPos == std::string::npos) || (nQuotePos == std::string::npos)) - return nQuotePos; + size_t nPos = vnPos; + do { + const size_t nBckSlashPos(find(cBckSlash, nPos)); + const size_t nQuotePos(find(cQuote, nPos)); + if ((nBckSlashPos == std::string::npos) || (nQuotePos == std::string::npos)) + return nQuotePos; - if (nQuotePos < nBckSlashPos) - return nQuotePos; + if (nQuotePos < nBckSlashPos) + return nQuotePos; - // Skip 2 characters: First is '\', second is that which is escaped by '\' - nPos = nBckSlashPos + 2; - } - while (nPos < nLen); + // Skip 2 characters: First is '\', second is that which is escaped by '\' + nPos = nBckSlashPos + 2; + } while (nPos < nLen); - return std::string::npos; + return std::string::npos; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Get escaped string from *this string. // Type: Method. // Args: None. // Return: CMIUtilString - The escaped version of the initial string. // Throws: None. //-- -CMIUtilString -CMIUtilString::Escape(bool vbEscapeQuotes /* = false */) const -{ - const size_t nLen(length()); - CMIUtilString strNew; - strNew.reserve(nLen); - for (size_t nIndex(0); nIndex < nLen; ++nIndex) - { - const char cUnescapedChar((*this)[nIndex]); - if (cUnescapedChar == '"' && vbEscapeQuotes) - strNew.append("\\\""); - else - strNew.append(ConvertToPrintableASCII((char)cUnescapedChar)); - } - return strNew; -} - -//++ ------------------------------------------------------------------------------------ -// Details: Get string with backslashes in front of double quote '"' and backslash '\\' +CMIUtilString CMIUtilString::Escape(bool vbEscapeQuotes /* = false */) const { + const size_t nLen(length()); + CMIUtilString strNew; + strNew.reserve(nLen); + for (size_t nIndex(0); nIndex < nLen; ++nIndex) { + const char cUnescapedChar((*this)[nIndex]); + if (cUnescapedChar == '"' && vbEscapeQuotes) + strNew.append("\\\""); + else + strNew.append(ConvertToPrintableASCII((char)cUnescapedChar)); + } + return strNew; +} + +//++ +//------------------------------------------------------------------------------------ +// Details: Get string with backslashes in front of double quote '"' and +// backslash '\\' // characters. // Type: Method. // Args: None. // Return: CMIUtilString - The wrapped version of the initial string. // Throws: None. //-- -CMIUtilString -CMIUtilString::AddSlashes() const -{ - const char cBckSlash('\\'); - const size_t nLen(length()); - CMIUtilString strNew; - strNew.reserve(nLen); - - size_t nOffset(0); - while (nOffset < nLen) - { - const size_t nUnescapedCharPos(find_first_of("\"\\", nOffset)); - const bool bUnescapedCharNotFound(nUnescapedCharPos == std::string::npos); - if (bUnescapedCharNotFound) - { - const size_t nAppendAll(std::string::npos); - strNew.append(*this, nOffset, nAppendAll); - break; - } - const size_t nAppendLen(nUnescapedCharPos - nOffset); - strNew.append(*this, nOffset, nAppendLen); - strNew.push_back(cBckSlash); - const char cUnescapedChar((*this)[nUnescapedCharPos]); - strNew.push_back(cUnescapedChar); - nOffset = nUnescapedCharPos + 1; +CMIUtilString CMIUtilString::AddSlashes() const { + const char cBckSlash('\\'); + const size_t nLen(length()); + CMIUtilString strNew; + strNew.reserve(nLen); + + size_t nOffset(0); + while (nOffset < nLen) { + const size_t nUnescapedCharPos(find_first_of("\"\\", nOffset)); + const bool bUnescapedCharNotFound(nUnescapedCharPos == std::string::npos); + if (bUnescapedCharNotFound) { + const size_t nAppendAll(std::string::npos); + strNew.append(*this, nOffset, nAppendAll); + break; } + const size_t nAppendLen(nUnescapedCharPos - nOffset); + strNew.append(*this, nOffset, nAppendLen); + strNew.push_back(cBckSlash); + const char cUnescapedChar((*this)[nUnescapedCharPos]); + strNew.push_back(cUnescapedChar); + nOffset = nUnescapedCharPos + 1; + } - return strNew; + return strNew; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Remove backslashes added by CMIUtilString::AddSlashes. // Type: Method. // Args: None. // Return: CMIUtilString - The initial version of wrapped string. // Throws: None. //-- -CMIUtilString -CMIUtilString::StripSlashes() const -{ - const char cBckSlash('\\'); - const size_t nLen(length()); - CMIUtilString strNew; - strNew.reserve(nLen); - - size_t nOffset(0); - while (nOffset < nLen) - { - const size_t nBckSlashPos(find(cBckSlash, nOffset)); - const bool bBckSlashNotFound(nBckSlashPos == std::string::npos); - if (bBckSlashNotFound) - { - const size_t nAppendAll(std::string::npos); - strNew.append(*this, nOffset, nAppendAll); - break; - } - const size_t nAppendLen(nBckSlashPos - nOffset); - strNew.append(*this, nOffset, nAppendLen); - const bool bBckSlashIsLast(nBckSlashPos == nLen); - if (bBckSlashIsLast) - { - strNew.push_back(cBckSlash); - break; - } - const char cEscapedChar((*this)[nBckSlashPos + 1]); - const size_t nEscapedCharPos(std::string("\"\\").find(cEscapedChar)); - const bool bEscapedCharNotFound(nEscapedCharPos == std::string::npos); - if (bEscapedCharNotFound) - strNew.push_back(cBckSlash); - strNew.push_back(cEscapedChar); - nOffset = nBckSlashPos + 2; - } - - return strNew; -} - -CMIUtilString -CMIUtilString::ConvertToPrintableASCII(const char vChar, bool bEscapeQuotes) -{ - switch (vChar) - { - case '\a': - return "\\a"; - case '\b': - return "\\b"; - case '\t': - return "\\t"; - case '\n': - return "\\n"; - case '\v': - return "\\v"; - case '\f': - return "\\f"; - case '\r': - return "\\r"; - case '\033': - return "\\e"; - case '\\': - return "\\\\"; - case '"': - if (bEscapeQuotes) - return "\\\""; - // fall thru - default: - if (::isprint(vChar)) - return Format("%c", vChar); - else - return Format("\\x%02" PRIx8, vChar); - } -} - -CMIUtilString -CMIUtilString::ConvertCharValueToPrintableASCII(char vChar, bool bEscapeQuotes) -{ - switch (vChar) - { - case '\a': - return "\\a"; - case '\b': - return "\\b"; - case '\t': - return "\\t"; - case '\n': - return "\\n"; - case '\v': - return "\\v"; - case '\f': - return "\\f"; - case '\r': - return "\\r"; - case '\033': - return "\\e"; - case '\\': - return "\\\\"; - case '"': - if (bEscapeQuotes) - return "\\\""; - // fall thru - default: - if (::isprint(vChar)) - return Format("%c", vChar); - else - return CMIUtilString(); +CMIUtilString CMIUtilString::StripSlashes() const { + const char cBckSlash('\\'); + const size_t nLen(length()); + CMIUtilString strNew; + strNew.reserve(nLen); + + size_t nOffset(0); + while (nOffset < nLen) { + const size_t nBckSlashPos(find(cBckSlash, nOffset)); + const bool bBckSlashNotFound(nBckSlashPos == std::string::npos); + if (bBckSlashNotFound) { + const size_t nAppendAll(std::string::npos); + strNew.append(*this, nOffset, nAppendAll); + break; } -} - -CMIUtilString -CMIUtilString::ConvertToPrintableASCII(const char16_t vChar16, bool bEscapeQuotes) -{ - if (vChar16 == (char16_t)(char)vChar16) - { - // Convert char16_t to char (if possible) - CMIUtilString str = ConvertCharValueToPrintableASCII((char)vChar16, bEscapeQuotes); - if (str.length() > 0) - return str; + const size_t nAppendLen(nBckSlashPos - nOffset); + strNew.append(*this, nOffset, nAppendLen); + const bool bBckSlashIsLast(nBckSlashPos == nLen); + if (bBckSlashIsLast) { + strNew.push_back(cBckSlash); + break; } - return Format("\\u%02" PRIx8 "%02" PRIx8, - (vChar16 >> 8) & 0xff, vChar16 & 0xff); + const char cEscapedChar((*this)[nBckSlashPos + 1]); + const size_t nEscapedCharPos(std::string("\"\\").find(cEscapedChar)); + const bool bEscapedCharNotFound(nEscapedCharPos == std::string::npos); + if (bEscapedCharNotFound) + strNew.push_back(cBckSlash); + strNew.push_back(cEscapedChar); + nOffset = nBckSlashPos + 2; + } + + return strNew; +} + +CMIUtilString CMIUtilString::ConvertToPrintableASCII(const char vChar, + bool bEscapeQuotes) { + switch (vChar) { + case '\a': + return "\\a"; + case '\b': + return "\\b"; + case '\t': + return "\\t"; + case '\n': + return "\\n"; + case '\v': + return "\\v"; + case '\f': + return "\\f"; + case '\r': + return "\\r"; + case '\033': + return "\\e"; + case '\\': + return "\\\\"; + case '"': + if (bEscapeQuotes) + return "\\\""; + // fall thru + default: + if (::isprint(vChar)) + return Format("%c", vChar); + else + return Format("\\x%02" PRIx8, vChar); + } } CMIUtilString -CMIUtilString::ConvertToPrintableASCII(const char32_t vChar32, bool bEscapeQuotes) -{ - if (vChar32 == (char32_t)(char)vChar32) - { - // Convert char32_t to char (if possible) - CMIUtilString str = ConvertCharValueToPrintableASCII((char)vChar32, bEscapeQuotes); - if (str.length() > 0) - return str; - } - return Format("\\U%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8, - (vChar32 >> 24) & 0xff, (vChar32 >> 16) & 0xff, - (vChar32 >> 8) & 0xff, vChar32 & 0xff); +CMIUtilString::ConvertCharValueToPrintableASCII(char vChar, + bool bEscapeQuotes) { + switch (vChar) { + case '\a': + return "\\a"; + case '\b': + return "\\b"; + case '\t': + return "\\t"; + case '\n': + return "\\n"; + case '\v': + return "\\v"; + case '\f': + return "\\f"; + case '\r': + return "\\r"; + case '\033': + return "\\e"; + case '\\': + return "\\\\"; + case '"': + if (bEscapeQuotes) + return "\\\""; + // fall thru + default: + if (::isprint(vChar)) + return Format("%c", vChar); + else + return CMIUtilString(); + } +} + +CMIUtilString CMIUtilString::ConvertToPrintableASCII(const char16_t vChar16, + bool bEscapeQuotes) { + if (vChar16 == (char16_t)(char)vChar16) { + // Convert char16_t to char (if possible) + CMIUtilString str = + ConvertCharValueToPrintableASCII((char)vChar16, bEscapeQuotes); + if (str.length() > 0) + return str; + } + return Format("\\u%02" PRIx8 "%02" PRIx8, (vChar16 >> 8) & 0xff, + vChar16 & 0xff); +} + +CMIUtilString CMIUtilString::ConvertToPrintableASCII(const char32_t vChar32, + bool bEscapeQuotes) { + if (vChar32 == (char32_t)(char)vChar32) { + // Convert char32_t to char (if possible) + CMIUtilString str = + ConvertCharValueToPrintableASCII((char)vChar32, bEscapeQuotes); + if (str.length() > 0) + return str; + } + return Format("\\U%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8, + (vChar32 >> 24) & 0xff, (vChar32 >> 16) & 0xff, + (vChar32 >> 8) & 0xff, vChar32 & 0xff); } diff --git a/lldb/tools/lldb-mi/MIUtilString.h b/lldb/tools/lldb-mi/MIUtilString.h index 23261605f3d..3b077722f9a 100644 --- a/lldb/tools/lldb-mi/MIUtilString.h +++ b/lldb/tools/lldb-mi/MIUtilString.h @@ -10,77 +10,84 @@ #pragma once // Third party headers: -#include <string> -#include <vector> #include <cinttypes> #include <cstdarg> +#include <string> +#include <vector> // In-house headers: #include "MIDataTypes.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code utility class. Used to help handle text. // Derived from std::string //-- -class CMIUtilString : public std::string -{ - // Typedefs: - public: - typedef std::vector<CMIUtilString> VecString_t; +class CMIUtilString : public std::string { + // Typedefs: +public: + typedef std::vector<CMIUtilString> VecString_t; - // Static method: - public: - static CMIUtilString Format(const CMIUtilString vFormating, ...); - static CMIUtilString FormatBinary(const MIuint64 vnDecimal); - static CMIUtilString FormatValist(const CMIUtilString &vrFormating, va_list vArgs); - static bool IsAllValidAlphaAndNumeric(const char *vpText); - static bool Compare(const CMIUtilString &vrLhs, const CMIUtilString &vrRhs); - static CMIUtilString ConvertToPrintableASCII(const char vChar, bool bEscapeQuotes = false); - static CMIUtilString ConvertToPrintableASCII(const char16_t vChar16, bool bEscapeQuotes = false); - static CMIUtilString ConvertToPrintableASCII(const char32_t vChar32, bool bEscapeQuotes = false); + // Static method: +public: + static CMIUtilString Format(const CMIUtilString vFormating, ...); + static CMIUtilString FormatBinary(const MIuint64 vnDecimal); + static CMIUtilString FormatValist(const CMIUtilString &vrFormating, + va_list vArgs); + static bool IsAllValidAlphaAndNumeric(const char *vpText); + static bool Compare(const CMIUtilString &vrLhs, const CMIUtilString &vrRhs); + static CMIUtilString ConvertToPrintableASCII(const char vChar, + bool bEscapeQuotes = false); + static CMIUtilString ConvertToPrintableASCII(const char16_t vChar16, + bool bEscapeQuotes = false); + static CMIUtilString ConvertToPrintableASCII(const char32_t vChar32, + bool bEscapeQuotes = false); - // Methods: - public: - /* ctor */ CMIUtilString(); - /* ctor */ CMIUtilString(const char *vpData); - /* ctor */ CMIUtilString(const std::string& vrStr); - // - bool ExtractNumber(MIint64 &vwrNumber) const; - CMIUtilString FindAndReplace(const CMIUtilString &vFind, const CMIUtilString &vReplaceWith) const; - bool IsNumber() const; - bool IsHexadecimalNumber() const; - bool IsQuoted() const; - CMIUtilString RemoveRepeatedCharacters(const char vChar); - size_t Split(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits) const; - size_t SplitConsiderQuotes(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits) const; - size_t SplitLines(VecString_t &vwVecSplits) const; - CMIUtilString StripCREndOfLine() const; - CMIUtilString StripCRAll() const; - CMIUtilString Trim() const; - CMIUtilString Trim(const char vChar) const; - size_t FindFirst(const CMIUtilString &vrPattern, size_t vnPos = 0) const; - size_t FindFirst(const CMIUtilString &vrPattern, bool vbSkipQuotedText, bool &vrwbNotFoundClosedQuote, - size_t vnPos = 0) const; - size_t FindFirstNot(const CMIUtilString &vrPattern, size_t vnPos = 0) const; - CMIUtilString Escape(bool vbEscapeQuotes = false) const; - CMIUtilString AddSlashes() const; - CMIUtilString StripSlashes() const; - // - CMIUtilString &operator=(const char *vpRhs); - CMIUtilString &operator=(const std::string &vrRhs); + // Methods: +public: + /* ctor */ CMIUtilString(); + /* ctor */ CMIUtilString(const char *vpData); + /* ctor */ CMIUtilString(const std::string &vrStr); + // + bool ExtractNumber(MIint64 &vwrNumber) const; + CMIUtilString FindAndReplace(const CMIUtilString &vFind, + const CMIUtilString &vReplaceWith) const; + bool IsNumber() const; + bool IsHexadecimalNumber() const; + bool IsQuoted() const; + CMIUtilString RemoveRepeatedCharacters(const char vChar); + size_t Split(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits) const; + size_t SplitConsiderQuotes(const CMIUtilString &vDelimiter, + VecString_t &vwVecSplits) const; + size_t SplitLines(VecString_t &vwVecSplits) const; + CMIUtilString StripCREndOfLine() const; + CMIUtilString StripCRAll() const; + CMIUtilString Trim() const; + CMIUtilString Trim(const char vChar) const; + size_t FindFirst(const CMIUtilString &vrPattern, size_t vnPos = 0) const; + size_t FindFirst(const CMIUtilString &vrPattern, bool vbSkipQuotedText, + bool &vrwbNotFoundClosedQuote, size_t vnPos = 0) const; + size_t FindFirstNot(const CMIUtilString &vrPattern, size_t vnPos = 0) const; + CMIUtilString Escape(bool vbEscapeQuotes = false) const; + CMIUtilString AddSlashes() const; + CMIUtilString StripSlashes() const; + // + CMIUtilString &operator=(const char *vpRhs); + CMIUtilString &operator=(const std::string &vrRhs); - // Overrideable: - public: - /* dtor */ virtual ~CMIUtilString(); + // Overrideable: +public: + /* dtor */ virtual ~CMIUtilString(); - // Static method: - private: - static CMIUtilString FormatPriv(const CMIUtilString &vrFormat, va_list vArgs); - static CMIUtilString ConvertCharValueToPrintableASCII(char vChar, bool bEscapeQuotes); + // Static method: +private: + static CMIUtilString FormatPriv(const CMIUtilString &vrFormat, va_list vArgs); + static CMIUtilString ConvertCharValueToPrintableASCII(char vChar, + bool bEscapeQuotes); - // Methods: - private: - bool ExtractNumberFromHexadecimal(MIint64 &vwrNumber) const; - CMIUtilString RemoveRepeatedCharacters(size_t vnPos, const char vChar); - size_t FindFirstQuote(size_t vnPos) const; + // Methods: +private: + bool ExtractNumberFromHexadecimal(MIint64 &vwrNumber) const; + CMIUtilString RemoveRepeatedCharacters(size_t vnPos, const char vChar); + size_t FindFirstQuote(size_t vnPos) const; }; diff --git a/lldb/tools/lldb-mi/MIUtilThreadBaseStd.cpp b/lldb/tools/lldb-mi/MIUtilThreadBaseStd.cpp index fac0aa61729..85780083a5a 100644 --- a/lldb/tools/lldb-mi/MIUtilThreadBaseStd.cpp +++ b/lldb/tools/lldb-mi/MIUtilThreadBaseStd.cpp @@ -11,10 +11,11 @@ #include <assert.h> // In-house headers: -#include "MIUtilThreadBaseStd.h" #include "MICmnThreadMgrStd.h" +#include "MIUtilThreadBaseStd.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Constructor. // Type: None. // Args: None. @@ -22,25 +23,23 @@ // Throws: None. //-- CMIUtilThreadActiveObjBase::CMIUtilThreadActiveObjBase() - : m_references(0) - , m_bHasBeenKilled(false) -{ -} + : m_references(0), m_bHasBeenKilled(false) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Destructor. // Type: None. // Args: None. // Return: None. // Throws: None. //-- -CMIUtilThreadActiveObjBase::~CMIUtilThreadActiveObjBase() -{ - // Make sure our thread is not alive before we die - m_thread.Join(); +CMIUtilThreadActiveObjBase::~CMIUtilThreadActiveObjBase() { + // Make sure our thread is not alive before we die + m_thread.Join(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Check if an object is already running. // Type: Method. // Args: None. @@ -48,14 +47,13 @@ CMIUtilThreadActiveObjBase::~CMIUtilThreadActiveObjBase() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIUtilThreadActiveObjBase::ThreadIsActive() -{ - // Create a new thread to occupy this threads Run() function - return m_thread.IsActive(); +bool CMIUtilThreadActiveObjBase::ThreadIsActive() { + // Create a new thread to occupy this threads Run() function + return m_thread.IsActive(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Set up *this thread. // Type: Method. // Args: None. @@ -63,14 +61,13 @@ CMIUtilThreadActiveObjBase::ThreadIsActive() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIUtilThreadActiveObjBase::ThreadExecute() -{ - // Create a new thread to occupy this threads Run() function - return m_thread.Start(ThreadEntry, this); +bool CMIUtilThreadActiveObjBase::ThreadExecute() { + // Create a new thread to occupy this threads Run() function + return m_thread.Start(ThreadEntry, this); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Acquire a reference to CMIUtilThreadActiveObjBase. // Type: Method. // Args: None. @@ -78,19 +75,18 @@ CMIUtilThreadActiveObjBase::ThreadExecute() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIUtilThreadActiveObjBase::Acquire() -{ - // Access to this function is serial - CMIUtilThreadLock serial(m_mutex); +bool CMIUtilThreadActiveObjBase::Acquire() { + // Access to this function is serial + CMIUtilThreadLock serial(m_mutex); - // >0 == *this thread is alive - m_references++; + // >0 == *this thread is alive + m_references++; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release a reference to CMIUtilThreadActiveObjBase. // Type: Method. // Args: None. @@ -98,19 +94,18 @@ CMIUtilThreadActiveObjBase::Acquire() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIUtilThreadActiveObjBase::Release() -{ - // Access to this function is serial - CMIUtilThreadLock serial(m_mutex); +bool CMIUtilThreadActiveObjBase::Release() { + // Access to this function is serial + CMIUtilThreadLock serial(m_mutex); - // 0 == kill off *this thread - m_references--; + // 0 == kill off *this thread + m_references--; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Force this thread to stop, regardless of references // Type: Method. // Args: None. @@ -118,19 +113,18 @@ CMIUtilThreadActiveObjBase::Release() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIUtilThreadActiveObjBase::ThreadKill() -{ - // Access to this function is serial - CMIUtilThreadLock serial(m_mutex); +bool CMIUtilThreadActiveObjBase::ThreadKill() { + // Access to this function is serial + CMIUtilThreadLock serial(m_mutex); - // Set this thread to killed status - m_bHasBeenKilled = true; + // Set this thread to killed status + m_bHasBeenKilled = true; - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Proxy to thread join. // Type: Method. // Args: None. @@ -138,73 +132,69 @@ CMIUtilThreadActiveObjBase::ThreadKill() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIUtilThreadActiveObjBase::ThreadJoin() -{ - return m_thread.Join(); -} +bool CMIUtilThreadActiveObjBase::ThreadJoin() { return m_thread.Join(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: This function is the entry point of this object thread. // It is a trampoline to an instances operation manager. // Type: Static method. -// Args: vpThisClass - (R) From the system (our CMIUtilThreadActiveObjBase from the ctor). +// Args: vpThisClass - (R) From the system (our CMIUtilThreadActiveObjBase +// from the ctor). // Return: MIuint - 0 = success. // Throws: None. //-- -MIuint -CMIUtilThreadActiveObjBase::ThreadEntry(void *vpThisClass) -{ - // The argument is a pointer to a CMIUtilThreadActiveObjBase class - // as passed from the initialize function, so we can safely cast it. - assert(vpThisClass != nullptr); - CMIUtilThreadActiveObjBase *pActive = reinterpret_cast<CMIUtilThreadActiveObjBase *>(vpThisClass); - - // Start the management routine of this object - pActive->ThreadManage(); - - // Thread death - return 0; +MIuint CMIUtilThreadActiveObjBase::ThreadEntry(void *vpThisClass) { + // The argument is a pointer to a CMIUtilThreadActiveObjBase class + // as passed from the initialize function, so we can safely cast it. + assert(vpThisClass != nullptr); + CMIUtilThreadActiveObjBase *pActive = + reinterpret_cast<CMIUtilThreadActiveObjBase *>(vpThisClass); + + // Start the management routine of this object + pActive->ThreadManage(); + + // Thread death + return 0; } -//++ ------------------------------------------------------------------------------------ -// Details: This function forms a small management routine, to handle the thread's running. +//++ +//------------------------------------------------------------------------------------ +// Details: This function forms a small management routine, to handle the +// thread's running. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -void -CMIUtilThreadActiveObjBase::ThreadManage() -{ - bool bAlive = true; +void CMIUtilThreadActiveObjBase::ThreadManage() { + bool bAlive = true; - // Infinite loop - while (bAlive) + // Infinite loop + while (bAlive) { + // Scope the lock while we access m_isDying { - // Scope the lock while we access m_isDying - { - // Lock down access to the interface - CMIUtilThreadLock serial(m_mutex); - - // Quit the run loop if we are dying - if (m_references == 0) - break; - } - // Execute the run routine - if (!ThreadRun(bAlive)) - // Thread's run function failed (MIstatus::failure) - break; - - // We will die if we have been signaled to die - bAlive &= !m_bHasBeenKilled; + // Lock down access to the interface + CMIUtilThreadLock serial(m_mutex); + + // Quit the run loop if we are dying + if (m_references == 0) + break; } + // Execute the run routine + if (!ThreadRun(bAlive)) + // Thread's run function failed (MIstatus::failure) + break; + + // We will die if we have been signaled to die + bAlive &= !m_bHasBeenKilled; + } - // Execute the finish routine just before we die - // to give the object a chance to clean up - ThreadFinish(); + // Execute the finish routine just before we die + // to give the object a chance to clean up + ThreadFinish(); - m_thread.Finish(); + m_thread.Finish(); } //--------------------------------------------------------------------------------------- @@ -212,25 +202,20 @@ CMIUtilThreadActiveObjBase::ThreadManage() //--------------------------------------------------------------------------------------- // -CMIUtilThread::CMIUtilThread() - : m_pThread(nullptr) - , m_bIsActive(false) -{ -} +CMIUtilThread::CMIUtilThread() : m_pThread(nullptr), m_bIsActive(false) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilThread destructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMIUtilThread::~CMIUtilThread() -{ - Join(); -} +CMIUtilThread::~CMIUtilThread() { Join(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Wait for thread to stop. // Type: Method. // Args: None. @@ -238,56 +223,52 @@ CMIUtilThread::~CMIUtilThread() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIUtilThread::Join() -{ - if (m_pThread != nullptr) +bool CMIUtilThread::Join() { + if (m_pThread != nullptr) { + // Wait for this thread to die + m_pThread->join(); + + // Scope the thread lock while we modify the pointer { - // Wait for this thread to die - m_pThread->join(); - - // Scope the thread lock while we modify the pointer - { - CMIUtilThreadLock _lock(m_mutex); - delete m_pThread; - m_pThread = nullptr; - } + CMIUtilThreadLock _lock(m_mutex); + delete m_pThread; + m_pThread = nullptr; } + } - return MIstatus::success; + return MIstatus::success; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Is the thread doing work. // Type: Method. // Args: None. // Return: bool - True = Yes active, false = not active. // Throws: None. //-- -bool -CMIUtilThread::IsActive() -{ - // Lock while we access the thread status - CMIUtilThreadLock _lock(m_mutex); - return m_bIsActive; +bool CMIUtilThread::IsActive() { + // Lock while we access the thread status + CMIUtilThreadLock _lock(m_mutex); + return m_bIsActive; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Finish this thread // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -void -CMIUtilThread::Finish() -{ - // Lock while we access the thread status - CMIUtilThreadLock _lock(m_mutex); - m_bIsActive = false; +void CMIUtilThread::Finish() { + // Lock while we access the thread status + CMIUtilThreadLock _lock(m_mutex); + m_bIsActive = false; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Set up *this thread. // Type: Method. // Args: vpFn (R) - Function pointer to thread's main function. @@ -296,53 +277,46 @@ CMIUtilThread::Finish() // MIstatus::failure - Functional failed. // Throws: None. //-- -bool -CMIUtilThread::Start(FnThreadProc vpFn, void *vpArg) -{ - // Lock while we access the thread pointer and status - CMIUtilThreadLock _lock(m_mutex); +bool CMIUtilThread::Start(FnThreadProc vpFn, void *vpArg) { + // Lock while we access the thread pointer and status + CMIUtilThreadLock _lock(m_mutex); - // Create the std thread, which starts immediately and update its status - m_pThread = new std::thread(vpFn, vpArg); - m_bIsActive = true; + // Create the std thread, which starts immediately and update its status + m_pThread = new std::thread(vpFn, vpArg); + m_bIsActive = true; - // We expect to always be able to create one - assert(m_pThread != nullptr); + // We expect to always be able to create one + assert(m_pThread != nullptr); - return MIstatus::success; + return MIstatus::success; } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Take resource. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -void -CMIUtilThreadMutex::Lock() -{ - m_mutex.lock(); -} +void CMIUtilThreadMutex::Lock() { m_mutex.lock(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release resource. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -void -CMIUtilThreadMutex::Unlock() -{ - m_mutex.unlock(); -} +void CMIUtilThreadMutex::Unlock() { m_mutex.unlock(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Take resource if available. Immediately return in either case. // Type: Method. // Args: None. @@ -350,8 +324,4 @@ CMIUtilThreadMutex::Unlock() // False - mutex could not be locked. // Throws: None. //-- -bool -CMIUtilThreadMutex::TryLock() -{ - return m_mutex.try_lock(); -} +bool CMIUtilThreadMutex::TryLock() { return m_mutex.try_lock(); } diff --git a/lldb/tools/lldb-mi/MIUtilThreadBaseStd.h b/lldb/tools/lldb-mi/MIUtilThreadBaseStd.h index 738f295b657..cfff7d459b4 100644 --- a/lldb/tools/lldb-mi/MIUtilThreadBaseStd.h +++ b/lldb/tools/lldb-mi/MIUtilThreadBaseStd.h @@ -13,147 +13,132 @@ #ifdef _MSC_VER #include <eh.h> #endif // _MSC_VER -#include <thread> #include <mutex> +#include <thread> // In-house headers: #include "MIDataTypes.h" #include "MIUtilString.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code utility class. Handle thread mutual exclusion. // Embed Mutexes in your Active Object and then use them through Locks. //-- -class CMIUtilThreadMutex -{ - // Methods: - public: - /* ctor */ CMIUtilThreadMutex(){} - // - void - Lock(); // Wait until mutex can be obtained - void - Unlock(); // Release the mutex - bool - TryLock(); // Gain the lock if available - - // Overrideable: - public: - // From CMICmnBase - /* dtor */ virtual ~CMIUtilThreadMutex(){} - - // Attributes: - private: - std::recursive_mutex m_mutex; +class CMIUtilThreadMutex { + // Methods: +public: + /* ctor */ CMIUtilThreadMutex() {} + // + void Lock(); // Wait until mutex can be obtained + void Unlock(); // Release the mutex + bool TryLock(); // Gain the lock if available + + // Overrideable: +public: + // From CMICmnBase + /* dtor */ virtual ~CMIUtilThreadMutex() {} + + // Attributes: +private: + std::recursive_mutex m_mutex; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code utility class. Thread object. //-- -class CMIUtilThread -{ - // Typedef: - public: - typedef MIuint (*FnThreadProc)(void *vpThisClass); - - // Methods: - public: - /* ctor */ CMIUtilThread(); - // - bool - Start(FnThreadProc vpFn, void *vpArg); // Start execution of this thread - bool - Join(); // Wait for this thread to stop - bool - IsActive(); // Returns true if this thread is running - void - Finish(); // Finish this thread - - // Overrideable: - public: - /* dtor */ virtual ~CMIUtilThread(); - - // Methods: - private: - CMIUtilThreadMutex m_mutex; - std::thread *m_pThread; - bool m_bIsActive; +class CMIUtilThread { + // Typedef: +public: + typedef MIuint (*FnThreadProc)(void *vpThisClass); + + // Methods: +public: + /* ctor */ CMIUtilThread(); + // + bool Start(FnThreadProc vpFn, void *vpArg); // Start execution of this thread + bool Join(); // Wait for this thread to stop + bool IsActive(); // Returns true if this thread is running + void Finish(); // Finish this thread + + // Overrideable: +public: + /* dtor */ virtual ~CMIUtilThread(); + + // Methods: +private: + CMIUtilThreadMutex m_mutex; + std::thread *m_pThread; + bool m_bIsActive; }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code utility class. Base class for a worker thread active // object. Runs an 'captive thread'. //-- -class CMIUtilThreadActiveObjBase -{ - // Methods: - public: - /* ctor */ CMIUtilThreadActiveObjBase(); - // - bool - Acquire(); // Obtain a reference to this object - bool - Release(); // Release a reference to this object - bool - ThreadIsActive(); // Return true if this object is running - bool - ThreadJoin(); // Wait for this thread to stop running - bool - ThreadKill(); // Force this thread to stop, regardless of references - bool - ThreadExecute(); // Start this objects execution in another thread - void ThreadManage(); - - // Overrideable: - public: - /* dtor */ virtual ~CMIUtilThreadActiveObjBase(); - // - // Each thread object must supple a unique name that can be used to locate it - virtual const CMIUtilString &ThreadGetName() const = 0; - - // Statics: - protected: - static MIuint - ThreadEntry(void *vpThisClass); // Thread entry point - - // Overrideable: - protected: - virtual bool - ThreadRun(bool &vrIsAlive) = 0; // Call the main worker method - virtual bool - ThreadFinish() = 0; // Finish of what you were doing - - // Attributes: - protected: - volatile MIuint m_references; // Stores the current lifetime state of this thread, 0 = running, > 0 = shutting down - volatile bool m_bHasBeenKilled; // Set to true when this thread has been killed - CMIUtilThread m_thread; // The execution thread - CMIUtilThreadMutex - m_mutex; // This mutex allows us to safely communicate with this thread object across the interface from multiple threads +class CMIUtilThreadActiveObjBase { + // Methods: +public: + /* ctor */ CMIUtilThreadActiveObjBase(); + // + bool Acquire(); // Obtain a reference to this object + bool Release(); // Release a reference to this object + bool ThreadIsActive(); // Return true if this object is running + bool ThreadJoin(); // Wait for this thread to stop running + bool ThreadKill(); // Force this thread to stop, regardless of references + bool ThreadExecute(); // Start this objects execution in another thread + void ThreadManage(); + + // Overrideable: +public: + /* dtor */ virtual ~CMIUtilThreadActiveObjBase(); + // + // Each thread object must supple a unique name that can be used to locate it + virtual const CMIUtilString &ThreadGetName() const = 0; + + // Statics: +protected: + static MIuint ThreadEntry(void *vpThisClass); // Thread entry point + + // Overrideable: +protected: + virtual bool ThreadRun(bool &vrIsAlive) = 0; // Call the main worker method + virtual bool ThreadFinish() = 0; // Finish of what you were doing + + // Attributes: +protected: + volatile MIuint m_references; // Stores the current lifetime state of this + // thread, 0 = running, > 0 = shutting down + volatile bool + m_bHasBeenKilled; // Set to true when this thread has been killed + CMIUtilThread m_thread; // The execution thread + CMIUtilThreadMutex m_mutex; // This mutex allows us to safely communicate with + // this thread object across the interface from + // multiple threads }; -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code utility class. Handle thread resource locking. // Put Locks inside all the methods of your Active Object that access // data shared with the captive thread. //-- -class CMIUtilThreadLock -{ - // Methods: - public: - /* ctor */ - CMIUtilThreadLock(CMIUtilThreadMutex &vMutex) - : m_rMutex(vMutex) - { - m_rMutex.Lock(); - } - - // Overrideable: - public: - /* dtor */ - virtual ~CMIUtilThreadLock() { m_rMutex.Unlock(); } - - // Attributes: - private: - CMIUtilThreadMutex &m_rMutex; +class CMIUtilThreadLock { + // Methods: +public: + /* ctor */ + CMIUtilThreadLock(CMIUtilThreadMutex &vMutex) : m_rMutex(vMutex) { + m_rMutex.Lock(); + } + + // Overrideable: +public: + /* dtor */ + virtual ~CMIUtilThreadLock() { m_rMutex.Unlock(); } + + // Attributes: +private: + CMIUtilThreadMutex &m_rMutex; }; diff --git a/lldb/tools/lldb-mi/MIUtilVariant.cpp b/lldb/tools/lldb-mi/MIUtilVariant.cpp index c5e86433242..c317e3e687f 100644 --- a/lldb/tools/lldb-mi/MIUtilVariant.cpp +++ b/lldb/tools/lldb-mi/MIUtilVariant.cpp @@ -10,93 +10,94 @@ // In-house headers: #include "MIUtilVariant.h" -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CDataObjectBase constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMIUtilVariant::CDataObjectBase::CDataObjectBase() -{ -} +CMIUtilVariant::CDataObjectBase::CDataObjectBase() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CDataObjectBase copy constructor. // Type: Method. // Args: vrOther - (R) The other object. // Return: None. // Throws: None. //-- -CMIUtilVariant::CDataObjectBase::CDataObjectBase(const CDataObjectBase &vrOther) -{ - MIunused(vrOther); +CMIUtilVariant::CDataObjectBase::CDataObjectBase( + const CDataObjectBase &vrOther) { + MIunused(vrOther); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CDataObjectBase copy constructor. // Type: Method. // Args: vrOther - (R) The other object. // Return: None. // Throws: None. //-- -CMIUtilVariant::CDataObjectBase::CDataObjectBase(CDataObjectBase &vrOther) -{ - MIunused(vrOther); +CMIUtilVariant::CDataObjectBase::CDataObjectBase(CDataObjectBase &vrOther) { + MIunused(vrOther); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CDataObjectBase move constructor. // Type: Method. // Args: vrwOther - (R) The other object. // Return: None. // Throws: None. //-- -CMIUtilVariant::CDataObjectBase::CDataObjectBase(CDataObjectBase &&vrwOther) -{ - MIunused(vrwOther); +CMIUtilVariant::CDataObjectBase::CDataObjectBase(CDataObjectBase &&vrwOther) { + MIunused(vrwOther); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CDataObjectBase destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -CMIUtilVariant::CDataObjectBase::~CDataObjectBase() -{ - Destroy(); -} +CMIUtilVariant::CDataObjectBase::~CDataObjectBase() { Destroy(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CDataObjectBase copy assignment. // Type: Method. // Args: vrOther - (R) The other object. // Return: None. // Throws: None. //-- -CMIUtilVariant::CDataObjectBase &CMIUtilVariant::CDataObjectBase::operator=(const CDataObjectBase &vrOther) -{ - Copy(vrOther); - return *this; +CMIUtilVariant::CDataObjectBase &CMIUtilVariant::CDataObjectBase:: +operator=(const CDataObjectBase &vrOther) { + Copy(vrOther); + return *this; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CDataObjectBase move assignment. // Type: Method. // Args: vrwOther - (R) The other object. // Return: None. // Throws: None. //-- -CMIUtilVariant::CDataObjectBase &CMIUtilVariant::CDataObjectBase::operator=(CDataObjectBase &&vrwOther) -{ - Copy(vrwOther); - vrwOther.Destroy(); - return *this; +CMIUtilVariant::CDataObjectBase &CMIUtilVariant::CDataObjectBase:: +operator=(CDataObjectBase &&vrwOther) { + Copy(vrwOther); + vrwOther.Destroy(); + return *this; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Create a new copy of *this class. // Type: Overrideable. // Args: None. @@ -104,58 +105,56 @@ CMIUtilVariant::CDataObjectBase &CMIUtilVariant::CDataObjectBase::operator=(CDat // Throws: None. //-- CMIUtilVariant::CDataObjectBase * -CMIUtilVariant::CDataObjectBase::CreateCopyOfSelf() -{ - // Override to implement copying of variant's data object - return new CDataObjectBase(); +CMIUtilVariant::CDataObjectBase::CreateCopyOfSelf() { + // Override to implement copying of variant's data object + return new CDataObjectBase(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Determine if *this object is a derived from CDataObjectBase. // Type: Overrideable. // Args: None. -// Return: bool - True = *this is derived from CDataObjectBase, false = *this is instance of the this base class. +// Return: bool - True = *this is derived from CDataObjectBase, false = +// *this is instance of the this base class. // Throws: None. //-- -bool -CMIUtilVariant::CDataObjectBase::GetIsDerivedClass() const -{ - // Override to in the derived class and return true - return false; +bool CMIUtilVariant::CDataObjectBase::GetIsDerivedClass() const { + // Override to in the derived class and return true + return false; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Perform a bitwise copy of *this object. // Type: Overrideable. // Args: vrOther - (R) The other object. // Return: None. // Throws: None. //-- -void -CMIUtilVariant::CDataObjectBase::Copy(const CDataObjectBase &vrOther) -{ - // Override to implement - MIunused(vrOther); +void CMIUtilVariant::CDataObjectBase::Copy(const CDataObjectBase &vrOther) { + // Override to implement + MIunused(vrOther); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release any resources used by *this object. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- -void -CMIUtilVariant::CDataObjectBase::Destroy() -{ - // Do nothing - override to implement +void CMIUtilVariant::CDataObjectBase::Destroy() { + // Do nothing - override to implement } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CDataObject copy constructor. // Type: Method. // Args: T - The object's type. @@ -163,14 +162,15 @@ CMIUtilVariant::CDataObjectBase::Destroy() // Return: None. // Throws: None. //-- -template <typename T> CMIUtilVariant::CDataObject<T>::CDataObject(const CDataObject &vrOther) -{ - if (this == &vrOther) - return; - Copy(vrOther); +template <typename T> +CMIUtilVariant::CDataObject<T>::CDataObject(const CDataObject &vrOther) { + if (this == &vrOther) + return; + Copy(vrOther); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CDataObject copy constructor. // Type: Method. // Args: T - The object's type. @@ -178,14 +178,15 @@ template <typename T> CMIUtilVariant::CDataObject<T>::CDataObject(const CDataObj // Return: None. // Throws: None. //-- -template <typename T> CMIUtilVariant::CDataObject<T>::CDataObject(CDataObject &vrOther) -{ - if (this == &vrOther) - return; - Copy(vrOther); +template <typename T> +CMIUtilVariant::CDataObject<T>::CDataObject(CDataObject &vrOther) { + if (this == &vrOther) + return; + Copy(vrOther); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CDataObject move constructor. // Type: Method. // Args: T - The object's type. @@ -193,15 +194,16 @@ template <typename T> CMIUtilVariant::CDataObject<T>::CDataObject(CDataObject &v // Return: None. // Throws: None. //-- -template <typename T> CMIUtilVariant::CDataObject<T>::CDataObject(CDataObject &&vrwOther) -{ - if (this == &vrwOther) - return; - Copy(vrwOther); - vrwOther.Destroy(); +template <typename T> +CMIUtilVariant::CDataObject<T>::CDataObject(CDataObject &&vrwOther) { + if (this == &vrwOther) + return; + Copy(vrwOther); + vrwOther.Destroy(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CDataObject copy assignment. // Type: Method. // Args: T - The object's type. @@ -209,15 +211,17 @@ template <typename T> CMIUtilVariant::CDataObject<T>::CDataObject(CDataObject && // Return: None. // Throws: None. //-- -template <typename T> CMIUtilVariant::CDataObject<T> &CMIUtilVariant::CDataObject<T>::operator=(const CDataObject &vrOther) -{ - if (this == &vrOther) - return *this; - Copy(vrOther); +template <typename T> +CMIUtilVariant::CDataObject<T> &CMIUtilVariant::CDataObject<T>:: +operator=(const CDataObject &vrOther) { + if (this == &vrOther) return *this; + Copy(vrOther); + return *this; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CDataObject move assignment. // Type: Method. // Args: T - The object's type. @@ -225,32 +229,32 @@ template <typename T> CMIUtilVariant::CDataObject<T> &CMIUtilVariant::CDataObjec // Return: None. // Throws: None. //-- -template <typename T> CMIUtilVariant::CDataObject<T> &CMIUtilVariant::CDataObject<T>::operator=(CDataObject &&vrwOther) -{ - if (this == &vrwOther) - return *this; - Copy(vrwOther); - vrwOther.Destroy(); +template <typename T> +CMIUtilVariant::CDataObject<T> &CMIUtilVariant::CDataObject<T>:: +operator=(CDataObject &&vrwOther) { + if (this == &vrwOther) return *this; + Copy(vrwOther); + vrwOther.Destroy(); + return *this; } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilVariant constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMIUtilVariant::CMIUtilVariant() - : m_pDataObject(nullptr) -{ -} +CMIUtilVariant::CMIUtilVariant() : m_pDataObject(nullptr) {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilVariant copy constructor. // Type: Method. // Args: vrOther - (R) The other object. @@ -258,15 +262,15 @@ CMIUtilVariant::CMIUtilVariant() // Throws: None. //-- CMIUtilVariant::CMIUtilVariant(const CMIUtilVariant &vrOther) - : m_pDataObject(nullptr) -{ - if (this == &vrOther) - return; + : m_pDataObject(nullptr) { + if (this == &vrOther) + return; - Copy(vrOther); + Copy(vrOther); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilVariant copy constructor. // Type: Method. // Args: vrOther - (R) The other object. @@ -274,15 +278,15 @@ CMIUtilVariant::CMIUtilVariant(const CMIUtilVariant &vrOther) // Throws: None. //-- CMIUtilVariant::CMIUtilVariant(CMIUtilVariant &vrOther) - : m_pDataObject(nullptr) -{ - if (this == &vrOther) - return; + : m_pDataObject(nullptr) { + if (this == &vrOther) + return; - Copy(vrOther); + Copy(vrOther); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilVariant move constructor. // Type: Method. // Args: vrwOther - (R) The other object. @@ -290,89 +294,83 @@ CMIUtilVariant::CMIUtilVariant(CMIUtilVariant &vrOther) // Throws: None. //-- CMIUtilVariant::CMIUtilVariant(CMIUtilVariant &&vrwOther) - : m_pDataObject(nullptr) -{ - if (this == &vrwOther) - return; + : m_pDataObject(nullptr) { + if (this == &vrwOther) + return; - Copy(vrwOther); - vrwOther.Destroy(); + Copy(vrwOther); + vrwOther.Destroy(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilVariant destructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -CMIUtilVariant::~CMIUtilVariant() -{ - Destroy(); -} +CMIUtilVariant::~CMIUtilVariant() { Destroy(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilVariant copy assignment. // Type: Method. // Args: vrOther - (R) The other object. // Return: None. // Throws: None. //-- -CMIUtilVariant &CMIUtilVariant::operator=(const CMIUtilVariant &vrOther) -{ - if (this == &vrOther) - return *this; - - Copy(vrOther); +CMIUtilVariant &CMIUtilVariant::operator=(const CMIUtilVariant &vrOther) { + if (this == &vrOther) return *this; + + Copy(vrOther); + return *this; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CMIUtilVariant move assignment. // Type: Method. // Args: vrwOther - (R) The other object. // Return: None. // Throws: None. //-- -CMIUtilVariant &CMIUtilVariant::operator=(CMIUtilVariant &&vrwOther) -{ - if (this == &vrwOther) - return *this; - - Copy(vrwOther); - vrwOther.Destroy(); +CMIUtilVariant &CMIUtilVariant::operator=(CMIUtilVariant &&vrwOther) { + if (this == &vrwOther) return *this; + + Copy(vrwOther); + vrwOther.Destroy(); + return *this; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release the resources used by *this object. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- -void -CMIUtilVariant::Destroy() -{ - if (m_pDataObject != nullptr) - delete m_pDataObject; - m_pDataObject = nullptr; +void CMIUtilVariant::Destroy() { + if (m_pDataObject != nullptr) + delete m_pDataObject; + m_pDataObject = nullptr; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Bitwise copy another data object to *this variant object. // Type: Method. // Args: vrOther - (R) The other object. // Return: None. // Throws: None. //-- -void -CMIUtilVariant::Copy(const CMIUtilVariant &vrOther) -{ - Destroy(); - - if (vrOther.m_pDataObject != nullptr) - { - m_pDataObject = vrOther.m_pDataObject->CreateCopyOfSelf(); - } +void CMIUtilVariant::Copy(const CMIUtilVariant &vrOther) { + Destroy(); + + if (vrOther.m_pDataObject != nullptr) { + m_pDataObject = vrOther.m_pDataObject->CreateCopyOfSelf(); + } } diff --git a/lldb/tools/lldb-mi/MIUtilVariant.h b/lldb/tools/lldb-mi/MIUtilVariant.h index 7fddb9ffda2..01dd615aad6 100644 --- a/lldb/tools/lldb-mi/MIUtilVariant.h +++ b/lldb/tools/lldb-mi/MIUtilVariant.h @@ -12,128 +12,127 @@ // In-house headers: #include "MIDataTypes.h" -//++ ============================================================================ +//++ +//============================================================================ // Details: MI common code utility class. The class implements behaviour of a // variant object which holds any data object of type T. A copy of the // data object specified is made and stored in *this wrapper. When the // *this object is destroyed the data object hold within calls its // destructor should it have one. //-- -class CMIUtilVariant -{ - // Methods: - public: - /* ctor */ CMIUtilVariant(); - /* ctor */ CMIUtilVariant(const CMIUtilVariant &vrOther); - /* ctor */ CMIUtilVariant(CMIUtilVariant &vrOther); - /* ctor */ CMIUtilVariant(CMIUtilVariant &&vrwOther); - /* dtor */ ~CMIUtilVariant(); - - template <typename T> void Set(const T &vArg); - template <typename T> T *Get() const; +class CMIUtilVariant { + // Methods: +public: + /* ctor */ CMIUtilVariant(); + /* ctor */ CMIUtilVariant(const CMIUtilVariant &vrOther); + /* ctor */ CMIUtilVariant(CMIUtilVariant &vrOther); + /* ctor */ CMIUtilVariant(CMIUtilVariant &&vrwOther); + /* dtor */ ~CMIUtilVariant(); - CMIUtilVariant &operator=(const CMIUtilVariant &vrOther); - CMIUtilVariant &operator=(CMIUtilVariant &&vrwOther); - - // Classes: - private: - //++ ---------------------------------------------------------------------- - // Details: Base class wrapper to hold the variant's data object when - // assigned to it by the Set() function. Do not use the CDataObjectBase - // to create objects, use only CDataObjectBase derived objects, - // see CDataObject() class. - //-- - class CDataObjectBase - { - // Methods: - public: - /* ctor */ CDataObjectBase(); - /* ctor */ CDataObjectBase(const CDataObjectBase &vrOther); - /* ctor */ CDataObjectBase(CDataObjectBase &vrOther); - /* ctor */ CDataObjectBase(CDataObjectBase &&vrwOther); - // - CDataObjectBase &operator=(const CDataObjectBase &vrOther); - CDataObjectBase &operator=(CDataObjectBase &&vrwOther); + template <typename T> void Set(const T &vArg); + template <typename T> T *Get() const; - // Overrideable: - public: - virtual ~CDataObjectBase(); - virtual CDataObjectBase *CreateCopyOfSelf(); - virtual bool GetIsDerivedClass() const; + CMIUtilVariant &operator=(const CMIUtilVariant &vrOther); + CMIUtilVariant &operator=(CMIUtilVariant &&vrwOther); - // Overrideable: - protected: - virtual void Copy(const CDataObjectBase &vrOther); - virtual void Destroy(); - }; + // Classes: +private: + //++ ---------------------------------------------------------------------- + // Details: Base class wrapper to hold the variant's data object when + // assigned to it by the Set() function. Do not use the + // CDataObjectBase + // to create objects, use only CDataObjectBase derived objects, + // see CDataObject() class. + //-- + class CDataObjectBase { + // Methods: + public: + /* ctor */ CDataObjectBase(); + /* ctor */ CDataObjectBase(const CDataObjectBase &vrOther); + /* ctor */ CDataObjectBase(CDataObjectBase &vrOther); + /* ctor */ CDataObjectBase(CDataObjectBase &&vrwOther); + // + CDataObjectBase &operator=(const CDataObjectBase &vrOther); + CDataObjectBase &operator=(CDataObjectBase &&vrwOther); - //++ ---------------------------------------------------------------------- - // Details: Derived from CDataObjectBase, this class is the wrapper for the - // data object as it has an aggregate of type T which is a copy - // of the data object assigned to the variant object. - //-- - template <typename T> class CDataObject : public CDataObjectBase - { - // Methods: - public: - /* ctor */ CDataObject(); - /* ctor */ CDataObject(const T &vArg); - /* ctor */ CDataObject(const CDataObject &vrOther); - /* ctor */ CDataObject(CDataObject &vrOther); - /* ctor */ CDataObject(CDataObject &&vrwOther); - // - CDataObject &operator=(const CDataObject &vrOther); - CDataObject &operator=(CDataObject &&vrwOther); - // - T &GetDataObject(); + // Overrideable: + public: + virtual ~CDataObjectBase(); + virtual CDataObjectBase *CreateCopyOfSelf(); + virtual bool GetIsDerivedClass() const; - // Overridden: - public: - // From CDataObjectBase - ~CDataObject() override; - CDataObjectBase *CreateCopyOfSelf() override; - bool GetIsDerivedClass() const override; + // Overrideable: + protected: + virtual void Copy(const CDataObjectBase &vrOther); + virtual void Destroy(); + }; - // Overrideable: - private: - virtual void Duplicate(const CDataObject &vrOther); + //++ ---------------------------------------------------------------------- + // Details: Derived from CDataObjectBase, this class is the wrapper for the + // data object as it has an aggregate of type T which is a copy + // of the data object assigned to the variant object. + //-- + template <typename T> class CDataObject : public CDataObjectBase { + // Methods: + public: + /* ctor */ CDataObject(); + /* ctor */ CDataObject(const T &vArg); + /* ctor */ CDataObject(const CDataObject &vrOther); + /* ctor */ CDataObject(CDataObject &vrOther); + /* ctor */ CDataObject(CDataObject &&vrwOther); + // + CDataObject &operator=(const CDataObject &vrOther); + CDataObject &operator=(CDataObject &&vrwOther); + // + T &GetDataObject(); - // Overridden: - private: - // From CDataObjectBase - void Destroy() override; + // Overridden: + public: + // From CDataObjectBase + ~CDataObject() override; + CDataObjectBase *CreateCopyOfSelf() override; + bool GetIsDerivedClass() const override; - // Attributes: - private: - T m_dataObj; - }; + // Overrideable: + private: + virtual void Duplicate(const CDataObject &vrOther); - // Methods + // Overridden: private: - void Destroy(); - void Copy(const CMIUtilVariant &vrOther); + // From CDataObjectBase + void Destroy() override; // Attributes: private: - CDataObjectBase *m_pDataObject; + T m_dataObj; + }; + + // Methods +private: + void Destroy(); + void Copy(const CMIUtilVariant &vrOther); + + // Attributes: +private: + CDataObjectBase *m_pDataObject; }; //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CDataObject constructor. // Type: Method. // Args: T - The object's type. // Return: None. // Throws: None. //-- -template <typename T> CMIUtilVariant::CDataObject<T>::CDataObject() -{ -} +template <typename T> CMIUtilVariant::CDataObject<T>::CDataObject() {} -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CDataObject constructor. // Type: Method. // Args: T - The object's type. @@ -141,38 +140,37 @@ template <typename T> CMIUtilVariant::CDataObject<T>::CDataObject() // Return: None. // Throws: None. //-- -template <typename T> CMIUtilVariant::CDataObject<T>::CDataObject(const T &vArg) -{ - m_dataObj = vArg; +template <typename T> +CMIUtilVariant::CDataObject<T>::CDataObject(const T &vArg) { + m_dataObj = vArg; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: CDataObject destructor. // Type: Overridden. // Args: T - The object's type. // Return: None. // Throws: None. //-- -template <typename T> CMIUtilVariant::CDataObject<T>::~CDataObject() -{ - Destroy(); +template <typename T> CMIUtilVariant::CDataObject<T>::~CDataObject() { + Destroy(); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the data object hold by *this object wrapper. // Type: Method. // Args: T - The object's type. // Return: T & - Reference to the data object. // Throws: None. //-- -template <typename T> -T & -CMIUtilVariant::CDataObject<T>::GetDataObject() -{ - return m_dataObj; +template <typename T> T &CMIUtilVariant::CDataObject<T>::GetDataObject() { + return m_dataObj; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Create a new copy of *this class. // Type: Overridden. // Args: T - The object's type. @@ -181,14 +179,14 @@ CMIUtilVariant::CDataObject<T>::GetDataObject() //-- template <typename T> CMIUtilVariant::CDataObjectBase * -CMIUtilVariant::CDataObject<T>::CreateCopyOfSelf() -{ - CDataObject *pCopy = new CDataObject<T>(m_dataObj); +CMIUtilVariant::CDataObject<T>::CreateCopyOfSelf() { + CDataObject *pCopy = new CDataObject<T>(m_dataObj); - return pCopy; + return pCopy; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Determine if *this object is a derived from CDataObjectBase. // Type: Overridden. // Args: T - The object's type. @@ -197,13 +195,12 @@ CMIUtilVariant::CDataObject<T>::CreateCopyOfSelf() // Throws: None. //-- template <typename T> -bool -CMIUtilVariant::CDataObject<T>::GetIsDerivedClass() const -{ - return true; +bool CMIUtilVariant::CDataObject<T>::GetIsDerivedClass() const { + return true; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Perform a bitwise copy of *this object. // Type: Overrideable. // Args: T - The object's type. @@ -212,32 +209,29 @@ CMIUtilVariant::CDataObject<T>::GetIsDerivedClass() const // Throws: None. //-- template <typename T> -void -CMIUtilVariant::CDataObject<T>::Duplicate(const CDataObject &vrOther) -{ - CDataObjectBase::Copy(vrOther); - m_dataObj = vrOther.m_dataObj; +void CMIUtilVariant::CDataObject<T>::Duplicate(const CDataObject &vrOther) { + CDataObjectBase::Copy(vrOther); + m_dataObj = vrOther.m_dataObj; } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Release any resources used by *this object. // Type: Overridden. // Args: None. // Return: None. // Throws: None. //-- -template <typename T> -void -CMIUtilVariant::CDataObject<T>::Destroy() -{ - CDataObjectBase::Destroy(); +template <typename T> void CMIUtilVariant::CDataObject<T>::Destroy() { + CDataObjectBase::Destroy(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Assign to the variant an object of a specified type. // Type: Template method. // Args: T - The object's type. @@ -245,30 +239,26 @@ CMIUtilVariant::CDataObject<T>::Destroy() // Return: None. // Throws: None. //-- -template <typename T> -void -CMIUtilVariant::Set(const T &vArg) -{ - m_pDataObject = new CDataObject<T>(vArg); +template <typename T> void CMIUtilVariant::Set(const T &vArg) { + m_pDataObject = new CDataObject<T>(vArg); } -//++ ------------------------------------------------------------------------------------ +//++ +//------------------------------------------------------------------------------------ // Details: Retrieve the data object from *this variant. // Type: Template method. // Args: T - The object's type. -// Return: T * - Pointer the data object, NULL = data object not assigned to *this variant. +// Return: T * - Pointer the data object, NULL = data object not assigned to +// *this variant. // Throws: None. //-- -template <typename T> -T * -CMIUtilVariant::Get() const -{ - if ((m_pDataObject != nullptr) && m_pDataObject->GetIsDerivedClass()) - { - CDataObject<T> *pDataObj = static_cast<CDataObject<T> *>(m_pDataObject); - return &pDataObj->GetDataObject(); - } +template <typename T> T *CMIUtilVariant::Get() const { + if ((m_pDataObject != nullptr) && m_pDataObject->GetIsDerivedClass()) { + CDataObject<T> *pDataObj = static_cast<CDataObject<T> *>(m_pDataObject); + return &pDataObj->GetDataObject(); + } - // Do not use a CDataObjectBase object, use only CDataObjectBase derived objects - return nullptr; + // Do not use a CDataObjectBase object, use only CDataObjectBase derived + // objects + return nullptr; } diff --git a/lldb/tools/lldb-mi/Platform.h b/lldb/tools/lldb-mi/Platform.h index 9db8f7a156c..42f8e2ff29d 100644 --- a/lldb/tools/lldb-mi/Platform.h +++ b/lldb/tools/lldb-mi/Platform.h @@ -10,23 +10,21 @@ #if defined(_MSC_VER) -#include <io.h> #include <eh.h> #include <inttypes.h> -#include <signal.h> -#include <lldb/Host/windows/Windows.h> +#include <io.h> #include <lldb/Host/HostGetOpt.h> +#include <lldb/Host/windows/Windows.h> +#include <signal.h> // This is not used by MI -struct timeval -{ - long tv_sec; - long tv_usec; +struct timeval { + long tv_sec; + long tv_usec; }; -struct winsize -{ - long ws_col; +struct winsize { + long ws_col; }; typedef unsigned char cc_t; @@ -43,16 +41,15 @@ typedef unsigned int tcflag_t; #define TCSANOW 0 #define NCCS 32 -struct termios -{ - tcflag_t c_iflag; // input mode flags - tcflag_t c_oflag; // output mode flags - tcflag_t c_cflag; // control mode flags - tcflag_t c_lflag; // local mode flags - cc_t c_line; // line discipline - cc_t c_cc[NCCS]; // control characters - speed_t c_ispeed; // input speed - speed_t c_ospeed; // output speed +struct termios { + tcflag_t c_iflag; // input mode flags + tcflag_t c_oflag; // output mode flags + tcflag_t c_cflag; // control mode flags + tcflag_t c_lflag; // local mode flags + cc_t c_line; // line discipline + cc_t c_cc[NCCS]; // control characters + speed_t c_ispeed; // input speed + speed_t c_ospeed; // output speed }; typedef long pid_t; @@ -63,7 +60,8 @@ typedef long pid_t; extern int ioctl(int d, int request, ...); extern int kill(pid_t pid, int sig); -extern int tcsetattr(int fd, int optional_actions, const struct termios *termios_p); +extern int tcsetattr(int fd, int optional_actions, + const struct termios *termios_p); extern int tcgetattr(int fildes, struct termios *termios_p); // signal handler function pointer type @@ -71,13 +69,13 @@ typedef void (*sighandler_t)(int); // CODETAG_IOR_SIGNALS // signal.h -#define SIGQUIT 3 // Terminal quit signal -#define SIGKILL 9 // Kill (cannot be caught or ignored) -#define SIGPIPE 13 // Write on a pipe with no one to read it -#define SIGCONT 18 // Continue executing, if stopped. -#define SIGTSTP 20 // Terminal stop signal -#define SIGSTOP 23 // Stop executing (cannot be caught or ignored) -#define SIGWINCH 28 // (== SIGVTALRM) +#define SIGQUIT 3 // Terminal quit signal +#define SIGKILL 9 // Kill (cannot be caught or ignored) +#define SIGPIPE 13 // Write on a pipe with no one to read it +#define SIGCONT 18 // Continue executing, if stopped. +#define SIGTSTP 20 // Terminal stop signal +#define SIGSTOP 23 // Stop executing (cannot be caught or ignored) +#define SIGWINCH 28 // (== SIGVTALRM) #else diff --git a/lldb/tools/lldb-perf/common/clang/lldb_perf_clang.cpp b/lldb/tools/lldb-perf/common/clang/lldb_perf_clang.cpp index ac9481c366e..ccd7601a5b8 100644 --- a/lldb/tools/lldb-perf/common/clang/lldb_perf_clang.cpp +++ b/lldb/tools/lldb-perf/common/clang/lldb_perf_clang.cpp @@ -7,107 +7,99 @@ // //===----------------------------------------------------------------------===// -#include "lldb-perf/lib/Timer.h" -#include "lldb-perf/lib/Metric.h" #include "lldb-perf/lib/Measurement.h" +#include "lldb-perf/lib/Metric.h" #include "lldb-perf/lib/Results.h" #include "lldb-perf/lib/TestCase.h" +#include "lldb-perf/lib/Timer.h" #include "lldb-perf/lib/Xcode.h" #include "llvm/ADT/STLExtras.h" -#include <iostream> -#include <unistd.h> #include <fstream> #include <getopt.h> +#include <iostream> +#include <unistd.h> using namespace lldb_perf; #define NUM_EXPR_ITERATIONS 3 -class ClangTest : public TestCase -{ +class ClangTest : public TestCase { public: - ClangTest () : - TestCase(), - m_time_create_target ([this] () -> void - { - m_memory_change_create_target.Start(); - m_target = m_debugger.CreateTarget(m_exe_path.c_str()); - m_memory_change_create_target.Stop(); - }, "time-create-target", "The time it takes to create a target."), - m_time_set_bp_main([this] () -> void - { - m_memory_change_break_main.Start(); - m_target.BreakpointCreateByName("main"); - m_memory_change_break_main.Stop(); - }, "time-set-break-main", "Elapsed time it takes to set a breakpoint at 'main' by name."), - m_memory_change_create_target (), - m_memory_change_break_main (), - m_memory_total (), - m_time_launch_stop_main(), - m_time_total (), - m_expr_first_evaluate([this] (SBFrame frame) -> void - { - frame.EvaluateExpression("Diags.DiagArgumentsStr[0].size()").GetError(); - }, "time-expr", "Elapsed time it takes to evaluate an expression for the first time."), - m_expr_frame_zero ([this] (SBFrame frame) -> void - { - frame.EvaluateExpression("Diags.DiagArgumentsStr[0].size()").GetError(); - }, "time-expr-frame-zero", "Elapsed time it takes to evaluate an expression 3 times at frame zero."), - m_expr_frame_non_zero ([this] (SBFrame frame) -> void - { - frame.EvaluateExpression("Diags.DiagArgumentsStr[0].size()").GetError(); - }, "time-expr-frame-non-zero", "Elapsed time it takes to evaluate an expression 3 times at a non-zero frame."), - m_exe_path(), - m_out_path(), - m_launch_info (NULL), - m_use_dsym (false) - { - } - - virtual - ~ClangTest () - { - } - - virtual bool - Setup (int& argc, const char**& argv) - { - if (m_exe_path.empty()) - return false; - m_launch_info.SetArguments(argv, false); - return true; - } - - void - DoTest () - { - } - - virtual void - TestStep (int counter, ActionWanted &next_action) - { - char temp_source_path[PATH_MAX] = "/tmp/main.XXXXXX.cpp"; - - switch (counter) - { - case 0: - { - //Xcode::RunCommand(m_debugger,"log enable -f /tmp/packets.txt gdb-remote packets",true); - - m_memory_total.Start(); - m_time_total.Start(); - - // Time creating the target - m_time_create_target(); - - m_time_set_bp_main(); - - int fd = mkstemps(temp_source_path, 4); - - if (fd >= 0) - { - const char *source_content = R"( -#include <stdio.h> + ClangTest() + : TestCase(), + m_time_create_target( + [this]() -> void { + m_memory_change_create_target.Start(); + m_target = m_debugger.CreateTarget(m_exe_path.c_str()); + m_memory_change_create_target.Stop(); + }, + "time-create-target", "The time it takes to create a target."), + m_time_set_bp_main( + [this]() -> void { + m_memory_change_break_main.Start(); + m_target.BreakpointCreateByName("main"); + m_memory_change_break_main.Stop(); + }, + "time-set-break-main", + "Elapsed time it takes to set a breakpoint at 'main' by name."), + m_memory_change_create_target(), m_memory_change_break_main(), + m_memory_total(), m_time_launch_stop_main(), m_time_total(), + m_expr_first_evaluate( + [this](SBFrame frame) -> void { + frame.EvaluateExpression("Diags.DiagArgumentsStr[0].size()") + .GetError(); + }, + "time-expr", "Elapsed time it takes to evaluate an expression for " + "the first time."), + m_expr_frame_zero( + [this](SBFrame frame) -> void { + frame.EvaluateExpression("Diags.DiagArgumentsStr[0].size()") + .GetError(); + }, + "time-expr-frame-zero", "Elapsed time it takes to evaluate an " + "expression 3 times at frame zero."), + m_expr_frame_non_zero( + [this](SBFrame frame) -> void { + frame.EvaluateExpression("Diags.DiagArgumentsStr[0].size()") + .GetError(); + }, + "time-expr-frame-non-zero", "Elapsed time it takes to evaluate an " + "expression 3 times at a non-zero " + "frame."), + m_exe_path(), m_out_path(), m_launch_info(NULL), m_use_dsym(false) {} + + virtual ~ClangTest() {} + + virtual bool Setup(int &argc, const char **&argv) { + if (m_exe_path.empty()) + return false; + m_launch_info.SetArguments(argv, false); + return true; + } + + void DoTest() {} + + virtual void TestStep(int counter, ActionWanted &next_action) { + char temp_source_path[PATH_MAX] = "/tmp/main.XXXXXX.cpp"; + + switch (counter) { + case 0: { + // Xcode::RunCommand(m_debugger,"log enable -f /tmp/packets.txt gdb-remote + // packets",true); + + m_memory_total.Start(); + m_time_total.Start(); + + // Time creating the target + m_time_create_target(); + + m_time_set_bp_main(); + + int fd = mkstemps(temp_source_path, 4); + + if (fd >= 0) { + const char *source_content = R"( #include <stdint.h> +#include <stdio.h> #include <vector> namespace { @@ -132,331 +124,299 @@ int main (int argc, char const *argv[], char const *envp[]) return 0; } )"; - write (fd, source_content, strlen(source_content)); - close(fd); - } - else - { - const char *error_cstr = strerror(errno); - fprintf (stderr, "error: failed to created temporary source file: '%s' (%s)", temp_source_path, error_cstr); - exit(2); - } - - m_time_launch_stop_main.Start(); - const char *clang_argv[] = { - "-cc1", - "-triple", "x86_64-apple-macosx10.8.0", - "-emit-obj", - "-mrelax-all", - "-disable-free", - "-disable-llvm-verifier", - "-main-file-name", "main.cpp", - "-mrelocation-model", "pic", - "-pic-level", "2", - "-mdisable-fp-elim", - "-masm-verbose", - "-munwind-tables", - "-target-cpu", "core2", - "-target-linker-version", "132.10.1", - "-v", - "-g", - "-O0", - "-fdeprecated-macro", - "-ferror-limit", "19", - "-fmessage-length", "298", - "-stack-protector", "1", - "-mstackrealign", - "-fblocks", - "-fobjc-runtime=macosx-10.8.0", - "-fobjc-dispatch-method=mixed", - "-fencode-extended-block-signature", - "-fcxx-exceptions", - "-fexceptions", - "-fdiagnostics-show-option", - "-fcolor-diagnostics", - "-backend-option", - "-vectorize-loops", - "-o", "/tmp/main.o", - "-x", "c++", - NULL, - NULL }; - clang_argv[llvm::array_lengthof(clang_argv)-2] = temp_source_path; - SBLaunchInfo launch_info(clang_argv); - Launch (launch_info); - next_action.None(); // Don't continue or do anything, just wait for next event... - } - break; - case 1: - { - m_time_launch_stop_main.Stop(); - m_time_total.Stop(); - SBFrame frame (m_thread.GetFrameAtIndex(0)); - - // Time the first expression evaluation - m_expr_first_evaluate(frame); - - SBValue result; - for (size_t i=0; i<NUM_EXPR_ITERATIONS; ++i) - { - m_expr_frame_zero(frame); - } - m_target.BreakpointCreateByName("DeclContext::lookup"); - next_action.Continue(); - } - break; - case 2: - { - SBFrame frame (m_thread.GetFrameAtIndex(21)); - SBValue result; - for (size_t i=0; i<NUM_EXPR_ITERATIONS; ++i) - { - m_expr_frame_non_zero(frame); - } - next_action.Continue(); - } - break; - default: - m_memory_total.Stop(); - next_action.Kill(); - break; - } - } - - void - WriteResults (Results &results) - { - Results::Dictionary& results_dict = results.GetDictionary(); - - m_time_set_bp_main.WriteAverageAndStandardDeviation(results); - results_dict.Add ("memory-change-create-target", - "Memory increase that occurs due to creating the target.", - m_memory_change_create_target.GetDeltaValue().GetResult(NULL, NULL)); - - results_dict.Add ("memory-change-break-main", - "Memory increase that occurs due to setting a breakpoint at main by name.", - m_memory_change_break_main.GetDeltaValue().GetResult(NULL, NULL)); - - m_time_create_target.WriteAverageAndStandardDeviation(results); - m_expr_first_evaluate.WriteAverageAndStandardDeviation(results); - m_expr_frame_zero.WriteAverageAndStandardDeviation(results); - m_expr_frame_non_zero.WriteAverageAndStandardDeviation(results); - results_dict.Add ("memory-total-break-main", - "The total memory that the current process is using after setting the first breakpoint.", - m_memory_total.GetStopValue().GetResult(NULL, NULL)); - - results_dict.AddDouble("time-launch-stop-main", - "The time it takes to launch the process and stop at main.", - m_time_launch_stop_main.GetDeltaValue()); - - results_dict.AddDouble("time-total", - "The time it takes to create the target, set breakpoint at main, launch clang and hit the breakpoint at main.", - m_time_total.GetDeltaValue()); - results.Write(GetResultFilePath()); - } - - - - const char * - GetExecutablePath () const - { - if (m_exe_path.empty()) - return NULL; - return m_exe_path.c_str(); - } - - const char * - GetResultFilePath () const - { - if (m_out_path.empty()) - return NULL; - return m_out_path.c_str(); + write(fd, source_content, strlen(source_content)); + close(fd); + } else { + const char *error_cstr = strerror(errno); + fprintf(stderr, + "error: failed to created temporary source file: '%s' (%s)", + temp_source_path, error_cstr); + exit(2); + } + + m_time_launch_stop_main.Start(); + const char *clang_argv[] = {"-cc1", + "-triple", + "x86_64-apple-macosx10.8.0", + "-emit-obj", + "-mrelax-all", + "-disable-free", + "-disable-llvm-verifier", + "-main-file-name", + "main.cpp", + "-mrelocation-model", + "pic", + "-pic-level", + "2", + "-mdisable-fp-elim", + "-masm-verbose", + "-munwind-tables", + "-target-cpu", + "core2", + "-target-linker-version", + "132.10.1", + "-v", + "-g", + "-O0", + "-fdeprecated-macro", + "-ferror-limit", + "19", + "-fmessage-length", + "298", + "-stack-protector", + "1", + "-mstackrealign", + "-fblocks", + "-fobjc-runtime=macosx-10.8.0", + "-fobjc-dispatch-method=mixed", + "-fencode-extended-block-signature", + "-fcxx-exceptions", + "-fexceptions", + "-fdiagnostics-show-option", + "-fcolor-diagnostics", + "-backend-option", + "-vectorize-loops", + "-o", + "/tmp/main.o", + "-x", + "c++", + NULL, + NULL}; + clang_argv[llvm::array_lengthof(clang_argv) - 2] = temp_source_path; + SBLaunchInfo launch_info(clang_argv); + Launch(launch_info); + next_action + .None(); // Don't continue or do anything, just wait for next event... + } break; + case 1: { + m_time_launch_stop_main.Stop(); + m_time_total.Stop(); + SBFrame frame(m_thread.GetFrameAtIndex(0)); + + // Time the first expression evaluation + m_expr_first_evaluate(frame); + + SBValue result; + for (size_t i = 0; i < NUM_EXPR_ITERATIONS; ++i) { + m_expr_frame_zero(frame); + } + m_target.BreakpointCreateByName("DeclContext::lookup"); + next_action.Continue(); + } break; + case 2: { + SBFrame frame(m_thread.GetFrameAtIndex(21)); + SBValue result; + for (size_t i = 0; i < NUM_EXPR_ITERATIONS; ++i) { + m_expr_frame_non_zero(frame); + } + next_action.Continue(); + } break; + default: + m_memory_total.Stop(); + next_action.Kill(); + break; } + } + + void WriteResults(Results &results) { + Results::Dictionary &results_dict = results.GetDictionary(); + + m_time_set_bp_main.WriteAverageAndStandardDeviation(results); + results_dict.Add( + "memory-change-create-target", + "Memory increase that occurs due to creating the target.", + m_memory_change_create_target.GetDeltaValue().GetResult(NULL, NULL)); + + results_dict.Add( + "memory-change-break-main", "Memory increase that occurs due to " + "setting a breakpoint at main by name.", + m_memory_change_break_main.GetDeltaValue().GetResult(NULL, NULL)); + + m_time_create_target.WriteAverageAndStandardDeviation(results); + m_expr_first_evaluate.WriteAverageAndStandardDeviation(results); + m_expr_frame_zero.WriteAverageAndStandardDeviation(results); + m_expr_frame_non_zero.WriteAverageAndStandardDeviation(results); + results_dict.Add("memory-total-break-main", + "The total memory that the current process is using after " + "setting the first breakpoint.", + m_memory_total.GetStopValue().GetResult(NULL, NULL)); + + results_dict.AddDouble( + "time-launch-stop-main", + "The time it takes to launch the process and stop at main.", + m_time_launch_stop_main.GetDeltaValue()); + + results_dict.AddDouble( + "time-total", "The time it takes to create the target, set breakpoint " + "at main, launch clang and hit the breakpoint at main.", + m_time_total.GetDeltaValue()); + results.Write(GetResultFilePath()); + } + + const char *GetExecutablePath() const { + if (m_exe_path.empty()) + return NULL; + return m_exe_path.c_str(); + } + + const char *GetResultFilePath() const { + if (m_out_path.empty()) + return NULL; + return m_out_path.c_str(); + } + + void SetExecutablePath(const char *path) { + if (path && path[0]) + m_exe_path = path; + else + m_exe_path.clear(); + } + + void SetResultFilePath(const char *path) { + if (path && path[0]) + m_out_path = path; + else + m_out_path.clear(); + } + + void SetUseDSYM(bool b) { m_use_dsym = b; } - void - SetExecutablePath (const char *path) - { - if (path && path[0]) - m_exe_path = path; - else - m_exe_path.clear(); - } - - void - SetResultFilePath (const char *path) - { - if (path && path[0]) - m_out_path = path; - else - m_out_path.clear(); - } - - void - SetUseDSYM (bool b) - { - m_use_dsym = b; - } - - - private: - // C++ formatters - TimeMeasurement<std::function<void()>> m_time_create_target; - TimeMeasurement<std::function<void()>> m_time_set_bp_main; - MemoryGauge m_memory_change_create_target; - MemoryGauge m_memory_change_break_main; - MemoryGauge m_memory_total; - TimeGauge m_time_launch_stop_main; - TimeGauge m_time_total; - TimeMeasurement<std::function<void(SBFrame)>> m_expr_first_evaluate; - TimeMeasurement<std::function<void(SBFrame)>> m_expr_frame_zero; - TimeMeasurement<std::function<void(SBFrame)>> m_expr_frame_non_zero; - std::string m_exe_path; - std::string m_out_path; - SBLaunchInfo m_launch_info; - bool m_use_dsym; - + // C++ formatters + TimeMeasurement<std::function<void()>> m_time_create_target; + TimeMeasurement<std::function<void()>> m_time_set_bp_main; + MemoryGauge m_memory_change_create_target; + MemoryGauge m_memory_change_break_main; + MemoryGauge m_memory_total; + TimeGauge m_time_launch_stop_main; + TimeGauge m_time_total; + TimeMeasurement<std::function<void(SBFrame)>> m_expr_first_evaluate; + TimeMeasurement<std::function<void(SBFrame)>> m_expr_frame_zero; + TimeMeasurement<std::function<void(SBFrame)>> m_expr_frame_non_zero; + std::string m_exe_path; + std::string m_out_path; + SBLaunchInfo m_launch_info; + bool m_use_dsym; }; +struct Options { + std::string clang_path; + std::string out_file; + bool verbose; + bool use_dsym; + bool error; + bool print_help; -struct Options -{ - std::string clang_path; - std::string out_file; - bool verbose; - bool use_dsym; - bool error; - bool print_help; - - Options() : - verbose (false), - error (false), - print_help (false) - { - } + Options() : verbose(false), error(false), print_help(false) {} }; static struct option g_long_options[] = { - { "verbose", no_argument, NULL, 'v' }, - { "clang", required_argument, NULL, 'c' }, - { "out-file", required_argument, NULL, 'o' }, - { "dsym", no_argument, NULL, 'd' }, - { NULL, 0, NULL, 0 } -}; - - -std::string -GetShortOptionString (struct option *long_options) -{ - std::string option_string; - for (int i = 0; long_options[i].name != NULL; ++i) - { - if (long_options[i].flag == NULL) - { - option_string.push_back ((char) long_options[i].val); - switch (long_options[i].has_arg) - { - default: - case no_argument: - break; - case required_argument: - option_string.push_back (':'); - break; - case optional_argument: - option_string.append (2, ':'); - break; - } - } + {"verbose", no_argument, NULL, 'v'}, + {"clang", required_argument, NULL, 'c'}, + {"out-file", required_argument, NULL, 'o'}, + {"dsym", no_argument, NULL, 'd'}, + {NULL, 0, NULL, 0}}; + +std::string GetShortOptionString(struct option *long_options) { + std::string option_string; + for (int i = 0; long_options[i].name != NULL; ++i) { + if (long_options[i].flag == NULL) { + option_string.push_back((char)long_options[i].val); + switch (long_options[i].has_arg) { + default: + case no_argument: + break; + case required_argument: + option_string.push_back(':'); + break; + case optional_argument: + option_string.append(2, ':'); + break; + } } - return option_string; + } + return option_string; } -int main(int argc, const char * argv[]) -{ +int main(int argc, const char *argv[]) { + + // Prepare for & make calls to getopt_long_only. - // Prepare for & make calls to getopt_long_only. - - std::string short_option_string (GetShortOptionString(g_long_options)); - - ClangTest test; + std::string short_option_string(GetShortOptionString(g_long_options)); - Options option_data; - bool done = false; + ClangTest test; + + Options option_data; + bool done = false; #if __GLIBC__ - optind = 0; + optind = 0; #else - optreset = 1; - optind = 1; + optreset = 1; + optind = 1; #endif - while (!done) - { - int long_options_index = -1; - const int short_option = ::getopt_long_only (argc, - const_cast<char **>(argv), - short_option_string.c_str(), - g_long_options, - &long_options_index); - - switch (short_option) - { - case 0: - // Already handled - break; - - case -1: - done = true; - break; - - case '?': - option_data.print_help = true; - break; - - case 'h': - option_data.print_help = true; - break; - - case 'v': - option_data.verbose = true; - break; - - case 'c': - { - SBFileSpec file(optarg); - if (file.Exists()) - test.SetExecutablePath(optarg); - else - fprintf(stderr, "error: file specified in --clang (-c) option doesn't exist: '%s'\n", optarg); - } - break; - - case 'o': - test.SetResultFilePath(optarg); - break; - - case 'd': - test.SetUseDSYM(true); - break; - - default: - option_data.error = true; - option_data.print_help = true; - fprintf (stderr, "error: unrecognized option %c\n", short_option); - break; - } + while (!done) { + int long_options_index = -1; + const int short_option = ::getopt_long_only( + argc, const_cast<char **>(argv), short_option_string.c_str(), + g_long_options, &long_options_index); + + switch (short_option) { + case 0: + // Already handled + break; + + case -1: + done = true; + break; + + case '?': + option_data.print_help = true; + break; + + case 'h': + option_data.print_help = true; + break; + + case 'v': + option_data.verbose = true; + break; + + case 'c': { + SBFileSpec file(optarg); + if (file.Exists()) + test.SetExecutablePath(optarg); + else + fprintf(stderr, "error: file specified in --clang (-c) option doesn't " + "exist: '%s'\n", + optarg); + } break; + + case 'o': + test.SetResultFilePath(optarg); + break; + + case 'd': + test.SetUseDSYM(true); + break; + + default: + option_data.error = true; + option_data.print_help = true; + fprintf(stderr, "error: unrecognized option %c\n", short_option); + break; } + } + if (test.GetExecutablePath() == NULL) { + // --clang is mandatory + option_data.print_help = true; + option_data.error = true; + fprintf(stderr, "error: the '--clang=PATH' option is mandatory\n"); + } - if (test.GetExecutablePath() == NULL) - { - // --clang is mandatory - option_data.print_help = true; - option_data.error = true; - fprintf (stderr, "error: the '--clang=PATH' option is mandatory\n"); - } - - if (option_data.print_help) - { - puts(R"( + if (option_data.print_help) { + puts(R"( NAME lldb_perf_clang -- a tool that measures LLDB peformance while debugging clang. @@ -467,18 +427,16 @@ DESCRIPTION Runs a set of static timing and memory tasks against clang and outputs results to a plist file. )"); - } - if (option_data.error) - { - exit(1); - } - - // Update argc and argv after parsing options - argc -= optind; - argv += optind; - - test.SetVerbose(true); - TestCase::Run(test, argc, argv); - return 0; + } + if (option_data.error) { + exit(1); + } + + // Update argc and argv after parsing options + argc -= optind; + argv += optind; + + test.SetVerbose(true); + TestCase::Run(test, argc, argv); + return 0; } - diff --git a/lldb/tools/lldb-perf/common/clang/main.cpp b/lldb/tools/lldb-perf/common/clang/main.cpp index 709c3946fb2..318a26b2c28 100644 --- a/lldb/tools/lldb-perf/common/clang/main.cpp +++ b/lldb/tools/lldb-perf/common/clang/main.cpp @@ -1,24 +1,20 @@ -#include <stdio.h> #include <stdint.h> +#include <stdio.h> #include <vector> namespace { - struct Foo - { - int i; int j; - }; - void doit (const Foo &foo) - { - printf ("doit(%i)\n", foo.i); - } +struct Foo { + int i; + int j; +}; +void doit(const Foo &foo) { printf("doit(%i)\n", foo.i); } } -int main (int argc, char const *argv[], char const *envp[]) -{ - std::vector<int> ints; - for (int i=0;i<10;++i) - ints.push_back(i); - printf ("hello world\n"); - Foo foo = { 12, 13 }; - doit (foo); - return 0; +int main(int argc, char const *argv[], char const *envp[]) { + std::vector<int> ints; + for (int i = 0; i < 10; ++i) + ints.push_back(i); + printf("hello world\n"); + Foo foo = {12, 13}; + doit(foo); + return 0; } diff --git a/lldb/tools/lldb-perf/common/stepping/lldb-perf-stepping.cpp b/lldb/tools/lldb-perf/common/stepping/lldb-perf-stepping.cpp index bb607ef06fa..0df8bdc9fdc 100644 --- a/lldb/tools/lldb-perf/common/stepping/lldb-perf-stepping.cpp +++ b/lldb/tools/lldb-perf/common/stepping/lldb-perf-stepping.cpp @@ -1,305 +1,259 @@ #include <CoreFoundation/CoreFoundation.h> -#include "lldb-perf/lib/Timer.h" -#include "lldb-perf/lib/Metric.h" #include "lldb-perf/lib/Measurement.h" +#include "lldb-perf/lib/Metric.h" #include "lldb-perf/lib/TestCase.h" +#include "lldb-perf/lib/Timer.h" #include "lldb-perf/lib/Xcode.h" -#include <unistd.h> -#include <string> #include <getopt.h> +#include <string> +#include <unistd.h> using namespace lldb_perf; -class StepTest : public TestCase -{ - typedef void (*no_function) (void); - +class StepTest : public TestCase { + typedef void (*no_function)(void); + public: - StepTest(bool use_single_stepping = false) : - m_main_source("stepping-testcase.cpp"), + StepTest(bool use_single_stepping = false) + : m_main_source("stepping-testcase.cpp"), m_use_single_stepping(use_single_stepping), - m_time_measurements(nullptr) - { - } - - virtual - ~StepTest() {} - - virtual bool - Setup (int& argc, const char**& argv) - { - TestCase::Setup (argc, argv); - - // Toggle the fast stepping command on or off as required. - const char *single_step_cmd = "settings set target.use-fast-stepping false"; - const char *fast_step_cmd = "settings set target.use-fast-stepping true"; - const char *cmd_to_use; - - if (m_use_single_stepping) - cmd_to_use = single_step_cmd; - else - cmd_to_use = fast_step_cmd; - - SBCommandReturnObject return_object; - m_debugger.GetCommandInterpreter().HandleCommand(cmd_to_use, - return_object); - if (!return_object.Succeeded()) - { - if (return_object.GetError() != NULL) - printf ("Got an error running settings set: %s.\n", return_object.GetError()); - else - printf ("Failed running settings set, no error.\n"); - } - - m_target = m_debugger.CreateTarget(m_app_path.c_str()); - m_first_bp = m_target.BreakpointCreateBySourceRegex("Here is some code to stop at originally.", m_main_source); - - const char* file_arg = m_app_path.c_str(); - const char* empty = nullptr; - const char* args[] = {file_arg, empty}; - SBLaunchInfo launch_info (args); - - return Launch (launch_info); + m_time_measurements(nullptr) {} + + virtual ~StepTest() {} + + virtual bool Setup(int &argc, const char **&argv) { + TestCase::Setup(argc, argv); + + // Toggle the fast stepping command on or off as required. + const char *single_step_cmd = "settings set target.use-fast-stepping false"; + const char *fast_step_cmd = "settings set target.use-fast-stepping true"; + const char *cmd_to_use; + + if (m_use_single_stepping) + cmd_to_use = single_step_cmd; + else + cmd_to_use = fast_step_cmd; + + SBCommandReturnObject return_object; + m_debugger.GetCommandInterpreter().HandleCommand(cmd_to_use, return_object); + if (!return_object.Succeeded()) { + if (return_object.GetError() != NULL) + printf("Got an error running settings set: %s.\n", + return_object.GetError()); + else + printf("Failed running settings set, no error.\n"); } - void - WriteResults (Results &results) - { - // Gotta turn off the last timer now. - m_individual_step_times.push_back(m_time_measurements.Stop()); - - size_t num_time_measurements = m_individual_step_times.size(); - - Results::Dictionary& results_dict = results.GetDictionary(); - const char *short_format_string = "step-time-%0.2d"; - const size_t short_size = strlen(short_format_string) + 5; - char short_buffer[short_size]; - const char *long_format_string = "The time it takes for step %d in the step sequence."; - const size_t long_size = strlen(long_format_string) + 5; - char long_buffer[long_size]; - - for (size_t i = 0; i < num_time_measurements; i++) - { - snprintf (short_buffer, short_size, short_format_string, i); - snprintf (long_buffer, long_size, long_format_string, i); - - results_dict.AddDouble(short_buffer, - long_buffer, - m_individual_step_times[i]); - - } - results_dict.AddDouble ("total-time", "Total time spent stepping.", m_time_measurements.GetMetric().GetSum()); - results_dict.AddDouble ("stddev-time", "StdDev of time spent stepping.", m_time_measurements.GetMetric().GetStandardDeviation()); - - results.Write(m_out_path.c_str()); - } - - - const char * - GetExecutablePath () const - { - if (m_app_path.empty()) - return NULL; - return m_app_path.c_str(); - } + m_target = m_debugger.CreateTarget(m_app_path.c_str()); + m_first_bp = m_target.BreakpointCreateBySourceRegex( + "Here is some code to stop at originally.", m_main_source); - const char * - GetResultFilePath () const - { - if (m_out_path.empty()) - return NULL; - return m_out_path.c_str(); - } + const char *file_arg = m_app_path.c_str(); + const char *empty = nullptr; + const char *args[] = {file_arg, empty}; + SBLaunchInfo launch_info(args); - void - SetExecutablePath (const char *path) - { - if (path && path[0]) - m_app_path = path; - else - m_app_path.clear(); - } - - void - SetResultFilePath (const char *path) - { - if (path && path[0]) - m_out_path = path; - else - m_out_path.clear(); - } - - void - SetUseSingleStep (bool use_it) - { - m_use_single_stepping = use_it; + return Launch(launch_info); + } + + void WriteResults(Results &results) { + // Gotta turn off the last timer now. + m_individual_step_times.push_back(m_time_measurements.Stop()); + + size_t num_time_measurements = m_individual_step_times.size(); + + Results::Dictionary &results_dict = results.GetDictionary(); + const char *short_format_string = "step-time-%0.2d"; + const size_t short_size = strlen(short_format_string) + 5; + char short_buffer[short_size]; + const char *long_format_string = + "The time it takes for step %d in the step sequence."; + const size_t long_size = strlen(long_format_string) + 5; + char long_buffer[long_size]; + + for (size_t i = 0; i < num_time_measurements; i++) { + snprintf(short_buffer, short_size, short_format_string, i); + snprintf(long_buffer, long_size, long_format_string, i); + + results_dict.AddDouble(short_buffer, long_buffer, + m_individual_step_times[i]); } + results_dict.AddDouble("total-time", "Total time spent stepping.", + m_time_measurements.GetMetric().GetSum()); + results_dict.AddDouble( + "stddev-time", "StdDev of time spent stepping.", + m_time_measurements.GetMetric().GetStandardDeviation()); + + results.Write(m_out_path.c_str()); + } + + const char *GetExecutablePath() const { + if (m_app_path.empty()) + return NULL; + return m_app_path.c_str(); + } + + const char *GetResultFilePath() const { + if (m_out_path.empty()) + return NULL; + return m_out_path.c_str(); + } + + void SetExecutablePath(const char *path) { + if (path && path[0]) + m_app_path = path; + else + m_app_path.clear(); + } + + void SetResultFilePath(const char *path) { + if (path && path[0]) + m_out_path = path; + else + m_out_path.clear(); + } + + void SetUseSingleStep(bool use_it) { m_use_single_stepping = use_it; } + private: - virtual void - TestStep (int counter, ActionWanted &next_action) - { - if (counter > 0) - { - m_individual_step_times.push_back(m_time_measurements.Stop()); - - } - - // Disable the breakpoint, just in case it gets multiple locations we don't want that confusing the stepping. - if (counter == 0) - m_first_bp.SetEnabled(false); - - next_action.StepOver(m_process.GetThreadAtIndex(0)); - m_time_measurements.Start(); - - + virtual void TestStep(int counter, ActionWanted &next_action) { + if (counter > 0) { + m_individual_step_times.push_back(m_time_measurements.Stop()); } - - SBBreakpoint m_first_bp; - SBFileSpec m_main_source; - TimeMeasurement<no_function> m_time_measurements; - std::vector<double> m_individual_step_times; - bool m_use_single_stepping; - std::string m_app_path; - std::string m_out_path; - + // Disable the breakpoint, just in case it gets multiple locations we don't + // want that confusing the stepping. + if (counter == 0) + m_first_bp.SetEnabled(false); + + next_action.StepOver(m_process.GetThreadAtIndex(0)); + m_time_measurements.Start(); + } + + SBBreakpoint m_first_bp; + SBFileSpec m_main_source; + TimeMeasurement<no_function> m_time_measurements; + std::vector<double> m_individual_step_times; + bool m_use_single_stepping; + std::string m_app_path; + std::string m_out_path; }; -struct Options -{ - std::string test_file_path; - std::string out_file; - bool verbose; - bool fast_step; - bool error; - bool print_help; - - Options() : - verbose (false), - fast_step (true), - error (false), - print_help (false) - { - } -}; +struct Options { + std::string test_file_path; + std::string out_file; + bool verbose; + bool fast_step; + bool error; + bool print_help; -static struct option g_long_options[] = { - { "verbose", no_argument, NULL, 'v' }, - { "single-step", no_argument, NULL, 's' }, - { "test-file", required_argument, NULL, 't' }, - { "out-file", required_argument, NULL, 'o' }, - { NULL, 0, NULL, 0 } + Options() + : verbose(false), fast_step(true), error(false), print_help(false) {} }; - -std::string -GetShortOptionString (struct option *long_options) -{ - std::string option_string; - for (int i = 0; long_options[i].name != NULL; ++i) - { - if (long_options[i].flag == NULL) - { - option_string.push_back ((char) long_options[i].val); - switch (long_options[i].has_arg) - { - default: - case no_argument: - break; - case required_argument: - option_string.push_back (':'); - break; - case optional_argument: - option_string.append (2, ':'); - break; - } - } +static struct option g_long_options[] = { + {"verbose", no_argument, NULL, 'v'}, + {"single-step", no_argument, NULL, 's'}, + {"test-file", required_argument, NULL, 't'}, + {"out-file", required_argument, NULL, 'o'}, + {NULL, 0, NULL, 0}}; + +std::string GetShortOptionString(struct option *long_options) { + std::string option_string; + for (int i = 0; long_options[i].name != NULL; ++i) { + if (long_options[i].flag == NULL) { + option_string.push_back((char)long_options[i].val); + switch (long_options[i].has_arg) { + default: + case no_argument: + break; + case required_argument: + option_string.push_back(':'); + break; + case optional_argument: + option_string.append(2, ':'); + break; + } } - return option_string; + } + return option_string; } -int main(int argc, const char * argv[]) -{ +int main(int argc, const char *argv[]) { + + // Prepare for & make calls to getopt_long_only. - // Prepare for & make calls to getopt_long_only. - - std::string short_option_string (GetShortOptionString(g_long_options)); - - StepTest test; + std::string short_option_string(GetShortOptionString(g_long_options)); - Options option_data; - bool done = false; + StepTest test; + + Options option_data; + bool done = false; #if __GLIBC__ - optind = 0; + optind = 0; #else - optreset = 1; - optind = 1; + optreset = 1; + optind = 1; #endif - while (!done) - { - int long_options_index = -1; - const int short_option = ::getopt_long_only (argc, - const_cast<char **>(argv), - short_option_string.c_str(), - g_long_options, - &long_options_index); - - switch (short_option) - { - case 0: - // Already handled - break; - - case -1: - done = true; - break; - - case '?': - option_data.print_help = true; - break; - - case 'h': - option_data.print_help = true; - break; - - case 'v': - option_data.verbose = true; - break; - - case 's': - option_data.fast_step = false; - test.SetUseSingleStep(true); - break; - - case 't': - { - SBFileSpec file(optarg); - if (file.Exists()) - test.SetExecutablePath(optarg); - else - fprintf(stderr, "error: file specified in --test-file (-t) option doesn't exist: '%s'\n", optarg); - } - break; - - case 'o': - test.SetResultFilePath(optarg); - break; - - default: - option_data.error = true; - option_data.print_help = true; - fprintf (stderr, "error: unrecognized option %c\n", short_option); - break; - } + while (!done) { + int long_options_index = -1; + const int short_option = ::getopt_long_only( + argc, const_cast<char **>(argv), short_option_string.c_str(), + g_long_options, &long_options_index); + + switch (short_option) { + case 0: + // Already handled + break; + + case -1: + done = true; + break; + + case '?': + option_data.print_help = true; + break; + + case 'h': + option_data.print_help = true; + break; + + case 'v': + option_data.verbose = true; + break; + + case 's': + option_data.fast_step = false; + test.SetUseSingleStep(true); + break; + + case 't': { + SBFileSpec file(optarg); + if (file.Exists()) + test.SetExecutablePath(optarg); + else + fprintf(stderr, "error: file specified in --test-file (-t) option " + "doesn't exist: '%s'\n", + optarg); + } break; + + case 'o': + test.SetResultFilePath(optarg); + break; + + default: + option_data.error = true; + option_data.print_help = true; + fprintf(stderr, "error: unrecognized option %c\n", short_option); + break; } + } - - if (option_data.print_help) - { - puts(R"( + if (option_data.print_help) { + puts(R"( NAME lldb-perf-stepping -- a tool that measures LLDB peformance of simple stepping operations. @@ -310,26 +264,24 @@ DESCRIPTION Runs a set of stepping operations, timing each step and outputs results to a plist file. )"); - exit(0); - } - if (option_data.error) - { - exit(1); - } - - if (test.GetExecutablePath() == NULL) - { - // --clang is mandatory - option_data.print_help = true; - option_data.error = true; - fprintf (stderr, "error: the '--test-file=PATH' option is mandatory\n"); - } - - // Update argc and argv after parsing options - argc -= optind; - argv += optind; - - test.SetVerbose(true); - TestCase::Run(test, argc, argv); - return 0; + exit(0); + } + if (option_data.error) { + exit(1); + } + + if (test.GetExecutablePath() == NULL) { + // --clang is mandatory + option_data.print_help = true; + option_data.error = true; + fprintf(stderr, "error: the '--test-file=PATH' option is mandatory\n"); + } + + // Update argc and argv after parsing options + argc -= optind; + argv += optind; + + test.SetVerbose(true); + TestCase::Run(test, argc, argv); + return 0; } diff --git a/lldb/tools/lldb-perf/common/stepping/stepping-testcase.cpp b/lldb/tools/lldb-perf/common/stepping/stepping-testcase.cpp index f842c2379c1..50f0164a217 100644 --- a/lldb/tools/lldb-perf/common/stepping/stepping-testcase.cpp +++ b/lldb/tools/lldb-perf/common/stepping/stepping-testcase.cpp @@ -1,42 +1,35 @@ #include <stdio.h> -#include <vector> #include <string> +#include <vector> + +struct struct_for_copying { + struct_for_copying(int in_int, double in_double, const char *in_string) + : int_value(in_int), double_value(in_double), string_value(in_string) {} + struct_for_copying() { struct_for_copying(0, 0, ""); } -struct struct_for_copying -{ - struct_for_copying (int in_int, double in_double, const char *in_string) : - int_value(in_int), - double_value(in_double), - string_value (in_string) - { - - } - struct_for_copying() - { - struct_for_copying (0, 0, ""); - } - - int int_value; - double double_value; - std::string string_value; + int int_value; + double double_value; + std::string string_value; }; -int main (int argc, char **argv) -{ - struct_for_copying input_struct (150 * argc, 10.0 * argc, argv[0]); - struct_for_copying output_struct; - int some_int = 44; - double some_double = 34.5; - double other_double; - size_t vector_size; - std::vector<struct_for_copying> my_vector; - - printf ("Here is some code to stop at originally. Got: %d, %p.\n", argc, argv); - output_struct = input_struct; - other_double = (some_double * some_int)/((double) argc); - other_double = other_double > 0 ? some_double/other_double : some_double > 0 ? other_double/some_double : 10.0; - my_vector.push_back (input_struct); - vector_size = my_vector.size(); - - return vector_size == 0 ? 0 : 1; +int main(int argc, char **argv) { + struct_for_copying input_struct(150 * argc, 10.0 * argc, argv[0]); + struct_for_copying output_struct; + int some_int = 44; + double some_double = 34.5; + double other_double; + size_t vector_size; + std::vector<struct_for_copying> my_vector; + + printf("Here is some code to stop at originally. Got: %d, %p.\n", argc, + argv); + output_struct = input_struct; + other_double = (some_double * some_int) / ((double)argc); + other_double = other_double > 0 + ? some_double / other_double + : some_double > 0 ? other_double / some_double : 10.0; + my_vector.push_back(input_struct); + vector_size = my_vector.size(); + + return vector_size == 0 ? 0 : 1; } diff --git a/lldb/tools/lldb-perf/darwin/formatters/fmts_tester.mm b/lldb/tools/lldb-perf/darwin/formatters/fmts_tester.mm index 57ce008297d..1915c4ad4c9 100644 --- a/lldb/tools/lldb-perf/darwin/formatters/fmts_tester.mm +++ b/lldb/tools/lldb-perf/darwin/formatters/fmts_tester.mm @@ -7,73 +7,76 @@ // //===----------------------------------------------------------------------===// - #import <Cocoa/Cocoa.h> -#include <vector> #include <list> #include <map> #include <string> +#include <vector> -int main() -{ - NSArray* nsarray = @[@1,@2,@"hello world",@3,@4,@"foobar"]; - NSMutableArray* nsmutablearray = [[NSMutableArray alloc] initWithCapacity:5]; - [nsmutablearray addObject:@1]; - [nsmutablearray addObject:@2]; - [nsmutablearray addObject:@"hello world"]; - [nsmutablearray addObject:@3]; - [nsmutablearray addObject:@4]; - [nsmutablearray addObject:@"foobar"]; - NSDictionary* nsdictionary = @{@1 : @1, @2 : @2, @"hello" : @"world", @3 : @3}; - NSMutableDictionary* nsmutabledictionary = [[NSMutableDictionary alloc] initWithCapacity:5]; - [nsmutabledictionary setObject:@1 forKey:@1]; - [nsmutabledictionary setObject:@2 forKey:@2]; - [nsmutabledictionary setObject:@"hello" forKey:@"world"]; - [nsmutabledictionary setObject:@3 forKey:@3]; - NSString* str0 = @"Hello world"; - NSString* str1 = @"Hello â„¥"; - NSString* str2 = @"Hello world"; - NSString* str3 = @"Hello â„¥"; - NSString* str4 = @"Hello world"; - NSDate* me = [NSDate dateWithNaturalLanguageString:@"April 10, 1985"]; - NSDate* cutie = [NSDate dateWithNaturalLanguageString:@"January 29, 1983"]; - NSDate* mom = [NSDate dateWithNaturalLanguageString:@"May 24, 1959"]; - NSDate* dad = [NSDate dateWithNaturalLanguageString:@"October 29, 1954"]; - NSDate* today = [NSDate dateWithNaturalLanguageString:@"March 14, 2013"]; - NSArray* bundles = [NSBundle allBundles]; - NSArray* frameworks = [NSBundle allFrameworks]; - NSSet* nsset = [NSSet setWithArray:nsarray]; - NSMutableSet* nsmutableset = [NSMutableSet setWithCapacity:5]; - [nsmutableset addObject:@1]; - [nsmutableset addObject:@2]; - [nsmutableset addObject:@"hello world"]; - [nsmutableset addObject:@3]; - [nsmutableset addObject:@4]; - [nsmutableset addObject:@"foobar"]; - std::vector<int> vector; - vector.push_back(1); - vector.push_back(2); - vector.push_back(3); - vector.push_back(4); - vector.push_back(5); - std::list<int> list; - list.push_back(1); - list.push_back(2); - list.push_back(3); - list.push_back(4); - list.push_back(5); - std::map<int,int> map; - map[1] = 1; - map[2] = 2; - map[3] = 3; - map[4] = 4; - map[5] = 5; - std::string sstr0("Hello world"); - std::string sstr1("Hello world"); - std::string sstr2("Hello world"); - std::string sstr3("Hello world"); - std::string sstr4("Hello world"); - int x = 0; - for (;;) - x++; +int main() { + NSArray *nsarray = @[ @1, @2, @"hello world", @3, @4, @"foobar" ]; + NSMutableArray *nsmutablearray = [[NSMutableArray alloc] initWithCapacity:5]; + [nsmutablearray addObject:@1]; + [nsmutablearray addObject:@2]; + [nsmutablearray addObject:@"hello world"]; + [nsmutablearray addObject:@3]; + [nsmutablearray addObject:@4]; + [nsmutablearray addObject:@"foobar"]; + NSDictionary *nsdictionary = + @{ @1 : @1, + @2 : @2, + @"hello" : @"world", + @3 : @3 }; + NSMutableDictionary *nsmutabledictionary = + [[NSMutableDictionary alloc] initWithCapacity:5]; + [nsmutabledictionary setObject:@1 forKey:@1]; + [nsmutabledictionary setObject:@2 forKey:@2]; + [nsmutabledictionary setObject:@"hello" forKey:@"world"]; + [nsmutabledictionary setObject:@3 forKey:@3]; + NSString *str0 = @"Hello world"; + NSString *str1 = @"Hello â„¥"; + NSString *str2 = @"Hello world"; + NSString *str3 = @"Hello â„¥"; + NSString *str4 = @"Hello world"; + NSDate *me = [NSDate dateWithNaturalLanguageString:@"April 10, 1985"]; + NSDate *cutie = [NSDate dateWithNaturalLanguageString:@"January 29, 1983"]; + NSDate *mom = [NSDate dateWithNaturalLanguageString:@"May 24, 1959"]; + NSDate *dad = [NSDate dateWithNaturalLanguageString:@"October 29, 1954"]; + NSDate *today = [NSDate dateWithNaturalLanguageString:@"March 14, 2013"]; + NSArray *bundles = [NSBundle allBundles]; + NSArray *frameworks = [NSBundle allFrameworks]; + NSSet *nsset = [NSSet setWithArray:nsarray]; + NSMutableSet *nsmutableset = [NSMutableSet setWithCapacity:5]; + [nsmutableset addObject:@1]; + [nsmutableset addObject:@2]; + [nsmutableset addObject:@"hello world"]; + [nsmutableset addObject:@3]; + [nsmutableset addObject:@4]; + [nsmutableset addObject:@"foobar"]; + std::vector<int> vector; + vector.push_back(1); + vector.push_back(2); + vector.push_back(3); + vector.push_back(4); + vector.push_back(5); + std::list<int> list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + list.push_back(4); + list.push_back(5); + std::map<int, int> map; + map[1] = 1; + map[2] = 2; + map[3] = 3; + map[4] = 4; + map[5] = 5; + std::string sstr0("Hello world"); + std::string sstr1("Hello world"); + std::string sstr2("Hello world"); + std::string sstr3("Hello world"); + std::string sstr4("Hello world"); + int x = 0; + for (;;) + x++; }
\ No newline at end of file diff --git a/lldb/tools/lldb-perf/darwin/formatters/formatters.cpp b/lldb/tools/lldb-perf/darwin/formatters/formatters.cpp index ee387561842..95524c4e594 100644 --- a/lldb/tools/lldb-perf/darwin/formatters/formatters.cpp +++ b/lldb/tools/lldb-perf/darwin/formatters/formatters.cpp @@ -9,238 +9,260 @@ #include <CoreFoundation/CoreFoundation.h> -#include "lldb-perf/lib/Timer.h" -#include "lldb-perf/lib/Metric.h" #include "lldb-perf/lib/Measurement.h" +#include "lldb-perf/lib/Metric.h" #include "lldb-perf/lib/TestCase.h" +#include "lldb-perf/lib/Timer.h" #include "lldb-perf/lib/Xcode.h" +#include <fstream> #include <iostream> #include <unistd.h> -#include <fstream> using namespace lldb_perf; -class FormattersTest : public TestCase -{ +class FormattersTest : public TestCase { public: - FormattersTest () : TestCase() - { - m_dump_std_vector_measurement = CreateTimeMeasurement([] (SBValue value) -> void { - lldb_perf::Xcode::FetchVariable (value,1,false); - }, "std-vector", "time to dump an std::vector"); - m_dump_std_list_measurement = CreateTimeMeasurement([] (SBValue value) -> void { - lldb_perf::Xcode::FetchVariable (value,1,false); - }, "std-list", "time to dump an std::list"); - m_dump_std_map_measurement = CreateTimeMeasurement([] (SBValue value) -> void { - lldb_perf::Xcode::FetchVariable (value,1,false); - }, "std-map", "time to dump an std::map"); - - // use this in manual mode - m_dump_std_string_measurement = CreateTimeMeasurement([] () -> void { - }, "std-string", "time to dump an std::string"); - - m_dump_nsstring_measurement = CreateTimeMeasurement([] (SBValue value) -> void { - lldb_perf::Xcode::FetchVariable (value,0,false); - }, "ns-string", "time to dump an NSString"); - - m_dump_nsarray_measurement = CreateTimeMeasurement([] (SBValue value) -> void { - lldb_perf::Xcode::FetchVariable (value,1,false); - }, "ns-array", "time to dump an NSArray"); - - m_dump_nsdictionary_measurement = CreateTimeMeasurement([] (SBValue value) -> void { - lldb_perf::Xcode::FetchVariable (value,1,false); - }, "ns-dictionary", "time to dump an NSDictionary"); - - m_dump_nsset_measurement = CreateTimeMeasurement([] (SBValue value) -> void { - lldb_perf::Xcode::FetchVariable (value,1,false); - }, "ns-set", "time to dump an NSSet"); - - m_dump_nsbundle_measurement = CreateTimeMeasurement([] (SBValue value) -> void { - lldb_perf::Xcode::FetchVariable (value,1,false); - }, "ns-bundle", "time to dump an NSBundle"); - - m_dump_nsdate_measurement = CreateTimeMeasurement([] (SBValue value) -> void { - lldb_perf::Xcode::FetchVariable (value,0,false); - }, "ns-date", "time to dump an NSDate"); - } + FormattersTest() : TestCase() { + m_dump_std_vector_measurement = CreateTimeMeasurement( + [](SBValue value) -> void { + lldb_perf::Xcode::FetchVariable(value, 1, false); + }, + "std-vector", "time to dump an std::vector"); + m_dump_std_list_measurement = CreateTimeMeasurement( + [](SBValue value) -> void { + lldb_perf::Xcode::FetchVariable(value, 1, false); + }, + "std-list", "time to dump an std::list"); + m_dump_std_map_measurement = CreateTimeMeasurement( + [](SBValue value) -> void { + lldb_perf::Xcode::FetchVariable(value, 1, false); + }, + "std-map", "time to dump an std::map"); - virtual - ~FormattersTest () - { - } - - virtual bool - Setup (int& argc, const char**& argv) - { - m_app_path.assign(argv[1]); - m_out_path.assign(argv[2]); - m_target = m_debugger.CreateTarget(m_app_path.c_str()); - m_target.BreakpointCreateByName("main"); - SBLaunchInfo launch_info(argv); - return Launch (launch_info); - } - - void - DoTest () - { - SBFrame frame_zero(m_thread.GetFrameAtIndex(0)); - - m_dump_nsarray_measurement(frame_zero.FindVariable("nsarray", lldb::eDynamicCanRunTarget)); - m_dump_nsarray_measurement(frame_zero.FindVariable("nsmutablearray", lldb::eDynamicCanRunTarget)); - - m_dump_nsdictionary_measurement(frame_zero.FindVariable("nsdictionary", lldb::eDynamicCanRunTarget)); - m_dump_nsdictionary_measurement(frame_zero.FindVariable("nsmutabledictionary", lldb::eDynamicCanRunTarget)); - - m_dump_nsstring_measurement(frame_zero.FindVariable("str0", lldb::eDynamicCanRunTarget)); - m_dump_nsstring_measurement(frame_zero.FindVariable("str1", lldb::eDynamicCanRunTarget)); - m_dump_nsstring_measurement(frame_zero.FindVariable("str2", lldb::eDynamicCanRunTarget)); - m_dump_nsstring_measurement(frame_zero.FindVariable("str3", lldb::eDynamicCanRunTarget)); - m_dump_nsstring_measurement(frame_zero.FindVariable("str4", lldb::eDynamicCanRunTarget)); - - m_dump_nsdate_measurement(frame_zero.FindVariable("me", lldb::eDynamicCanRunTarget)); - m_dump_nsdate_measurement(frame_zero.FindVariable("cutie", lldb::eDynamicCanRunTarget)); - m_dump_nsdate_measurement(frame_zero.FindVariable("mom", lldb::eDynamicCanRunTarget)); - m_dump_nsdate_measurement(frame_zero.FindVariable("dad", lldb::eDynamicCanRunTarget)); - m_dump_nsdate_measurement(frame_zero.FindVariable("today", lldb::eDynamicCanRunTarget)); - - m_dump_nsbundle_measurement(frame_zero.FindVariable("bundles", lldb::eDynamicCanRunTarget)); - m_dump_nsbundle_measurement(frame_zero.FindVariable("frameworks", lldb::eDynamicCanRunTarget)); - - m_dump_nsset_measurement(frame_zero.FindVariable("nsset", lldb::eDynamicCanRunTarget)); - m_dump_nsset_measurement(frame_zero.FindVariable("nsmutableset", lldb::eDynamicCanRunTarget)); - - m_dump_std_vector_measurement(frame_zero.FindVariable("vector", lldb::eDynamicCanRunTarget)); - m_dump_std_list_measurement(frame_zero.FindVariable("list", lldb::eDynamicCanRunTarget)); - m_dump_std_map_measurement(frame_zero.FindVariable("map", lldb::eDynamicCanRunTarget)); - - auto sstr0 = frame_zero.FindVariable("sstr0", lldb::eDynamicCanRunTarget); - auto sstr1 = frame_zero.FindVariable("sstr1", lldb::eDynamicCanRunTarget); - auto sstr2 = frame_zero.FindVariable("sstr2", lldb::eDynamicCanRunTarget); - auto sstr3 = frame_zero.FindVariable("sstr3", lldb::eDynamicCanRunTarget); - auto sstr4 = frame_zero.FindVariable("sstr4", lldb::eDynamicCanRunTarget); - - m_dump_std_string_measurement.Start(); - Xcode::FetchVariable(sstr0,0,false); - m_dump_std_string_measurement.Stop(); - - m_dump_std_string_measurement.Start(); - Xcode::FetchVariable(sstr1,0,false); - m_dump_std_string_measurement.Stop(); - - m_dump_std_string_measurement.Start(); - Xcode::FetchVariable(sstr2,0,false); - m_dump_std_string_measurement.Stop(); - - m_dump_std_string_measurement.Start(); - Xcode::FetchVariable(sstr3,0,false); - m_dump_std_string_measurement.Stop(); - - m_dump_std_string_measurement.Start(); - Xcode::FetchVariable(sstr4,0,false); - m_dump_std_string_measurement.Stop(); - - } - - virtual void - TestStep (int counter, ActionWanted &next_action) - { - switch (counter) - { - case 0: - m_target.BreakpointCreateByLocation("fmts_tester.mm", 78); - next_action.Continue(); - break; - case 1: - DoTest (); - next_action.Continue(); - break; - case 2: - DoTest (); - next_action.Continue(); - break; - case 3: - DoTest (); - next_action.Continue(); - break; - case 4: - DoTest (); - next_action.Continue(); - break; - case 5: - DoTest (); - next_action.Continue(); - break; - case 6: - DoTest (); - next_action.Continue(); - break; - case 7: - DoTest (); - next_action.Continue(); - break; - case 8: - DoTest (); - next_action.Continue(); - break; - case 9: - DoTest (); - next_action.Continue(); - break; - case 10: - DoTest (); - next_action.Continue(); - break; - default: - next_action.Kill(); - break; - } - } - - virtual void - WriteResults (Results &results) - { - m_dump_std_vector_measurement.WriteAverageAndStandardDeviation(results); - m_dump_std_list_measurement.WriteAverageAndStandardDeviation(results); - m_dump_std_map_measurement.WriteAverageAndStandardDeviation(results); - m_dump_std_string_measurement.WriteAverageAndStandardDeviation(results); - - m_dump_nsstring_measurement.WriteAverageAndStandardDeviation(results); - m_dump_nsarray_measurement.WriteAverageAndStandardDeviation(results); - m_dump_nsdictionary_measurement.WriteAverageAndStandardDeviation(results); - m_dump_nsset_measurement.WriteAverageAndStandardDeviation(results); - m_dump_nsbundle_measurement.WriteAverageAndStandardDeviation(results); - m_dump_nsdate_measurement.WriteAverageAndStandardDeviation(results); - results.Write(m_out_path.c_str()); + // use this in manual mode + m_dump_std_string_measurement = CreateTimeMeasurement( + []() -> void {}, "std-string", "time to dump an std::string"); + + m_dump_nsstring_measurement = CreateTimeMeasurement( + [](SBValue value) -> void { + lldb_perf::Xcode::FetchVariable(value, 0, false); + }, + "ns-string", "time to dump an NSString"); + + m_dump_nsarray_measurement = CreateTimeMeasurement( + [](SBValue value) -> void { + lldb_perf::Xcode::FetchVariable(value, 1, false); + }, + "ns-array", "time to dump an NSArray"); + + m_dump_nsdictionary_measurement = CreateTimeMeasurement( + [](SBValue value) -> void { + lldb_perf::Xcode::FetchVariable(value, 1, false); + }, + "ns-dictionary", "time to dump an NSDictionary"); + + m_dump_nsset_measurement = CreateTimeMeasurement( + [](SBValue value) -> void { + lldb_perf::Xcode::FetchVariable(value, 1, false); + }, + "ns-set", "time to dump an NSSet"); + + m_dump_nsbundle_measurement = CreateTimeMeasurement( + [](SBValue value) -> void { + lldb_perf::Xcode::FetchVariable(value, 1, false); + }, + "ns-bundle", "time to dump an NSBundle"); + + m_dump_nsdate_measurement = CreateTimeMeasurement( + [](SBValue value) -> void { + lldb_perf::Xcode::FetchVariable(value, 0, false); + }, + "ns-date", "time to dump an NSDate"); + } + + virtual ~FormattersTest() {} + + virtual bool Setup(int &argc, const char **&argv) { + m_app_path.assign(argv[1]); + m_out_path.assign(argv[2]); + m_target = m_debugger.CreateTarget(m_app_path.c_str()); + m_target.BreakpointCreateByName("main"); + SBLaunchInfo launch_info(argv); + return Launch(launch_info); + } + + void DoTest() { + SBFrame frame_zero(m_thread.GetFrameAtIndex(0)); + + m_dump_nsarray_measurement( + frame_zero.FindVariable("nsarray", lldb::eDynamicCanRunTarget)); + m_dump_nsarray_measurement( + frame_zero.FindVariable("nsmutablearray", lldb::eDynamicCanRunTarget)); + + m_dump_nsdictionary_measurement( + frame_zero.FindVariable("nsdictionary", lldb::eDynamicCanRunTarget)); + m_dump_nsdictionary_measurement(frame_zero.FindVariable( + "nsmutabledictionary", lldb::eDynamicCanRunTarget)); + + m_dump_nsstring_measurement( + frame_zero.FindVariable("str0", lldb::eDynamicCanRunTarget)); + m_dump_nsstring_measurement( + frame_zero.FindVariable("str1", lldb::eDynamicCanRunTarget)); + m_dump_nsstring_measurement( + frame_zero.FindVariable("str2", lldb::eDynamicCanRunTarget)); + m_dump_nsstring_measurement( + frame_zero.FindVariable("str3", lldb::eDynamicCanRunTarget)); + m_dump_nsstring_measurement( + frame_zero.FindVariable("str4", lldb::eDynamicCanRunTarget)); + + m_dump_nsdate_measurement( + frame_zero.FindVariable("me", lldb::eDynamicCanRunTarget)); + m_dump_nsdate_measurement( + frame_zero.FindVariable("cutie", lldb::eDynamicCanRunTarget)); + m_dump_nsdate_measurement( + frame_zero.FindVariable("mom", lldb::eDynamicCanRunTarget)); + m_dump_nsdate_measurement( + frame_zero.FindVariable("dad", lldb::eDynamicCanRunTarget)); + m_dump_nsdate_measurement( + frame_zero.FindVariable("today", lldb::eDynamicCanRunTarget)); + + m_dump_nsbundle_measurement( + frame_zero.FindVariable("bundles", lldb::eDynamicCanRunTarget)); + m_dump_nsbundle_measurement( + frame_zero.FindVariable("frameworks", lldb::eDynamicCanRunTarget)); + + m_dump_nsset_measurement( + frame_zero.FindVariable("nsset", lldb::eDynamicCanRunTarget)); + m_dump_nsset_measurement( + frame_zero.FindVariable("nsmutableset", lldb::eDynamicCanRunTarget)); + + m_dump_std_vector_measurement( + frame_zero.FindVariable("vector", lldb::eDynamicCanRunTarget)); + m_dump_std_list_measurement( + frame_zero.FindVariable("list", lldb::eDynamicCanRunTarget)); + m_dump_std_map_measurement( + frame_zero.FindVariable("map", lldb::eDynamicCanRunTarget)); + + auto sstr0 = frame_zero.FindVariable("sstr0", lldb::eDynamicCanRunTarget); + auto sstr1 = frame_zero.FindVariable("sstr1", lldb::eDynamicCanRunTarget); + auto sstr2 = frame_zero.FindVariable("sstr2", lldb::eDynamicCanRunTarget); + auto sstr3 = frame_zero.FindVariable("sstr3", lldb::eDynamicCanRunTarget); + auto sstr4 = frame_zero.FindVariable("sstr4", lldb::eDynamicCanRunTarget); + + m_dump_std_string_measurement.Start(); + Xcode::FetchVariable(sstr0, 0, false); + m_dump_std_string_measurement.Stop(); + + m_dump_std_string_measurement.Start(); + Xcode::FetchVariable(sstr1, 0, false); + m_dump_std_string_measurement.Stop(); + + m_dump_std_string_measurement.Start(); + Xcode::FetchVariable(sstr2, 0, false); + m_dump_std_string_measurement.Stop(); + + m_dump_std_string_measurement.Start(); + Xcode::FetchVariable(sstr3, 0, false); + m_dump_std_string_measurement.Stop(); + + m_dump_std_string_measurement.Start(); + Xcode::FetchVariable(sstr4, 0, false); + m_dump_std_string_measurement.Stop(); + } + + virtual void TestStep(int counter, ActionWanted &next_action) { + switch (counter) { + case 0: + m_target.BreakpointCreateByLocation("fmts_tester.mm", 78); + next_action.Continue(); + break; + case 1: + DoTest(); + next_action.Continue(); + break; + case 2: + DoTest(); + next_action.Continue(); + break; + case 3: + DoTest(); + next_action.Continue(); + break; + case 4: + DoTest(); + next_action.Continue(); + break; + case 5: + DoTest(); + next_action.Continue(); + break; + case 6: + DoTest(); + next_action.Continue(); + break; + case 7: + DoTest(); + next_action.Continue(); + break; + case 8: + DoTest(); + next_action.Continue(); + break; + case 9: + DoTest(); + next_action.Continue(); + break; + case 10: + DoTest(); + next_action.Continue(); + break; + default: + next_action.Kill(); + break; } - + } + + virtual void WriteResults(Results &results) { + m_dump_std_vector_measurement.WriteAverageAndStandardDeviation(results); + m_dump_std_list_measurement.WriteAverageAndStandardDeviation(results); + m_dump_std_map_measurement.WriteAverageAndStandardDeviation(results); + m_dump_std_string_measurement.WriteAverageAndStandardDeviation(results); + + m_dump_nsstring_measurement.WriteAverageAndStandardDeviation(results); + m_dump_nsarray_measurement.WriteAverageAndStandardDeviation(results); + m_dump_nsdictionary_measurement.WriteAverageAndStandardDeviation(results); + m_dump_nsset_measurement.WriteAverageAndStandardDeviation(results); + m_dump_nsbundle_measurement.WriteAverageAndStandardDeviation(results); + m_dump_nsdate_measurement.WriteAverageAndStandardDeviation(results); + results.Write(m_out_path.c_str()); + } + private: - // C++ formatters - TimeMeasurement<std::function<void(SBValue)>> m_dump_std_vector_measurement; - TimeMeasurement<std::function<void(SBValue)>> m_dump_std_list_measurement; - TimeMeasurement<std::function<void(SBValue)>> m_dump_std_map_measurement; - TimeMeasurement<std::function<void()>> m_dump_std_string_measurement; - - // Cocoa formatters - TimeMeasurement<std::function<void(SBValue)>> m_dump_nsstring_measurement; - TimeMeasurement<std::function<void(SBValue)>> m_dump_nsarray_measurement; - TimeMeasurement<std::function<void(SBValue)>> m_dump_nsdictionary_measurement; - TimeMeasurement<std::function<void(SBValue)>> m_dump_nsset_measurement; - TimeMeasurement<std::function<void(SBValue)>> m_dump_nsbundle_measurement; - TimeMeasurement<std::function<void(SBValue)>> m_dump_nsdate_measurement; - - // useful files - std::string m_app_path; - std::string m_out_path; + // C++ formatters + TimeMeasurement<std::function<void(SBValue)>> m_dump_std_vector_measurement; + TimeMeasurement<std::function<void(SBValue)>> m_dump_std_list_measurement; + TimeMeasurement<std::function<void(SBValue)>> m_dump_std_map_measurement; + TimeMeasurement<std::function<void()>> m_dump_std_string_measurement; + + // Cocoa formatters + TimeMeasurement<std::function<void(SBValue)>> m_dump_nsstring_measurement; + TimeMeasurement<std::function<void(SBValue)>> m_dump_nsarray_measurement; + TimeMeasurement<std::function<void(SBValue)>> m_dump_nsdictionary_measurement; + TimeMeasurement<std::function<void(SBValue)>> m_dump_nsset_measurement; + TimeMeasurement<std::function<void(SBValue)>> m_dump_nsbundle_measurement; + TimeMeasurement<std::function<void(SBValue)>> m_dump_nsdate_measurement; + + // useful files + std::string m_app_path; + std::string m_out_path; }; // argv[1] == path to app // argv[2] == path to result -int main(int argc, const char * argv[]) -{ - FormattersTest frmtest; - frmtest.SetVerbose(true); - TestCase::Run(frmtest,argc,argv); - return 0; +int main(int argc, const char *argv[]) { + FormattersTest frmtest; + frmtest.SetVerbose(true); + TestCase::Run(frmtest, argc, argv); + return 0; } - diff --git a/lldb/tools/lldb-perf/darwin/sketch/sketch.cpp b/lldb/tools/lldb-perf/darwin/sketch/sketch.cpp index 93e39165c13..ddcb4453db9 100644 --- a/lldb/tools/lldb-perf/darwin/sketch/sketch.cpp +++ b/lldb/tools/lldb-perf/darwin/sketch/sketch.cpp @@ -9,152 +9,141 @@ #include <CoreFoundation/CoreFoundation.h> -#include "lldb-perf/lib/Timer.h" -#include "lldb-perf/lib/Metric.h" #include "lldb-perf/lib/Measurement.h" +#include "lldb-perf/lib/Metric.h" #include "lldb-perf/lib/TestCase.h" +#include "lldb-perf/lib/Timer.h" #include "lldb-perf/lib/Xcode.h" -#include <iostream> -#include <unistd.h> #include <fstream> #include <getopt.h> +#include <iostream> +#include <unistd.h> using namespace lldb_perf; static struct option g_long_options[] = { - { "verbose", no_argument, NULL, 'v' }, - { "sketch", required_argument, NULL, 'c' }, - { "foobar", required_argument, NULL, 'f' }, - { "out-file", required_argument, NULL, 'o' }, - { NULL, 0, NULL, 0 } -}; + {"verbose", no_argument, NULL, 'v'}, + {"sketch", required_argument, NULL, 'c'}, + {"foobar", required_argument, NULL, 'f'}, + {"out-file", required_argument, NULL, 'o'}, + {NULL, 0, NULL, 0}}; -class SketchTest : public TestCase -{ +class SketchTest : public TestCase { public: - SketchTest () : - m_fetch_frames_measurement ([this] () -> void - { - Xcode::FetchFrames (GetProcess(),false,false); - }, "fetch-frames", "time to dump backtrace for every frame in every thread"), - m_file_line_bp_measurement([this] (const char* file, uint32_t line) -> void - { - Xcode::CreateFileLineBreakpoint(GetTarget(), file, line); - }, "file-line-bkpt", "time to set a breakpoint given a file and line"), - m_fetch_modules_measurement ([this] () -> void - { - Xcode::FetchModules(GetTarget()); - }, "fetch-modules", "time to get info for all modules in the process"), - m_fetch_vars_measurement([this] (int depth) -> void - { - SBProcess process (GetProcess()); - auto threads_count = process.GetNumThreads(); - for (size_t thread_num = 0; thread_num < threads_count; thread_num++) - { - SBThread thread(process.GetThreadAtIndex(thread_num)); - SBFrame frame(thread.GetFrameAtIndex(0)); - Xcode::FetchVariables(frame,depth,GetVerbose()); - } - }, "fetch-vars", "time to dump variables for the topmost frame in every thread"), - m_run_expr_measurement([this] (SBFrame frame, const char* expr) -> void - { - SBValue value(frame.EvaluateExpression(expr, lldb::eDynamicCanRunTarget)); - Xcode::FetchVariable (value, 0, GetVerbose()); - }, "run-expr", "time to evaluate an expression and display the result") - { - m_app_path.clear(); - m_out_path.clear(); - m_doc_path.clear(); - m_print_help = false; - } - - virtual - ~SketchTest () - { + SketchTest() + : m_fetch_frames_measurement( + [this]() -> void { + Xcode::FetchFrames(GetProcess(), false, false); + }, + "fetch-frames", + "time to dump backtrace for every frame in every thread"), + m_file_line_bp_measurement( + [this](const char *file, uint32_t line) -> void { + Xcode::CreateFileLineBreakpoint(GetTarget(), file, line); + }, + "file-line-bkpt", "time to set a breakpoint given a file and line"), + m_fetch_modules_measurement( + [this]() -> void { Xcode::FetchModules(GetTarget()); }, + "fetch-modules", "time to get info for all modules in the process"), + m_fetch_vars_measurement( + [this](int depth) -> void { + SBProcess process(GetProcess()); + auto threads_count = process.GetNumThreads(); + for (size_t thread_num = 0; thread_num < threads_count; + thread_num++) { + SBThread thread(process.GetThreadAtIndex(thread_num)); + SBFrame frame(thread.GetFrameAtIndex(0)); + Xcode::FetchVariables(frame, depth, GetVerbose()); + } + }, + "fetch-vars", + "time to dump variables for the topmost frame in every thread"), + m_run_expr_measurement( + [this](SBFrame frame, const char *expr) -> void { + SBValue value( + frame.EvaluateExpression(expr, lldb::eDynamicCanRunTarget)); + Xcode::FetchVariable(value, 0, GetVerbose()); + }, + "run-expr", + "time to evaluate an expression and display the result") { + m_app_path.clear(); + m_out_path.clear(); + m_doc_path.clear(); + m_print_help = false; + } + + virtual ~SketchTest() {} + + virtual bool ParseOption(int short_option, const char *optarg) { + switch (short_option) { + case 0: + return false; + + case -1: + return false; + + case '?': + case 'h': + m_print_help = true; + break; + + case 'v': + SetVerbose(true); + break; + + case 'c': { + SBFileSpec file(optarg); + if (file.Exists()) + SetExecutablePath(optarg); + else + fprintf(stderr, "error: file specified in --sketch (-c) option doesn't " + "exist: '%s'\n", + optarg); + } break; + + case 'f': { + SBFileSpec file(optarg); + if (file.Exists()) + SetDocumentPath(optarg); + else + fprintf(stderr, "error: file specified in --foobar (-f) option doesn't " + "exist: '%s'\n", + optarg); + } break; + + case 'o': + SetResultFilePath(optarg); + break; + + default: + m_print_help = true; + fprintf(stderr, "error: unrecognized option %c\n", short_option); + break; } - - virtual bool - ParseOption (int short_option, const char* optarg) - { - switch (short_option) - { - case 0: - return false; - - case -1: - return false; - - case '?': - case 'h': - m_print_help = true; - break; - - case 'v': - SetVerbose(true); - break; - - case 'c': - { - SBFileSpec file(optarg); - if (file.Exists()) - SetExecutablePath(optarg); - else - fprintf(stderr, "error: file specified in --sketch (-c) option doesn't exist: '%s'\n", optarg); - } - break; - - case 'f': - { - SBFileSpec file(optarg); - if (file.Exists()) - SetDocumentPath(optarg); - else - fprintf(stderr, "error: file specified in --foobar (-f) option doesn't exist: '%s'\n", optarg); - } - break; - - case 'o': - SetResultFilePath(optarg); - break; - - default: - m_print_help = true; - fprintf (stderr, "error: unrecognized option %c\n", short_option); - break; - } - return true; + return true; + } + + virtual struct option *GetLongOptions() { return g_long_options; } + + virtual bool Setup(int &argc, const char **&argv) { + TestCase::Setup(argc, argv); + bool error = false; + + if (GetExecutablePath() == NULL) { + // --sketch is mandatory + error = true; + fprintf(stderr, "error: the '--sketch=PATH' option is mandatory\n"); } - - virtual struct option* - GetLongOptions () - { - return g_long_options; + + if (GetDocumentPath() == NULL) { + // --foobar is mandatory + error = true; + fprintf(stderr, "error: the '--foobar=PATH' option is mandatory\n"); } - - virtual bool - Setup (int& argc, const char**& argv) - { - TestCase::Setup(argc,argv); - bool error = false; - - if (GetExecutablePath() == NULL) - { - // --sketch is mandatory - error = true; - fprintf (stderr, "error: the '--sketch=PATH' option is mandatory\n"); - } - - if (GetDocumentPath() == NULL) - { - // --foobar is mandatory - error = true; - fprintf (stderr, "error: the '--foobar=PATH' option is mandatory\n"); - } - - if (error || GetPrintHelp()) - { - puts(R"( + + if (error || GetPrintHelp()) { + puts(R"( NAME lldb_perf_sketch -- a tool that measures LLDB peformance while debugging sketch. @@ -165,216 +154,177 @@ public: Runs a set of static timing and memory tasks against sketch and outputs results to a plist file. )"); - } - - if (error) - { - exit(1); - } - lldb::SBLaunchInfo launch_info = GetLaunchInfo(); - m_target = m_debugger.CreateTarget(m_app_path.c_str()); - m_file_line_bp_measurement("SKTDocument.m",245); - m_file_line_bp_measurement("SKTDocument.m",283); - m_file_line_bp_measurement("SKTText.m",326); - return Launch (launch_info); - } - - lldb::SBLaunchInfo - GetLaunchInfo () - { - const char* file_arg = m_doc_path.c_str(); - const char* persist_arg = "-ApplePersistenceIgnoreState"; - const char* persist_skip = "YES"; - const char* empty = nullptr; - const char* args[] = {file_arg,persist_arg,persist_skip,empty}; - return SBLaunchInfo(args); - } - - void - DoTest () - { - m_fetch_frames_measurement(); - m_fetch_modules_measurement(); - m_fetch_vars_measurement(1); - } - - virtual void - TestStep (int counter, ActionWanted &next_action) - { - static int launch = 1; - switch (counter % 10) - { - case 0: - { - DoTest (); - if (counter == 0) - m_file_line_bp_measurement("SKTDocument.m",254); - next_action.Continue(); - } - break; - - case 1: - { - DoTest (); - m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"properties"); - m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[properties description]"); - m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"typeName"); - m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"data"); - m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[data description]"); - next_action.Continue(); - } - break; - - case 2: - { - DoTest (); - next_action.Continue(); - } - break; - - case 3: - { - DoTest (); - next_action.StepOver(m_thread); - } - break; - - case 4: - { - DoTest (); - m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"layoutManager"); - m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"contents"); - next_action.StepOver(m_thread); - } - break; - - case 5: - { - DoTest (); - next_action.StepOver(m_thread); - } - break; - - case 6: - { - DoTest (); - next_action.StepOver(m_thread); - } - break; - - case 7: - { - DoTest (); - m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"@\"an NSString\""); - m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[(id)@\"an NSString\" description]"); - m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"@[@1,@2,@3]"); - next_action.StepOut(m_thread); - } - break; - - case 8: - { - DoTest (); - m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[graphics description]"); - m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"[selectionIndexes description]"); - m_run_expr_measurement(m_thread.GetFrameAtIndex(0),"(BOOL)NSIntersectsRect(rect, graphicDrawingBounds)"); - } - next_action.CallNext(); - break; - case 9: - if (++launch < 10) - next_action.Relaunch(GetLaunchInfo()); - else - next_action.Kill(); - break; - - - default: - { - next_action.Kill(); - } - break; - } - } - - virtual void - WriteResults (Results &results) - { - m_fetch_frames_measurement.WriteAverageAndStandardDeviation(results); - m_file_line_bp_measurement.WriteAverageAndStandardDeviation(results); - m_fetch_modules_measurement.WriteAverageAndStandardDeviation(results); - m_fetch_vars_measurement.WriteAverageAndStandardDeviation(results); - m_run_expr_measurement.WriteAverageAndStandardDeviation(results); - results.Write(GetResultFilePath()); - } - - void - SetExecutablePath (const char* str) - { - if (str) - m_app_path.assign(str); - } - - const char* - GetExecutablePath () - { - if (m_app_path.empty()) - return NULL; - return m_app_path.c_str(); - } - - void - SetDocumentPath (const char* str) - { - if (str) - m_doc_path.assign(str); - } - - const char* - GetDocumentPath () - { - if (m_doc_path.empty()) - return NULL; - return m_doc_path.c_str(); } - - void - SetResultFilePath (const char* str) - { - if (str) - m_out_path.assign(str); + if (error) { + exit(1); } - - const char* - GetResultFilePath () - { - if (m_out_path.empty()) - return "/dev/stdout"; - return m_out_path.c_str(); + lldb::SBLaunchInfo launch_info = GetLaunchInfo(); + m_target = m_debugger.CreateTarget(m_app_path.c_str()); + m_file_line_bp_measurement("SKTDocument.m", 245); + m_file_line_bp_measurement("SKTDocument.m", 283); + m_file_line_bp_measurement("SKTText.m", 326); + return Launch(launch_info); + } + + lldb::SBLaunchInfo GetLaunchInfo() { + const char *file_arg = m_doc_path.c_str(); + const char *persist_arg = "-ApplePersistenceIgnoreState"; + const char *persist_skip = "YES"; + const char *empty = nullptr; + const char *args[] = {file_arg, persist_arg, persist_skip, empty}; + return SBLaunchInfo(args); + } + + void DoTest() { + m_fetch_frames_measurement(); + m_fetch_modules_measurement(); + m_fetch_vars_measurement(1); + } + + virtual void TestStep(int counter, ActionWanted &next_action) { + static int launch = 1; + switch (counter % 10) { + case 0: { + DoTest(); + if (counter == 0) + m_file_line_bp_measurement("SKTDocument.m", 254); + next_action.Continue(); + } break; + + case 1: { + DoTest(); + m_run_expr_measurement(m_thread.GetFrameAtIndex(0), "properties"); + m_run_expr_measurement(m_thread.GetFrameAtIndex(0), + "[properties description]"); + m_run_expr_measurement(m_thread.GetFrameAtIndex(0), "typeName"); + m_run_expr_measurement(m_thread.GetFrameAtIndex(0), "data"); + m_run_expr_measurement(m_thread.GetFrameAtIndex(0), "[data description]"); + next_action.Continue(); + } break; + + case 2: { + DoTest(); + next_action.Continue(); + } break; + + case 3: { + DoTest(); + next_action.StepOver(m_thread); + } break; + + case 4: { + DoTest(); + m_run_expr_measurement(m_thread.GetFrameAtIndex(0), "layoutManager"); + m_run_expr_measurement(m_thread.GetFrameAtIndex(0), "contents"); + next_action.StepOver(m_thread); + } break; + + case 5: { + DoTest(); + next_action.StepOver(m_thread); + } break; + + case 6: { + DoTest(); + next_action.StepOver(m_thread); + } break; + + case 7: { + DoTest(); + m_run_expr_measurement(m_thread.GetFrameAtIndex(0), "@\"an NSString\""); + m_run_expr_measurement(m_thread.GetFrameAtIndex(0), + "[(id)@\"an NSString\" description]"); + m_run_expr_measurement(m_thread.GetFrameAtIndex(0), "@[@1,@2,@3]"); + next_action.StepOut(m_thread); + } break; + + case 8: { + DoTest(); + m_run_expr_measurement(m_thread.GetFrameAtIndex(0), + "[graphics description]"); + m_run_expr_measurement(m_thread.GetFrameAtIndex(0), + "[selectionIndexes description]"); + m_run_expr_measurement( + m_thread.GetFrameAtIndex(0), + "(BOOL)NSIntersectsRect(rect, graphicDrawingBounds)"); } - - bool - GetPrintHelp () - { - return m_print_help; + next_action.CallNext(); + break; + case 9: + if (++launch < 10) + next_action.Relaunch(GetLaunchInfo()); + else + next_action.Kill(); + break; + + default: { next_action.Kill(); } break; } - + } + + virtual void WriteResults(Results &results) { + m_fetch_frames_measurement.WriteAverageAndStandardDeviation(results); + m_file_line_bp_measurement.WriteAverageAndStandardDeviation(results); + m_fetch_modules_measurement.WriteAverageAndStandardDeviation(results); + m_fetch_vars_measurement.WriteAverageAndStandardDeviation(results); + m_run_expr_measurement.WriteAverageAndStandardDeviation(results); + results.Write(GetResultFilePath()); + } + + void SetExecutablePath(const char *str) { + if (str) + m_app_path.assign(str); + } + + const char *GetExecutablePath() { + if (m_app_path.empty()) + return NULL; + return m_app_path.c_str(); + } + + void SetDocumentPath(const char *str) { + if (str) + m_doc_path.assign(str); + } + + const char *GetDocumentPath() { + if (m_doc_path.empty()) + return NULL; + return m_doc_path.c_str(); + } + + void SetResultFilePath(const char *str) { + if (str) + m_out_path.assign(str); + } + + const char *GetResultFilePath() { + if (m_out_path.empty()) + return "/dev/stdout"; + return m_out_path.c_str(); + } + + bool GetPrintHelp() { return m_print_help; } + private: - Measurement<lldb_perf::TimeGauge, std::function<void()>> m_fetch_frames_measurement; - Measurement<lldb_perf::TimeGauge, std::function<void(const char*, uint32_t)>> m_file_line_bp_measurement; - Measurement<lldb_perf::TimeGauge, std::function<void()>> m_fetch_modules_measurement; - Measurement<lldb_perf::TimeGauge, std::function<void(int)>> m_fetch_vars_measurement; - Measurement<lldb_perf::TimeGauge, std::function<void(SBFrame, const char*)>> m_run_expr_measurement; - - std::string m_app_path; - std::string m_doc_path; - std::string m_out_path; - bool m_print_help; + Measurement<lldb_perf::TimeGauge, std::function<void()>> + m_fetch_frames_measurement; + Measurement<lldb_perf::TimeGauge, std::function<void(const char *, uint32_t)>> + m_file_line_bp_measurement; + Measurement<lldb_perf::TimeGauge, std::function<void()>> + m_fetch_modules_measurement; + Measurement<lldb_perf::TimeGauge, std::function<void(int)>> + m_fetch_vars_measurement; + Measurement<lldb_perf::TimeGauge, std::function<void(SBFrame, const char *)>> + m_run_expr_measurement; + + std::string m_app_path; + std::string m_doc_path; + std::string m_out_path; + bool m_print_help; }; -int main(int argc, const char * argv[]) -{ - SketchTest test; - return TestCase::Run(test, argc, argv); +int main(int argc, const char *argv[]) { + SketchTest test; + return TestCase::Run(test, argc, argv); } diff --git a/lldb/tools/lldb-perf/lib/Gauge.cpp b/lldb/tools/lldb-perf/lib/Gauge.cpp index 4c4593b3b29..8c3333daad6 100644 --- a/lldb/tools/lldb-perf/lib/Gauge.cpp +++ b/lldb/tools/lldb-perf/lib/Gauge.cpp @@ -11,43 +11,40 @@ #include "lldb/lldb-forward.h" template <> -lldb_perf::Results::ResultSP -lldb_perf::GetResult (const char *description, double value) -{ - if (description && description[0]) - { - std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ()); - value_dict_ap->AddString("description", NULL, description); - value_dict_ap->AddDouble("value", NULL, value); - return Results::ResultSP (value_dict_ap.release()); - } - return Results::ResultSP (new Results::Double (NULL, NULL, value)); +lldb_perf::Results::ResultSP lldb_perf::GetResult(const char *description, + double value) { + if (description && description[0]) { + std::unique_ptr<Results::Dictionary> value_dict_ap( + new Results::Dictionary()); + value_dict_ap->AddString("description", NULL, description); + value_dict_ap->AddDouble("value", NULL, value); + return Results::ResultSP(value_dict_ap.release()); + } + return Results::ResultSP(new Results::Double(NULL, NULL, value)); } template <> -lldb_perf::Results::ResultSP -lldb_perf::GetResult (const char *description, uint64_t value) -{ - if (description && description[0]) - { - std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ()); - value_dict_ap->AddString("description", NULL, description); - value_dict_ap->AddUnsigned("value", NULL, value); - return Results::ResultSP (value_dict_ap.release()); - } - return Results::ResultSP (new Results::Unsigned (NULL, NULL, value)); +lldb_perf::Results::ResultSP lldb_perf::GetResult(const char *description, + uint64_t value) { + if (description && description[0]) { + std::unique_ptr<Results::Dictionary> value_dict_ap( + new Results::Dictionary()); + value_dict_ap->AddString("description", NULL, description); + value_dict_ap->AddUnsigned("value", NULL, value); + return Results::ResultSP(value_dict_ap.release()); + } + return Results::ResultSP(new Results::Unsigned(NULL, NULL, value)); } template <> -lldb_perf::Results::ResultSP -lldb_perf::GetResult (const char *description, std::string value) -{ - if (description && description[0]) - { - std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ()); - value_dict_ap->AddString("description", NULL, description); - value_dict_ap->AddString("value", NULL, value.c_str()); - return Results::ResultSP (value_dict_ap.release()); - } - return Results::ResultSP (new Results::String (NULL, NULL, value.c_str())); +lldb_perf::Results::ResultSP lldb_perf::GetResult(const char *description, + std::string value) { + if (description && description[0]) { + std::unique_ptr<Results::Dictionary> value_dict_ap( + new Results::Dictionary()); + value_dict_ap->AddString("description", NULL, description); + value_dict_ap->AddString("value", NULL, value.c_str()); + return Results::ResultSP(value_dict_ap.release()); + } + return Results::ResultSP(new Results::String(NULL, NULL, value.c_str())); } diff --git a/lldb/tools/lldb-perf/lib/Gauge.h b/lldb/tools/lldb-perf/lib/Gauge.h index fc5c444a38b..1fecbdb5eef 100644 --- a/lldb/tools/lldb-perf/lib/Gauge.h +++ b/lldb/tools/lldb-perf/lib/Gauge.h @@ -17,48 +17,35 @@ namespace lldb_perf { -template <class T> -class Gauge -{ +template <class T> class Gauge { public: - typedef T ValueType; - - Gauge () - {} - - virtual - ~Gauge () - {} - - virtual void - Start () = 0; - - virtual ValueType - Stop () = 0; - - virtual ValueType - GetStartValue () const = 0; - - virtual ValueType - GetStopValue () const = 0; - - virtual ValueType - GetDeltaValue () const = 0; + typedef T ValueType; + + Gauge() {} + + virtual ~Gauge() {} + + virtual void Start() = 0; + + virtual ValueType Stop() = 0; + virtual ValueType GetStartValue() const = 0; + + virtual ValueType GetStopValue() const = 0; + + virtual ValueType GetDeltaValue() const = 0; }; template <class T> -Results::ResultSP GetResult (const char *description, T value); +Results::ResultSP GetResult(const char *description, T value); -template <> -Results::ResultSP GetResult (const char *description, double value); +template <> Results::ResultSP GetResult(const char *description, double value); template <> -Results::ResultSP GetResult (const char *description, uint64_t value); +Results::ResultSP GetResult(const char *description, uint64_t value); template <> -Results::ResultSP GetResult (const char *description, std::string value); - +Results::ResultSP GetResult(const char *description, std::string value); } #endif diff --git a/lldb/tools/lldb-perf/lib/Measurement.h b/lldb/tools/lldb-perf/lib/Measurement.h index 877e618d546..1795211a549 100644 --- a/lldb/tools/lldb-perf/lib/Measurement.h +++ b/lldb/tools/lldb-perf/lib/Measurement.h @@ -11,207 +11,148 @@ #define __PerfTestDriver__Measurement__ #include "Gauge.h" -#include "Timer.h" -#include "Metric.h" #include "MemoryGauge.h" +#include "Metric.h" +#include "Timer.h" -namespace lldb_perf -{ -template <typename GaugeType, typename Callable> -class Measurement -{ +namespace lldb_perf { +template <typename GaugeType, typename Callable> class Measurement { public: - Measurement () : - m_gauge (), - m_callable (), - m_metric () - { - } - - Measurement (Callable callable, const char* name, const char* desc) : - m_gauge (), - m_callable (callable), - m_metric (Metric<typename GaugeType::ValueType>(name, desc)) - { - } + Measurement() : m_gauge(), m_callable(), m_metric() {} - Measurement (const char* name, const char* desc) : - m_gauge (), - m_callable (), - m_metric (Metric<typename GaugeType::ValueType>(name, desc)) - { - } + Measurement(Callable callable, const char *name, const char *desc) + : m_gauge(), m_callable(callable), + m_metric(Metric<typename GaugeType::ValueType>(name, desc)) {} - template <typename GaugeType_Rhs, typename Callable_Rhs> - Measurement (const Measurement<GaugeType_Rhs, Callable_Rhs>& rhs) : - m_gauge(rhs.GetGauge()), - m_callable(rhs.GetCallable()), - m_metric(rhs.GetMetric()) - { - } + Measurement(const char *name, const char *desc) + : m_gauge(), m_callable(), + m_metric(Metric<typename GaugeType::ValueType>(name, desc)) {} - template <typename... Args> - void - operator () (Args... args) - { - m_gauge.Start(); - m_callable(args...); - m_metric.Append (m_gauge.Stop()); - } - - virtual const Callable& - GetCallable () const - { - return m_callable; - } - - virtual const GaugeType& - GetGauge () const - { - return m_gauge; - } - - virtual const Metric<typename GaugeType::ValueType>& - GetMetric () const - { - return m_metric; - } - - void - Start () - { - m_gauge.Start(); - } - - typename GaugeType::ValueType - Stop () - { - auto value = m_gauge.Stop(); - m_metric.Append(value); - return value; - } + template <typename GaugeType_Rhs, typename Callable_Rhs> + Measurement(const Measurement<GaugeType_Rhs, Callable_Rhs> &rhs) + : m_gauge(rhs.GetGauge()), m_callable(rhs.GetCallable()), + m_metric(rhs.GetMetric()) {} - void - WriteStartValue (Results &results) - { - auto metric = GetMetric (); - results.GetDictionary().Add(metric.GetName(), metric.GetDescription(), lldb_perf::GetResult<typename GaugeType::ValueType> (NULL, metric.GetStartValue())); - } - - void - WriteStopValue (Results &results) - { - auto metric = GetMetric (); - results.GetDictionary().Add(metric.GetName(), metric.GetDescription(), lldb_perf::GetResult<typename GaugeType::ValueType> (NULL, metric.GetStopValue())); - } + template <typename... Args> void operator()(Args... args) { + m_gauge.Start(); + m_callable(args...); + m_metric.Append(m_gauge.Stop()); + } - void - WriteAverageValue (Results &results) - { - auto metric = GetMetric (); - results.GetDictionary().Add(metric.GetName(), metric.GetDescription(), lldb_perf::GetResult<typename GaugeType::ValueType> (NULL, metric.GetAverage())); - } - - void - WriteAverageAndStandardDeviation (Results &results) - { - auto metric = GetMetric (); - auto dictionary = (Results::Dictionary*)results.GetDictionary().Add(metric.GetName(), metric.GetDescription(), lldb_perf::GetResult<typename GaugeType::ValueType> (NULL, metric.GetAverage())).get(); - if (dictionary) - { - dictionary->Add("stddev", NULL, lldb_perf::GetResult<typename GaugeType::ValueType> (NULL, metric.GetStandardDeviation())); - } - } - - void - WriteStandardDeviation (Results &results) - { - auto metric = GetMetric (); - results.GetDictionary().Add(metric.GetName(), metric.GetDescription(), lldb_perf::GetResult<typename GaugeType::ValueType> (NULL, metric.GetStandardDeviation())); - } + virtual const Callable &GetCallable() const { return m_callable; } + + virtual const GaugeType &GetGauge() const { return m_gauge; } + + virtual const Metric<typename GaugeType::ValueType> &GetMetric() const { + return m_metric; + } + + void Start() { m_gauge.Start(); } + + typename GaugeType::ValueType Stop() { + auto value = m_gauge.Stop(); + m_metric.Append(value); + return value; + } + + void WriteStartValue(Results &results) { + auto metric = GetMetric(); + results.GetDictionary().Add( + metric.GetName(), metric.GetDescription(), + lldb_perf::GetResult<typename GaugeType::ValueType>( + NULL, metric.GetStartValue())); + } + + void WriteStopValue(Results &results) { + auto metric = GetMetric(); + results.GetDictionary().Add( + metric.GetName(), metric.GetDescription(), + lldb_perf::GetResult<typename GaugeType::ValueType>( + NULL, metric.GetStopValue())); + } + + void WriteAverageValue(Results &results) { + auto metric = GetMetric(); + results.GetDictionary().Add( + metric.GetName(), metric.GetDescription(), + lldb_perf::GetResult<typename GaugeType::ValueType>( + NULL, metric.GetAverage())); + } + + void WriteAverageAndStandardDeviation(Results &results) { + auto metric = GetMetric(); + auto dictionary = + (Results::Dictionary *)results.GetDictionary() + .Add(metric.GetName(), metric.GetDescription(), + lldb_perf::GetResult<typename GaugeType::ValueType>( + NULL, metric.GetAverage())) + .get(); + if (dictionary) { + dictionary->Add("stddev", NULL, + lldb_perf::GetResult<typename GaugeType::ValueType>( + NULL, metric.GetStandardDeviation())); + } + } + + void WriteStandardDeviation(Results &results) { + auto metric = GetMetric(); + results.GetDictionary().Add( + metric.GetName(), metric.GetDescription(), + lldb_perf::GetResult<typename GaugeType::ValueType>( + NULL, metric.GetStandardDeviation())); + } protected: - GaugeType m_gauge; - Callable m_callable; - Metric<typename GaugeType::ValueType> m_metric; + GaugeType m_gauge; + Callable m_callable; + Metric<typename GaugeType::ValueType> m_metric; }; - + template <typename Callable> -class TimeMeasurement : public Measurement<TimeGauge,Callable> -{ +class TimeMeasurement : public Measurement<TimeGauge, Callable> { public: - TimeMeasurement () : - Measurement<TimeGauge,Callable> () - { - } - - TimeMeasurement (Callable callable, - const char* name = NULL, - const char* descr = NULL) : - Measurement<TimeGauge,Callable> (callable, name, descr) - { - } - - template <typename Callable_Rhs> - TimeMeasurement (const TimeMeasurement<Callable_Rhs>& rhs) : - Measurement<TimeGauge,Callable>(rhs) - { - } - - template <typename GaugeType_Rhs, typename Callable_Rhs> - TimeMeasurement (const Measurement<GaugeType_Rhs, Callable_Rhs>& rhs) : - Measurement<GaugeType_Rhs,Callable_Rhs>(rhs) - { - } - - template <typename... Args> - void - operator () (Args... args) - { - Measurement<TimeGauge,Callable>::operator()(args...); - } + TimeMeasurement() : Measurement<TimeGauge, Callable>() {} + + TimeMeasurement(Callable callable, const char *name = NULL, + const char *descr = NULL) + : Measurement<TimeGauge, Callable>(callable, name, descr) {} + + template <typename Callable_Rhs> + TimeMeasurement(const TimeMeasurement<Callable_Rhs> &rhs) + : Measurement<TimeGauge, Callable>(rhs) {} + + template <typename GaugeType_Rhs, typename Callable_Rhs> + TimeMeasurement(const Measurement<GaugeType_Rhs, Callable_Rhs> &rhs) + : Measurement<GaugeType_Rhs, Callable_Rhs>(rhs) {} + + template <typename... Args> void operator()(Args... args) { + Measurement<TimeGauge, Callable>::operator()(args...); + } }; template <typename Callable> -class MemoryMeasurement : public Measurement<MemoryGauge,Callable> -{ +class MemoryMeasurement : public Measurement<MemoryGauge, Callable> { public: - MemoryMeasurement () : Measurement<MemoryGauge,Callable> () - { - } - - MemoryMeasurement (Callable callable, - const char* name, - const char* descr) : - Measurement<MemoryGauge,Callable> (callable, name, descr) - { - } + MemoryMeasurement() : Measurement<MemoryGauge, Callable>() {} - MemoryMeasurement (const char* name, const char* descr) : - Measurement<MemoryGauge,Callable> (name, descr) - { - } + MemoryMeasurement(Callable callable, const char *name, const char *descr) + : Measurement<MemoryGauge, Callable>(callable, name, descr) {} - template <typename Callable_Rhs> - MemoryMeasurement (const MemoryMeasurement<Callable_Rhs>& rhs) : - Measurement<MemoryGauge,Callable>(rhs) - { - } - - template <typename GaugeType_Rhs, typename Callable_Rhs> - MemoryMeasurement (const Measurement<GaugeType_Rhs, Callable_Rhs>& rhs) : - Measurement<GaugeType_Rhs,Callable_Rhs>(rhs) - { - } - - template <typename... Args> - void - operator () (Args... args) - { - Measurement<MemoryGauge,Callable>::operator()(args...); - } + MemoryMeasurement(const char *name, const char *descr) + : Measurement<MemoryGauge, Callable>(name, descr) {} + + template <typename Callable_Rhs> + MemoryMeasurement(const MemoryMeasurement<Callable_Rhs> &rhs) + : Measurement<MemoryGauge, Callable>(rhs) {} + + template <typename GaugeType_Rhs, typename Callable_Rhs> + MemoryMeasurement(const Measurement<GaugeType_Rhs, Callable_Rhs> &rhs) + : Measurement<GaugeType_Rhs, Callable_Rhs>(rhs) {} + + template <typename... Args> void operator()(Args... args) { + Measurement<MemoryGauge, Callable>::operator()(args...); + } }; - } #endif /* defined(__PerfTestDriver__Measurement__) */ diff --git a/lldb/tools/lldb-perf/lib/MemoryGauge.cpp b/lldb/tools/lldb-perf/lib/MemoryGauge.cpp index 2a46453f540..2727f9b5687 100644 --- a/lldb/tools/lldb-perf/lib/MemoryGauge.cpp +++ b/lldb/tools/lldb-perf/lib/MemoryGauge.cpp @@ -12,154 +12,122 @@ #include <assert.h> #include <cmath> #include <mach/mach.h> -#include <mach/task.h> #include <mach/mach_traps.h> +#include <mach/task.h> using namespace lldb_perf; -MemoryStats::MemoryStats (mach_vm_size_t virtual_size, - mach_vm_size_t resident_size, - mach_vm_size_t max_resident_size) : - m_virtual_size (virtual_size), - m_resident_size (resident_size), - m_max_resident_size (max_resident_size) -{ -} - -MemoryStats::MemoryStats (const MemoryStats& rhs) : - m_virtual_size (rhs.m_virtual_size), - m_resident_size (rhs.m_resident_size), - m_max_resident_size (rhs.m_max_resident_size) -{ -} +MemoryStats::MemoryStats(mach_vm_size_t virtual_size, + mach_vm_size_t resident_size, + mach_vm_size_t max_resident_size) + : m_virtual_size(virtual_size), m_resident_size(resident_size), + m_max_resident_size(max_resident_size) {} +MemoryStats::MemoryStats(const MemoryStats &rhs) + : m_virtual_size(rhs.m_virtual_size), m_resident_size(rhs.m_resident_size), + m_max_resident_size(rhs.m_max_resident_size) {} -MemoryStats& -MemoryStats::operator = (const MemoryStats& rhs) -{ - if (this != &rhs) - { - m_virtual_size = rhs.m_virtual_size; - m_resident_size = rhs.m_resident_size; - m_max_resident_size = rhs.m_max_resident_size; - } - return *this; +MemoryStats &MemoryStats::operator=(const MemoryStats &rhs) { + if (this != &rhs) { + m_virtual_size = rhs.m_virtual_size; + m_resident_size = rhs.m_resident_size; + m_max_resident_size = rhs.m_max_resident_size; + } + return *this; } -MemoryStats& -MemoryStats::operator += (const MemoryStats& rhs) -{ - m_virtual_size += rhs.m_virtual_size; - m_resident_size += rhs.m_resident_size; - m_max_resident_size += rhs.m_max_resident_size; - return *this; +MemoryStats &MemoryStats::operator+=(const MemoryStats &rhs) { + m_virtual_size += rhs.m_virtual_size; + m_resident_size += rhs.m_resident_size; + m_max_resident_size += rhs.m_max_resident_size; + return *this; } -MemoryStats -MemoryStats::operator - (const MemoryStats& rhs) -{ - return MemoryStats(m_virtual_size - rhs.m_virtual_size, - m_resident_size - rhs.m_resident_size, - m_max_resident_size - rhs.m_max_resident_size); +MemoryStats MemoryStats::operator-(const MemoryStats &rhs) { + return MemoryStats(m_virtual_size - rhs.m_virtual_size, + m_resident_size - rhs.m_resident_size, + m_max_resident_size - rhs.m_max_resident_size); } -MemoryStats -MemoryStats::operator + (const MemoryStats& rhs) -{ - return MemoryStats(m_virtual_size + rhs.m_virtual_size, - m_resident_size + rhs.m_resident_size, - m_max_resident_size + rhs.m_max_resident_size); +MemoryStats MemoryStats::operator+(const MemoryStats &rhs) { + return MemoryStats(m_virtual_size + rhs.m_virtual_size, + m_resident_size + rhs.m_resident_size, + m_max_resident_size + rhs.m_max_resident_size); } -MemoryStats -MemoryStats::operator / (size_t n) -{ - MemoryStats result(*this); - result.m_virtual_size /= n; - result.m_resident_size /= n; - result.m_max_resident_size /= n; - return result; +MemoryStats MemoryStats::operator/(size_t n) { + MemoryStats result(*this); + result.m_virtual_size /= n; + result.m_resident_size /= n; + result.m_max_resident_size /= n; + return result; } -MemoryStats -MemoryStats::operator * (const MemoryStats& rhs) -{ - return MemoryStats(m_virtual_size * rhs.m_virtual_size, - m_resident_size * rhs.m_resident_size, - m_max_resident_size * rhs.m_max_resident_size); +MemoryStats MemoryStats::operator*(const MemoryStats &rhs) { + return MemoryStats(m_virtual_size * rhs.m_virtual_size, + m_resident_size * rhs.m_resident_size, + m_max_resident_size * rhs.m_max_resident_size); } -Results::ResultSP -MemoryStats::GetResult (const char *name, const char *description) const -{ - std::unique_ptr<Results::Dictionary> dict_ap (new Results::Dictionary (name, NULL)); - dict_ap->AddUnsigned("resident", NULL, GetResidentSize()); - dict_ap->AddUnsigned("max_resident", NULL, GetMaxResidentSize()); - return Results::ResultSP(dict_ap.release()); +Results::ResultSP MemoryStats::GetResult(const char *name, + const char *description) const { + std::unique_ptr<Results::Dictionary> dict_ap( + new Results::Dictionary(name, NULL)); + dict_ap->AddUnsigned("resident", NULL, GetResidentSize()); + dict_ap->AddUnsigned("max_resident", NULL, GetMaxResidentSize()); + return Results::ResultSP(dict_ap.release()); } -MemoryGauge::ValueType -MemoryGauge::Now () -{ - task_t task = mach_task_self(); - mach_task_basic_info_data_t taskBasicInfo; - mach_msg_type_number_t count = MACH_TASK_BASIC_INFO_COUNT; - auto task_info_ret = task_info(task, MACH_TASK_BASIC_INFO, (task_info_t) & taskBasicInfo, &count); - if (task_info_ret == KERN_SUCCESS) { - return MemoryStats(taskBasicInfo.virtual_size, taskBasicInfo.resident_size, taskBasicInfo.resident_size_max); - } - return 0; +MemoryGauge::ValueType MemoryGauge::Now() { + task_t task = mach_task_self(); + mach_task_basic_info_data_t taskBasicInfo; + mach_msg_type_number_t count = MACH_TASK_BASIC_INFO_COUNT; + auto task_info_ret = task_info(task, MACH_TASK_BASIC_INFO, + (task_info_t)&taskBasicInfo, &count); + if (task_info_ret == KERN_SUCCESS) { + return MemoryStats(taskBasicInfo.virtual_size, taskBasicInfo.resident_size, + taskBasicInfo.resident_size_max); + } + return 0; } -MemoryGauge::MemoryGauge () : - m_state(MemoryGauge::State::eNeverUsed), - m_start(), - m_delta() -{ -} +MemoryGauge::MemoryGauge() + : m_state(MemoryGauge::State::eNeverUsed), m_start(), m_delta() {} -void -MemoryGauge::Start () -{ - m_state = MemoryGauge::State::eCounting; - m_start = Now(); +void MemoryGauge::Start() { + m_state = MemoryGauge::State::eCounting; + m_start = Now(); } -MemoryGauge::ValueType -MemoryGauge::Stop () -{ - m_stop = Now(); - assert(m_state == MemoryGauge::State::eCounting && "cannot stop a non-started gauge"); - m_state = MemoryGauge::State::eStopped; - m_delta = m_stop - m_start; - return m_delta; +MemoryGauge::ValueType MemoryGauge::Stop() { + m_stop = Now(); + assert(m_state == MemoryGauge::State::eCounting && + "cannot stop a non-started gauge"); + m_state = MemoryGauge::State::eStopped; + m_delta = m_stop - m_start; + return m_delta; } - -MemoryGauge::ValueType -MemoryGauge::GetDeltaValue () const -{ - assert(m_state == MemoryGauge::State::eStopped && "gauge must be used before you can evaluate it"); - return m_delta; +MemoryGauge::ValueType MemoryGauge::GetDeltaValue() const { + assert(m_state == MemoryGauge::State::eStopped && + "gauge must be used before you can evaluate it"); + return m_delta; } template <> -Results::ResultSP -lldb_perf::GetResult (const char *description, MemoryStats value) -{ - return value.GetResult (NULL, description); +Results::ResultSP lldb_perf::GetResult(const char *description, + MemoryStats value) { + return value.GetResult(NULL, description); } -MemoryStats -sqrt (const MemoryStats& arg) -{ - long double virt_size = arg.GetVirtualSize(); - long double resident_size = arg.GetResidentSize(); - long double max_resident_size = arg.GetMaxResidentSize(); - - virt_size = sqrtl(virt_size); - resident_size = sqrtl(resident_size); - max_resident_size = sqrtl(max_resident_size); - - return MemoryStats(virt_size,resident_size,max_resident_size); +MemoryStats sqrt(const MemoryStats &arg) { + long double virt_size = arg.GetVirtualSize(); + long double resident_size = arg.GetResidentSize(); + long double max_resident_size = arg.GetMaxResidentSize(); + + virt_size = sqrtl(virt_size); + resident_size = sqrtl(resident_size); + max_resident_size = sqrtl(max_resident_size); + + return MemoryStats(virt_size, resident_size, max_resident_size); } diff --git a/lldb/tools/lldb-perf/lib/MemoryGauge.h b/lldb/tools/lldb-perf/lib/MemoryGauge.h index a1221b6b66c..beed624bf1a 100644 --- a/lldb/tools/lldb-perf/lib/MemoryGauge.h +++ b/lldb/tools/lldb-perf/lib/MemoryGauge.h @@ -17,131 +17,76 @@ namespace lldb_perf { -class MemoryStats -{ +class MemoryStats { public: - MemoryStats (mach_vm_size_t virtual_size = 0, - mach_vm_size_t resident_size = 0, - mach_vm_size_t max_resident_size = 0); - MemoryStats (const MemoryStats& rhs); - - MemoryStats& - operator = (const MemoryStats& rhs); - - MemoryStats& - operator += (const MemoryStats& rhs); - - MemoryStats - operator - (const MemoryStats& rhs); - - MemoryStats - operator + (const MemoryStats& rhs); - - MemoryStats - operator / (size_t rhs); - - MemoryStats - operator * (const MemoryStats& rhs); - - mach_vm_size_t - GetVirtualSize () const - { - return m_virtual_size; - } - - mach_vm_size_t - GetResidentSize () const - { - return m_resident_size; - } - - mach_vm_size_t - GetMaxResidentSize () const - { - return m_max_resident_size; - } - - void - SetVirtualSize (mach_vm_size_t vs) - { - m_virtual_size = vs; - } - - void - SetResidentSize (mach_vm_size_t rs) - { - m_resident_size = rs; - } - - void - SetMaxResidentSize (mach_vm_size_t mrs) - { - m_max_resident_size = mrs; - } - - Results::ResultSP - GetResult (const char *name, const char *description) const; + MemoryStats(mach_vm_size_t virtual_size = 0, mach_vm_size_t resident_size = 0, + mach_vm_size_t max_resident_size = 0); + MemoryStats(const MemoryStats &rhs); + + MemoryStats &operator=(const MemoryStats &rhs); + + MemoryStats &operator+=(const MemoryStats &rhs); + + MemoryStats operator-(const MemoryStats &rhs); + + MemoryStats operator+(const MemoryStats &rhs); + + MemoryStats operator/(size_t rhs); + + MemoryStats operator*(const MemoryStats &rhs); + + mach_vm_size_t GetVirtualSize() const { return m_virtual_size; } + + mach_vm_size_t GetResidentSize() const { return m_resident_size; } + + mach_vm_size_t GetMaxResidentSize() const { return m_max_resident_size; } + + void SetVirtualSize(mach_vm_size_t vs) { m_virtual_size = vs; } + + void SetResidentSize(mach_vm_size_t rs) { m_resident_size = rs; } + + void SetMaxResidentSize(mach_vm_size_t mrs) { m_max_resident_size = mrs; } + + Results::ResultSP GetResult(const char *name, const char *description) const; + private: - mach_vm_size_t m_virtual_size; - mach_vm_size_t m_resident_size; - mach_vm_size_t m_max_resident_size; + mach_vm_size_t m_virtual_size; + mach_vm_size_t m_resident_size; + mach_vm_size_t m_max_resident_size; }; - -class MemoryGauge : public Gauge<MemoryStats> -{ + +class MemoryGauge : public Gauge<MemoryStats> { public: - MemoryGauge (); - - virtual - ~MemoryGauge () - { - } - - void - Start (); - - ValueType - Stop (); - - virtual ValueType - GetStartValue() const - { - return m_start; - } - - virtual ValueType - GetStopValue() const - { - return m_stop; - } - - virtual ValueType - GetDeltaValue() const; + MemoryGauge(); + + virtual ~MemoryGauge() {} + + void Start(); + + ValueType Stop(); + + virtual ValueType GetStartValue() const { return m_start; } + + virtual ValueType GetStopValue() const { return m_stop; } + + virtual ValueType GetDeltaValue() const; private: - enum class State - { - eNeverUsed, - eCounting, - eStopped - }; - - ValueType - Now (); - - State m_state; - ValueType m_start; - ValueType m_stop; - ValueType m_delta; + enum class State { eNeverUsed, eCounting, eStopped }; + + ValueType Now(); + + State m_state; + ValueType m_start; + ValueType m_stop; + ValueType m_delta; }; template <> -Results::ResultSP -GetResult (const char *description, MemoryStats value); - +Results::ResultSP GetResult(const char *description, MemoryStats value); + } // namespace lldb_perf -lldb_perf::MemoryStats -sqrt (const lldb_perf::MemoryStats& arg); +lldb_perf::MemoryStats sqrt(const lldb_perf::MemoryStats &arg); #endif // #ifndef __PerfTestDriver__MemoryGauge__ diff --git a/lldb/tools/lldb-perf/lib/Metric.cpp b/lldb/tools/lldb-perf/lib/Metric.cpp index 1951cdb0250..f049e6c246a 100644 --- a/lldb/tools/lldb-perf/lib/Metric.cpp +++ b/lldb/tools/lldb-perf/lib/Metric.cpp @@ -13,72 +13,47 @@ using namespace lldb_perf; -template <class T> -Metric<T>::Metric () : Metric ("") -{ -} +template <class T> Metric<T>::Metric() : Metric("") {} template <class T> -Metric<T>::Metric (const char* n, const char* d) : - m_name(n ? n : ""), - m_description(d ? d : ""), - m_dataset () -{ -} +Metric<T>::Metric(const char *n, const char *d) + : m_name(n ? n : ""), m_description(d ? d : ""), m_dataset() {} -template <class T> -void -Metric<T>::Append (T v) -{ - m_dataset.push_back(v); -} +template <class T> void Metric<T>::Append(T v) { m_dataset.push_back(v); } -template <class T> -size_t -Metric<T>::GetCount () const -{ - return m_dataset.size(); +template <class T> size_t Metric<T>::GetCount() const { + return m_dataset.size(); } -template <class T> -T -Metric<T>::GetSum () const -{ - T sum = 0; - for (auto v : m_dataset) - sum += v; - return sum; +template <class T> T Metric<T>::GetSum() const { + T sum = 0; + for (auto v : m_dataset) + sum += v; + return sum; } -template <class T> -T -Metric<T>::GetAverage () const -{ - return GetSum()/GetCount(); +template <class T> T Metric<T>::GetAverage() const { + return GetSum() / GetCount(); } - // Knuth's algorithm for stddev - massive cancellation resistant template <class T> -T -Metric<T>::GetStandardDeviation (StandardDeviationMode mode) const -{ - size_t n = 0; - T mean = 0; - T M2 = 0; - for (auto x : m_dataset) - { - n = n + 1; - T delta = x - mean; - mean = mean + delta/n; - M2 = M2+delta*(x-mean); - } - T variance; - if (mode == StandardDeviationMode::ePopulation || n == 1) - variance = M2 / n; - else - variance = M2 / (n - 1); - return sqrt(variance); +T Metric<T>::GetStandardDeviation(StandardDeviationMode mode) const { + size_t n = 0; + T mean = 0; + T M2 = 0; + for (auto x : m_dataset) { + n = n + 1; + T delta = x - mean; + mean = mean + delta / n; + M2 = M2 + delta * (x - mean); + } + T variance; + if (mode == StandardDeviationMode::ePopulation || n == 1) + variance = M2 / n; + else + variance = M2 / (n - 1); + return sqrt(variance); } template class lldb_perf::Metric<double>; diff --git a/lldb/tools/lldb-perf/lib/Metric.h b/lldb/tools/lldb-perf/lib/Metric.h index 45342d25b41..bee02cbe76d 100644 --- a/lldb/tools/lldb-perf/lib/Metric.h +++ b/lldb/tools/lldb-perf/lib/Metric.h @@ -10,62 +10,48 @@ #ifndef __PerfTestDriver__Metric__ #define __PerfTestDriver__Metric__ -#include <vector> -#include <string> #include <mach/task_info.h> +#include <string> +#include <vector> namespace lldb_perf { class MemoryStats; -template <class ValueType> -class Metric -{ +template <class ValueType> class Metric { public: - enum class StandardDeviationMode - { - eSample, - ePopulation - }; - - Metric (); - Metric (const char*, const char* = NULL); - - void - Append (ValueType v); - - ValueType - GetAverage () const; - - size_t - GetCount () const; - - ValueType - GetSum () const; - - ValueType - GetStandardDeviation (StandardDeviationMode mode = StandardDeviationMode::ePopulation) const; - - const char* - GetName () const - { - if (m_name.empty()) - return NULL; - return m_name.c_str(); - } + enum class StandardDeviationMode { eSample, ePopulation }; + + Metric(); + Metric(const char *, const char * = NULL); + + void Append(ValueType v); + + ValueType GetAverage() const; + + size_t GetCount() const; + + ValueType GetSum() const; + + ValueType GetStandardDeviation( + StandardDeviationMode mode = StandardDeviationMode::ePopulation) const; + + const char *GetName() const { + if (m_name.empty()) + return NULL; + return m_name.c_str(); + } - const char* - GetDescription () const - { - if (m_description.empty()) - return NULL; - return m_description.c_str(); - } + const char *GetDescription() const { + if (m_description.empty()) + return NULL; + return m_description.c_str(); + } private: - std::string m_name; - std::string m_description; - std::vector<ValueType> m_dataset; + std::string m_name; + std::string m_description; + std::vector<ValueType> m_dataset; }; } diff --git a/lldb/tools/lldb-perf/lib/Results.cpp b/lldb/tools/lldb-perf/lib/Results.cpp index 6abf67e53b6..17a022f2ea1 100644 --- a/lldb/tools/lldb-perf/lib/Results.cpp +++ b/lldb/tools/lldb-perf/lib/Results.cpp @@ -19,257 +19,221 @@ using namespace lldb_perf; -static void -AddResultToArray (CFCMutableArray &array, Results::Result *result); - -static void -AddResultToDictionary (CFCMutableDictionary &parent_dict, const char *key, Results::Result *result); - -static void -AddResultToArray (CFCMutableArray &parent_array, Results::Result *result) -{ - switch (result->GetType()) - { - case Results::Result::Type::Invalid: - break; - - case Results::Result::Type::Array: - { - Results::Array *value = result->GetAsArray(); - CFCMutableArray array; - value->ForEach([&array](const Results::ResultSP &value_sp) -> bool - { - AddResultToArray (array, value_sp.get()); - return true; - }); - parent_array.AppendValue(array.get(), true); - } - break; - - case Results::Result::Type::Dictionary: - { - Results::Dictionary *value = result->GetAsDictionary(); - CFCMutableDictionary dict; - value->ForEach([&dict](const std::string &key, const Results::ResultSP &value_sp) -> bool - { - AddResultToDictionary (dict, key.c_str(), value_sp.get()); - return true; - }); - if (result->GetDescription()) - { - dict.AddValueCString(CFSTR("description"), result->GetDescription()); - } - parent_array.AppendValue(dict.get(), true); - } - break; - - case Results::Result::Type::Double: - { - double d = result->GetAsDouble()->GetValue(); - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberDoubleType, &d)); - if (cf_number.get()) - parent_array.AppendValue(cf_number.get(), true); - } - break; - case Results::Result::Type::String: - { - CFCString cfstr (result->GetAsString()->GetValue()); - if (cfstr.get()) - parent_array.AppendValue(cfstr.get(), true); - } - break; - - case Results::Result::Type::Unsigned: - { - uint64_t uval64 = result->GetAsUnsigned()->GetValue(); - CFCReleaser<CFNumberRef> cf_number(::CFNumberCreate (kCFAllocatorDefault, kCFNumberSInt64Type, &uval64)); - if (cf_number.get()) - parent_array.AppendValue(cf_number.get(), true); - } - break; - - default: - assert (!"unhandled result"); - break; +static void AddResultToArray(CFCMutableArray &array, Results::Result *result); + +static void AddResultToDictionary(CFCMutableDictionary &parent_dict, + const char *key, Results::Result *result); + +static void AddResultToArray(CFCMutableArray &parent_array, + Results::Result *result) { + switch (result->GetType()) { + case Results::Result::Type::Invalid: + break; + + case Results::Result::Type::Array: { + Results::Array *value = result->GetAsArray(); + CFCMutableArray array; + value->ForEach([&array](const Results::ResultSP &value_sp) -> bool { + AddResultToArray(array, value_sp.get()); + return true; + }); + parent_array.AppendValue(array.get(), true); + } break; + + case Results::Result::Type::Dictionary: { + Results::Dictionary *value = result->GetAsDictionary(); + CFCMutableDictionary dict; + value->ForEach([&dict](const std::string &key, + const Results::ResultSP &value_sp) -> bool { + AddResultToDictionary(dict, key.c_str(), value_sp.get()); + return true; + }); + if (result->GetDescription()) { + dict.AddValueCString(CFSTR("description"), result->GetDescription()); } + parent_array.AppendValue(dict.get(), true); + } break; + + case Results::Result::Type::Double: { + double d = result->GetAsDouble()->GetValue(); + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &d)); + if (cf_number.get()) + parent_array.AppendValue(cf_number.get(), true); + } break; + case Results::Result::Type::String: { + CFCString cfstr(result->GetAsString()->GetValue()); + if (cfstr.get()) + parent_array.AppendValue(cfstr.get(), true); + } break; + + case Results::Result::Type::Unsigned: { + uint64_t uval64 = result->GetAsUnsigned()->GetValue(); + CFCReleaser<CFNumberRef> cf_number( + ::CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &uval64)); + if (cf_number.get()) + parent_array.AppendValue(cf_number.get(), true); + } break; + + default: + assert(!"unhandled result"); + break; + } } - -static void -AddResultToDictionary (CFCMutableDictionary &parent_dict, const char *key, Results::Result *result) -{ - assert (key && key[0]); - CFCString cf_key(key); - switch (result->GetType()) - { - case Results::Result::Type::Invalid: - break; - - case Results::Result::Type::Array: - { - Results::Array *value = result->GetAsArray(); - CFCMutableArray array; - value->ForEach([&array](const Results::ResultSP &value_sp) -> bool - { - AddResultToArray (array, value_sp.get()); - return true; - }); - parent_dict.AddValue(cf_key.get(), array.get(), true); - } - break; - case Results::Result::Type::Dictionary: - { - Results::Dictionary *value = result->GetAsDictionary(); - CFCMutableDictionary dict; - value->ForEach([&dict](const std::string &key, const Results::ResultSP &value_sp) -> bool - { - AddResultToDictionary (dict, key.c_str(), value_sp.get()); - return true; - }); - if (result->GetDescription()) - { - dict.AddValueCString(CFSTR("description"), result->GetDescription()); - } - parent_dict.AddValue(cf_key.get(), dict.get(), true); - } - break; - case Results::Result::Type::Double: - { - parent_dict.SetValueDouble(cf_key.get(), result->GetAsDouble()->GetValue(), true); - } - break; - case Results::Result::Type::String: - { - parent_dict.SetValueCString(cf_key.get(), result->GetAsString()->GetValue(), true); - } - break; - - case Results::Result::Type::Unsigned: - { - parent_dict.SetValueUInt64 (cf_key.get(), result->GetAsUnsigned()->GetValue(), true); - } - break; - default: - assert (!"unhandled result"); - break; +static void AddResultToDictionary(CFCMutableDictionary &parent_dict, + const char *key, Results::Result *result) { + assert(key && key[0]); + CFCString cf_key(key); + switch (result->GetType()) { + case Results::Result::Type::Invalid: + break; + + case Results::Result::Type::Array: { + Results::Array *value = result->GetAsArray(); + CFCMutableArray array; + value->ForEach([&array](const Results::ResultSP &value_sp) -> bool { + AddResultToArray(array, value_sp.get()); + return true; + }); + parent_dict.AddValue(cf_key.get(), array.get(), true); + } break; + case Results::Result::Type::Dictionary: { + Results::Dictionary *value = result->GetAsDictionary(); + CFCMutableDictionary dict; + value->ForEach([&dict](const std::string &key, + const Results::ResultSP &value_sp) -> bool { + AddResultToDictionary(dict, key.c_str(), value_sp.get()); + return true; + }); + if (result->GetDescription()) { + dict.AddValueCString(CFSTR("description"), result->GetDescription()); } + parent_dict.AddValue(cf_key.get(), dict.get(), true); + } break; + case Results::Result::Type::Double: { + parent_dict.SetValueDouble(cf_key.get(), result->GetAsDouble()->GetValue(), + true); + } break; + case Results::Result::Type::String: { + parent_dict.SetValueCString(cf_key.get(), result->GetAsString()->GetValue(), + true); + } break; + + case Results::Result::Type::Unsigned: { + parent_dict.SetValueUInt64(cf_key.get(), + result->GetAsUnsigned()->GetValue(), true); + } break; + default: + assert(!"unhandled result"); + break; + } } -void -Results::Write (const char *out_path) -{ +void Results::Write(const char *out_path) { #ifdef __APPLE__ - CFCMutableDictionary dict; - - m_results.ForEach([&dict](const std::string &key, const ResultSP &value_sp) -> bool - { - AddResultToDictionary (dict, key.c_str(), value_sp.get()); - return true; - }); - CFDataRef xmlData = CFPropertyListCreateData(kCFAllocatorDefault, dict.get(), kCFPropertyListXMLFormat_v1_0, 0, NULL); - - if (out_path == NULL) - out_path = "/dev/stdout"; + CFCMutableDictionary dict; + + m_results.ForEach( + [&dict](const std::string &key, const ResultSP &value_sp) -> bool { + AddResultToDictionary(dict, key.c_str(), value_sp.get()); + return true; + }); + CFDataRef xmlData = CFPropertyListCreateData( + kCFAllocatorDefault, dict.get(), kCFPropertyListXMLFormat_v1_0, 0, NULL); + + if (out_path == NULL) + out_path = "/dev/stdout"; + + CFURLRef file = CFURLCreateFromFileSystemRepresentation( + NULL, (const UInt8 *)out_path, strlen(out_path), FALSE); - CFURLRef file = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8*)out_path, strlen(out_path), FALSE); - - CFURLWriteDataAndPropertiesToResource(file, xmlData, NULL, NULL); + CFURLWriteDataAndPropertiesToResource(file, xmlData, NULL, NULL); #endif } -Results::ResultSP -Results::Dictionary::AddUnsigned (const char *name, const char *description, uint64_t value) -{ - assert (name && name[0]); - if (description && description[0]) - { - std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ()); - value_dict_ap->AddString("description", NULL, description); - value_dict_ap->AddUnsigned("value", NULL, value); - m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release()); - } - else - m_dictionary[std::string(name)] = ResultSP (new Unsigned (name, description, value)); - return m_dictionary[std::string(name)]; +Results::ResultSP Results::Dictionary::AddUnsigned(const char *name, + const char *description, + uint64_t value) { + assert(name && name[0]); + if (description && description[0]) { + std::unique_ptr<Results::Dictionary> value_dict_ap( + new Results::Dictionary()); + value_dict_ap->AddString("description", NULL, description); + value_dict_ap->AddUnsigned("value", NULL, value); + m_dictionary[std::string(name)] = ResultSP(value_dict_ap.release()); + } else + m_dictionary[std::string(name)] = + ResultSP(new Unsigned(name, description, value)); + return m_dictionary[std::string(name)]; } -Results::ResultSP -Results::Dictionary::AddDouble (const char *name, const char *description, double value) -{ - assert (name && name[0]); - - if (description && description[0]) - { - std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ()); - value_dict_ap->AddString("description", NULL, description); - value_dict_ap->AddDouble("value", NULL, value); - m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release()); - } - else - m_dictionary[std::string(name)] = ResultSP (new Double (name, description, value)); - return m_dictionary[std::string(name)]; +Results::ResultSP Results::Dictionary::AddDouble(const char *name, + const char *description, + double value) { + assert(name && name[0]); + + if (description && description[0]) { + std::unique_ptr<Results::Dictionary> value_dict_ap( + new Results::Dictionary()); + value_dict_ap->AddString("description", NULL, description); + value_dict_ap->AddDouble("value", NULL, value); + m_dictionary[std::string(name)] = ResultSP(value_dict_ap.release()); + } else + m_dictionary[std::string(name)] = + ResultSP(new Double(name, description, value)); + return m_dictionary[std::string(name)]; } -Results::ResultSP -Results::Dictionary::AddString (const char *name, const char *description, const char *value) -{ - assert (name && name[0]); - if (description && description[0]) - { - std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ()); - value_dict_ap->AddString("description", NULL, description); - value_dict_ap->AddString("value", NULL, value); - m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release()); - } - else - m_dictionary[std::string(name)] = ResultSP (new String (name, description, value)); - return m_dictionary[std::string(name)]; +Results::ResultSP Results::Dictionary::AddString(const char *name, + const char *description, + const char *value) { + assert(name && name[0]); + if (description && description[0]) { + std::unique_ptr<Results::Dictionary> value_dict_ap( + new Results::Dictionary()); + value_dict_ap->AddString("description", NULL, description); + value_dict_ap->AddString("value", NULL, value); + m_dictionary[std::string(name)] = ResultSP(value_dict_ap.release()); + } else + m_dictionary[std::string(name)] = + ResultSP(new String(name, description, value)); + return m_dictionary[std::string(name)]; } -Results::ResultSP -Results::Dictionary::Add (const char *name, const char *description, const ResultSP &result_sp) -{ - assert (name && name[0]); - if (description && description[0]) - { - std::unique_ptr<Results::Dictionary> value_dict_ap (new Results::Dictionary ()); - value_dict_ap->AddString("description", NULL, description); - value_dict_ap->Add("value", NULL, result_sp); - m_dictionary[std::string(name)] = ResultSP (value_dict_ap.release()); - } - else - m_dictionary[std::string(name)] = result_sp; - return m_dictionary[std::string(name)]; +Results::ResultSP Results::Dictionary::Add(const char *name, + const char *description, + const ResultSP &result_sp) { + assert(name && name[0]); + if (description && description[0]) { + std::unique_ptr<Results::Dictionary> value_dict_ap( + new Results::Dictionary()); + value_dict_ap->AddString("description", NULL, description); + value_dict_ap->Add("value", NULL, result_sp); + m_dictionary[std::string(name)] = ResultSP(value_dict_ap.release()); + } else + m_dictionary[std::string(name)] = result_sp; + return m_dictionary[std::string(name)]; } -void -Results::Dictionary::ForEach (const std::function <bool (const std::string &, const ResultSP &)> &callback) -{ - collection::const_iterator pos, end = m_dictionary.end(); - for (pos = m_dictionary.begin(); pos != end; ++pos) - { - if (callback (pos->first.c_str(), pos->second) == false) - return; - } +void Results::Dictionary::ForEach( + const std::function<bool(const std::string &, const ResultSP &)> + &callback) { + collection::const_iterator pos, end = m_dictionary.end(); + for (pos = m_dictionary.begin(); pos != end; ++pos) { + if (callback(pos->first.c_str(), pos->second) == false) + return; + } } - - -Results::ResultSP -Results::Array::Append (const ResultSP &result_sp) -{ - m_array.push_back (result_sp); - return result_sp; +Results::ResultSP Results::Array::Append(const ResultSP &result_sp) { + m_array.push_back(result_sp); + return result_sp; } -void -Results::Array::ForEach (const std::function <bool (const ResultSP &)> &callback) -{ - collection::const_iterator pos, end = m_array.end(); - for (pos = m_array.begin(); pos != end; ++pos) - { - if (callback (*pos) == false) - return; - } +void Results::Array::ForEach( + const std::function<bool(const ResultSP &)> &callback) { + collection::const_iterator pos, end = m_array.end(); + for (pos = m_array.begin(); pos != end; ++pos) { + if (callback(*pos) == false) + return; + } } - - - diff --git a/lldb/tools/lldb-perf/lib/Results.h b/lldb/tools/lldb-perf/lib/Results.h index 388077e7f58..a3d467ff01a 100644 --- a/lldb/tools/lldb-perf/lib/Results.h +++ b/lldb/tools/lldb-perf/lib/Results.h @@ -17,296 +17,189 @@ namespace lldb_perf { -class Results -{ +class Results { public: - class Array; - class Dictionary; - class Double; - class String; - class Unsigned; - - class Result - { - public: - enum class Type - { - Invalid, - Array, - Dictionary, - Double, - String, - Unsigned - }; - - Result (Type type, const char *name, const char *description) : - m_name (), - m_description(), - m_type (type) - { - if (name && name[0]) - m_name = name; - if (description && description[0]) - m_description = description; - } - - virtual - ~Result() - { - } - - virtual void - Write (Results &results) = 0; - - Array * - GetAsArray () - { - if (m_type == Type::Array) - return (Array *)this; - return NULL; - } - Dictionary * - GetAsDictionary () - { - if (m_type == Type::Dictionary) - return (Dictionary *)this; - return NULL; - } - Double * - GetAsDouble () - { - if (m_type == Type::Double) - return (Double *)this; - return NULL; - } - - String * - GetAsString () - { - if (m_type == Type::String) - return (String *)this; - return NULL; - } - Unsigned * - GetAsUnsigned () - { - if (m_type == Type::Unsigned) - return (Unsigned *)this; - return NULL; - } - - const char * - GetName() const - { - if (m_name.empty()) - return NULL; - return m_name.c_str(); - } - - const char * - GetDescription() const - { - if (m_description.empty()) - return NULL; - return m_description.c_str(); - } - - Type - GetType() const - { - return m_type; - } - - protected: - std::string m_name; - std::string m_description; - Type m_type; - }; - - typedef std::shared_ptr<Result> ResultSP; - - class Array : public Result - { - public: - Array (const char *name, const char *description) : - Result (Type::Array, name, description) - { - } - - virtual - ~Array() - { - } - - ResultSP - Append (const ResultSP &result_sp); - - void - ForEach (const std::function <bool (const ResultSP &)> &callback); - - virtual void - Write (Results &results) - { - } - protected: - typedef std::vector<ResultSP> collection; - collection m_array; - }; - - class Dictionary : public Result - { - public: - Dictionary () : - Result (Type::Dictionary, NULL, NULL) - { - } - - Dictionary (const char *name, const char *description) : - Result (Type::Dictionary, name, description) - { - } - - virtual - ~Dictionary() - { - } - - virtual void - Write (Results &results) - { - } - - void - ForEach (const std::function <bool (const std::string &, const ResultSP &)> &callback); - - ResultSP - Add (const char *name, const char *description, const ResultSP &result_sp); - - ResultSP - AddDouble (const char *name, const char *descriptiorn, double value); - - ResultSP - AddUnsigned (const char *name, const char *description, uint64_t value); - - ResultSP - AddString (const char *name, const char *description, const char *value); - - protected: - - typedef std::map<std::string, ResultSP> collection; - collection m_dictionary; - }; - - class String : public Result - { - public: - String (const char *name, const char *description, const char *value) : - Result (Type::String, name, description), - m_string () - { - if (value && value[0]) - m_string = value; - } - - virtual - ~String() - { - } - - virtual void - Write (Results &results) - { - } - - const char * - GetValue () const - { - return m_string.empty() ? NULL : m_string.c_str(); - } - - protected: - std::string m_string; - }; - - class Double : public Result - { - public: - Double (const char *name, const char *description, double value) : - Result (Type::Double, name, description), - m_double (value) - { - } - - virtual - ~Double() - { - } - - virtual void - Write (Results &results) - { - } - - double - GetValue () const - { - return m_double; - } - - protected: - double m_double; - }; - - class Unsigned : public Result - { - public: - Unsigned (const char *name, const char *description, uint64_t value) : - Result (Type::Unsigned, name, description), - m_unsigned (value) - { - } - - virtual - ~Unsigned() - { - } - - virtual void - Write (Results &results) - { - } - - uint64_t - GetValue () const - { - return m_unsigned; - } - - protected: - uint64_t m_unsigned; - }; - - Results () : - m_results () - { + class Array; + class Dictionary; + class Double; + class String; + class Unsigned; + + class Result { + public: + enum class Type { Invalid, Array, Dictionary, Double, String, Unsigned }; + + Result(Type type, const char *name, const char *description) + : m_name(), m_description(), m_type(type) { + if (name && name[0]) + m_name = name; + if (description && description[0]) + m_description = description; } - - ~Results() - { + + virtual ~Result() {} + + virtual void Write(Results &results) = 0; + + Array *GetAsArray() { + if (m_type == Type::Array) + return (Array *)this; + return NULL; + } + Dictionary *GetAsDictionary() { + if (m_type == Type::Dictionary) + return (Dictionary *)this; + return NULL; + } + Double *GetAsDouble() { + if (m_type == Type::Double) + return (Double *)this; + return NULL; + } + + String *GetAsString() { + if (m_type == Type::String) + return (String *)this; + return NULL; + } + Unsigned *GetAsUnsigned() { + if (m_type == Type::Unsigned) + return (Unsigned *)this; + return NULL; + } + + const char *GetName() const { + if (m_name.empty()) + return NULL; + return m_name.c_str(); + } + + const char *GetDescription() const { + if (m_description.empty()) + return NULL; + return m_description.c_str(); + } + + Type GetType() const { return m_type; } + + protected: + std::string m_name; + std::string m_description; + Type m_type; + }; + + typedef std::shared_ptr<Result> ResultSP; + + class Array : public Result { + public: + Array(const char *name, const char *description) + : Result(Type::Array, name, description) {} + + virtual ~Array() {} + + ResultSP Append(const ResultSP &result_sp); + + void ForEach(const std::function<bool(const ResultSP &)> &callback); + + virtual void Write(Results &results) {} + + protected: + typedef std::vector<ResultSP> collection; + collection m_array; + }; + + class Dictionary : public Result { + public: + Dictionary() : Result(Type::Dictionary, NULL, NULL) {} + + Dictionary(const char *name, const char *description) + : Result(Type::Dictionary, name, description) {} + + virtual ~Dictionary() {} + + virtual void Write(Results &results) {} + + void ForEach(const std::function<bool(const std::string &, + const ResultSP &)> &callback); + + ResultSP Add(const char *name, const char *description, + const ResultSP &result_sp); + + ResultSP AddDouble(const char *name, const char *descriptiorn, + double value); + + ResultSP AddUnsigned(const char *name, const char *description, + uint64_t value); + + ResultSP AddString(const char *name, const char *description, + const char *value); + + protected: + typedef std::map<std::string, ResultSP> collection; + collection m_dictionary; + }; + + class String : public Result { + public: + String(const char *name, const char *description, const char *value) + : Result(Type::String, name, description), m_string() { + if (value && value[0]) + m_string = value; } - - Dictionary & - GetDictionary () - { - return m_results; + + virtual ~String() {} + + virtual void Write(Results &results) {} + + const char *GetValue() const { + return m_string.empty() ? NULL : m_string.c_str(); } - void - Write (const char *path); - + protected: + std::string m_string; + }; + + class Double : public Result { + public: + Double(const char *name, const char *description, double value) + : Result(Type::Double, name, description), m_double(value) {} + + virtual ~Double() {} + + virtual void Write(Results &results) {} + + double GetValue() const { return m_double; } + + protected: + double m_double; + }; + + class Unsigned : public Result { + public: + Unsigned(const char *name, const char *description, uint64_t value) + : Result(Type::Unsigned, name, description), m_unsigned(value) {} + + virtual ~Unsigned() {} + + virtual void Write(Results &results) {} + + uint64_t GetValue() const { return m_unsigned; } + + protected: + uint64_t m_unsigned; + }; + + Results() : m_results() {} + + ~Results() {} + + Dictionary &GetDictionary() { return m_results; } + + void Write(const char *path); + protected: - Dictionary m_results; + Dictionary m_results; }; - + } // namespace lldb_perf #endif // #ifndef __PerfTestDriver_Results_h__ diff --git a/lldb/tools/lldb-perf/lib/TestCase.cpp b/lldb/tools/lldb-perf/lib/TestCase.cpp index c23a5e51977..39394898996 100644 --- a/lldb/tools/lldb-perf/lib/TestCase.cpp +++ b/lldb/tools/lldb-perf/lib/TestCase.cpp @@ -13,346 +13,296 @@ using namespace lldb_perf; -TestCase::TestCase () : - m_debugger(), - m_target(), - m_process(), - m_thread(), - m_listener(), - m_verbose(false), - m_step(0) -{ - SBDebugger::Initialize(); - SBHostOS::ThreadCreated ("<lldb-tester.app.main>"); - m_debugger = SBDebugger::Create(false); - m_listener = m_debugger.GetListener(); - m_listener.StartListeningForEventClass (m_debugger, SBProcess::GetBroadcasterClass(), SBProcess::eBroadcastBitStateChanged | SBProcess::eBroadcastBitInterrupt); +TestCase::TestCase() + : m_debugger(), m_target(), m_process(), m_thread(), m_listener(), + m_verbose(false), m_step(0) { + SBDebugger::Initialize(); + SBHostOS::ThreadCreated("<lldb-tester.app.main>"); + m_debugger = SBDebugger::Create(false); + m_listener = m_debugger.GetListener(); + m_listener.StartListeningForEventClass( + m_debugger, SBProcess::GetBroadcasterClass(), + SBProcess::eBroadcastBitStateChanged | SBProcess::eBroadcastBitInterrupt); } -static std::string -GetShortOptionString (struct option *long_options) -{ - std::string option_string; - for (int i = 0; long_options[i].name != NULL; ++i) - { - if (long_options[i].flag == NULL) - { - option_string.push_back ((char) long_options[i].val); - switch (long_options[i].has_arg) - { - default: - case no_argument: - break; - case required_argument: - option_string.push_back (':'); - break; - case optional_argument: - option_string.append (2, ':'); - break; - } - } +static std::string GetShortOptionString(struct option *long_options) { + std::string option_string; + for (int i = 0; long_options[i].name != NULL; ++i) { + if (long_options[i].flag == NULL) { + option_string.push_back((char)long_options[i].val); + switch (long_options[i].has_arg) { + default: + case no_argument: + break; + case required_argument: + option_string.push_back(':'); + break; + case optional_argument: + option_string.append(2, ':'); + break; + } } - return option_string; + } + return option_string; } -bool -TestCase::Setup (int& argc, const char**& argv) -{ - bool done = false; - - struct option* long_options = GetLongOptions(); - - if (long_options) - { - std::string short_option_string (GetShortOptionString(long_options)); - - #if __GLIBC__ - optind = 0; - #else - optreset = 1; - optind = 1; - #endif - while (!done) - { - int long_options_index = -1; - const int short_option = ::getopt_long_only (argc, - const_cast<char **>(argv), - short_option_string.c_str(), - long_options, - &long_options_index); - - switch (short_option) - { - case 0: - // Already handled - break; - - case -1: - done = true; - break; - - default: - done = !ParseOption(short_option, optarg); - break; - } - } - argc -= optind; - argv += optind; +bool TestCase::Setup(int &argc, const char **&argv) { + bool done = false; + + struct option *long_options = GetLongOptions(); + + if (long_options) { + std::string short_option_string(GetShortOptionString(long_options)); + +#if __GLIBC__ + optind = 0; +#else + optreset = 1; + optind = 1; +#endif + while (!done) { + int long_options_index = -1; + const int short_option = ::getopt_long_only( + argc, const_cast<char **>(argv), short_option_string.c_str(), + long_options, &long_options_index); + + switch (short_option) { + case 0: + // Already handled + break; + + case -1: + done = true; + break; + + default: + done = !ParseOption(short_option, optarg); + break; + } } - - return false; -} + argc -= optind; + argv += optind; + } -bool -TestCase::Launch (lldb::SBLaunchInfo &launch_info) -{ - lldb::SBError error; - m_process = m_target.Launch (launch_info, error); - if (!error.Success()) - fprintf (stderr, "error: %s\n", error.GetCString()); - if (m_process.IsValid()) - return true; - return false; + return false; } -bool -TestCase::Launch (std::initializer_list<const char*> args) -{ - std::vector<const char*> args_vect(args); - args_vect.push_back(NULL); - lldb::SBLaunchInfo launch_info((const char**)&args_vect[0]); - return Launch(launch_info); +bool TestCase::Launch(lldb::SBLaunchInfo &launch_info) { + lldb::SBError error; + m_process = m_target.Launch(launch_info, error); + if (!error.Success()) + fprintf(stderr, "error: %s\n", error.GetCString()); + if (m_process.IsValid()) + return true; + return false; } -void -TestCase::SetVerbose (bool b) -{ - m_verbose = b; +bool TestCase::Launch(std::initializer_list<const char *> args) { + std::vector<const char *> args_vect(args); + args_vect.push_back(NULL); + lldb::SBLaunchInfo launch_info((const char **)&args_vect[0]); + return Launch(launch_info); } -bool -TestCase::GetVerbose () -{ - return m_verbose; -} +void TestCase::SetVerbose(bool b) { m_verbose = b; } + +bool TestCase::GetVerbose() { return m_verbose; } -void -TestCase::Loop () -{ - while (true) - { - bool call_test_step = false; - if (m_process.IsValid()) - { - SBEvent evt; - m_listener.WaitForEvent (UINT32_MAX, evt); - StateType state = SBProcess::GetStateFromEvent (evt); +void TestCase::Loop() { + while (true) { + bool call_test_step = false; + if (m_process.IsValid()) { + SBEvent evt; + m_listener.WaitForEvent(UINT32_MAX, evt); + StateType state = SBProcess::GetStateFromEvent(evt); + if (m_verbose) + printf("event = %s\n", SBDebugger::StateAsCString(state)); + if (SBProcess::GetRestartedFromEvent(evt)) { + if (m_verbose) { + const uint32_t num_threads = m_process.GetNumThreads(); + for (auto thread_index = 0; thread_index < num_threads; + thread_index++) { + SBThread thread(m_process.GetThreadAtIndex(thread_index)); + SBFrame frame(thread.GetFrameAtIndex(0)); + SBStream strm; + strm.RedirectToFileHandle(stdout, false); + frame.GetDescription(strm); + } + puts("restarted"); + } + call_test_step = false; + } else { + switch (state) { + case eStateInvalid: + case eStateDetached: + case eStateCrashed: + case eStateUnloaded: + break; + case eStateExited: + return; + case eStateConnected: + case eStateAttaching: + case eStateLaunching: + case eStateRunning: + case eStateStepping: + call_test_step = false; + break; + + case eStateStopped: + case eStateSuspended: { + call_test_step = true; + bool fatal = false; + bool selected_thread = false; + const uint32_t num_threads = m_process.GetNumThreads(); + for (auto thread_index = 0; thread_index < num_threads; + thread_index++) { + SBThread thread(m_process.GetThreadAtIndex(thread_index)); + SBFrame frame(thread.GetFrameAtIndex(0)); + SBStream strm; + strm.RedirectToFileHandle(stdout, false); + frame.GetDescription(strm); + bool select_thread = false; + StopReason stop_reason = thread.GetStopReason(); if (m_verbose) - printf("event = %s\n",SBDebugger::StateAsCString(state)); - if (SBProcess::GetRestartedFromEvent(evt)) - { - if (m_verbose) - { - const uint32_t num_threads = m_process.GetNumThreads(); - for (auto thread_index = 0; thread_index < num_threads; thread_index++) - { - SBThread thread(m_process.GetThreadAtIndex(thread_index)); - SBFrame frame(thread.GetFrameAtIndex(0)); - SBStream strm; - strm.RedirectToFileHandle(stdout, false); - frame.GetDescription(strm); - } - puts("restarted"); - } - call_test_step = false; + printf("tid = 0x%llx pc = 0x%llx ", thread.GetThreadID(), + frame.GetPC()); + switch (stop_reason) { + case eStopReasonNone: + if (m_verbose) + printf("none\n"); + break; + + case eStopReasonTrace: + select_thread = true; + if (m_verbose) + printf("trace\n"); + break; + + case eStopReasonPlanComplete: + select_thread = true; + if (m_verbose) + printf("plan complete\n"); + break; + case eStopReasonThreadExiting: + if (m_verbose) + printf("thread exiting\n"); + break; + case eStopReasonExec: + if (m_verbose) + printf("exec\n"); + break; + case eStopReasonInvalid: + if (m_verbose) + printf("invalid\n"); + break; + case eStopReasonException: + select_thread = true; + if (m_verbose) + printf("exception\n"); + fatal = true; + break; + case eStopReasonBreakpoint: + select_thread = true; + if (m_verbose) + printf("breakpoint id = %lld.%lld\n", + thread.GetStopReasonDataAtIndex(0), + thread.GetStopReasonDataAtIndex(1)); + break; + case eStopReasonWatchpoint: + select_thread = true; + if (m_verbose) + printf("watchpoint id = %lld\n", + thread.GetStopReasonDataAtIndex(0)); + break; + case eStopReasonSignal: + select_thread = true; + if (m_verbose) + printf("signal %d\n", (int)thread.GetStopReasonDataAtIndex(0)); + break; } - else - { - switch (state) - { - case eStateInvalid: - case eStateDetached: - case eStateCrashed: - case eStateUnloaded: - break; - case eStateExited: - return; - case eStateConnected: - case eStateAttaching: - case eStateLaunching: - case eStateRunning: - case eStateStepping: - call_test_step = false; - break; - - case eStateStopped: - case eStateSuspended: - { - call_test_step = true; - bool fatal = false; - bool selected_thread = false; - const uint32_t num_threads = m_process.GetNumThreads(); - for (auto thread_index = 0; thread_index < num_threads; thread_index++) - { - SBThread thread(m_process.GetThreadAtIndex(thread_index)); - SBFrame frame(thread.GetFrameAtIndex(0)); - SBStream strm; - strm.RedirectToFileHandle(stdout, false); - frame.GetDescription(strm); - bool select_thread = false; - StopReason stop_reason = thread.GetStopReason(); - if (m_verbose) printf("tid = 0x%llx pc = 0x%llx ",thread.GetThreadID(),frame.GetPC()); - switch (stop_reason) - { - case eStopReasonNone: - if (m_verbose) - printf("none\n"); - break; - - case eStopReasonTrace: - select_thread = true; - if (m_verbose) - printf("trace\n"); - break; - - case eStopReasonPlanComplete: - select_thread = true; - if (m_verbose) - printf("plan complete\n"); - break; - case eStopReasonThreadExiting: - if (m_verbose) - printf("thread exiting\n"); - break; - case eStopReasonExec: - if (m_verbose) - printf("exec\n"); - break; - case eStopReasonInvalid: - if (m_verbose) - printf("invalid\n"); - break; - case eStopReasonException: - select_thread = true; - if (m_verbose) - printf("exception\n"); - fatal = true; - break; - case eStopReasonBreakpoint: - select_thread = true; - if (m_verbose) - printf("breakpoint id = %lld.%lld\n",thread.GetStopReasonDataAtIndex(0),thread.GetStopReasonDataAtIndex(1)); - break; - case eStopReasonWatchpoint: - select_thread = true; - if (m_verbose) - printf("watchpoint id = %lld\n",thread.GetStopReasonDataAtIndex(0)); - break; - case eStopReasonSignal: - select_thread = true; - if (m_verbose) - printf("signal %d\n",(int)thread.GetStopReasonDataAtIndex(0)); - break; - } - if (select_thread && !selected_thread) - { - m_thread = thread; - selected_thread = m_process.SetSelectedThread(thread); - } - } - if (fatal) - { - if (m_verbose) Xcode::RunCommand(m_debugger,"bt all",true); - exit(1); - } - } - break; - } + if (select_thread && !selected_thread) { + m_thread = thread; + selected_thread = m_process.SetSelectedThread(thread); } - } - else - { - call_test_step = true; + } + if (fatal) { + if (m_verbose) + Xcode::RunCommand(m_debugger, "bt all", true); + exit(1); + } + } break; } + } + } else { + call_test_step = true; + } - if (call_test_step) - { - do_the_call: - if (m_verbose) - printf("RUNNING STEP %d\n",m_step); - ActionWanted action; - TestStep(m_step, action); - m_step++; - SBError err; - switch (action.type) - { - case ActionWanted::Type::eNone: - // Just exit and wait for the next event - break; - case ActionWanted::Type::eContinue: - err = m_process.Continue(); - break; - case ActionWanted::Type::eStepOut: - if (action.thread.IsValid() == false) - { - if (m_verbose) - { - Xcode::RunCommand(m_debugger,"bt all",true); - printf("error: invalid thread for step out on step %d\n", m_step); - } - exit(501); - } - m_process.SetSelectedThread(action.thread); - action.thread.StepOut(); - break; - case ActionWanted::Type::eStepOver: - if (action.thread.IsValid() == false) - { - if (m_verbose) - { - Xcode::RunCommand(m_debugger,"bt all",true); - printf("error: invalid thread for step over %d\n",m_step); - } - exit(500); - } - m_process.SetSelectedThread(action.thread); - action.thread.StepOver(); - break; - case ActionWanted::Type::eRelaunch: - if (m_process.IsValid()) - { - m_process.Kill(); - m_process.Clear(); - } - Launch(action.launch_info); - break; - case ActionWanted::Type::eKill: - if (m_verbose) - printf("kill\n"); - m_process.Kill(); - return; - case ActionWanted::Type::eCallNext: - goto do_the_call; - break; - } + if (call_test_step) { + do_the_call: + if (m_verbose) + printf("RUNNING STEP %d\n", m_step); + ActionWanted action; + TestStep(m_step, action); + m_step++; + SBError err; + switch (action.type) { + case ActionWanted::Type::eNone: + // Just exit and wait for the next event + break; + case ActionWanted::Type::eContinue: + err = m_process.Continue(); + break; + case ActionWanted::Type::eStepOut: + if (action.thread.IsValid() == false) { + if (m_verbose) { + Xcode::RunCommand(m_debugger, "bt all", true); + printf("error: invalid thread for step out on step %d\n", m_step); + } + exit(501); + } + m_process.SetSelectedThread(action.thread); + action.thread.StepOut(); + break; + case ActionWanted::Type::eStepOver: + if (action.thread.IsValid() == false) { + if (m_verbose) { + Xcode::RunCommand(m_debugger, "bt all", true); + printf("error: invalid thread for step over %d\n", m_step); + } + exit(500); + } + m_process.SetSelectedThread(action.thread); + action.thread.StepOver(); + break; + case ActionWanted::Type::eRelaunch: + if (m_process.IsValid()) { + m_process.Kill(); + m_process.Clear(); } + Launch(action.launch_info); + break; + case ActionWanted::Type::eKill: + if (m_verbose) + printf("kill\n"); + m_process.Kill(); + return; + case ActionWanted::Type::eCallNext: + goto do_the_call; + break; + } + } + } - } - - if (GetVerbose()) printf("I am gonna die at step %d\n",m_step); + if (GetVerbose()) + printf("I am gonna die at step %d\n", m_step); } -int -TestCase::Run (TestCase& test, int argc, const char** argv) -{ - if (test.Setup(argc, argv)) - { - test.Loop(); - Results results; - test.WriteResults(results); - return RUN_SUCCESS; - } - else - return RUN_SETUP_ERROR; +int TestCase::Run(TestCase &test, int argc, const char **argv) { + if (test.Setup(argc, argv)) { + test.Loop(); + Results results; + test.WriteResults(results); + return RUN_SUCCESS; + } else + return RUN_SETUP_ERROR; } - diff --git a/lldb/tools/lldb-perf/lib/TestCase.h b/lldb/tools/lldb-perf/lib/TestCase.h index 811d0432b58..8ec1a47d7b4 100644 --- a/lldb/tools/lldb-perf/lib/TestCase.h +++ b/lldb/tools/lldb-perf/lib/TestCase.h @@ -10,195 +10,135 @@ #ifndef __PerfTestDriver__TestCase__ #define __PerfTestDriver__TestCase__ -#include "lldb/API/LLDB.h" #include "Measurement.h" +#include "lldb/API/LLDB.h" #include <getopt.h> namespace lldb_perf { class Results; - -class TestCase -{ + +class TestCase { public: - TestCase(); - - struct ActionWanted - { - enum class Type - { - eStepOver, - eContinue, - eStepOut, - eRelaunch, - eCallNext, - eNone, - eKill - } type; - lldb::SBThread thread; - lldb::SBLaunchInfo launch_info; - - ActionWanted () : - type (Type::eContinue), - thread (), - launch_info (NULL) - { - } - - void - None () - { - type = Type::eNone; - thread = lldb::SBThread(); - } - - void - Continue() - { - type = Type::eContinue; - thread = lldb::SBThread(); - } - - void - StepOver (lldb::SBThread t) - { - type = Type::eStepOver; - thread = t; - } - - void - StepOut (lldb::SBThread t) - { - type = Type::eStepOut; - thread = t; - } - - void - Relaunch (lldb::SBLaunchInfo l) - { - type = Type::eRelaunch; - thread = lldb::SBThread(); - launch_info = l; - } - - void - Kill () - { - type = Type::eKill; - thread = lldb::SBThread(); - } - - void - CallNext () - { - type = Type::eCallNext; - thread = lldb::SBThread(); - } - }; - - virtual - ~TestCase () - { - } - - virtual bool - Setup (int& argc, const char**& argv); - - virtual void - TestStep (int counter, ActionWanted &next_action) = 0; - - bool - Launch (lldb::SBLaunchInfo &launch_info); - - bool - Launch (std::initializer_list<const char*> args = {}); - - void - Loop(); - - void - SetVerbose (bool); - - bool - GetVerbose (); - - virtual void - WriteResults (Results &results) = 0; - - template <typename G,typename A> - Measurement<G,A> CreateMeasurement (A a, const char* name = NULL, const char* description = NULL) - { - return Measurement<G,A> (a,name, description); - } - - template <typename A> - TimeMeasurement<A> CreateTimeMeasurement (A a, const char* name = NULL, const char* description = NULL) - { - return TimeMeasurement<A> (a,name, description); - } - - template <typename A> - MemoryMeasurement<A> CreateMemoryMeasurement (A a, const char* name = NULL, const char* description = NULL) - { - return MemoryMeasurement<A> (a,name, description); - } - - static int - Run (TestCase& test, int argc, const char** argv); - - virtual bool - ParseOption (int short_option, const char* optarg) - { - return false; + TestCase(); + + struct ActionWanted { + enum class Type { + eStepOver, + eContinue, + eStepOut, + eRelaunch, + eCallNext, + eNone, + eKill + } type; + lldb::SBThread thread; + lldb::SBLaunchInfo launch_info; + + ActionWanted() : type(Type::eContinue), thread(), launch_info(NULL) {} + + void None() { + type = Type::eNone; + thread = lldb::SBThread(); } - - virtual struct option* - GetLongOptions () - { - return NULL; + + void Continue() { + type = Type::eContinue; + thread = lldb::SBThread(); } - - lldb::SBDebugger & - GetDebugger() - { - return m_debugger; + + void StepOver(lldb::SBThread t) { + type = Type::eStepOver; + thread = t; } - lldb::SBTarget & - GetTarget() - { - return m_target; + void StepOut(lldb::SBThread t) { + type = Type::eStepOut; + thread = t; } - - lldb::SBProcess & - GetProcess () - { - return m_process; + + void Relaunch(lldb::SBLaunchInfo l) { + type = Type::eRelaunch; + thread = lldb::SBThread(); + launch_info = l; } - - lldb::SBThread & - GetThread () - { - return m_thread; + + void Kill() { + type = Type::eKill; + thread = lldb::SBThread(); } - - int - GetStep () - { - return m_step; + + void CallNext() { + type = Type::eCallNext; + thread = lldb::SBThread(); } - - static const int RUN_SUCCESS = 0; - static const int RUN_SETUP_ERROR = 100; - + }; + + virtual ~TestCase() {} + + virtual bool Setup(int &argc, const char **&argv); + + virtual void TestStep(int counter, ActionWanted &next_action) = 0; + + bool Launch(lldb::SBLaunchInfo &launch_info); + + bool Launch(std::initializer_list<const char *> args = {}); + + void Loop(); + + void SetVerbose(bool); + + bool GetVerbose(); + + virtual void WriteResults(Results &results) = 0; + + template <typename G, typename A> + Measurement<G, A> CreateMeasurement(A a, const char *name = NULL, + const char *description = NULL) { + return Measurement<G, A>(a, name, description); + } + + template <typename A> + TimeMeasurement<A> CreateTimeMeasurement(A a, const char *name = NULL, + const char *description = NULL) { + return TimeMeasurement<A>(a, name, description); + } + + template <typename A> + MemoryMeasurement<A> CreateMemoryMeasurement(A a, const char *name = NULL, + const char *description = NULL) { + return MemoryMeasurement<A>(a, name, description); + } + + static int Run(TestCase &test, int argc, const char **argv); + + virtual bool ParseOption(int short_option, const char *optarg) { + return false; + } + + virtual struct option *GetLongOptions() { return NULL; } + + lldb::SBDebugger &GetDebugger() { return m_debugger; } + + lldb::SBTarget &GetTarget() { return m_target; } + + lldb::SBProcess &GetProcess() { return m_process; } + + lldb::SBThread &GetThread() { return m_thread; } + + int GetStep() { return m_step; } + + static const int RUN_SUCCESS = 0; + static const int RUN_SETUP_ERROR = 100; + protected: - lldb::SBDebugger m_debugger; - lldb::SBTarget m_target; - lldb::SBProcess m_process; - lldb::SBThread m_thread; - lldb::SBListener m_listener; - bool m_verbose; - int m_step; + lldb::SBDebugger m_debugger; + lldb::SBTarget m_target; + lldb::SBProcess m_process; + lldb::SBThread m_thread; + lldb::SBListener m_listener; + bool m_verbose; + int m_step; }; } diff --git a/lldb/tools/lldb-perf/lib/Timer.cpp b/lldb/tools/lldb-perf/lib/Timer.cpp index 4bbab904c63..d22122847b4 100644 --- a/lldb/tools/lldb-perf/lib/Timer.cpp +++ b/lldb/tools/lldb-perf/lib/Timer.cpp @@ -12,50 +12,36 @@ using namespace lldb_perf; -TimeGauge::TimeType -TimeGauge::Now () -{ - return high_resolution_clock::now(); -} +TimeGauge::TimeType TimeGauge::Now() { return high_resolution_clock::now(); } -TimeGauge::TimeGauge () : - m_start(), - m_state(TimeGauge::State::eNeverUsed) -{ -} +TimeGauge::TimeGauge() : m_start(), m_state(TimeGauge::State::eNeverUsed) {} -void -TimeGauge::Start () -{ - m_state = TimeGauge::State::eCounting; - m_start = Now(); +void TimeGauge::Start() { + m_state = TimeGauge::State::eCounting; + m_start = Now(); } -double -TimeGauge::Stop () -{ - m_stop = Now(); - assert(m_state == TimeGauge::State::eCounting && "cannot stop a non-started clock"); - m_state = TimeGauge::State::eStopped; - m_delta = duration_cast<duration<double>>(m_stop-m_start).count(); - return m_delta; +double TimeGauge::Stop() { + m_stop = Now(); + assert(m_state == TimeGauge::State::eCounting && + "cannot stop a non-started clock"); + m_state = TimeGauge::State::eStopped; + m_delta = duration_cast<duration<double>>(m_stop - m_start).count(); + return m_delta; } -double -TimeGauge::GetStartValue () const -{ - return (double)m_start.time_since_epoch().count() * (double)system_clock::period::num / (double)system_clock::period::den; +double TimeGauge::GetStartValue() const { + return (double)m_start.time_since_epoch().count() * + (double)system_clock::period::num / (double)system_clock::period::den; } -double -TimeGauge::GetStopValue () const -{ - return (double)m_stop.time_since_epoch().count() * (double)system_clock::period::num / (double)system_clock::period::den; +double TimeGauge::GetStopValue() const { + return (double)m_stop.time_since_epoch().count() * + (double)system_clock::period::num / (double)system_clock::period::den; } -double -TimeGauge::GetDeltaValue () const -{ - assert(m_state == TimeGauge::State::eStopped && "clock must be used before you can evaluate it"); - return m_delta; +double TimeGauge::GetDeltaValue() const { + assert(m_state == TimeGauge::State::eStopped && + "clock must be used before you can evaluate it"); + return m_delta; } diff --git a/lldb/tools/lldb-perf/lib/Timer.h b/lldb/tools/lldb-perf/lib/Timer.h index ff179355cd4..ddedc2d7c48 100644 --- a/lldb/tools/lldb-perf/lib/Timer.h +++ b/lldb/tools/lldb-perf/lib/Timer.h @@ -16,50 +16,33 @@ using namespace std::chrono; -namespace lldb_perf -{ -class TimeGauge : public Gauge<double> -{ +namespace lldb_perf { +class TimeGauge : public Gauge<double> { public: - TimeGauge (); - - virtual - ~TimeGauge () - { - } - - void - Start (); - - double - Stop (); - - virtual double - GetStartValue () const; - - virtual double - GetStopValue () const; + TimeGauge(); - virtual double - GetDeltaValue () const; + virtual ~TimeGauge() {} + + void Start(); + + double Stop(); + + virtual double GetStartValue() const; + + virtual double GetStopValue() const; + + virtual double GetDeltaValue() const; private: - enum class State - { - eNeverUsed, - eCounting, - eStopped - }; - - typedef high_resolution_clock::time_point TimeType; - TimeType m_start; - TimeType m_stop; - double m_delta; - State m_state; - - TimeType - Now (); - + enum class State { eNeverUsed, eCounting, eStopped }; + + typedef high_resolution_clock::time_point TimeType; + TimeType m_start; + TimeType m_stop; + double m_delta; + State m_state; + + TimeType Now(); }; } diff --git a/lldb/tools/lldb-perf/lib/Xcode.cpp b/lldb/tools/lldb-perf/lib/Xcode.cpp index 7b35e1c8cb5..c20fb98c4b9 100644 --- a/lldb/tools/lldb-perf/lib/Xcode.cpp +++ b/lldb/tools/lldb-perf/lib/Xcode.cpp @@ -13,153 +13,125 @@ using namespace std; using namespace lldb_perf; -void -Xcode::FetchVariable (SBValue value, uint32_t expand, bool verbose) -{ - auto name = value.GetName(); - auto num_value = value.GetValueAsUnsigned(0); - auto summary = value.GetSummary(); - auto in_scope = value.IsInScope(); - auto has_children = value.MightHaveChildren(); - auto type_1 = value.GetType(); - auto type_2 = value.GetType(); - auto type_name_1 = value.GetTypeName(); - auto type_3 = value.GetType(); - auto type_name_2 = value.GetTypeName(); - if (verbose) - printf("%s %s = 0x%llx (%llu) %s\n",value.GetTypeName(),value.GetName(),num_value, num_value,summary); - if (expand > 0) - { - auto count = value.GetNumChildren(); - for (int i = 0; i < count; i++) - { - SBValue child(value.GetChildAtIndex(i, lldb::eDynamicCanRunTarget, true)); - FetchVariable (child,expand-1,verbose); - } - } +void Xcode::FetchVariable(SBValue value, uint32_t expand, bool verbose) { + auto name = value.GetName(); + auto num_value = value.GetValueAsUnsigned(0); + auto summary = value.GetSummary(); + auto in_scope = value.IsInScope(); + auto has_children = value.MightHaveChildren(); + auto type_1 = value.GetType(); + auto type_2 = value.GetType(); + auto type_name_1 = value.GetTypeName(); + auto type_3 = value.GetType(); + auto type_name_2 = value.GetTypeName(); + if (verbose) + printf("%s %s = 0x%llx (%llu) %s\n", value.GetTypeName(), value.GetName(), + num_value, num_value, summary); + if (expand > 0) { + auto count = value.GetNumChildren(); + for (int i = 0; i < count; i++) { + SBValue child(value.GetChildAtIndex(i, lldb::eDynamicCanRunTarget, true)); + FetchVariable(child, expand - 1, verbose); + } + } } -void -Xcode::FetchModules (SBTarget target, bool verbose) -{ - auto count = target.GetNumModules(); - for (int i = 0; i < count; i++) - { - SBModule module(target.GetModuleAtIndex(i)); - auto fspec = module.GetFileSpec(); - std::string path(1024,0); - fspec.GetPath(&path[0],1024); - auto uuid = module.GetUUIDBytes(); - if (verbose) - { - printf("%s %s\n",path.c_str(),module.GetUUIDString()); - } - } +void Xcode::FetchModules(SBTarget target, bool verbose) { + auto count = target.GetNumModules(); + for (int i = 0; i < count; i++) { + SBModule module(target.GetModuleAtIndex(i)); + auto fspec = module.GetFileSpec(); + std::string path(1024, 0); + fspec.GetPath(&path[0], 1024); + auto uuid = module.GetUUIDBytes(); + if (verbose) { + printf("%s %s\n", path.c_str(), module.GetUUIDString()); + } + } } -void -Xcode::FetchVariables (SBFrame frame, uint32_t expand, bool verbose) -{ - auto values = frame.GetVariables (true,true,true,false, eDynamicCanRunTarget); - auto count = values.GetSize(); - for (int i = 0; i < count; i++) - { - SBValue value(values.GetValueAtIndex(i)); - FetchVariable (value,expand,verbose); - } +void Xcode::FetchVariables(SBFrame frame, uint32_t expand, bool verbose) { + auto values = + frame.GetVariables(true, true, true, false, eDynamicCanRunTarget); + auto count = values.GetSize(); + for (int i = 0; i < count; i++) { + SBValue value(values.GetValueAtIndex(i)); + FetchVariable(value, expand, verbose); + } } -void -Xcode::FetchFrames(SBProcess process, bool variables, bool verbose) -{ - auto pCount = process.GetNumThreads(); - for (int p = 0; p < pCount; p++) - { - SBThread thread(process.GetThreadAtIndex(p)); - auto tCount = thread.GetNumFrames (); - if (verbose) - printf("%s %d %d {%d}\n",thread.GetQueueName(),tCount,thread.GetStopReason(),eStopReasonBreakpoint); - for (int t = 0; t < tCount; t++) - { - SBFrame frame(thread.GetFrameAtIndex(t)); - auto fp = frame.GetFP(); - SBThread thread_dup = frame.GetThread(); - SBFileSpec filespec(process.GetTarget().GetExecutable()); - std::string path(1024,0); - filespec.GetPath(&path[0],1024); - auto state = process.GetState(); - auto pCount_dup = process.GetNumThreads(); - auto byte_size = process.GetAddressByteSize(); - auto pc = frame.GetPC(); - SBSymbolContext context(frame.GetSymbolContext(0x0000006e)); - SBModule module(context.GetModule()); - SBLineEntry entry(context.GetLineEntry()); - SBFileSpec entry_filespec(process.GetTarget().GetExecutable()); - std::string entry_path(1024,0); - entry_filespec.GetPath(&entry_path[0],1024); - auto line_1 = entry.GetLine(); - auto line_2 = entry.GetLine(); - auto fname = frame.GetFunctionName(); - if (verbose) - printf("%llu %s %d %d %llu %s %d %s\n",fp,path.c_str(),state,byte_size,pc,entry_path.c_str(),line_1,fname); - if (variables) - FetchVariables (frame, 0, verbose); - } - } +void Xcode::FetchFrames(SBProcess process, bool variables, bool verbose) { + auto pCount = process.GetNumThreads(); + for (int p = 0; p < pCount; p++) { + SBThread thread(process.GetThreadAtIndex(p)); + auto tCount = thread.GetNumFrames(); + if (verbose) + printf("%s %d %d {%d}\n", thread.GetQueueName(), tCount, + thread.GetStopReason(), eStopReasonBreakpoint); + for (int t = 0; t < tCount; t++) { + SBFrame frame(thread.GetFrameAtIndex(t)); + auto fp = frame.GetFP(); + SBThread thread_dup = frame.GetThread(); + SBFileSpec filespec(process.GetTarget().GetExecutable()); + std::string path(1024, 0); + filespec.GetPath(&path[0], 1024); + auto state = process.GetState(); + auto pCount_dup = process.GetNumThreads(); + auto byte_size = process.GetAddressByteSize(); + auto pc = frame.GetPC(); + SBSymbolContext context(frame.GetSymbolContext(0x0000006e)); + SBModule module(context.GetModule()); + SBLineEntry entry(context.GetLineEntry()); + SBFileSpec entry_filespec(process.GetTarget().GetExecutable()); + std::string entry_path(1024, 0); + entry_filespec.GetPath(&entry_path[0], 1024); + auto line_1 = entry.GetLine(); + auto line_2 = entry.GetLine(); + auto fname = frame.GetFunctionName(); + if (verbose) + printf("%llu %s %d %d %llu %s %d %s\n", fp, path.c_str(), state, + byte_size, pc, entry_path.c_str(), line_1, fname); + if (variables) + FetchVariables(frame, 0, verbose); + } + } } -void -Xcode::RunExpression (SBFrame frame, const char* expression, bool po, bool verbose) -{ - SBValue value (frame.EvaluateExpression (expression, eDynamicCanRunTarget)); - FetchVariable (value,0,verbose); - if (po) - { - auto descr = value.GetObjectDescription(); - if (descr) - printf("po = %s\n",descr); - } +void Xcode::RunExpression(SBFrame frame, const char *expression, bool po, + bool verbose) { + SBValue value(frame.EvaluateExpression(expression, eDynamicCanRunTarget)); + FetchVariable(value, 0, verbose); + if (po) { + auto descr = value.GetObjectDescription(); + if (descr) + printf("po = %s\n", descr); + } } -void -Xcode::Next (SBThread thread) -{ - thread.StepOver(); -} +void Xcode::Next(SBThread thread) { thread.StepOver(); } -void -Xcode::Continue (SBProcess process) -{ - process.Continue(); -} +void Xcode::Continue(SBProcess process) { process.Continue(); } -void -Xcode::RunCommand (SBDebugger debugger, const char* cmd, bool verbose) -{ - SBCommandReturnObject sb_ret; - auto interpreter = debugger.GetCommandInterpreter(); - interpreter.HandleCommand(cmd,sb_ret); - if (verbose) - printf("%s\n%s\n",sb_ret.GetOutput(false),sb_ret.GetError(false)); +void Xcode::RunCommand(SBDebugger debugger, const char *cmd, bool verbose) { + SBCommandReturnObject sb_ret; + auto interpreter = debugger.GetCommandInterpreter(); + interpreter.HandleCommand(cmd, sb_ret); + if (verbose) + printf("%s\n%s\n", sb_ret.GetOutput(false), sb_ret.GetError(false)); } -SBThread -Xcode::GetThreadWithStopReason (SBProcess process, StopReason reason) -{ - auto threads_count = process.GetNumThreads(); - for (auto thread_num = 0; thread_num < threads_count; thread_num++) - { - SBThread thread(process.GetThreadAtIndex(thread_num)); - if (thread.GetStopReason() == reason) - { - return thread; - } - } - return SBThread(); +SBThread Xcode::GetThreadWithStopReason(SBProcess process, StopReason reason) { + auto threads_count = process.GetNumThreads(); + for (auto thread_num = 0; thread_num < threads_count; thread_num++) { + SBThread thread(process.GetThreadAtIndex(thread_num)); + if (thread.GetStopReason() == reason) { + return thread; + } + } + return SBThread(); } -SBBreakpoint -Xcode::CreateFileLineBreakpoint (SBTarget target, const char* file, uint32_t line) -{ - return target.BreakpointCreateByLocation(file, line); +SBBreakpoint Xcode::CreateFileLineBreakpoint(SBTarget target, const char *file, + uint32_t line) { + return target.BreakpointCreateByLocation(file, line); } diff --git a/lldb/tools/lldb-perf/lib/Xcode.h b/lldb/tools/lldb-perf/lib/Xcode.h index 77e02536937..41f58dcd505 100644 --- a/lldb/tools/lldb-perf/lib/Xcode.h +++ b/lldb/tools/lldb-perf/lib/Xcode.h @@ -10,54 +10,48 @@ #ifndef __PerfTestDriver__Xcode__ #define __PerfTestDriver__Xcode__ +#include "lldb/API/SBBreakpoint.h" +#include "lldb/API/SBCommandInterpreter.h" +#include "lldb/API/SBCommandReturnObject.h" +#include "lldb/API/SBDebugger.h" #include "lldb/API/SBDefines.h" -#include "lldb/API/SBValue.h" -#include "lldb/API/SBTarget.h" +#include "lldb/API/SBLineEntry.h" #include "lldb/API/SBModule.h" #include "lldb/API/SBProcess.h" -#include "lldb/API/SBLineEntry.h" +#include "lldb/API/SBTarget.h" #include "lldb/API/SBThread.h" -#include "lldb/API/SBDebugger.h" -#include "lldb/API/SBCommandInterpreter.h" -#include "lldb/API/SBCommandReturnObject.h" -#include "lldb/API/SBBreakpoint.h" +#include "lldb/API/SBValue.h" using namespace lldb; -namespace lldb_perf -{ -class Xcode -{ +namespace lldb_perf { +class Xcode { public: - static void - FetchVariable (SBValue value, uint32_t expand = 0, bool verbose = false); - - static void - FetchModules (SBTarget target, bool verbose = false); - - static void - FetchVariables (SBFrame frame, uint32_t expand = 0, bool verbose = false); - - static void - FetchFrames (SBProcess process, bool variables = false, bool verbose = false); - - static void - RunExpression (SBFrame frame, const char* expression, bool po = false, bool verbose = false); - - static void - Next (SBThread thread); - - static void - Continue (SBProcess process); - - static void - RunCommand (SBDebugger debugger, const char* cmd, bool verbose = false); - - static SBThread - GetThreadWithStopReason (SBProcess process, StopReason reason); - - static SBBreakpoint - CreateFileLineBreakpoint (SBTarget target, const char* file, uint32_t line); + static void FetchVariable(SBValue value, uint32_t expand = 0, + bool verbose = false); + + static void FetchModules(SBTarget target, bool verbose = false); + + static void FetchVariables(SBFrame frame, uint32_t expand = 0, + bool verbose = false); + + static void FetchFrames(SBProcess process, bool variables = false, + bool verbose = false); + + static void RunExpression(SBFrame frame, const char *expression, + bool po = false, bool verbose = false); + + static void Next(SBThread thread); + + static void Continue(SBProcess process); + + static void RunCommand(SBDebugger debugger, const char *cmd, + bool verbose = false); + + static SBThread GetThreadWithStopReason(SBProcess process, StopReason reason); + + static SBBreakpoint CreateFileLineBreakpoint(SBTarget target, + const char *file, uint32_t line); }; } diff --git a/lldb/tools/lldb-server/Acceptor.cpp b/lldb/tools/lldb-server/Acceptor.cpp index 1bf86eb7da6..938d7795e45 100644 --- a/lldb/tools/lldb-server/Acceptor.cpp +++ b/lldb/tools/lldb-server/Acceptor.cpp @@ -25,10 +25,9 @@ using namespace llvm; namespace { -struct SocketScheme -{ - const char* m_scheme; - const Socket::SocketProtocol m_protocol; +struct SocketScheme { + const char *m_scheme; + const Socket::SocketProtocol m_protocol; }; SocketScheme socket_schemes[] = { @@ -38,134 +37,102 @@ SocketScheme socket_schemes[] = { {"unix-abstract", Socket::ProtocolUnixAbstract}, }; -bool -FindProtocolByScheme(const char* scheme, Socket::SocketProtocol& protocol) -{ - for (auto s: socket_schemes) - { - if (!strcmp(s.m_scheme, scheme)) - { - protocol = s.m_protocol; - return true; - } +bool FindProtocolByScheme(const char *scheme, + Socket::SocketProtocol &protocol) { + for (auto s : socket_schemes) { + if (!strcmp(s.m_scheme, scheme)) { + protocol = s.m_protocol; + return true; } - return false; + } + return false; } -const char* -FindSchemeByProtocol(const Socket::SocketProtocol protocol) -{ - for (auto s: socket_schemes) - { - if (s.m_protocol == protocol) - return s.m_scheme; - } - return nullptr; +const char *FindSchemeByProtocol(const Socket::SocketProtocol protocol) { + for (auto s : socket_schemes) { + if (s.m_protocol == protocol) + return s.m_scheme; + } + return nullptr; } - } -Error -Acceptor::Listen(int backlog) -{ - return m_listener_socket_up->Listen(StringRef(m_name.c_str()), - backlog); +Error Acceptor::Listen(int backlog) { + return m_listener_socket_up->Listen(StringRef(m_name.c_str()), backlog); } -Error -Acceptor::Accept(const bool child_processes_inherit, Connection *&conn) -{ - Socket* conn_socket = nullptr; - auto error = m_listener_socket_up->Accept(StringRef(m_name.c_str()), - child_processes_inherit, - conn_socket); - if (error.Success()) - conn = new ConnectionFileDescriptor(conn_socket); - - return error; -} +Error Acceptor::Accept(const bool child_processes_inherit, Connection *&conn) { + Socket *conn_socket = nullptr; + auto error = m_listener_socket_up->Accept( + StringRef(m_name.c_str()), child_processes_inherit, conn_socket); + if (error.Success()) + conn = new ConnectionFileDescriptor(conn_socket); -Socket::SocketProtocol -Acceptor::GetSocketProtocol() const -{ - return m_listener_socket_up->GetSocketProtocol(); + return error; } -const char* -Acceptor::GetSocketScheme() const -{ - return FindSchemeByProtocol(GetSocketProtocol()); +Socket::SocketProtocol Acceptor::GetSocketProtocol() const { + return m_listener_socket_up->GetSocketProtocol(); } -std::string -Acceptor::GetLocalSocketId() const -{ - return m_local_socket_id(); +const char *Acceptor::GetSocketScheme() const { + return FindSchemeByProtocol(GetSocketProtocol()); } -std::unique_ptr<Acceptor> -Acceptor::Create(StringRef name, const bool child_processes_inherit, Error &error) -{ - error.Clear(); - - Socket::SocketProtocol socket_protocol = Socket::ProtocolUnixDomain; - int port; - std::string scheme, host, path; - // Try to match socket name as URL - e.g., tcp://localhost:5555 - if (UriParser::Parse(name.str(), scheme, host, port, path)) - { - if (!FindProtocolByScheme(scheme.c_str(), socket_protocol)) - error.SetErrorStringWithFormat("Unknown protocol scheme \"%s\"", scheme.c_str()); - else - name = name.drop_front(scheme.size() + strlen("://")); - } +std::string Acceptor::GetLocalSocketId() const { return m_local_socket_id(); } + +std::unique_ptr<Acceptor> Acceptor::Create(StringRef name, + const bool child_processes_inherit, + Error &error) { + error.Clear(); + + Socket::SocketProtocol socket_protocol = Socket::ProtocolUnixDomain; + int port; + std::string scheme, host, path; + // Try to match socket name as URL - e.g., tcp://localhost:5555 + if (UriParser::Parse(name.str(), scheme, host, port, path)) { + if (!FindProtocolByScheme(scheme.c_str(), socket_protocol)) + error.SetErrorStringWithFormat("Unknown protocol scheme \"%s\"", + scheme.c_str()); else - { - std::string host_str; - std::string port_str; - int32_t port = INT32_MIN; - // Try to match socket name as $host:port - e.g., localhost:5555 - if (Socket::DecodeHostAndPort (name, host_str, port_str, port, nullptr)) - socket_protocol = Socket::ProtocolTcp; - } + name = name.drop_front(scheme.size() + strlen("://")); + } else { + std::string host_str; + std::string port_str; + int32_t port = INT32_MIN; + // Try to match socket name as $host:port - e.g., localhost:5555 + if (Socket::DecodeHostAndPort(name, host_str, port_str, port, nullptr)) + socket_protocol = Socket::ProtocolTcp; + } + + if (error.Fail()) + return std::unique_ptr<Acceptor>(); - if (error.Fail()) - return std::unique_ptr<Acceptor>(); - - std::unique_ptr<Socket> listener_socket_up = Socket::Create( - socket_protocol, child_processes_inherit, error); - - LocalSocketIdFunc local_socket_id; - if (error.Success()) - { - if (listener_socket_up->GetSocketProtocol() == Socket::ProtocolTcp) - { - TCPSocket* tcp_socket = static_cast<TCPSocket*>(listener_socket_up.get()); - local_socket_id = [tcp_socket]() { - auto local_port = tcp_socket->GetLocalPortNumber(); - return (local_port != 0) ? llvm::to_string(local_port) : ""; - }; - } - else - { - const std::string socket_name = name; - local_socket_id = [socket_name](){ - return socket_name; - }; - } - - return std::unique_ptr<Acceptor>( - new Acceptor(std::move(listener_socket_up), name, local_socket_id)); + std::unique_ptr<Socket> listener_socket_up = + Socket::Create(socket_protocol, child_processes_inherit, error); + + LocalSocketIdFunc local_socket_id; + if (error.Success()) { + if (listener_socket_up->GetSocketProtocol() == Socket::ProtocolTcp) { + TCPSocket *tcp_socket = + static_cast<TCPSocket *>(listener_socket_up.get()); + local_socket_id = [tcp_socket]() { + auto local_port = tcp_socket->GetLocalPortNumber(); + return (local_port != 0) ? llvm::to_string(local_port) : ""; + }; + } else { + const std::string socket_name = name; + local_socket_id = [socket_name]() { return socket_name; }; } - return std::unique_ptr<Acceptor>(); + return std::unique_ptr<Acceptor>( + new Acceptor(std::move(listener_socket_up), name, local_socket_id)); + } + + return std::unique_ptr<Acceptor>(); } -Acceptor::Acceptor(std::unique_ptr<Socket> &&listener_socket, - StringRef name, +Acceptor::Acceptor(std::unique_ptr<Socket> &&listener_socket, StringRef name, const LocalSocketIdFunc &local_socket_id) - : m_listener_socket_up(std::move(listener_socket)), - m_name(name.str()), - m_local_socket_id(local_socket_id) -{ -} + : m_listener_socket_up(std::move(listener_socket)), m_name(name.str()), + m_local_socket_id(local_socket_id) {} diff --git a/lldb/tools/lldb-server/Acceptor.h b/lldb/tools/lldb-server/Acceptor.h index 37fba26c881..f0638ef1ae6 100644 --- a/lldb/tools/lldb-server/Acceptor.h +++ b/lldb/tools/lldb-server/Acceptor.h @@ -17,52 +17,45 @@ #include <memory> #include <string> -namespace llvm -{ - class StringRef; +namespace llvm { +class StringRef; } namespace lldb_private { namespace lldb_server { -class Acceptor -{ +class Acceptor { public: - virtual ~Acceptor() = default; + virtual ~Acceptor() = default; - Error - Listen(int backlog); + Error Listen(int backlog); - Error - Accept(const bool child_processes_inherit, Connection *&conn); + Error Accept(const bool child_processes_inherit, Connection *&conn); - static std::unique_ptr<Acceptor> - Create(llvm::StringRef name, const bool child_processes_inherit, Error &error); + static std::unique_ptr<Acceptor> Create(llvm::StringRef name, + const bool child_processes_inherit, + Error &error); - Socket::SocketProtocol - GetSocketProtocol() const; + Socket::SocketProtocol GetSocketProtocol() const; - const char* - GetSocketScheme() const; + const char *GetSocketScheme() const; - // Returns either TCP port number as string or domain socket path. - // Empty string is returned in case of error. - std::string - GetLocalSocketId() const; + // Returns either TCP port number as string or domain socket path. + // Empty string is returned in case of error. + std::string GetLocalSocketId() const; private: - typedef std::function<std::string()> LocalSocketIdFunc; + typedef std::function<std::string()> LocalSocketIdFunc; - Acceptor(std::unique_ptr<Socket> &&listener_socket, - llvm::StringRef name, - const LocalSocketIdFunc &local_socket_id); + Acceptor(std::unique_ptr<Socket> &&listener_socket, llvm::StringRef name, + const LocalSocketIdFunc &local_socket_id); - const std::unique_ptr<Socket> m_listener_socket_up; - const std::string m_name; - const LocalSocketIdFunc m_local_socket_id; + const std::unique_ptr<Socket> m_listener_socket_up; + const std::string m_name; + const LocalSocketIdFunc m_local_socket_id; }; } // namespace lldb_server } // namespace lldb_private -#endif // lldb_server_Acceptor_h_ +#endif // lldb_server_Acceptor_h_ diff --git a/lldb/tools/lldb-server/LLDBServerUtilities.cpp b/lldb/tools/lldb-server/LLDBServerUtilities.cpp index 438d9f127d6..86d8469933e 100644 --- a/lldb/tools/lldb-server/LLDBServerUtilities.cpp +++ b/lldb/tools/lldb-server/LLDBServerUtilities.cpp @@ -21,47 +21,37 @@ using namespace lldb; using namespace lldb_private::lldb_server; using namespace llvm; -bool -LLDBServerUtilities::SetupLogging(const std::string& log_file, - const StringRef& log_channels, - uint32_t log_options) -{ - lldb::StreamSP log_stream_sp; - if (log_file.empty()) - { - log_stream_sp.reset(new StreamFile(stdout, false)); +bool LLDBServerUtilities::SetupLogging(const std::string &log_file, + const StringRef &log_channels, + uint32_t log_options) { + lldb::StreamSP log_stream_sp; + if (log_file.empty()) { + log_stream_sp.reset(new StreamFile(stdout, false)); + } else { + uint32_t options = File::eOpenOptionWrite | File::eOpenOptionCanCreate | + File::eOpenOptionCloseOnExec | File::eOpenOptionAppend; + if (!(log_options & LLDB_LOG_OPTION_APPEND)) + options |= File::eOpenOptionTruncate; + + log_stream_sp.reset(new StreamFile(log_file.c_str(), options)); + } + + SmallVector<StringRef, 32> channel_array; + log_channels.split(channel_array, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false); + for (auto channel_with_categories : channel_array) { + StreamString error_stream; + Args channel_then_categories(channel_with_categories); + std::string channel(channel_then_categories.GetArgumentAtIndex(0)); + channel_then_categories.Shift(); // Shift off the channel + + bool success = Log::EnableLogChannel( + log_stream_sp, log_options, channel.c_str(), + channel_then_categories.GetConstArgumentVector(), error_stream); + if (!success) { + fprintf(stderr, "Unable to open log file '%s' for channel \"%s\"\n", + log_file.c_str(), channel_with_categories.str().c_str()); + return false; } - else - { - uint32_t options = File::eOpenOptionWrite | File::eOpenOptionCanCreate | - File::eOpenOptionCloseOnExec | File::eOpenOptionAppend; - if (!(log_options & LLDB_LOG_OPTION_APPEND)) - options |= File::eOpenOptionTruncate; - - log_stream_sp.reset(new StreamFile(log_file.c_str(), options)); - } - - SmallVector<StringRef, 32> channel_array; - log_channels.split(channel_array, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false); - for (auto channel_with_categories : channel_array) - { - StreamString error_stream; - Args channel_then_categories(channel_with_categories); - std::string channel(channel_then_categories.GetArgumentAtIndex(0)); - channel_then_categories.Shift (); // Shift off the channel - - bool success = Log::EnableLogChannel(log_stream_sp, - log_options, - channel.c_str(), - channel_then_categories.GetConstArgumentVector(), - error_stream); - if (!success) - { - fprintf(stderr, "Unable to open log file '%s' for channel \"%s\"\n", - log_file.c_str(), - channel_with_categories.str().c_str()); - return false; - } - } - return true; + } + return true; } diff --git a/lldb/tools/lldb-server/LLDBServerUtilities.h b/lldb/tools/lldb-server/LLDBServerUtilities.h index cab892a5edc..36ec70d9ef9 100644 --- a/lldb/tools/lldb-server/LLDBServerUtilities.h +++ b/lldb/tools/lldb-server/LLDBServerUtilities.h @@ -14,12 +14,11 @@ namespace lldb_private { namespace lldb_server { -class LLDBServerUtilities -{ +class LLDBServerUtilities { public: - static bool - SetupLogging(const std::string& log_file, const llvm::StringRef& log_channels, uint32_t log_options); + static bool SetupLogging(const std::string &log_file, + const llvm::StringRef &log_channels, + uint32_t log_options); }; - } } diff --git a/lldb/tools/lldb-server/lldb-gdbserver.cpp b/lldb/tools/lldb-server/lldb-gdbserver.cpp index b8c59e29eb5..5a388722b3c 100644 --- a/lldb/tools/lldb-server/lldb-gdbserver.cpp +++ b/lldb/tools/lldb-server/lldb-gdbserver.cpp @@ -24,6 +24,10 @@ // Other libraries and framework includes #include "llvm/ADT/StringRef.h" +#include "Acceptor.h" +#include "LLDBServerUtilities.h" +#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h" +#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h" #include "lldb/Core/Error.h" #include "lldb/Core/PluginManager.h" #include "lldb/Host/ConnectionFileDescriptor.h" @@ -32,10 +36,6 @@ #include "lldb/Host/Pipe.h" #include "lldb/Host/Socket.h" #include "lldb/Host/StringConvert.h" -#include "Acceptor.h" -#include "LLDBServerUtilities.h" -#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h" -#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h" #ifndef LLGS_PROGRAM_NAME #define LLGS_PROGRAM_NAME "lldb-server" @@ -58,21 +58,24 @@ using namespace lldb_private::process_gdb_remote; static int g_debug = 0; static int g_verbose = 0; -static struct option g_long_options[] = -{ - { "debug", no_argument, &g_debug, 1 }, - { "verbose", no_argument, &g_verbose, 1 }, - { "log-file", required_argument, NULL, 'l' }, - { "log-channels", required_argument, NULL, 'c' }, - { "attach", required_argument, NULL, 'a' }, - { "named-pipe", required_argument, NULL, 'N' }, - { "pipe", required_argument, NULL, 'U' }, - { "native-regs", no_argument, NULL, 'r' }, // Specify to use the native registers instead of the gdb defaults for the architecture. NOTE: this is a do-nothing arg as it's behavior is default now. FIXME remove call from lldb-platform. - { "reverse-connect", no_argument, NULL, 'R' }, // Specifies that llgs attaches to the client address:port rather than llgs listening for a connection from address on port. - { "setsid", no_argument, NULL, 'S' }, // Call setsid() to make llgs run in its own session. - { NULL, 0, NULL, 0 } -}; - +static struct option g_long_options[] = { + {"debug", no_argument, &g_debug, 1}, + {"verbose", no_argument, &g_verbose, 1}, + {"log-file", required_argument, NULL, 'l'}, + {"log-channels", required_argument, NULL, 'c'}, + {"attach", required_argument, NULL, 'a'}, + {"named-pipe", required_argument, NULL, 'N'}, + {"pipe", required_argument, NULL, 'U'}, + {"native-regs", no_argument, NULL, + 'r'}, // Specify to use the native registers instead of the gdb defaults + // for the architecture. NOTE: this is a do-nothing arg as it's + // behavior is default now. FIXME remove call from lldb-platform. + {"reverse-connect", no_argument, NULL, + 'R'}, // Specifies that llgs attaches to the client address:port rather + // than llgs listening for a connection from address on port. + {"setsid", no_argument, NULL, + 'S'}, // Call setsid() to make llgs run in its own session. + {NULL, 0, NULL, 0}}; //---------------------------------------------------------------------- // Watch for signals @@ -80,418 +83,401 @@ static struct option g_long_options[] = static int g_sighup_received_count = 0; #ifndef _WIN32 -static void -sighup_handler(MainLoopBase &mainloop) -{ - ++g_sighup_received_count; +static void sighup_handler(MainLoopBase &mainloop) { + ++g_sighup_received_count; - Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf ("lldb-server:%s swallowing SIGHUP (receive count=%d)", __FUNCTION__, g_sighup_received_count); + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("lldb-server:%s swallowing SIGHUP (receive count=%d)", + __FUNCTION__, g_sighup_received_count); - if (g_sighup_received_count >= 2) - mainloop.RequestTermination(); + if (g_sighup_received_count >= 2) + mainloop.RequestTermination(); } #endif // #ifndef _WIN32 -static void -display_usage (const char *progname, const char* subcommand) -{ - fprintf(stderr, "Usage:\n %s %s " - "[--log-file log-file-name] " - "[--log-channels log-channel-list] " - "[--setsid] " - "[--named-pipe named-pipe-path] " - "[--native-regs] " - "[--attach pid] " - "[[HOST]:PORT] " - "[-- PROGRAM ARG1 ARG2 ...]\n", progname, subcommand); - exit(0); +static void display_usage(const char *progname, const char *subcommand) { + fprintf(stderr, "Usage:\n %s %s " + "[--log-file log-file-name] " + "[--log-channels log-channel-list] " + "[--setsid] " + "[--named-pipe named-pipe-path] " + "[--native-regs] " + "[--attach pid] " + "[[HOST]:PORT] " + "[-- PROGRAM ARG1 ARG2 ...]\n", + progname, subcommand); + exit(0); } -void -handle_attach_to_pid (GDBRemoteCommunicationServerLLGS &gdb_server, lldb::pid_t pid) -{ - Error error = gdb_server.AttachToProcess (pid); - if (error.Fail ()) - { - fprintf (stderr, "error: failed to attach to pid %" PRIu64 ": %s\n", pid, error.AsCString()); - exit(1); - } +void handle_attach_to_pid(GDBRemoteCommunicationServerLLGS &gdb_server, + lldb::pid_t pid) { + Error error = gdb_server.AttachToProcess(pid); + if (error.Fail()) { + fprintf(stderr, "error: failed to attach to pid %" PRIu64 ": %s\n", pid, + error.AsCString()); + exit(1); + } } -void -handle_attach_to_process_name (GDBRemoteCommunicationServerLLGS &gdb_server, const std::string &process_name) -{ - // FIXME implement. +void handle_attach_to_process_name(GDBRemoteCommunicationServerLLGS &gdb_server, + const std::string &process_name) { + // FIXME implement. } -void -handle_attach (GDBRemoteCommunicationServerLLGS &gdb_server, const std::string &attach_target) -{ - assert (!attach_target.empty () && "attach_target cannot be empty"); - - // First check if the attach_target is convertible to a long. If so, we'll use it as a pid. - char *end_p = nullptr; - const long int pid = strtol (attach_target.c_str (), &end_p, 10); - - // We'll call it a match if the entire argument is consumed. - if (end_p && static_cast<size_t> (end_p - attach_target.c_str ()) == attach_target.size ()) - handle_attach_to_pid (gdb_server, static_cast<lldb::pid_t> (pid)); - else - handle_attach_to_process_name (gdb_server, attach_target); +void handle_attach(GDBRemoteCommunicationServerLLGS &gdb_server, + const std::string &attach_target) { + assert(!attach_target.empty() && "attach_target cannot be empty"); + + // First check if the attach_target is convertible to a long. If so, we'll use + // it as a pid. + char *end_p = nullptr; + const long int pid = strtol(attach_target.c_str(), &end_p, 10); + + // We'll call it a match if the entire argument is consumed. + if (end_p && + static_cast<size_t>(end_p - attach_target.c_str()) == + attach_target.size()) + handle_attach_to_pid(gdb_server, static_cast<lldb::pid_t>(pid)); + else + handle_attach_to_process_name(gdb_server, attach_target); } -void -handle_launch (GDBRemoteCommunicationServerLLGS &gdb_server, int argc, const char *const argv[]) -{ - Error error; - error = gdb_server.SetLaunchArguments (argv, argc); - if (error.Fail ()) - { - fprintf (stderr, "error: failed to set launch args for '%s': %s\n", argv[0], error.AsCString()); - exit(1); - } - - unsigned int launch_flags = eLaunchFlagStopAtEntry | eLaunchFlagDebug; - - error = gdb_server.SetLaunchFlags (launch_flags); - if (error.Fail ()) - { - fprintf (stderr, "error: failed to set launch flags for '%s': %s\n", argv[0], error.AsCString()); - exit(1); - } - - error = gdb_server.LaunchProcess (); - if (error.Fail ()) - { - fprintf (stderr, "error: failed to launch '%s': %s\n", argv[0], error.AsCString()); - exit(1); - } +void handle_launch(GDBRemoteCommunicationServerLLGS &gdb_server, int argc, + const char *const argv[]) { + Error error; + error = gdb_server.SetLaunchArguments(argv, argc); + if (error.Fail()) { + fprintf(stderr, "error: failed to set launch args for '%s': %s\n", argv[0], + error.AsCString()); + exit(1); + } + + unsigned int launch_flags = eLaunchFlagStopAtEntry | eLaunchFlagDebug; + + error = gdb_server.SetLaunchFlags(launch_flags); + if (error.Fail()) { + fprintf(stderr, "error: failed to set launch flags for '%s': %s\n", argv[0], + error.AsCString()); + exit(1); + } + + error = gdb_server.LaunchProcess(); + if (error.Fail()) { + fprintf(stderr, "error: failed to launch '%s': %s\n", argv[0], + error.AsCString()); + exit(1); + } } -Error -writeSocketIdToPipe(Pipe &port_pipe, const std::string &socket_id) -{ - size_t bytes_written = 0; - // Write the port number as a C string with the NULL terminator. - return port_pipe.Write(socket_id.c_str(), socket_id.size() + 1, bytes_written); +Error writeSocketIdToPipe(Pipe &port_pipe, const std::string &socket_id) { + size_t bytes_written = 0; + // Write the port number as a C string with the NULL terminator. + return port_pipe.Write(socket_id.c_str(), socket_id.size() + 1, + bytes_written); } -Error -writeSocketIdToPipe(const char *const named_pipe_path, const std::string &socket_id) -{ - Pipe port_name_pipe; - // Wait for 10 seconds for pipe to be opened. - auto error = port_name_pipe.OpenAsWriterWithTimeout(named_pipe_path, false, - std::chrono::seconds{10}); - if (error.Fail()) - return error; - return writeSocketIdToPipe(port_name_pipe, socket_id); +Error writeSocketIdToPipe(const char *const named_pipe_path, + const std::string &socket_id) { + Pipe port_name_pipe; + // Wait for 10 seconds for pipe to be opened. + auto error = port_name_pipe.OpenAsWriterWithTimeout(named_pipe_path, false, + std::chrono::seconds{10}); + if (error.Fail()) + return error; + return writeSocketIdToPipe(port_name_pipe, socket_id); } -Error -writeSocketIdToPipe(int unnamed_pipe_fd, const std::string &socket_id) -{ +Error writeSocketIdToPipe(int unnamed_pipe_fd, const std::string &socket_id) { #if defined(_WIN32) - return Error("Unnamed pipes are not supported on Windows."); + return Error("Unnamed pipes are not supported on Windows."); #else - Pipe port_pipe{Pipe::kInvalidDescriptor, unnamed_pipe_fd}; - return writeSocketIdToPipe(port_pipe, socket_id); + Pipe port_pipe{Pipe::kInvalidDescriptor, unnamed_pipe_fd}; + return writeSocketIdToPipe(port_pipe, socket_id); #endif } -void -ConnectToRemote(MainLoop &mainloop, GDBRemoteCommunicationServerLLGS &gdb_server, - bool reverse_connect, const char *const host_and_port, - const char *const progname, const char *const subcommand, - const char *const named_pipe_path, int unnamed_pipe_fd) -{ - Error error; - - if (host_and_port && host_and_port[0]) - { - // Parse out host and port. - std::string final_host_and_port; - std::string connection_host; - std::string connection_port; - uint32_t connection_portno = 0; - - // If host_and_port starts with ':', default the host to be "localhost" and expect the remainder to be the port. - if (host_and_port[0] == ':') - final_host_and_port.append ("localhost"); - final_host_and_port.append (host_and_port); - - const std::string::size_type colon_pos = final_host_and_port.find (':'); - if (colon_pos != std::string::npos) - { - connection_host = final_host_and_port.substr (0, colon_pos); - connection_port = final_host_and_port.substr (colon_pos + 1); - connection_portno = StringConvert::ToUInt32 (connection_port.c_str (), 0); - } +void ConnectToRemote(MainLoop &mainloop, + GDBRemoteCommunicationServerLLGS &gdb_server, + bool reverse_connect, const char *const host_and_port, + const char *const progname, const char *const subcommand, + const char *const named_pipe_path, int unnamed_pipe_fd) { + Error error; + + if (host_and_port && host_and_port[0]) { + // Parse out host and port. + std::string final_host_and_port; + std::string connection_host; + std::string connection_port; + uint32_t connection_portno = 0; + + // If host_and_port starts with ':', default the host to be "localhost" and + // expect the remainder to be the port. + if (host_and_port[0] == ':') + final_host_and_port.append("localhost"); + final_host_and_port.append(host_and_port); + + const std::string::size_type colon_pos = final_host_and_port.find(':'); + if (colon_pos != std::string::npos) { + connection_host = final_host_and_port.substr(0, colon_pos); + connection_port = final_host_and_port.substr(colon_pos + 1); + connection_portno = StringConvert::ToUInt32(connection_port.c_str(), 0); + } - std::unique_ptr<Connection> connection_up; - - if (reverse_connect) - { - // llgs will connect to the gdb-remote client. - - // Ensure we have a port number for the connection. - if (connection_portno == 0) - { - fprintf (stderr, "error: port number must be specified on when using reverse connect"); - exit (1); - } - - // Build the connection string. - char connection_url[512]; - snprintf(connection_url, sizeof(connection_url), "connect://%s", final_host_and_port.c_str ()); - - // Create the connection. - connection_up.reset(new ConnectionFileDescriptor); - auto connection_result = connection_up->Connect (connection_url, &error); - if (connection_result != eConnectionStatusSuccess) - { - fprintf (stderr, "error: failed to connect to client at '%s' (connection status: %d)", connection_url, static_cast<int> (connection_result)); - exit (-1); - } - if (error.Fail ()) - { - fprintf (stderr, "error: failed to connect to client at '%s': %s", connection_url, error.AsCString ()); - exit (-1); - } - } - else - { - std::unique_ptr<Acceptor> acceptor_up(Acceptor::Create(final_host_and_port, false, error)); - if (error.Fail()) - { - fprintf(stderr, "failed to create acceptor: %s", error.AsCString()); - exit(1); - } - error = acceptor_up->Listen(1); - if (error.Fail()) - { - fprintf(stderr, "failed to listen: %s\n", error.AsCString()); - exit(1); - } - const std::string socket_id = acceptor_up->GetLocalSocketId(); - if (!socket_id.empty()) - { - // If we have a named pipe to write the socket id back to, do that now. - if (named_pipe_path && named_pipe_path[0]) - { - error = writeSocketIdToPipe (named_pipe_path, socket_id); - if (error.Fail ()) - fprintf (stderr, "failed to write to the named pipe \'%s\': %s", - named_pipe_path, error.AsCString()); - } - // If we have an unnamed pipe to write the socket id back to, do that now. - else if (unnamed_pipe_fd >= 0) - { - error = writeSocketIdToPipe(unnamed_pipe_fd, socket_id); - if (error.Fail()) - fprintf(stderr, "failed to write to the unnamed pipe: %s", - error.AsCString()); - } - } - else - { - fprintf (stderr, "unable to get the socket id for the listening connection\n"); - } - - Connection* conn = nullptr; - error = acceptor_up->Accept(false, conn); - if (error.Fail()) - { - printf ("failed to accept new connection: %s\n", error.AsCString()); - exit(1); - } - connection_up.reset(conn); + std::unique_ptr<Connection> connection_up; + + if (reverse_connect) { + // llgs will connect to the gdb-remote client. + + // Ensure we have a port number for the connection. + if (connection_portno == 0) { + fprintf(stderr, "error: port number must be specified on when using " + "reverse connect"); + exit(1); + } + + // Build the connection string. + char connection_url[512]; + snprintf(connection_url, sizeof(connection_url), "connect://%s", + final_host_and_port.c_str()); + + // Create the connection. + connection_up.reset(new ConnectionFileDescriptor); + auto connection_result = connection_up->Connect(connection_url, &error); + if (connection_result != eConnectionStatusSuccess) { + fprintf(stderr, "error: failed to connect to client at '%s' " + "(connection status: %d)", + connection_url, static_cast<int>(connection_result)); + exit(-1); + } + if (error.Fail()) { + fprintf(stderr, "error: failed to connect to client at '%s': %s", + connection_url, error.AsCString()); + exit(-1); + } + } else { + std::unique_ptr<Acceptor> acceptor_up( + Acceptor::Create(final_host_and_port, false, error)); + if (error.Fail()) { + fprintf(stderr, "failed to create acceptor: %s", error.AsCString()); + exit(1); + } + error = acceptor_up->Listen(1); + if (error.Fail()) { + fprintf(stderr, "failed to listen: %s\n", error.AsCString()); + exit(1); + } + const std::string socket_id = acceptor_up->GetLocalSocketId(); + if (!socket_id.empty()) { + // If we have a named pipe to write the socket id back to, do that now. + if (named_pipe_path && named_pipe_path[0]) { + error = writeSocketIdToPipe(named_pipe_path, socket_id); + if (error.Fail()) + fprintf(stderr, "failed to write to the named pipe \'%s\': %s", + named_pipe_path, error.AsCString()); } - error = gdb_server.InitializeConnection (std::move(connection_up)); - if (error.Fail()) - { - fprintf(stderr, "Failed to initialize connection: %s\n", error.AsCString()); - exit(-1); + // If we have an unnamed pipe to write the socket id back to, do that + // now. + else if (unnamed_pipe_fd >= 0) { + error = writeSocketIdToPipe(unnamed_pipe_fd, socket_id); + if (error.Fail()) + fprintf(stderr, "failed to write to the unnamed pipe: %s", + error.AsCString()); } - printf ("Connection established.\n"); + } else { + fprintf(stderr, + "unable to get the socket id for the listening connection\n"); + } + + Connection *conn = nullptr; + error = acceptor_up->Accept(false, conn); + if (error.Fail()) { + printf("failed to accept new connection: %s\n", error.AsCString()); + exit(1); + } + connection_up.reset(conn); + } + error = gdb_server.InitializeConnection(std::move(connection_up)); + if (error.Fail()) { + fprintf(stderr, "Failed to initialize connection: %s\n", + error.AsCString()); + exit(-1); } + printf("Connection established.\n"); + } } //---------------------------------------------------------------------- // main //---------------------------------------------------------------------- -int -main_gdbserver (int argc, char *argv[]) -{ - Error error; - MainLoop mainloop; +int main_gdbserver(int argc, char *argv[]) { + Error error; + MainLoop mainloop; #ifndef _WIN32 - // Setup signal handlers first thing. - signal(SIGPIPE, SIG_IGN); - MainLoop::SignalHandleUP sighup_handle = mainloop.RegisterSignal(SIGHUP, sighup_handler, error); + // Setup signal handlers first thing. + signal(SIGPIPE, SIG_IGN); + MainLoop::SignalHandleUP sighup_handle = + mainloop.RegisterSignal(SIGHUP, sighup_handler, error); #endif - const char *progname = argv[0]; - const char *subcommand = argv[1]; - argc--; - argv++; - int long_option_index = 0; - int ch; - std::string attach_target; - std::string named_pipe_path; - std::string log_file; - StringRef log_channels; // e.g. "lldb process threads:gdb-remote default:linux all" - int unnamed_pipe_fd = -1; - bool reverse_connect = false; - - // ProcessLaunchInfo launch_info; - ProcessAttachInfo attach_info; - - bool show_usage = false; - int option_error = 0; + const char *progname = argv[0]; + const char *subcommand = argv[1]; + argc--; + argv++; + int long_option_index = 0; + int ch; + std::string attach_target; + std::string named_pipe_path; + std::string log_file; + StringRef + log_channels; // e.g. "lldb process threads:gdb-remote default:linux all" + int unnamed_pipe_fd = -1; + bool reverse_connect = false; + + // ProcessLaunchInfo launch_info; + ProcessAttachInfo attach_info; + + bool show_usage = false; + int option_error = 0; #if __GLIBC__ - optind = 0; + optind = 0; #else - optreset = 1; - optind = 1; + optreset = 1; + optind = 1; #endif - std::string short_options(OptionParser::GetShortOptionString(g_long_options)); + std::string short_options(OptionParser::GetShortOptionString(g_long_options)); - while ((ch = getopt_long_only(argc, argv, short_options.c_str(), g_long_options, &long_option_index)) != -1) - { - switch (ch) - { - case 0: // Any optional that auto set themselves will return 0 - break; + while ((ch = getopt_long_only(argc, argv, short_options.c_str(), + g_long_options, &long_option_index)) != -1) { + switch (ch) { + case 0: // Any optional that auto set themselves will return 0 + break; - case 'l': // Set Log File - if (optarg && optarg[0]) - log_file.assign(optarg); - break; + case 'l': // Set Log File + if (optarg && optarg[0]) + log_file.assign(optarg); + break; - case 'c': // Log Channels - if (optarg && optarg[0]) - log_channels = StringRef(optarg); - break; + case 'c': // Log Channels + if (optarg && optarg[0]) + log_channels = StringRef(optarg); + break; - case 'N': // named pipe - if (optarg && optarg[0]) - named_pipe_path = optarg; - break; + case 'N': // named pipe + if (optarg && optarg[0]) + named_pipe_path = optarg; + break; - case 'U': // unnamed pipe - if (optarg && optarg[0]) - unnamed_pipe_fd = StringConvert::ToUInt32(optarg, -1); - break; + case 'U': // unnamed pipe + if (optarg && optarg[0]) + unnamed_pipe_fd = StringConvert::ToUInt32(optarg, -1); + break; - case 'r': - // Do nothing, native regs is the default these days - break; + case 'r': + // Do nothing, native regs is the default these days + break; - case 'R': - reverse_connect = true; - break; + case 'R': + reverse_connect = true; + break; #ifndef _WIN32 - case 'S': - // Put llgs into a new session. Terminals group processes - // into sessions and when a special terminal key sequences - // (like control+c) are typed they can cause signals to go out to - // all processes in a session. Using this --setsid (-S) option - // will cause debugserver to run in its own sessions and be free - // from such issues. - // - // This is useful when llgs is spawned from a command - // line application that uses llgs to do the debugging, - // yet that application doesn't want llgs receiving the - // signals sent to the session (i.e. dying when anyone hits ^C). - { - const ::pid_t new_sid = setsid(); - if (new_sid == -1) - { - const char *errno_str = strerror(errno); - fprintf (stderr, "failed to set new session id for %s (%s)\n", LLGS_PROGRAM_NAME, errno_str ? errno_str : "<no error string>"); - } - } - break; -#endif - - case 'a': // attach {pid|process_name} - if (optarg && optarg[0]) - attach_target = optarg; - break; - - case 'h': /* fall-through is intentional */ - case '?': - show_usage = true; - break; - } - } - - if (show_usage || option_error) - { - display_usage(progname, subcommand); - exit(option_error); - } - - if (!LLDBServerUtilities::SetupLogging(log_file, log_channels, LLDB_LOG_OPTION_PREPEND_TIMESTAMP)) - return -1; - - Log *log(lldb_private::GetLogIfAnyCategoriesSet (GDBR_LOG_VERBOSE)); - if (log) - { - log->Printf ("lldb-server launch"); - for (int i = 0; i < argc; i++) - { - log->Printf ("argv[%i] = '%s'", i, argv[i]); + case 'S': + // Put llgs into a new session. Terminals group processes + // into sessions and when a special terminal key sequences + // (like control+c) are typed they can cause signals to go out to + // all processes in a session. Using this --setsid (-S) option + // will cause debugserver to run in its own sessions and be free + // from such issues. + // + // This is useful when llgs is spawned from a command + // line application that uses llgs to do the debugging, + // yet that application doesn't want llgs receiving the + // signals sent to the session (i.e. dying when anyone hits ^C). + { + const ::pid_t new_sid = setsid(); + if (new_sid == -1) { + const char *errno_str = strerror(errno); + fprintf(stderr, "failed to set new session id for %s (%s)\n", + LLGS_PROGRAM_NAME, + errno_str ? errno_str : "<no error string>"); } - } + } + break; +#endif - // Skip any options we consumed with getopt_long_only. - argc -= optind; - argv += optind; + case 'a': // attach {pid|process_name} + if (optarg && optarg[0]) + attach_target = optarg; + break; - if (argc == 0) - { - display_usage(progname, subcommand); - exit(255); + case 'h': /* fall-through is intentional */ + case '?': + show_usage = true; + break; } - - GDBRemoteCommunicationServerLLGS gdb_server(mainloop); - - const char *const host_and_port = argv[0]; - argc -= 1; - argv += 1; - - // Any arguments left over are for the program that we need to launch. If there - // are no arguments, then the GDB server will start up and wait for an 'A' packet - // to launch a program, or a vAttach packet to attach to an existing process, unless - // explicitly asked to attach with the --attach={pid|program_name} form. - if (!attach_target.empty ()) - handle_attach (gdb_server, attach_target); - else if (argc > 0) - handle_launch (gdb_server, argc, argv); - - // Print version info. - printf("%s-%s", LLGS_PROGRAM_NAME, LLGS_VERSION_STR); - - ConnectToRemote(mainloop, gdb_server, reverse_connect, - host_and_port, progname, subcommand, - named_pipe_path.c_str(), unnamed_pipe_fd); - - - if (! gdb_server.IsConnected()) - { - fprintf (stderr, "no connection information provided, unable to run\n"); - display_usage (progname, subcommand); - return 1; + } + + if (show_usage || option_error) { + display_usage(progname, subcommand); + exit(option_error); + } + + if (!LLDBServerUtilities::SetupLogging(log_file, log_channels, + LLDB_LOG_OPTION_PREPEND_TIMESTAMP)) + return -1; + + Log *log(lldb_private::GetLogIfAnyCategoriesSet(GDBR_LOG_VERBOSE)); + if (log) { + log->Printf("lldb-server launch"); + for (int i = 0; i < argc; i++) { + log->Printf("argv[%i] = '%s'", i, argv[i]); } - - mainloop.Run(); - fprintf(stderr, "lldb-server exiting...\n"); - - return 0; + } + + // Skip any options we consumed with getopt_long_only. + argc -= optind; + argv += optind; + + if (argc == 0) { + display_usage(progname, subcommand); + exit(255); + } + + GDBRemoteCommunicationServerLLGS gdb_server(mainloop); + + const char *const host_and_port = argv[0]; + argc -= 1; + argv += 1; + + // Any arguments left over are for the program that we need to launch. If + // there + // are no arguments, then the GDB server will start up and wait for an 'A' + // packet + // to launch a program, or a vAttach packet to attach to an existing process, + // unless + // explicitly asked to attach with the --attach={pid|program_name} form. + if (!attach_target.empty()) + handle_attach(gdb_server, attach_target); + else if (argc > 0) + handle_launch(gdb_server, argc, argv); + + // Print version info. + printf("%s-%s", LLGS_PROGRAM_NAME, LLGS_VERSION_STR); + + ConnectToRemote(mainloop, gdb_server, reverse_connect, host_and_port, + progname, subcommand, named_pipe_path.c_str(), + unnamed_pipe_fd); + + if (!gdb_server.IsConnected()) { + fprintf(stderr, "no connection information provided, unable to run\n"); + display_usage(progname, subcommand); + return 1; + } + + mainloop.Run(); + fprintf(stderr, "lldb-server exiting...\n"); + + return 0; } diff --git a/lldb/tools/lldb-server/lldb-platform.cpp b/lldb/tools/lldb-server/lldb-platform.cpp index 3292080da63..d6bfaa24ee7 100644 --- a/lldb/tools/lldb-server/lldb-platform.cpp +++ b/lldb/tools/lldb-server/lldb-platform.cpp @@ -26,6 +26,10 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/FileUtilities.h" +#include "Acceptor.h" +#include "LLDBServerUtilities.h" +#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h" +#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h" #include "lldb/Core/Error.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/FileSpec.h" @@ -33,10 +37,6 @@ #include "lldb/Host/HostGetOpt.h" #include "lldb/Host/OptionParser.h" #include "lldb/Host/common/TCPSocket.h" -#include "Acceptor.h" -#include "LLDBServerUtilities.h" -#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h" -#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h" using namespace lldb; using namespace lldb_private; @@ -52,365 +52,335 @@ static int g_debug = 0; static int g_verbose = 0; static int g_server = 0; -static struct option g_long_options[] = -{ - { "debug", no_argument, &g_debug, 1 }, - { "verbose", no_argument, &g_verbose, 1 }, - { "log-file", required_argument, NULL, 'l' }, - { "log-channels", required_argument, NULL, 'c' }, - { "listen", required_argument, NULL, 'L' }, - { "port-offset", required_argument, NULL, 'p' }, - { "gdbserver-port", required_argument, NULL, 'P' }, - { "min-gdbserver-port", required_argument, NULL, 'm' }, - { "max-gdbserver-port", required_argument, NULL, 'M' }, - { "socket-file", required_argument, NULL, 'f' }, - { "server", no_argument, &g_server, 1 }, - { NULL, 0, NULL, 0 } -}; - -#if defined (__APPLE__) -#define LOW_PORT (IPPORT_RESERVED) -#define HIGH_PORT (IPPORT_HIFIRSTAUTO) +static struct option g_long_options[] = { + {"debug", no_argument, &g_debug, 1}, + {"verbose", no_argument, &g_verbose, 1}, + {"log-file", required_argument, NULL, 'l'}, + {"log-channels", required_argument, NULL, 'c'}, + {"listen", required_argument, NULL, 'L'}, + {"port-offset", required_argument, NULL, 'p'}, + {"gdbserver-port", required_argument, NULL, 'P'}, + {"min-gdbserver-port", required_argument, NULL, 'm'}, + {"max-gdbserver-port", required_argument, NULL, 'M'}, + {"socket-file", required_argument, NULL, 'f'}, + {"server", no_argument, &g_server, 1}, + {NULL, 0, NULL, 0}}; + +#if defined(__APPLE__) +#define LOW_PORT (IPPORT_RESERVED) +#define HIGH_PORT (IPPORT_HIFIRSTAUTO) #else -#define LOW_PORT (1024u) -#define HIGH_PORT (49151u) +#define LOW_PORT (1024u) +#define HIGH_PORT (49151u) #endif //---------------------------------------------------------------------- // Watch for signals //---------------------------------------------------------------------- -static void -signal_handler(int signo) -{ - switch (signo) - { - case SIGHUP: - // Use SIGINT first, if that does not work, use SIGHUP as a last resort. - // And we should not call exit() here because it results in the global destructors - // to be invoked and wreaking havoc on the threads still running. - Host::SystemLog(Host::eSystemLogWarning, "SIGHUP received, exiting lldb-server...\n"); - abort(); - break; - } +static void signal_handler(int signo) { + switch (signo) { + case SIGHUP: + // Use SIGINT first, if that does not work, use SIGHUP as a last resort. + // And we should not call exit() here because it results in the global + // destructors + // to be invoked and wreaking havoc on the threads still running. + Host::SystemLog(Host::eSystemLogWarning, + "SIGHUP received, exiting lldb-server...\n"); + abort(); + break; + } } -static void -display_usage (const char *progname, const char *subcommand) -{ - fprintf(stderr, "Usage:\n %s %s [--log-file log-file-name] [--log-channels log-channel-list] [--port-file port-file-path] --server --listen port\n", progname, subcommand); - exit(0); +static void display_usage(const char *progname, const char *subcommand) { + fprintf(stderr, "Usage:\n %s %s [--log-file log-file-name] [--log-channels " + "log-channel-list] [--port-file port-file-path] --server " + "--listen port\n", + progname, subcommand); + exit(0); } -static Error -save_socket_id_to_file(const std::string &socket_id, const FileSpec &file_spec) -{ - FileSpec temp_file_spec(file_spec.GetDirectory().AsCString(), false); - auto error = FileSystem::MakeDirectory(temp_file_spec, eFilePermissionsDirectoryDefault); - if (error.Fail()) - return Error("Failed to create directory %s: %s", temp_file_spec.GetCString(), error.AsCString()); - - llvm::SmallString<PATH_MAX> temp_file_path; - temp_file_spec.AppendPathComponent("port-file.%%%%%%"); - auto err_code = llvm::sys::fs::createUniqueFile(temp_file_spec.GetCString(), temp_file_path); - if (err_code) - return Error("Failed to create temp file: %s", err_code.message().c_str()); - - llvm::FileRemover tmp_file_remover(temp_file_path.c_str()); - - { - std::ofstream temp_file(temp_file_path.c_str(), std::ios::out); - if (!temp_file.is_open()) - return Error("Failed to open temp file %s", temp_file_path.c_str()); - temp_file << socket_id; - } - - err_code = llvm::sys::fs::rename(temp_file_path.c_str(), file_spec.GetPath().c_str()); - if (err_code) - return Error("Failed to rename file %s to %s: %s", - temp_file_path.c_str(), file_spec.GetPath().c_str(), err_code.message().c_str()); - - tmp_file_remover.releaseFile(); - return Error(); +static Error save_socket_id_to_file(const std::string &socket_id, + const FileSpec &file_spec) { + FileSpec temp_file_spec(file_spec.GetDirectory().AsCString(), false); + auto error = FileSystem::MakeDirectory(temp_file_spec, + eFilePermissionsDirectoryDefault); + if (error.Fail()) + return Error("Failed to create directory %s: %s", + temp_file_spec.GetCString(), error.AsCString()); + + llvm::SmallString<PATH_MAX> temp_file_path; + temp_file_spec.AppendPathComponent("port-file.%%%%%%"); + auto err_code = llvm::sys::fs::createUniqueFile(temp_file_spec.GetCString(), + temp_file_path); + if (err_code) + return Error("Failed to create temp file: %s", err_code.message().c_str()); + + llvm::FileRemover tmp_file_remover(temp_file_path.c_str()); + + { + std::ofstream temp_file(temp_file_path.c_str(), std::ios::out); + if (!temp_file.is_open()) + return Error("Failed to open temp file %s", temp_file_path.c_str()); + temp_file << socket_id; + } + + err_code = llvm::sys::fs::rename(temp_file_path.c_str(), + file_spec.GetPath().c_str()); + if (err_code) + return Error("Failed to rename file %s to %s: %s", temp_file_path.c_str(), + file_spec.GetPath().c_str(), err_code.message().c_str()); + + tmp_file_remover.releaseFile(); + return Error(); } //---------------------------------------------------------------------- // main //---------------------------------------------------------------------- -int -main_platform (int argc, char *argv[]) -{ - const char *progname = argv[0]; - const char *subcommand = argv[1]; - argc--; - argv++; - signal (SIGPIPE, SIG_IGN); - signal (SIGHUP, signal_handler); - int long_option_index = 0; - Error error; - std::string listen_host_port; - int ch; - - std::string log_file; - StringRef log_channels; // e.g. "lldb process threads:gdb-remote default:linux all" - - GDBRemoteCommunicationServerPlatform::PortMap gdbserver_portmap; - int min_gdbserver_port = 0; - int max_gdbserver_port = 0; - uint16_t port_offset = 0; - - FileSpec socket_file; - bool show_usage = false; - int option_error = 0; - int socket_error = -1; - - std::string short_options(OptionParser::GetShortOptionString(g_long_options)); - +int main_platform(int argc, char *argv[]) { + const char *progname = argv[0]; + const char *subcommand = argv[1]; + argc--; + argv++; + signal(SIGPIPE, SIG_IGN); + signal(SIGHUP, signal_handler); + int long_option_index = 0; + Error error; + std::string listen_host_port; + int ch; + + std::string log_file; + StringRef + log_channels; // e.g. "lldb process threads:gdb-remote default:linux all" + + GDBRemoteCommunicationServerPlatform::PortMap gdbserver_portmap; + int min_gdbserver_port = 0; + int max_gdbserver_port = 0; + uint16_t port_offset = 0; + + FileSpec socket_file; + bool show_usage = false; + int option_error = 0; + int socket_error = -1; + + std::string short_options(OptionParser::GetShortOptionString(g_long_options)); + #if __GLIBC__ - optind = 0; + optind = 0; #else - optreset = 1; - optind = 1; + optreset = 1; + optind = 1; #endif - while ((ch = getopt_long_only(argc, argv, short_options.c_str(), g_long_options, &long_option_index)) != -1) - { - switch (ch) - { - case 0: // Any optional that auto set themselves will return 0 - break; - - case 'L': - listen_host_port.append (optarg); - break; - - case 'l': // Set Log File - if (optarg && optarg[0]) - log_file.assign(optarg); - break; - - case 'c': // Log Channels - if (optarg && optarg[0]) - log_channels = StringRef(optarg); - break; - - case 'f': // Socket file - if (optarg && optarg[0]) - socket_file.SetFile(optarg, false); - break; - - case 'p': - { - char *end = NULL; - long tmp_port_offset = strtoul(optarg, &end, 0); - if (end && *end == '\0') - { - if (LOW_PORT <= tmp_port_offset && tmp_port_offset <= HIGH_PORT) - { - port_offset = (uint16_t)tmp_port_offset; - } - else - { - fprintf (stderr, "error: port offset %li is not in the valid user port range of %u - %u\n", tmp_port_offset, LOW_PORT, HIGH_PORT); - option_error = 5; - } - } - else - { - fprintf (stderr, "error: invalid port offset string %s\n", optarg); - option_error = 4; - } - } - break; - - case 'P': - case 'm': - case 'M': - { - char *end = NULL; - long portnum = strtoul(optarg, &end, 0); - if (end && *end == '\0') - { - if (LOW_PORT <= portnum && portnum <= HIGH_PORT) - { - if (ch == 'P') - gdbserver_portmap[(uint16_t)portnum] = LLDB_INVALID_PROCESS_ID; - else if (ch == 'm') - min_gdbserver_port = portnum; - else - max_gdbserver_port = portnum; - } - else - { - fprintf (stderr, "error: port number %li is not in the valid user port range of %u - %u\n", portnum, LOW_PORT, HIGH_PORT); - option_error = 1; - } - } - else - { - fprintf (stderr, "error: invalid port number string %s\n", optarg); - option_error = 2; - } - } - break; - - case 'h': /* fall-through is intentional */ - case '?': - show_usage = true; - break; + while ((ch = getopt_long_only(argc, argv, short_options.c_str(), + g_long_options, &long_option_index)) != -1) { + switch (ch) { + case 0: // Any optional that auto set themselves will return 0 + break; + + case 'L': + listen_host_port.append(optarg); + break; + + case 'l': // Set Log File + if (optarg && optarg[0]) + log_file.assign(optarg); + break; + + case 'c': // Log Channels + if (optarg && optarg[0]) + log_channels = StringRef(optarg); + break; + + case 'f': // Socket file + if (optarg && optarg[0]) + socket_file.SetFile(optarg, false); + break; + + case 'p': { + char *end = NULL; + long tmp_port_offset = strtoul(optarg, &end, 0); + if (end && *end == '\0') { + if (LOW_PORT <= tmp_port_offset && tmp_port_offset <= HIGH_PORT) { + port_offset = (uint16_t)tmp_port_offset; + } else { + fprintf(stderr, "error: port offset %li is not in the valid user " + "port range of %u - %u\n", + tmp_port_offset, LOW_PORT, HIGH_PORT); + option_error = 5; } + } else { + fprintf(stderr, "error: invalid port offset string %s\n", optarg); + option_error = 4; + } + } break; + + case 'P': + case 'm': + case 'M': { + char *end = NULL; + long portnum = strtoul(optarg, &end, 0); + if (end && *end == '\0') { + if (LOW_PORT <= portnum && portnum <= HIGH_PORT) { + if (ch == 'P') + gdbserver_portmap[(uint16_t)portnum] = LLDB_INVALID_PROCESS_ID; + else if (ch == 'm') + min_gdbserver_port = portnum; + else + max_gdbserver_port = portnum; + } else { + fprintf(stderr, "error: port number %li is not in the valid user " + "port range of %u - %u\n", + portnum, LOW_PORT, HIGH_PORT); + option_error = 1; + } + } else { + fprintf(stderr, "error: invalid port number string %s\n", optarg); + option_error = 2; + } + } break; + + case 'h': /* fall-through is intentional */ + case '?': + show_usage = true; + break; + } + } + + if (!LLDBServerUtilities::SetupLogging(log_file, log_channels, 0)) + return -1; + + // Make a port map for a port range that was specified. + if (min_gdbserver_port < max_gdbserver_port) { + for (uint16_t port = min_gdbserver_port; port < max_gdbserver_port; ++port) + gdbserver_portmap[port] = LLDB_INVALID_PROCESS_ID; + } else if (min_gdbserver_port != max_gdbserver_port) { + fprintf(stderr, "error: --min-gdbserver-port (%u) is greater than " + "--max-gdbserver-port (%u)\n", + min_gdbserver_port, max_gdbserver_port); + option_error = 3; + } + + // Print usage and exit if no listening port is specified. + if (listen_host_port.empty()) + show_usage = true; + + if (show_usage || option_error) { + display_usage(progname, subcommand); + exit(option_error); + } + + // Skip any options we consumed with getopt_long_only. + argc -= optind; + argv += optind; + lldb_private::Args inferior_arguments; + inferior_arguments.SetArguments(argc, const_cast<const char **>(argv)); + + const bool children_inherit_listen_socket = false; + // the test suite makes many connections in parallel, let's not miss any. + // The highest this should get reasonably is a function of the number + // of target CPUs. For now, let's just use 100. + const int backlog = 100; + + std::unique_ptr<Acceptor> acceptor_up(Acceptor::Create( + listen_host_port, children_inherit_listen_socket, error)); + if (error.Fail()) { + fprintf(stderr, "failed to create acceptor: %s", error.AsCString()); + exit(socket_error); + } + + error = acceptor_up->Listen(backlog); + if (error.Fail()) { + printf("failed to listen: %s\n", error.AsCString()); + exit(socket_error); + } + if (socket_file) { + error = + save_socket_id_to_file(acceptor_up->GetLocalSocketId(), socket_file); + if (error.Fail()) { + fprintf(stderr, "failed to write socket id to %s: %s\n", + socket_file.GetPath().c_str(), error.AsCString()); + return 1; } + } - if (!LLDBServerUtilities::SetupLogging(log_file, log_channels, 0)) - return -1; + do { + GDBRemoteCommunicationServerPlatform platform( + acceptor_up->GetSocketProtocol(), acceptor_up->GetSocketScheme()); - // Make a port map for a port range that was specified. - if (min_gdbserver_port < max_gdbserver_port) - { - for (uint16_t port = min_gdbserver_port; port < max_gdbserver_port; ++port) - gdbserver_portmap[port] = LLDB_INVALID_PROCESS_ID; - } - else if (min_gdbserver_port != max_gdbserver_port) - { - fprintf (stderr, "error: --min-gdbserver-port (%u) is greater than --max-gdbserver-port (%u)\n", min_gdbserver_port, max_gdbserver_port); - option_error = 3; - } + if (port_offset > 0) + platform.SetPortOffset(port_offset); - // Print usage and exit if no listening port is specified. - if (listen_host_port.empty()) - show_usage = true; - - if (show_usage || option_error) - { - display_usage(progname, subcommand); - exit(option_error); + if (!gdbserver_portmap.empty()) { + platform.SetPortMap(std::move(gdbserver_portmap)); } - // Skip any options we consumed with getopt_long_only. - argc -= optind; - argv += optind; - lldb_private::Args inferior_arguments; - inferior_arguments.SetArguments(argc, const_cast<const char**>(argv)); - - const bool children_inherit_listen_socket = false; - // the test suite makes many connections in parallel, let's not miss any. - // The highest this should get reasonably is a function of the number - // of target CPUs. For now, let's just use 100. - const int backlog = 100; - - std::unique_ptr<Acceptor> acceptor_up(Acceptor::Create(listen_host_port, children_inherit_listen_socket, error)); - if (error.Fail()) - { - fprintf(stderr, "failed to create acceptor: %s", error.AsCString()); - exit(socket_error); + const bool children_inherit_accept_socket = true; + Connection *conn = nullptr; + error = acceptor_up->Accept(children_inherit_accept_socket, conn); + if (error.Fail()) { + printf("error: %s\n", error.AsCString()); + exit(socket_error); } - - error = acceptor_up->Listen(backlog); - if (error.Fail()) - { - printf("failed to listen: %s\n", error.AsCString()); - exit(socket_error); + printf("Connection established.\n"); + if (g_server) { + // Collect child zombie processes. + while (waitpid(-1, nullptr, WNOHANG) > 0) + ; + if (fork()) { + // Parent doesn't need a connection to the lldb client + delete conn; + + // Parent will continue to listen for new connections. + continue; + } else { + // Child process will handle the connection and exit. + g_server = 0; + // Listening socket is owned by parent process. + acceptor_up.release(); + } + } else { + // If not running as a server, this process will not accept + // connections while a connection is active. + acceptor_up.reset(); } - if (socket_file) - { - error = save_socket_id_to_file(acceptor_up->GetLocalSocketId(), socket_file); - if (error.Fail()) - { - fprintf(stderr, "failed to write socket id to %s: %s\n", socket_file.GetPath().c_str(), error.AsCString()); - return 1; - } - } - - do { - GDBRemoteCommunicationServerPlatform platform(acceptor_up->GetSocketProtocol(), - acceptor_up->GetSocketScheme()); - - if (port_offset > 0) - platform.SetPortOffset(port_offset); - - if (!gdbserver_portmap.empty()) - { - platform.SetPortMap(std::move(gdbserver_portmap)); - } - - const bool children_inherit_accept_socket = true; - Connection* conn = nullptr; - error = acceptor_up->Accept(children_inherit_accept_socket, conn); - if (error.Fail()) - { - printf ("error: %s\n", error.AsCString()); - exit(socket_error); - } - printf ("Connection established.\n"); - if (g_server) - { - // Collect child zombie processes. - while (waitpid(-1, nullptr, WNOHANG) > 0); - if (fork()) - { - // Parent doesn't need a connection to the lldb client - delete conn; - - // Parent will continue to listen for new connections. - continue; - } - else - { - // Child process will handle the connection and exit. - g_server = 0; - // Listening socket is owned by parent process. - acceptor_up.release(); - } - } + platform.SetConnection(conn); + + if (platform.IsConnected()) { + if (inferior_arguments.GetArgumentCount() > 0) { + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; + uint16_t port = 0; + std::string socket_name; + Error error = platform.LaunchGDBServer(inferior_arguments, + "", // hostname + pid, port, socket_name); + if (error.Success()) + platform.SetPendingGdbServer(pid, port, socket_name); else - { - // If not running as a server, this process will not accept - // connections while a connection is active. - acceptor_up.reset(); + fprintf(stderr, "failed to start gdbserver: %s\n", error.AsCString()); + } + + // After we connected, we need to get an initial ack from... + if (platform.HandshakeWithClient()) { + bool interrupt = false; + bool done = false; + while (!interrupt && !done) { + if (platform.GetPacketAndSendResponse(UINT32_MAX, error, interrupt, + done) != + GDBRemoteCommunication::PacketResult::Success) + break; } - platform.SetConnection (conn); - - if (platform.IsConnected()) - { - if (inferior_arguments.GetArgumentCount() > 0) - { - lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; - uint16_t port = 0; - std::string socket_name; - Error error = platform.LaunchGDBServer(inferior_arguments, - "", // hostname - pid, - port, - socket_name); - if (error.Success()) - platform.SetPendingGdbServer(pid, port, socket_name); - else - fprintf(stderr, "failed to start gdbserver: %s\n", error.AsCString()); - } - - // After we connected, we need to get an initial ack from... - if (platform.HandshakeWithClient()) - { - bool interrupt = false; - bool done = false; - while (!interrupt && !done) - { - if (platform.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done) != GDBRemoteCommunication::PacketResult::Success) - break; - } - - if (error.Fail()) - { - fprintf(stderr, "error: %s\n", error.AsCString()); - } - } - else - { - fprintf(stderr, "error: handshake with client failed\n"); - } + + if (error.Fail()) { + fprintf(stderr, "error: %s\n", error.AsCString()); } - } while (g_server); + } else { + fprintf(stderr, "error: handshake with client failed\n"); + } + } + } while (g_server); - fprintf(stderr, "lldb-server exiting...\n"); + fprintf(stderr, "lldb-server exiting...\n"); - return 0; + return 0; } diff --git a/lldb/tools/lldb-server/lldb-server.cpp b/lldb/tools/lldb-server/lldb-server.cpp index 9ece640b288..06ef0498749 100644 --- a/lldb/tools/lldb-server/lldb-server.cpp +++ b/lldb/tools/lldb-server/lldb-server.cpp @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Initialization/SystemLifetimeManager.h" #include "lldb/Initialization/SystemInitializerCommon.h" +#include "lldb/Initialization/SystemLifetimeManager.h" #include "lldb/lldb-private.h" #include "llvm/ADT/STLExtras.h" @@ -17,66 +17,57 @@ #include <stdio.h> #include <stdlib.h> -static llvm::ManagedStatic<lldb_private::SystemLifetimeManager> g_debugger_lifetime; +static llvm::ManagedStatic<lldb_private::SystemLifetimeManager> + g_debugger_lifetime; -static void -display_usage (const char *progname) -{ - fprintf(stderr, "Usage:\n" - " %s v[ersion]\n" - " %s g[dbserver] [options]\n" - " %s p[latform] [options]\n" - "Invoke subcommand for additional help\n", progname, progname, progname); - exit(0); +static void display_usage(const char *progname) { + fprintf(stderr, "Usage:\n" + " %s v[ersion]\n" + " %s g[dbserver] [options]\n" + " %s p[latform] [options]\n" + "Invoke subcommand for additional help\n", + progname, progname, progname); + exit(0); } // Forward declarations of subcommand main methods. -int main_gdbserver (int argc, char *argv[]); -int main_platform (int argc, char *argv[]); +int main_gdbserver(int argc, char *argv[]); +int main_platform(int argc, char *argv[]); -static void -initialize () -{ - g_debugger_lifetime->Initialize(llvm::make_unique<lldb_private::SystemInitializerCommon>(), nullptr); +static void initialize() { + g_debugger_lifetime->Initialize( + llvm::make_unique<lldb_private::SystemInitializerCommon>(), nullptr); } -static void -terminate () -{ - g_debugger_lifetime->Terminate(); -} +static void terminate() { g_debugger_lifetime->Terminate(); } //---------------------------------------------------------------------- // main //---------------------------------------------------------------------- -int -main (int argc, char *argv[]) -{ - int option_error = 0; - const char *progname = argv[0]; - if (argc < 2) - { - display_usage(progname); - exit(option_error); - } +int main(int argc, char *argv[]) { + int option_error = 0; + const char *progname = argv[0]; + if (argc < 2) { + display_usage(progname); + exit(option_error); + } - switch (argv[1][0]) - { - case 'g': - initialize(); - main_gdbserver(argc, argv); - terminate(); - break; - case 'p': - initialize(); - main_platform(argc, argv); - terminate(); - break; - case 'v': - fprintf(stderr, "%s\n", lldb_private::GetVersion()); - break; - default: - display_usage(progname); - exit(option_error); - } + switch (argv[1][0]) { + case 'g': + initialize(); + main_gdbserver(argc, argv); + terminate(); + break; + case 'p': + initialize(); + main_platform(argc, argv); + terminate(); + break; + case 'v': + fprintf(stderr, "%s\n", lldb_private::GetVersion()); + break; + default: + display_usage(progname); + exit(option_error); + } } |