diff options
author | Kate Stone <katherine.stone@apple.com> | 2016-09-06 20:57:50 +0000 |
---|---|---|
committer | Kate Stone <katherine.stone@apple.com> | 2016-09-06 20:57:50 +0000 |
commit | b9c1b51e45b845debb76d8658edabca70ca56079 (patch) | |
tree | dfcb5a13ef2b014202340f47036da383eaee74aa /lldb/tools | |
parent | d5aa73376966339caad04013510626ec2e42c760 (diff) | |
download | bcm5719-llvm-b9c1b51e45b845debb76d8658edabca70ca56079.tar.gz bcm5719-llvm-b9c1b51e45b845debb76d8658edabca70ca56079.zip |
*** This commit represents a complete reformatting of the LLDB source code
*** to conform to clang-format’s LLVM style. This kind of mass change has
*** two obvious implications:
Firstly, merging this particular commit into a downstream fork may be a huge
effort. Alternatively, it may be worth merging all changes up to this commit,
performing the same reformatting operation locally, and then discarding the
merge for this particular commit. The commands used to accomplish this
reformatting were as follows (with current working directory as the root of
the repository):
find . \( -iname "*.c" -or -iname "*.cpp" -or -iname "*.h" -or -iname "*.mm" \) -exec clang-format -i {} +
find . -iname "*.py" -exec autopep8 --in-place --aggressive --aggressive {} + ;
The version of clang-format used was 3.9.0, and autopep8 was 1.2.4.
Secondly, “blame” style tools will generally point to this commit instead of
a meaningful prior commit. There are alternatives available that will attempt
to look through this change and find the appropriate prior commit. YMMV.
llvm-svn: 280751
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); + } } |