Index: vendor/lldb/dist/docs/lldb-gdb-remote.txt =================================================================== --- vendor/lldb/dist/docs/lldb-gdb-remote.txt (revision 320966) +++ vendor/lldb/dist/docs/lldb-gdb-remote.txt (revision 320967) @@ -1,1888 +1,1915 @@ LLDB has added new GDB server packets to better support multi-threaded and remote debugging. Why? Normally you need to start the correct GDB and the correct GDB server when debugging. If you have mismatch, then things go wrong very quickly. LLDB makes extensive use of the GDB remote protocol and we wanted to make sure that the experience was a bit more dynamic where we can discover information about a remote target with having to know anything up front. We also ran into performance issues with the existing GDB remote protocol that can be overcome when using a reliable communications layer. Some packets improve performance, others allow for remote process launching (if you have an OS), and others allow us to dynamically figure out what registers a thread might have. Again with GDB, both sides pre-agree on how the registers will look (how many, their register number,name and offsets). We prefer to be able to dynamically determine what kind of architecture, OS and vendor we are debugging, as well as how things are laid out when it comes to the thread register contexts. Below are the details on the new packets we have added above and beyond the standard GDB remote protocol packets. //---------------------------------------------------------------------- // "QStartNoAckMode" // // BRIEF // Try to enable no ACK mode to skip sending ACKs and NACKs. // // PRIORITY TO IMPLEMENT // High. Any GDB remote server that can implement this should if the // connection is reliable. This improves packet throughput and increases // the performance of the connection. //---------------------------------------------------------------------- Having to send an ACK/NACK after every packet slows things down a bit, so we have a way to disable ACK packets to minimize the traffic for reliable communication interfaces (like sockets). Below GDB or LLDB will send this packet to try and disable ACKs. All lines that start with "send packet: " are from GDB/LLDB, and all lines that start with "read packet: " are from the GDB remote server: send packet: $QStartNoAckMode#b0 read packet: + read packet: $OK#9a send packet: + //---------------------------------------------------------------------- // "A" - launch args packet // // BRIEF // Launch a program using the supplied arguments // // PRIORITY TO IMPLEMENT // Low. Only needed if the remote target wants to launch a target after // making a connection to a GDB server that isn't already connected to // an inferior process. //---------------------------------------------------------------------- We have added support for the "set program arguments" packet where we can start a connection to a remote server and then later supply the path to the executable and the arguments to use when executing: GDB remote docs for this: set program arguments(reserved) Aarglen,argnum,arg,... Where A is followed by the length in bytes of the hex encoded argument, followed by an argument integer, and followed by the ASCII characters converted into hex bytes foreach arg send packet: $A98,0,2f566f6c756d65732f776f726b2f67636c6179746f6e2f446f63756d656e74732f7372632f6174746163682f612e6f7574#00 read packet: $OK#00 The above packet helps when you have remote debugging abilities where you could launch a process on a remote host, this isn't needed for bare board debugging. //---------------------------------------------------------------------- // "QEnvironment:NAME=VALUE" // // BRIEF // Setup the environment up for a new child process that will soon be // launched using the "A" packet. // // NB: key/value pairs are sent as-is so gdb-remote protocol meta characters // (e.g. '#' or '$') are not acceptable. If any non-printable or // metacharacters are present in the strings, QEnvironmentHexEncoded // should be used instead if it is available. If you don't want to // scan the environment strings before sending, prefer // the QEnvironmentHexEncoded packet over QEnvironment, if it is // available. // // PRIORITY TO IMPLEMENT // Low. Only needed if the remote target wants to launch a target after // making a connection to a GDB server that isn't already connected to // an inferior process. //---------------------------------------------------------------------- Both GDB and LLDB support passing down environment variables. Is it ok to respond with a "$#00" (unimplemented): send packet: $QEnvironment:ACK_COLOR_FILENAME=bold yellow#00 read packet: $OK#00 This packet can be sent one or more times _prior_ to sending a "A" packet. //---------------------------------------------------------------------- // "QEnvironmentHexEncoded:HEX-ENCODING(NAME=VALUE)" // // BRIEF // Setup the environment up for a new child process that will soon be // launched using the "A" packet. // // The only difference between this packet and QEnvironment is that the // environment key-value pair is ascii hex encoded for transmission. // This allows values with gdb-remote metacharacters like '#' to be sent. // // PRIORITY TO IMPLEMENT // Low. Only needed if the remote target wants to launch a target after // making a connection to a GDB server that isn't already connected to // an inferior process. //---------------------------------------------------------------------- Both GDB and LLDB support passing down environment variables. Is it ok to respond with a "$#00" (unimplemented): send packet: $QEnvironment:41434b5f434f4c4f525f46494c454e414d453d626f6c642379656c6c6f77#00 read packet: $OK#00 This packet can be sent one or more times _prior_ to sending a "A" packet. //---------------------------------------------------------------------- +// "QEnableErrorStrings" +// +// BRIEF +// This packet enables reporting of Error strings in remote packet +// replies from the server to client. If the server supports this +// feature, it should send an OK response. The client can expect the +// following error replies if this feature is enabled in the server -> +// +// EXX;AAAAAAAAA +// +// where AAAAAAAAA will be a hex encoded ASCII string. +// XX is hex encoded byte number. +// +// It must be noted that even if the client has enabled reporting +// strings in error replies, it must not expect error strings to all +// error replies. +// +// PRIORITY TO IMPLEMENT +// Low. Only needed if the remote target wants to provide strings that +// are human readable along with an error code. +//---------------------------------------------------------------------- + +send packet: $QErrorStringInPacketSupported +read packet: $OK#00 + +//---------------------------------------------------------------------- // "QSetSTDIN:" // "QSetSTDOUT:" // "QSetSTDERR:" // // BRIEF // Setup where STDIN, STDOUT, and STDERR go prior to sending an "A" // packet. // // PRIORITY TO IMPLEMENT // Low. Only needed if the remote target wants to launch a target after // making a connection to a GDB server that isn't already connected to // an inferior process. //---------------------------------------------------------------------- When launching a program through the GDB remote protocol with the "A" packet, you might also want to specify where stdin/out/err go: QSetSTDIN: QSetSTDOUT: QSetSTDERR: These packets must be sent _prior_ to sending a "A" packet. //---------------------------------------------------------------------- // "QSetWorkingDir:" // // BRIEF // Set the working directory prior to sending an "A" packet. // // PRIORITY TO IMPLEMENT // Low. Only needed if the remote target wants to launch a target after // making a connection to a GDB server that isn't already connected to // an inferior process. //---------------------------------------------------------------------- Or specify the working directory: QSetWorkingDir: This packet must be sent _prior_ to sending a "A" packet. //---------------------------------------------------------------------- // "QSetDisableASLR:" // // BRIEF // Enable or disable ASLR on the next "A" packet. // // PRIORITY TO IMPLEMENT // Low. Only needed if the remote target wants to launch a target after // making a connection to a GDB server that isn't already connected to // an inferior process and if the target supports disabling ASLR // (Address space layout randomization). //---------------------------------------------------------------------- Or control if ASLR is enabled/disabled: send packet: QSetDisableASLR:1 read packet: OK send packet: QSetDisableASLR:0 read packet: OK This packet must be sent _prior_ to sending a "A" packet. //---------------------------------------------------------------------- // QListThreadsInStopReply // // BRIEF // Enable the threads: and thread-pcs: data in the question-mark packet // ("T packet") responses when the stub reports that a program has // stopped executing. // // PRIORITY TO IMPLEMENT // Performance. This is a performance benefit to lldb if the thread id's // and thread pc values are provided to lldb in the T stop packet -- if // they are not provided to lldb, lldb will likely need to send one to // two packets per thread to fetch the data at every private stop. //---------------------------------------------------------------------- send packet: QListThreadsInStopReply read packet: OK //---------------------------------------------------------------------- // jTraceStart: // // BRIEF // Packet for starting trace of type lldb::TraceType. The following // parameters should be appended to the packet formatted as a JSON // dictionary, where the schematic for the JSON dictionary in terms of // the recognized Keys is given below in the table. // Different tracing types could require different custom parameters. // Such custom tracing parameters if needed should be collectively // specified in a JSON dictionary and the dictionary can be appended // to this packet (as Value corresponding to "params"). Since sending // JSON data over gdb-remote protocol has certain limitations, binary // escaping convention should be used. // // Following is the list of parameters - // // Key Value (Integer) (O)Optional/ // (except params which should be a (M)Mandatory // JSON dictionary) // ========== ==================================================== // // type The type of trace to start (see M // lldb-enumerations for TraceType) // // buffersize The size of the buffer to allocate M // for trace gathering. // // threadid The id of the thread to start tracing O // on. // // metabuffersize The size of buffer to hold meta data O // used for decoding the trace data. // // params Any parameters that are specific to O // certain trace technologies should be // collectively specified as a JSON // dictionary // ========== ==================================================== // // Each tracing instance is identified by a trace id which is returned // as the reply to this packet. In case the tracing failed to begin an -// error code is returned instead. +// error code along with a hex encoded ASCII message is returned +// instead. //---------------------------------------------------------------------- send packet: jTraceStart:{"type":,"buffersize":}] -read packet: /E +read packet: /E;AAAAAAAAA //---------------------------------------------------------------------- // jTraceStop: // // BRIEF // Stop tracing instance with trace id , of course trace // needs to be started before. The following parameters should be // formatted as a JSON dictionary to the packet. Since sending // JSON data over gdb-remote protocol has certain limitations, binary // escaping convention should be used. // // Following is the list of parameters - // // Key Value (Integer) (O)Optional/ // (M)Mandatory // ========== ==================================================== // // traceid The trace id of the tracing instance M // // threadid The id of the thread to stop tracing O // on. Since could map to // multiple trace instances (in case it // maps to the complete process), the // threadid of a particular thread could // be appended as "threadid:;" // to stop tracing on that thread. // ========== ==================================================== // -// An OK response is sent in case of success else an error code is -// returned. +// An OK response is sent in case of success else an error code along +// with a hex encoded ASCII message is returned. //---------------------------------------------------------------------- send packet: jTraceStop:{"traceid":}] -read packet: /E +read packet: /E;AAAAAAAAA //---------------------------------------------------------------------- // jTraceBufferRead: // // BRIEF // Packet for reading the trace for tracing instance , i.e the // id obtained from StartTrace API. The following parameters should be // formatted as a JSON dictionary to the packet. Since sending // JSON data over gdb-remote protocol has certain limitations, binary // escaping convention should be used. // // Following is the list of parameters - // // Key Value (Integer) (O)Optional/ // (M)Mandatory // ========== ==================================================== // traceid The trace id of the tracing instance M // // offset The offset to start reading the data M // from. // // buffersize The size of the data intended to read. M // // threadid The id of the thread to retrieve data O // from. // ========== ==================================================== // // The trace data is sent as raw binary data if the read was successful -// else an error code is sent. +// else an error code along with a hex encoded ASCII message is sent. //---------------------------------------------------------------------- send packet: jTraceBufferRead:{"traceid":,"offset":,"buffersize":}] -read packet: /E +read packet: /E;AAAAAAAAA //---------------------------------------------------------------------- // jTraceMetaRead: // // BRIEF // Similar Packet as above except it reads meta data. //---------------------------------------------------------------------- /---------------------------------------------------------------------- // jTraceConfigRead: // // BRIEF // Request the trace configuration for the tracing instance with id // . // // Following is the list of parameters - // // Key Value (Integer) (O)Optional/ // (M)Mandatory // ========== ==================================================== // traceid The trace id of the tracing instance M // // threadid The id of the thread to obtain trace O // configuration from. Since // could map to multiple trace instances // (in case it maps to the complete // process), the threadid of a particular // thread could be appended as // "threadid:;" to obtain the // trace configuration of that thread. // ========== ==================================================== // // In the response packet the trace configuration is sent as text, // formatted as a JSON dictionary. Since sending JSON data over // gdb-remote protocol has certain limitations, binary escaping // convention is used. // In case the trace instance with the was not found, an -// error code is returned. +// error code along with a hex encoded ASCII message is returned. //---------------------------------------------------------------------- send packet: jTraceConfigRead:{"traceid":} -read packet: {"conf1":,"conf2":,"params":{"paramName":paramValue}]}];/E +read packet: {"conf1":,"conf2":,"params":{"paramName":paramValue}]}];/E;AAAAAAAAA //---------------------------------------------------------------------- // "qRegisterInfo" // // BRIEF // Discover register information from the remote GDB server. // // PRIORITY TO IMPLEMENT // High. Any target that can self describe its registers, should do so. // This means if new registers are ever added to a remote target, they // will get picked up automatically, and allows registers to change // depending on the actual CPU type that is used. // // NB: As of summer 2015, lldb can get register information from the // "qXfer:features:read:target.xml" FSF gdb standard register packet // where the stub provides register definitions in an XML file. // If qXfer:features:read:target.xml is supported, qRegisterInfo does // not need to be implemented. //---------------------------------------------------------------------- With LLDB, for register information, remote GDB servers can add support for the "qRegisterInfoN" packet where "N" is a zero based base16 register number that must start at zero and increase by one for each register that is supported. The response is done in typical GDB remote fashion where a series of "KEY:VALUE;" pairs are returned. An example for the x86_64 registers is included below: send packet: $qRegisterInfo0#00 read packet: $name:rax;bitsize:64;offset:0;encoding:uint;format:hex;set:General Purpose Registers;gcc:0;dwarf:0;#00 send packet: $qRegisterInfo1#00 read packet: $name:rbx;bitsize:64;offset:8;encoding:uint;format:hex;set:General Purpose Registers;gcc:3;dwarf:3;#00 send packet: $qRegisterInfo2#00 read packet: $name:rcx;bitsize:64;offset:16;encoding:uint;format:hex;set:General Purpose Registers;gcc:2;dwarf:2;#00 send packet: $qRegisterInfo3#00 read packet: $name:rdx;bitsize:64;offset:24;encoding:uint;format:hex;set:General Purpose Registers;gcc:1;dwarf:1;#00 send packet: $qRegisterInfo4#00 read packet: $name:rdi;bitsize:64;offset:32;encoding:uint;format:hex;set:General Purpose Registers;gcc:5;dwarf:5;#00 send packet: $qRegisterInfo5#00 read packet: $name:rsi;bitsize:64;offset:40;encoding:uint;format:hex;set:General Purpose Registers;gcc:4;dwarf:4;#00 send packet: $qRegisterInfo6#00 read packet: $name:rbp;alt-name:fp;bitsize:64;offset:48;encoding:uint;format:hex;set:General Purpose Registers;gcc:6;dwarf:6;generic:fp;#00 send packet: $qRegisterInfo7#00 read packet: $name:rsp;alt-name:sp;bitsize:64;offset:56;encoding:uint;format:hex;set:General Purpose Registers;gcc:7;dwarf:7;generic:sp;#00 send packet: $qRegisterInfo8#00 read packet: $name:r8;bitsize:64;offset:64;encoding:uint;format:hex;set:General Purpose Registers;gcc:8;dwarf:8;#00 send packet: $qRegisterInfo9#00 read packet: $name:r9;bitsize:64;offset:72;encoding:uint;format:hex;set:General Purpose Registers;gcc:9;dwarf:9;#00 send packet: $qRegisterInfoa#00 read packet: $name:r10;bitsize:64;offset:80;encoding:uint;format:hex;set:General Purpose Registers;gcc:10;dwarf:10;#00 send packet: $qRegisterInfob#00 read packet: $name:r11;bitsize:64;offset:88;encoding:uint;format:hex;set:General Purpose Registers;gcc:11;dwarf:11;#00 send packet: $qRegisterInfoc#00 read packet: $name:r12;bitsize:64;offset:96;encoding:uint;format:hex;set:General Purpose Registers;gcc:12;dwarf:12;#00 send packet: $qRegisterInfod#00 read packet: $name:r13;bitsize:64;offset:104;encoding:uint;format:hex;set:General Purpose Registers;gcc:13;dwarf:13;#00 send packet: $qRegisterInfoe#00 read packet: $name:r14;bitsize:64;offset:112;encoding:uint;format:hex;set:General Purpose Registers;gcc:14;dwarf:14;#00 send packet: $qRegisterInfof#00 read packet: $name:r15;bitsize:64;offset:120;encoding:uint;format:hex;set:General Purpose Registers;gcc:15;dwarf:15;#00 send packet: $qRegisterInfo10#00 read packet: $name:rip;alt-name:pc;bitsize:64;offset:128;encoding:uint;format:hex;set:General Purpose Registers;gcc:16;dwarf:16;generic:pc;#00 send packet: $qRegisterInfo11#00 read packet: $name:rflags;alt-name:flags;bitsize:64;offset:136;encoding:uint;format:hex;set:General Purpose Registers;#00 send packet: $qRegisterInfo12#00 read packet: $name:cs;bitsize:64;offset:144;encoding:uint;format:hex;set:General Purpose Registers;#00 send packet: $qRegisterInfo13#00 read packet: $name:fs;bitsize:64;offset:152;encoding:uint;format:hex;set:General Purpose Registers;#00 send packet: $qRegisterInfo14#00 read packet: $name:gs;bitsize:64;offset:160;encoding:uint;format:hex;set:General Purpose Registers;#00 send packet: $qRegisterInfo15#00 read packet: $name:fctrl;bitsize:16;offset:176;encoding:uint;format:hex;set:Floating Point Registers;#00 send packet: $qRegisterInfo16#00 read packet: $name:fstat;bitsize:16;offset:178;encoding:uint;format:hex;set:Floating Point Registers;#00 send packet: $qRegisterInfo17#00 read packet: $name:ftag;bitsize:8;offset:180;encoding:uint;format:hex;set:Floating Point Registers;#00 send packet: $qRegisterInfo18#00 read packet: $name:fop;bitsize:16;offset:182;encoding:uint;format:hex;set:Floating Point Registers;#00 send packet: $qRegisterInfo19#00 read packet: $name:fioff;bitsize:32;offset:184;encoding:uint;format:hex;set:Floating Point Registers;#00 send packet: $qRegisterInfo1a#00 read packet: $name:fiseg;bitsize:16;offset:188;encoding:uint;format:hex;set:Floating Point Registers;#00 send packet: $qRegisterInfo1b#00 read packet: $name:fooff;bitsize:32;offset:192;encoding:uint;format:hex;set:Floating Point Registers;#00 send packet: $qRegisterInfo1c#00 read packet: $name:foseg;bitsize:16;offset:196;encoding:uint;format:hex;set:Floating Point Registers;#00 send packet: $qRegisterInfo1d#00 read packet: $name:mxcsr;bitsize:32;offset:200;encoding:uint;format:hex;set:Floating Point Registers;#00 send packet: $qRegisterInfo1e#00 read packet: $name:mxcsrmask;bitsize:32;offset:204;encoding:uint;format:hex;set:Floating Point Registers;#00 send packet: $qRegisterInfo1f#00 read packet: $name:stmm0;bitsize:80;offset:208;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:33;dwarf:33;#00 send packet: $qRegisterInfo20#00 read packet: $name:stmm1;bitsize:80;offset:224;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:34;dwarf:34;#00 send packet: $qRegisterInfo21#00 read packet: $name:stmm2;bitsize:80;offset:240;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:35;dwarf:35;#00 send packet: $qRegisterInfo22#00 read packet: $name:stmm3;bitsize:80;offset:256;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:36;dwarf:36;#00 send packet: $qRegisterInfo23#00 read packet: $name:stmm4;bitsize:80;offset:272;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:37;dwarf:37;#00 send packet: $qRegisterInfo24#00 read packet: $name:stmm5;bitsize:80;offset:288;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:38;dwarf:38;#00 send packet: $qRegisterInfo25#00 read packet: $name:stmm6;bitsize:80;offset:304;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:39;dwarf:39;#00 send packet: $qRegisterInfo26#00 read packet: $name:stmm7;bitsize:80;offset:320;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:40;dwarf:40;#00 send packet: $qRegisterInfo27#00 read packet: $name:xmm0;bitsize:128;offset:336;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:17;dwarf:17;#00 send packet: $qRegisterInfo28#00 read packet: $name:xmm1;bitsize:128;offset:352;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:18;dwarf:18;#00 send packet: $qRegisterInfo29#00 read packet: $name:xmm2;bitsize:128;offset:368;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:19;dwarf:19;#00 send packet: $qRegisterInfo2a#00 read packet: $name:xmm3;bitsize:128;offset:384;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:20;dwarf:20;#00 send packet: $qRegisterInfo2b#00 read packet: $name:xmm4;bitsize:128;offset:400;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:21;dwarf:21;#00 send packet: $qRegisterInfo2c#00 read packet: $name:xmm5;bitsize:128;offset:416;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:22;dwarf:22;#00 send packet: $qRegisterInfo2d#00 read packet: $name:xmm6;bitsize:128;offset:432;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:23;dwarf:23;#00 send packet: $qRegisterInfo2e#00 read packet: $name:xmm7;bitsize:128;offset:448;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:24;dwarf:24;#00 send packet: $qRegisterInfo2f#00 read packet: $name:xmm8;bitsize:128;offset:464;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:25;dwarf:25;#00 send packet: $qRegisterInfo30#00 read packet: $name:xmm9;bitsize:128;offset:480;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:26;dwarf:26;#00 send packet: $qRegisterInfo31#00 read packet: $name:xmm10;bitsize:128;offset:496;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:27;dwarf:27;#00 send packet: $qRegisterInfo32#00 read packet: $name:xmm11;bitsize:128;offset:512;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:28;dwarf:28;#00 send packet: $qRegisterInfo33#00 read packet: $name:xmm12;bitsize:128;offset:528;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:29;dwarf:29;#00 send packet: $qRegisterInfo34#00 read packet: $name:xmm13;bitsize:128;offset:544;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:30;dwarf:30;#00 send packet: $qRegisterInfo35#00 read packet: $name:xmm14;bitsize:128;offset:560;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:31;dwarf:31;#00 send packet: $qRegisterInfo36#00 read packet: $name:xmm15;bitsize:128;offset:576;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:32;dwarf:32;#00 send packet: $qRegisterInfo37#00 read packet: $name:trapno;bitsize:32;offset:696;encoding:uint;format:hex;set:Exception State Registers;#00 send packet: $qRegisterInfo38#00 read packet: $name:err;bitsize:32;offset:700;encoding:uint;format:hex;set:Exception State Registers;#00 send packet: $qRegisterInfo39#00 read packet: $name:faultvaddr;bitsize:64;offset:704;encoding:uint;format:hex;set:Exception State Registers;#00 send packet: $qRegisterInfo3a#00 read packet: $E45#00 As we see above we keep making subsequent calls to the remote server to discover all registers by increasing the number appended to qRegisterInfo and we get a response back that is a series of "key=value;" strings. The offset: fields should not leave a gap anywhere in the g/G packet -- the register values should be appended one after another. For instance, if the register context for a thread looks like struct rctx { uint32_t gpr1; // offset 0 uint32_t gpr2; // offset 4 uint32_t gpr3; // offset 8 uint64_t fp1; // offset 16 }; You may end up with a 4-byte gap between gpr3 and fp1 on architectures that align values like this. The correct offset: value for fp1 is 12 - in the g/G packet fp1 will immediately follow gpr3, even though the in-memory thread structure has an empty 4 bytes for alignment between these two registers. The keys and values are detailed below: Key Value ========== ================================================================ name The primary register name as a string ("rbp" for example) alt-name An alternate name for a register as a string ("fp" for example for the above "rbp") bitsize Size in bits of a register (32, 64, etc). Base 10. offset The offset within the "g" and "G" packet of the register data for this register. This is the byte offset once the data has been transformed into binary, not the character offset into the g/G packet. Base 10. encoding The encoding type of the register which must be one of: uint (unsigned integer) sint (signed integer) ieee754 (IEEE 754 float) vector (vector register) format The preferred format for display of this register. The value must be one of: binary decimal hex float vector-sint8 vector-uint8 vector-sint16 vector-uint16 vector-sint32 vector-uint32 vector-float32 vector-uint128 set The register set name as a string that this register belongs to. gcc The GCC compiler registers number for this register (used for EH frame and other compiler information that is encoded in the executable files). The supplied number will be decoded like a string passed to strtoul() with a base of zero, so the number can be decimal, or hex if it is prefixed with "0x". NOTE: If the compiler doesn't have a register number for this register, this key/value pair should be omitted. dwarf The DWARF register number for this register that is used for this register in the debug information. The supplied number will be decoded like a string passed to strtoul() with a base of zero, so the number can be decimal, or hex if it is prefixed with "0x". NOTE: If the compiler doesn't have a register number for this register, this key/value pair should be omitted. generic If the register is a generic register that most CPUs have, classify it correctly so the debugger knows. Valid values are one of: pc (a program counter register. for example "name=eip;" (i386), "name=rip;" (x86_64), "name=r15;" (32 bit arm) would include a "generic=pc;" key value pair) sp (a stack pointer register. for example "name=esp;" (i386), "name=rsp;" (x86_64), "name=r13;" (32 bit arm) would include a "generic=sp;" key value pair) fp (a frame pointer register. for example "name=ebp;" (i386), "name=rbp;" (x86_64), "name=r7;" (32 bit arm with macosx ABI) would include a "generic=fp;" key value pair) ra (a return address register. for example "name=lr;" (32 bit ARM) would include a "generic=ra;" key value pair) fp (a CPU flags register. for example "name=eflags;" (i386), "name=rflags;" (x86_64), "name=cpsr;" (32 bit ARM) would include a "generic=flags;" key value pair) arg1 - arg8 (specified for registers that contain function arguments when the argument fits into a register) container-regs The value for this key is a comma separated list of raw hex (optional leading "0x") register numbers. This specifies that this register is contained in other concrete register values. For example "eax" is in the lower 32 bits of the "rax" register value for x86_64, so "eax" could specify that it is contained in "rax" by specifying the register number for "rax" (whose register number is 0x00) "container-regs:00;" If a register is comprised of one or more registers, like "d0" is ARM which is a 64 bit register, it might be made up of "s0" and "s1". If the register number for "s0" is 0x20, and the register number of "s1" is "0x21", the "container-regs" key/value pair would be: "container-regs:20,21;" This is handy for defining what GDB used to call "pseudo" registers. These registers are never requested by LLDB via the register read or write packets, the container registers will be requested on behalf of this register. invalidate-regs The value for this key is a comma separated list of raw hex (optional leading "0x") register numbers. This specifies which register values should be invalidated when this register is modified. For example if modifying "eax" would cause "rax", "eax", "ax", "ah", and "al" to be modified where rax is 0x0, eax is 0x15, ax is 0x25, ah is 0x35, and al is 0x39, the "invalidate-regs" key/value pair would be: "invalidate-regs:0,15,25,35,39;" If there is a single register that gets invalidated, then omit the comma and just list a single register: "invalidate-regs:0;" This is handy when modifying a specific register can cause other register values to change. For example, when debugging an ARM target, modifying the CPSR register can cause the r8 - r14 and cpsr value to change depending on if the mode has changed. //---------------------------------------------------------------------- // "qPlatform_shell" // // BRIEF // Run a command in a shell on the connected remote machine. // // PRIORITY TO IMPLEMENT // High. This command allows LLDB clients to run arbitrary shell // commands on a remote host. // /---------------------------------------------------------------------- The request consists of the command to be executed encoded in ASCII characters converted into hex bytes. The response to this packet consists of the letter F followed by the return code, followed by the signal number (or 0 if no signal was delivered), and escaped bytes of captured program output. Below is an example communication from a client sending an "ls -la" command: send packet: $qPlatform_shell:6c73202d6c61,00000002#ec read packet: $F,00000000,00000000,total 4736 drwxrwxr-x 16 username groupname 4096 Aug 15 21:36 . drwxr-xr-x 17 username groupname 4096 Aug 10 16:39 .. -rw-rw-r-- 1 username groupname 73875 Aug 12 16:46 notes.txt drwxrwxr-x 5 username groupname 4096 Aug 15 21:36 source.cpp -rw-r--r-- 1 username groupname 2792 Aug 12 16:46 a.out -rw-r--r-- 1 username groupname 3190 Aug 12 16:46 Makefile //---------------------------------------------------------------------- // "qPlatform_mkdir" // // BRIEF // Creates a new directory on the connected remote machine. // // PRIORITY TO IMPLEMENT // Low. This command allows LLDB clients to create new directories on // a remote host. // /---------------------------------------------------------------------- Request: qPlatform_mkdir:, Reply: F mkdir called successfully and returned with the given return code Exx An error occurred //---------------------------------------------------------------------- // "qPlatform_chmod" // // BRIEF // Change the permissions of a file on the connected remote machine. // // PRIORITY TO IMPLEMENT // Low. This command allows LLDB clients to change the permissions of // a file on the remote host. // /---------------------------------------------------------------------- Request: qPlatform_chmod:, Reply: F chmod called successfully and returned with the given return code Exx An error occurred //---------------------------------------------------------------------- // "qHostInfo" // // BRIEF // Get information about the host we are remotely connected to. // // PRIORITY TO IMPLEMENT // High. This packet is usually very easy to implement and can help // LLDB select the correct plug-ins for the job based on the target // triple information that is supplied. //---------------------------------------------------------------------- LLDB supports a host info call that gets all sorts of details of the system that is being debugged: send packet: $qHostInfo#00 read packet: $cputype:16777223;cpusubtype:3;ostype:darwin;vendor:apple;endian:little;ptrsize:8;#00 Key value pairs are one of: cputype: is a number that is the mach-o CPU type that is being debugged (base 10) cpusubtype: is a number that is the mach-o CPU subtype type that is being debugged (base 10) triple: a string for the target triple (x86_64-apple-macosx) that can be used to specify arch + vendor + os in one entry vendor: a string for the vendor (apple), not needed if "triple" is specified ostype: a string for the OS being debugged (macosx, linux, freebsd, ios, watchos), not needed if "triple" is specified endian: is one of "little", "big", or "pdp" ptrsize: an unsigned number that represents how big pointers are in bytes on the debug target hostname: the hostname of the host that is running the GDB server if available os_build: a string for the OS build for the remote host as a string value os_kernel: a string describing the kernel version os_version: a version string that represents the current OS version (10.8.2) watchpoint_exceptions_received: one of "before" or "after" to specify if a watchpoint is triggered before or after the pc when it stops default_packet_timeout: an unsigned number that specifies the default timeout in seconds distribution_id: optional. For linux, specifies distribution id (e.g. ubuntu, fedora, etc.) osmajor: optional, specifies the major version number of the OS (e.g. for Mac OS X 10.11.2, it would be 10) osminor: optional, specifies the minor version number of the OS (e.g. for Mac OS X 10.11.2, it would be 11) ospatch: optional, specifies the patch level number of the OS (e.g. for Mac OS X 10.11.2, it would be 2) //---------------------------------------------------------------------- // "qGDBServerVersion" // // BRIEF // Get version information about this implementation of the gdb-remote // protocol. // // PRIORITY TO IMPLEMENT // High. This packet is usually very easy to implement and can help // LLDB to work around bugs in a server's implementation when they // are found. //---------------------------------------------------------------------- The goal of this packet is to provide enough information about an implementation of the gdb-remote-protocol server that lldb can work around implementation problems that are discovered after the version has been released/deployed. The name and version number should be sufficiently unique that lldb can unambiguously identify the origin of the program (for instance, debugserver from lldb) and the version/submission number/patch level of the program - whatever is appropriate for your server implementation. The packet follows the key-value pair model, semicolon separated. send packet: $qGDBServerVersion#00 read packet: $name:debugserver;version:310.2;#00 Other clients may find other key-value pairs to be useful for identifying a gdb stub. Patch level, release name, build number may all be keys that better describe your implementation's version. Suggested key names: name : the name of your remote server - "debugserver" is the lldb standard implementation version : identifies the version number of this server patch_level : the patch level of this server release_name : the name of this release, if your project uses names build_number : if you use a build system with increasing build numbers, this may be the right key name for your server major_version : major version number minor_version : minor version number //---------------------------------------------------------------------- // "qProcessInfo" // // BRIEF // Get information about the process we are currently debugging. // // PRIORITY TO IMPLEMENT // Medium. On systems which can launch multiple different architecture processes, // the qHostInfo may not disambiguate sufficiently to know what kind of // process is being debugged. // e.g. on a 64-bit x86 Mac system both 32-bit and 64-bit user processes are possible, // and with Mach-O universal files, the executable file may contain both 32- and // 64-bit slices so it may be impossible to know until you're attached to a real // process to know what you're working with. // // All numeric fields return base-16 numbers without any "0x" prefix. //---------------------------------------------------------------------- An i386 process: send packet: $qProcessInfo#00 read packet: $pid:42a8;parent-pid:42bf;real-uid:ecf;real-gid:b;effective-uid:ecf;effective-gid:b;cputype:7;cpusubtype:3;ostype:macosx;vendor:apple;endian:little;ptrsize:4;#00 An x86_64 process: send packet: $qProcessInfo#00 read packet: $pid:d22c;parent-pid:d34d;real-uid:ecf;real-gid:b;effective-uid:ecf;effective-gid:b;cputype:1000007;cpusubtype:3;ostype:macosx;vendor:apple;endian:little;ptrsize:8;#00 Key value pairs include: pid: the process id parent-pid: the process of the parent process (often debugserver will become the parent when attaching) real-uid: the real user id of the process real-gid: the real group id of the process effective-uid: the effective user id of the process effective-gid: the effective group id of the process cputype: the Mach-O CPU type of the process (base 16) cpusubtype: the Mach-O CPU subtype of the process (base 16) ostype: is a string the represents the OS being debugged (darwin, linux, freebsd) vendor: is a string that represents the vendor (apple) endian: is one of "little", "big", or "pdp" ptrsize: is a number that represents how big pointers are in bytes //---------------------------------------------------------------------- // "qShlibInfoAddr" // // BRIEF // Get an address where the dynamic linker stores information about // where shared libraries are loaded. // // PRIORITY TO IMPLEMENT // High if you have a dynamic loader plug-in in LLDB for your target // triple (see the "qHostInfo" packet) that can use this information. // Many times address load randomization can make it hard to detect // where the dynamic loader binary and data structures are located and // some platforms know, or can find out where this information is. // // Low if you have a debug target where all object and symbol files // contain static load addresses. //---------------------------------------------------------------------- LLDB and GDB both support the "qShlibInfoAddr" packet which is a hint to each debugger as to where to find the dynamic loader information. For darwin binaries that run in user land this is the address of the "all_image_infos" structure in the "/usr/lib/dyld" executable, or the result of a TASK_DYLD_INFO call. The result is returned as big endian hex bytes that are the address value: send packet: $qShlibInfoAddr#00 read packet: $7fff5fc40040#00 //---------------------------------------------------------------------- // "qThreadStopInfo" // // BRIEF // Get information about why a thread, whose ID is "", is stopped. // // PRIORITY TO IMPLEMENT // High if you need to support multi-threaded or multi-core debugging. // Many times one thread will hit a breakpoint and while the debugger // is in the process of suspending the other threads, other threads // will also hit a breakpoint. This packet allows LLDB to know why all // threads (live system debug) / cores (JTAG) in your program have // stopped and allows LLDB to display and control your program // correctly. //---------------------------------------------------------------------- LLDB tries to use the "qThreadStopInfo" packet which is formatted as "qThreadStopInfo%x" where %x is the hex thread ID. This requests information about why a thread is stopped. The response is the same as the stop reply packets and tells us what happened to the other threads. The standard GDB remote packets love to think that there is only _one_ reason that _one_ thread stops at a time. This allows us to see why all threads stopped and allows us to implement better multi-threaded debugging support. //---------------------------------------------------------------------- // "QThreadSuffixSupported" // // BRIEF // Try to enable thread suffix support for the 'g', 'G', 'p', and 'P' // packets. // // PRIORITY TO IMPLEMENT // High. Adding a thread suffix allows us to read and write registers // more efficiently and stops us from having to select a thread with // one packet and then read registers with a second packet. It also // makes sure that no errors can occur where the debugger thinks it // already has a thread selected (see the "Hg" packet from the standard // GDB remote protocol documentation) yet the remote GDB server actually // has another thread selected. //---------------------------------------------------------------------- When reading thread registers, you currently need to set the current thread, then read the registers. This is kind of cumbersome, so we added the ability to query if the remote GDB server supports adding a "thread:;" suffix to all packets that request information for a thread. To test if the remote GDB server supports this feature: send packet: $QThreadSuffixSupported#00 read packet: OK If "OK" is returned, then the 'g', 'G', 'p' and 'P' packets can accept a thread suffix. So to send a 'g' packet (read all register values): send packet: $g;thread:;#00 read packet: .... send packet: $G;thread:;#00 read packet: .... send packet: $p1a;thread:;#00 read packet: .... send packet: $P1a=1234abcd;thread:;#00 read packet: .... otherwise, without this you would need to always send two packets: send packet: $Hg#00 read packet: .... send packet: $g#00 read packet: .... We also added support for allocating and deallocating memory. We use this to allocate memory so we can run JITed code. //---------------------------------------------------------------------- // "_M," // // BRIEF // Allocate memory on the remote target with the specified size and // permissions. // // PRIORITY TO IMPLEMENT // High if you want LLDB to be able to JIT code and run that code. JIT // code also needs data which is also allocated and tracked. // // Low if you don't support running JIT'ed code. //---------------------------------------------------------------------- The allocate memory packet starts with "_M,". It returns a raw big endian address value, or "" for unimplemented, or "EXX" for an error code. The packet is formatted as: char packet[256]; int packet_len; packet_len = ::snprintf ( packet, sizeof(packet), "_M%zx,%s%s%s", (size_t)size, permissions & lldb::ePermissionsReadable ? "r" : "", permissions & lldb::ePermissionsWritable ? "w" : "", permissions & lldb::ePermissionsExecutable ? "x" : ""); You request a size and give the permissions. This packet does NOT need to be implemented if you don't want to support running JITed code. The return value is just the address of the newly allocated memory as raw big endian hex bytes. //---------------------------------------------------------------------- // "_m" // // BRIEF // Deallocate memory that was previously allocated using an allocate // memory pack. // // PRIORITY TO IMPLEMENT // High if you want LLDB to be able to JIT code and run that code. JIT // code also needs data which is also allocated and tracked. // // Low if you don't support running JIT'ed code. //---------------------------------------------------------------------- The deallocate memory packet is "_m" where you pass in the address you got back from a previous call to the allocate memory packet. It returns "OK" if the memory was successfully deallocated, or "EXX" for an error, or "" if not supported. //---------------------------------------------------------------------- // "qMemoryRegionInfo:" // // BRIEF // Get information about the address range that contains "" // // PRIORITY TO IMPLEMENT // Medium. This is nice to have, but it isn't necessary. It helps LLDB // do stack unwinding when we branch into memory that isn't executable. // If we can detect that the code we are stopped in isn't executable, // then we can recover registers for stack frames above the current // frame. Otherwise we must assume we are in some JIT'ed code (not JIT // code that LLDB has made) and assume that no registers are available // in higher stack frames. //---------------------------------------------------------------------- We added a way to get information for a memory region. The packet is: qMemoryRegionInfo: Where is a big endian hex address. The response is returned in a series of tuples like the data returned in a stop reply packet. The currently valid tuples to return are: start:; // is a big endian hex address that is // the start address of the range that contains size:; // is a big endian hex byte size of the address // of the range that contains permissions:; // is a string that contains one // or more of the characters from "rwx" name:; // is a hex encoded string that contains the name of // the memory region mapped at the given address. In case of // regions backed by a file it have to be the absolute path of // the file while for anonymous regions it have to be the name // associated to the region if that is available. error:; // where is // a hex encoded string value that // contains an error string If the address requested is not in a mapped region (e.g. we've jumped through a NULL pointer and are at 0x0) currently lldb expects to get back the size of the unmapped region -- that is, the distance to the next valid region. For instance, with a Mac OS X process which has nothing mapped in the first 4GB of its address space, if we're asking about address 0x2, qMemoryRegionInfo:2 start:2;size:fffffffe; The lack of 'permissions:' indicates that none of read/write/execute are valid for this region. //---------------------------------------------------------------------- // "x" - Binary memory read // // Like the 'm' (read) and 'M' (write) packets, this is a partner to the // 'X' (write binary data) packet, 'x'. // // It is called like // // xADDRESS,LENGTH // // where both ADDRESS and LENGTH are big-endian base 16 values. // // To test if this packet is available, send a addr/len of 0: // // x0,0 // // and you will get an "OK" response. // // The reply will be the data requested in 8-bit binary data format. // The standard quoting is applied to the payload -- characters // } # $ * // will all be escaped with '}' (0x7d) character and then XOR'ed with 0x20. // // A typical use to read 512 bytes at 0x1000 would look like // // x0x1000,0x200 // // The "0x" prefixes are optional - like most of the gdb-remote packets, // omitting them will work fine; these numbers are always base 16. // // The length of the payload is not provided. A reliable, 8-bit clean, // transport layer is assumed. //---------------------------------------------------------------------- //---------------------------------------------------------------------- // Detach and stay stopped: // // We extended the "D" packet to specify that the monitor should keep the // target suspended on detach. The normal behavior is to resume execution // on detach. We will send: // // qSupportsDetachAndStayStopped: // // to query whether the monitor supports the extended detach, and if it does, // when we want the monitor to detach but not resume the target, we will // send: // // D1 // // In any case, if we want the normal detach behavior we will just send: // // D //---------------------------------------------------------------------- //---------------------------------------------------------------------- // QSaveRegisterState // QSaveRegisterState;thread:XXXX; // // BRIEF // The QSaveRegisterState packet tells the remote debugserver to save // all registers and return a non-zero unique integer ID that // represents these save registers. If thread suffixes are enabled the // second form of this packet is used, otherwise the first form is // used. This packet is called prior to executing an expression, so // the remote GDB server should do anything it needs to in order to // ensure the registers that are saved are correct. On MacOSX this // involves calling "thread_abort_safely(mach_port_t thread)" to // ensure we get the correct registers for a thread in case it is // currently having code run on its behalf in the kernel. // // RESPONSE // unsigned - The save_id result is a non-zero unsigned integer value // that can be passed back to the GDB server using a // QRestoreRegisterState packet to restore the registers // one time. // "EXX" - or an error code in the form of EXX where XX is a // hex error code. // // PRIORITY TO IMPLEMENT // Low, this is mostly a convenience packet to avoid having to send all // registers via a g packet. It should only be implemented if support // for the QRestoreRegisterState is added. //---------------------------------------------------------------------- //---------------------------------------------------------------------- // QRestoreRegisterState: // QRestoreRegisterState:;thread:XXXX; // // BRIEF // The QRestoreRegisterState packet tells the remote debugserver to // restore all registers using the "save_id" which is an unsigned // integer that was returned from a previous call to // QSaveRegisterState. The restoration process can only be done once // as the data backing the register state will be freed upon the // completion of the QRestoreRegisterState command. // // If thread suffixes are enabled the second form of this packet is // used, otherwise the first form is used. // // RESPONSE // "OK" - if all registers were successfully restored // "EXX" - for any errors // // PRIORITY TO IMPLEMENT // Low, this is mostly a convenience packet to avoid having to send all // registers via a g packet. It should only be implemented if support // for the QSaveRegisterState is added. //---------------------------------------------------------------------- //---------------------------------------------------------------------- // qFileLoadAddress: // // BRIEF // Get the load address of a memory mapped file. // The load address is defined as the address of the first memory // region what contains data mapped from the specified file. // // RESPONSE // - Load address of the file in big endian encoding // "E01" - the requested file isn't loaded // "EXX" - for any other errors // // PRIORITY TO IMPLEMENT // Low, required if dynamic linker don't fill in the load address of // some object file in the rendezvous data structure. //---------------------------------------------------------------------- //---------------------------------------------------------------------- // qModuleInfo:; // // BRIEF // Get information for a module by given module path and architecture. // // RESPONSE // "(uuid|md5):...;triple:...;file_offset:...;file_size...;" // "EXX" - for any errors // // PRIORITY TO IMPLEMENT // Optional, required if dynamic loader cannot fetch module's information like // UUID directly from inferior's memory. //---------------------------------------------------------------------- //---------------------------------------------------------------------- // jModulesInfo:[{"file":"...",triple:"..."}, ...] // // BRIEF // Get information for a list of modules by given module path and // architecture. // // RESPONSE // A JSON array of dictionaries containing the following keys: uuid, // triple, file_path, file_offset, file_size. The meaning of the fields // is the same as in the qModuleInfo packet. The server signals the // failure to retrieve the module info for a file by ommiting the // corresponding array entry from the response. The server may also // include entries the client did not ask for, if it has reason to // the modules will be interesting to the client. // // PRIORITY TO IMPLEMENT // Optional. If not implemented, qModuleInfo packet will be used, which // may be slower if the target contains a large number of modules and // the communication link has a non-negligible latency. //---------------------------------------------------------------------- //---------------------------------------------------------------------- // Stop reply packet extensions // // BRIEF // This section describes some of the additional information you can // specify in stop reply packets that help LLDB to know more detailed // information about your threads. // // DESCRIPTION // Standard GDB remote stop reply packets are reply packets sent in // response to a packet that made the program run. They come in the // following forms: // // "SAA" // "S" means signal and "AA" is a hex signal number that describes why // the thread or stopped. It doesn't specify which thread, so the "T" // packet is recommended to use instead of the "S" packet. // // "TAAkey1:value1;key2:value2;..." // "T" means a thread stopped due to a unix signal where "AA" is a hex // signal number that describes why the program stopped. This is // followed by a series of key/value pairs: // - If key is a hex number, it is a register number and value is // the hex value of the register in debuggee endian byte order. // - If key == "thread", then the value is the big endian hex // thread-id of the stopped thread. // - If key == "core", then value is a hex number of the core on // which the stop was detected. // - If key == "watch" or key == "rwatch" or key == "awatch", then // value is the data address in big endian hex // - If key == "library", then value is ignore and "qXfer:libraries:read" // packets should be used to detect any newly loaded shared libraries // // "WAA" // "W" means the process exited and "AA" is the exit status. // // "XAA" // "X" means the process exited and "AA" is signal that caused the program // to exit. // // "O" // "O" means STDOUT has data that was written to its console and is // being delivered to the debugger. This packet happens asynchronously // and the debugger is expected to continue to wait for another stop reply // packet. // // LLDB EXTENSIONS // // We have extended the "T" packet to be able to also understand the // following keys and values: // // KEY VALUE DESCRIPTION // =========== ======== ================================================ // "metype" unsigned mach exception type (the value of the EXC_XXX enumerations) // as an unsigned integer. For targets with mach // kernels only. // // "mecount" unsigned mach exception data count as an unsigned integer // For targets with mach kernels only. // // "medata" unsigned There should be "mecount" of these and it is the data // that goes along with a mach exception (as an unsigned // integer). For targets with mach kernels only. // // "name" string The name of the thread as a plain string. The string // must not contain an special packet characters or // contain a ':' or a ';'. Use "hexname" if the thread // name has special characters. // // "hexname" ascii-hex An ASCII hex string that contains the name of the thread // // "qaddr" hex Big endian hex value that contains the libdispatch // queue address for the queue of the thread. // // "reason" enum The enumeration must be one of: // "trace" the program stopped after a single instruction // was executed on a core. Usually done when single // stepping past a breakpoint // "breakpoint" a breakpoint set using a 'z' packet was hit. // "trap" stopped due to user interruption // "signal" stopped due to an actual unix signal, not // just the debugger using a unix signal to keep // the GDB remote client happy. // "watchpoint". Should be used in conjunction with // the "watch"/"rwatch"/"awatch" key value pairs. // "exception" an exception stop reason. Use with // the "description" key/value pair to describe the // exceptional event the user should see as the stop // reason. // "description" ascii-hex An ASCII hex string that contains a more descriptive // reason that the thread stopped. This is only needed // if none of the key/value pairs are enough to // describe why something stopped. // // "threads" comma-sep-base16 A list of thread ids for all threads (including // the thread that we're reporting as stopped) that // are live in the process right now. lldb may // request that this be included in the T packet via // the QListThreadsInStopReply packet earlier in // the debug session. // // Example: // threads:63387,633b2,63424,63462,63486; // // "thread-pcs" comma-sep-base16 A list of pc values for all threads that currently // exist in the process, including the thread that // this T packet is reporting as stopped. // This key-value pair will only be emitted when the // "threads" key is already included in the T packet. // The pc values correspond to the threads reported // in the "threads" list. The number of pcs in the // "thread-pcs" list will be the same as the number of // threads in the "threads" list. // lldb may request that this be included in the T // packet via the QListThreadsInStopReply packet // earlier in the debug session. // // Example: // thread-pcs:dec14,2cf872b0,2cf8681c,2d02d68c,2cf716a8; // // BEST PRACTICES: // Since register values can be supplied with this packet, it is often useful // to return the PC, SP, FP, LR (if any), and FLAGS registers so that separate // packets don't need to be sent to read each of these registers from each // thread. // // If a thread is stopped for no reason (like just because another thread // stopped, or because when one core stops all cores should stop), use a // "T" packet with "00" as the signal number and fill in as many key values // and registers as possible. // // LLDB likes to know why a thread stopped since many thread control // operations like stepping over a source line, actually are implemented // by running the process multiple times. If a breakpoint is hit while // trying to step over a source line and LLDB finds out that a breakpoint // is hit in the "reason", we will know to stop trying to do the step // over because something happened that should stop us from trying to // do the step. If we are at a breakpoint and we disable the breakpoint // at the current PC and do an instruction single step, knowing that // we stopped due to a "trace" helps us know that we can continue // running versus stopping due to a "breakpoint" (if we have two // breakpoint instruction on consecutive instructions). So the more info // we can get about the reason a thread stops, the better job LLDB can // do when controlling your process. A typical GDB server behavior is // to send a SIGTRAP for breakpoints _and_ also when instruction single // stepping, in this case the debugger doesn't really know why we // stopped and it can make it hard for the debugger to control your // program correctly. What if a real SIGTRAP was delivered to a thread // while we were trying to single step? We wouldn't know the difference // with a standard GDB remote server and we could do the wrong thing. // // PRIORITY TO IMPLEMENT // High. Having the extra information in your stop reply packets makes // your debug session more reliable and informative. //---------------------------------------------------------------------- //---------------------------------------------------------------------- // PLATFORM EXTENSION - for use as a GDB remote platform //---------------------------------------------------------------------- // "qfProcessInfo" // "qsProcessInfo" // // BRIEF // Get the first process info (qfProcessInfo) or subsequent process // info (qsProcessInfo) for one or more processes on the remote // platform. The first call gets the first match and subsequent calls // to qsProcessInfo gets the subsequent matches. Return an error EXX, // where XX are two hex digits, when no more matches are available. // // PRIORITY TO IMPLEMENT // Required. The qfProcessInfo packet can be followed by a ':' and // some key value pairs. The key value pairs in the command are: // // KEY VALUE DESCRIPTION // =========== ======== ================================================ // "name" ascii-hex An ASCII hex string that contains the name of // the process that will be matched. // "name_match" enum One of: "equals", "starts_with", "ends_with", // "contains" or "regex" // "pid" integer A string value containing the decimal process ID // "parent_pid" integer A string value containing the decimal parent // process ID // "uid" integer A string value containing the decimal user ID // "gid" integer A string value containing the decimal group ID // "euid" integer A string value containing the decimal effective user ID // "egid" integer A string value containing the decimal effective group ID // "all_users" bool A boolean value that specifies if processes should // be listed for all users, not just the user that the // platform is running as // "triple" string An ASCII triple string ("x86_64", // "x86_64-apple-macosx", "armv7-apple-ios") // // The response consists of key/value pairs where the key is separated from the // values with colons and each pair is terminated with a semi colon. For a list // of the key/value pairs in the response see the "qProcessInfoPID" packet // documentation. // // Sample packet/response: // send packet: $qfProcessInfo#00 // read packet: $pid:60001;ppid:59948;uid:7746;gid:11;euid:7746;egid:11;name:6c6c6462;triple:x86_64-apple-macosx;#00 // send packet: $qsProcessInfo#00 // read packet: $pid:59992;ppid:192;uid:7746;gid:11;euid:7746;egid:11;name:6d64776f726b6572;triple:x86_64-apple-macosx;#00 // send packet: $qsProcessInfo#00 // read packet: $E04#00 //---------------------------------------------------------------------- //---------------------------------------------------------------------- // PLATFORM EXTENSION - for use as a GDB remote platform //---------------------------------------------------------------------- // "qLaunchGDBServer" // // BRIEF // Have the remote platform launch a GDB server. // // PRIORITY TO IMPLEMENT // Required. The qLaunchGDBServer packet must be followed by a ':' and // some key value pairs. The key value pairs in the command are: // // KEY VALUE DESCRIPTION // =========== ======== ================================================ // "port" integer A string value containing the decimal port ID or // zero if the port should be bound and returned // // "host" integer The host that connections should be limited to // when the GDB server is connected to. // // The response consists of key/value pairs where the key is separated from the // values with colons and each pair is terminated with a semi colon. // // Sample packet/response: // send packet: $qLaunchGDBServer:port:0;host:lldb.apple.com;#00 // read packet: $pid:60025;port:50776;#00 // // The "pid" key/value pair is only specified if the remote platform launched // a separate process for the GDB remote server and can be omitted if no // process was separately launched. // // The "port" key/value pair in the response lets clients know what port number // to attach to in case zero was specified as the "port" in the sent command. //---------------------------------------------------------------------- //---------------------------------------------------------------------- // PLATFORM EXTENSION - for use as a GDB remote platform //---------------------------------------------------------------------- // "qProcessInfoPID:PID" // // BRIEF // Have the remote platform get detailed information on a process by // ID. PID is specified as a decimal integer. // // PRIORITY TO IMPLEMENT // Optional. // // The response consists of key/value pairs where the key is separated from the // values with colons and each pair is terminated with a semi colon. // // The key value pairs in the response are: // // KEY VALUE DESCRIPTION // =========== ======== ================================================ // "pid" integer Process ID as a decimal integer string // "ppid" integer Parent process ID as a decimal integer string // "uid" integer A string value containing the decimal user ID // "gid" integer A string value containing the decimal group ID // "euid" integer A string value containing the decimal effective user ID // "egid" integer A string value containing the decimal effective group ID // "name" ascii-hex An ASCII hex string that contains the name of the process // "triple" string A target triple ("x86_64-apple-macosx", "armv7-apple-ios") // // Sample packet/response: // send packet: $qProcessInfoPID:60050#00 // read packet: $pid:60050;ppid:59948;uid:7746;gid:11;euid:7746;egid:11;name:6c6c6462;triple:x86_64-apple-macosx;#00 //---------------------------------------------------------------------- //---------------------------------------------------------------------- // "vAttachName" // // BRIEF // Same as vAttach, except instead of a "pid" you send a process name. // // PRIORITY TO IMPLEMENT // Low. Only needed for "process attach -n". If the packet isn't supported // then "process attach -n" will fail gracefully. So you need only to support // it if attaching to a process by name makes sense for your environment. //---------------------------------------------------------------------- //---------------------------------------------------------------------- // "vAttachWait" // // BRIEF // Same as vAttachName, except that the stub should wait for the next instance // of a process by that name to be launched and attach to that. // // PRIORITY TO IMPLEMENT // Low. Only needed to support "process attach -w -n" which will fail // gracefully if the packet is not supported. //---------------------------------------------------------------------- //---------------------------------------------------------------------- // "qAttachOrWaitSupported" // // BRIEF // This is a binary "is it supported" query. Return OK if you support // vAttachOrWait // // PRIORITY TO IMPLEMENT // Low. This is required if you support vAttachOrWait, otherwise no support // is needed since the standard "I don't recognize this packet" response // will do the right thing. //---------------------------------------------------------------------- //---------------------------------------------------------------------- // "vAttachOrWait" // // BRIEF // Same as vAttachWait, except that the stub will attach to a process // by name if it exists, and if it does not, it will wait for a process // of that name to appear and attach to it. // // PRIORITY TO IMPLEMENT // Low. Only needed to implement "process attach -w -i false -n". If // you don't implement it but do implement -n AND lldb can somehow get // a process list from your device, it will fall back on scanning the // process list, and sending vAttach or vAttachWait depending on // whether the requested process exists already. This is racy, // however, so if you want to support this behavior it is better to // support this packet. //---------------------------------------------------------------------- //---------------------------------------------------------------------- // "jThreadExtendedInfo" // // BRIEF // This packet, which takes its arguments as JSON and sends its reply as // JSON, allows the gdb remote stub to provide additional information // about a given thread. // // PRIORITY TO IMPLEMENT // Low. This packet is only needed if the gdb remote stub wants to // provide interesting additional information about a thread for the // user. // // This packet takes its arguments in JSON form ( http://www.json.org ). // At a minimum, a thread must be specified, for example: // // jThreadExtendedInfo:{"thread":612910} // // Because this is a JSON string, the thread number is provided in base10. // Additional key-value pairs may be provided by lldb to the gdb remote // stub. For instance, on some versions of Mac OS X, lldb can read offset // information out of the system libraries. Using those offsets, debugserver // is able to find the Thread Specific Address (TSD) for a thread and include // that in the return information. So lldb will send these additional fields // like so: // // jThreadExtendedInfo:{"plo_pthread_tsd_base_address_offset":0,"plo_pthread_tsd_base_offset":224,"plo_pthread_tsd_entry_size":8,"thread":612910} // // There are no requirements for what is included in the response. A simple // reply on a Mac OS X Yosemite / iOS 8 may include the pthread_t value, the // Thread Specific Data (TSD) address, the dispatch_queue_t value if the thread // is associated with a GCD queue, and the requested Quality of Service (QoS) // information about that thread. For instance, a reply may look like: // // {"tsd_address":4371349728,"requested_qos":{"enum_value":33,"constant_name":"QOS_CLASS_USER_INTERACTIVE","printable_name":"User Interactive"},"pthread_t":4371349504,"dispatch_queue_t":140735087127872} // // tsd_address, pthread_t, and dispatch_queue_t are all simple key-value pairs. // The JSON standard requires that numbers be expressed in base 10 - so all of // these are. requested_qos is a dictionary with three key-value pairs in it - // so the UI layer may choose the form most appropriate for displaying to the user. // // Sending JSON over gdb-remote protocol introduces some problems. We may be // sending strings with arbitrary contents in them, including the '#', '$', and '*' // characters that have special meaning in gdb-remote protocol and cannot occur // in the middle of the string. The standard solution for this would be to require // ascii-hex encoding of all strings, or ascii-hex encode the entire JSON payload. // // Instead, the binary escaping convention is used for JSON data. This convention // (e.g. used for the X packet) says that if '#', '$', '*', or '}' are to occur in // the payload, the character '}' (0x7d) is emitted, then the metacharacter is emitted // xor'ed by 0x20. The '}' character occurs in every JSON payload at least once, and // '}' ^ 0x20 happens to be ']' so the raw packet characters for a request will look // like // // jThreadExtendedInfo:{"thread":612910}] // // on the wire. //---------------------------------------------------------------------- //---------------------------------------------------------------------- // "QEnableCompression" // // BRIEF // This packet enables compression of the packets that the debug stub sends to lldb. // If the debug stub can support compression, it indictes this in the reply of the // "qSupported" packet. e.g. // LLDB SENDS: qSupported:xmlRegisters=i386,arm,mips // STUB REPLIES: qXfer:features:read+;SupportedCompressions=lzfse,zlib-deflate,lz4,lzma;DefaultCompressionMinSize=384 // // If lldb knows how to use any of these compression algorithms, it can ask that this // compression mode be enabled. It may optionally change the minimum packet size // where compression is used. Typically small packets do not benefit from compression, // as well as compression headers -- compression is most beneficial with larger packets. // // QEnableCompression:type:zlib-deflate; // or // QEnableCompression:type:zlib-deflate;minsize:512; // // The debug stub should reply with an uncompressed "OK" packet to indicate that the // request was accepted. All further packets the stub sends will use this compression. // // Packets are compressed as the last step before they are sent from the stub, and // decompressed as the first step after they are received. The packet format in compressed // mode becomes one of two: // // $N#00 // // $C:#00 // // Where "#00" is the actual checksum value if noack mode is not enabled. The checksum // value is for the "N" or // "C:" bytes in the packet. // // The size of the uncompressed payload in base10 is provided because it will simplify // decompression if the final buffer size needed is known ahead of time. // // Compression on low-latency connections is unlikely to be an improvement. Particularly // when the debug stub and lldb are running on the same host. It should only be used // for slow connections, and likely only for larger packets. // // Example compression algorithsm that may be used include // // zlib-deflate // The raw DEFLATE format as described in IETF RFC 1951. With the ZLIB library, you // can compress to this format with an initialization like // deflateInit2 (&stream, 5, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY) // and you can decompress with an initialization like // inflateInit2 (&stream, -15) // // lz4 // https://en.wikipedia.org/wiki/LZ4_(compression_algorithm) // https://github.com/Cyan4973/lz4 // The libcompression APIs on darwin systems call this COMPRESSION_LZ4_RAW. // // lzfse // An Apple proprietary compression algorithm implemented in libcompression. // // lzma // libcompression implements "LZMA level 6", the default compression for the // open source LZMA implementation. //---------------------------------------------------------------------- //---------------------------------------------------------------------- // "jGetLoadedDynamicLibrariesInfos" // // BRIEF // This packet asks the remote debug stub to send the details about libraries // being added/removed from the process as a performance optimization. // // There are three ways this packet can be used. All three return a dictionary of // binary images formatted the same way. // // On MacOS X 10.11, iOS 9, tvOS 9, watchOS 2 and earlier, the packet is used like // jGetLoadedDynamicLibrariesInfos:{"image_count":1,"image_list_address":140734800075128} // where the image_list_address is an array of {void* load_addr, void* mod_date, void* pathname} // in the inferior process memory (and image_count is the number of elements in this array). // lldb is using information from the dyld_all_image_infos structure to make these requests to // debugserver. This use is not supported on macOS 10.12, iOS 10, tvOS 10, watchOS 3 or newer. // // On macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer, there are two calls. One requests information // on all shared libraries: // jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true} // And the second requests information about a list of shared libraries, given their load addresses: // jGetLoadedDynamicLibrariesInfos:{"solib_addresses":[8382824135,3258302053,830202858503]} // // The second call is both a performance optimization (instead of having lldb read the mach-o header/load commands // out of memory with generic read packets) but also adds additional information in the form of the // filename of the shared libraries (which is not available in the mach-o header/load commands.) // // An example using the Mac OS X 10.11 style call: // // LLDB SENDS: jGetLoadedDynamicLibrariesInfos:{"image_count":1,"image_list_address":140734800075128} // STUB REPLIES: ${"images":[{"load_address":4294967296,"mod_date":0,"pathname":"/tmp/a.out","uuid":"02CF262C-ED6F-3965-9E14-63538B465CFF","mach_header":{"magic":4277009103,"cputype":16777223,"cpusubtype":18446744071562067971,"filetype":2},"segments":{"name":"__PAGEZERO","vmaddr":0,"vmsize":4294967296,"fileoff":0,"filesize":0,"maxprot":0},{"name":"__TEXT","vmaddr":4294967296,"vmsize":4096,"fileoff":0,"filesize":4096,"maxprot":7},{"name":"__LINKEDIT","vmaddr":4294971392,"vmsize":4096,"fileoff":4096,"filesize":152,"maxprot":7}}]}#00 // // Or pretty-printed, // // STUB REPLIES: ${"images": // [ // {"load_address":4294967296, // "mod_date":0, // "pathname":"/tmp/a.out", // "uuid":"02CF262C-ED6F-3965-9E14-63538B465CFF", // "mach_header": // {"magic":4277009103, // "cputype":16777223, // "cpusubtype":18446744071562067971, // "filetype":2 // }, // "segments": // [ // {"name":"__PAGEZERO", // "vmaddr":0, // "vmsize":4294967296, // "fileoff":0, // "filesize":0, // "maxprot":0 // }, // {"name":"__TEXT", // "vmaddr":4294967296, // "vmsize":4096, // "fileoff":0, // "filesize":4096, // "maxprot":7 // }, // {"name":"__LINKEDIT", // "vmaddr":4294971392, // "vmsize":4096, // "fileoff":4096, // "filesize":152, // "maxprot":7 // } // ] // } // ] // } // // // This is similar to the qXfer:libraries:read packet, and it could // be argued that it should be merged into that packet. A separate // packet was created primarily because lldb needs to specify the // number of images to be read and the address from which the initial // information is read. Also the XML DTD would need to be extended // quite a bit to provide all the information that the DynamicLoaderMacOSX // would need to work correctly on this platform. // // PRIORITY TO IMPLEMENT // On Mac OS X 10.11, iOS 9, tvOS 9, watchOS 2 and older: Low. If this packet is absent, // lldb will read the Mach-O headers/load commands out of memory. // On macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer: High. If this packet is absent, // lldb will not know anything about shared libraries in the inferior, or where the main // executable loaded. //---------------------------------------------------------------------- //---------------------------------------------------------------------- // "jThreadsInfo" // // BRIEF // Ask for the server for thread stop information of all threads. // // PRIORITY TO IMPLEMENT // Low. This is a performance optimization, which speeds up debugging by avoiding // multiple round-trips for retrieving thread information. The information from this // packet can be retrieved using a combination of qThreadStopInfo and m packets. //---------------------------------------------------------------------- The data in this packet is very similar to the stop reply packets, but is packaged in JSON and uses JSON arrays where applicable. The JSON output looks like: [ { "tid":1580681, "metype":6, "medata":[2,0], "reason":"exception", "qaddr":140735118423168, "registers": { "0":"8000000000000000", "1":"0000000000000000", "2":"20fabf5fff7f0000", "3":"e8f8bf5fff7f0000", "4":"0100000000000000", "5":"d8f8bf5fff7f0000", "6":"b0f8bf5fff7f0000", "7":"20f4bf5fff7f0000", "8":"8000000000000000", "9":"61a8db78a61500db", "10":"3200000000000000", "11":"4602000000000000", "12":"0000000000000000", "13":"0000000000000000", "14":"0000000000000000", "15":"0000000000000000", "16":"960b000001000000", "17":"0202000000000000", "18":"2b00000000000000", "19":"0000000000000000", "20":"0000000000000000" }, "memory":[ {"address":140734799804592,"bytes":"c8f8bf5fff7f0000c9a59e8cff7f0000"}, {"address":140734799804616,"bytes":"00000000000000000100000000000000"} ] } ] It contains an array of dictionaries with all of the key value pairs that are normally in the stop reply packet, including the expedited registers. The registers are passed as hex-encoded JSON string in debuggee-endian byte order. Note that the register numbers are decimal numbers, unlike the stop-reply packet, where they are written in hex. The packet also contains expedited memory in the "memory" key. This allows the server to expedite memory that the client is likely to use (e.g., areas around the stack pointer, which are needed for computing backtraces) and it reduces the packet count. On MacOSX with debugserver, we expedite the frame pointer backchain for a thread (up to 256 entries) by reading 2 pointers worth of bytes at the frame pointer (for the previous FP and PC), and follow the backchain. Most backtraces on MacOSX and iOS now don't require us to read any memory! //---------------------------------------------------------------------- // "jGetSharedCacheInfo" // // BRIEF // This packet asks the remote debug stub to send the details about the inferior's // shared cache. The shared cache is a collection of common libraries/frameworks that // are mapped into every process at the same address on Darwin systems, and can be // identified by a load address and UUID. // // // LLDB SENDS: jGetSharedCacheInfo:{} // STUB REPLIES: ${"shared_cache_base_address":140735683125248,"shared_cache_uuid":"DDB8D70C-C9A2-3561-B2C8-BE48A4F33F96","no_shared_cache":false,"shared_cache_private_cache":false]}#00 // // PRIORITY TO IMPLEMENT // Low. When both lldb and the inferior process are running on the same computer, and lldb // and the inferior process have the same shared cache, lldb may (as an optimization) read // the shared cache out of its own memory instead of using gdb-remote read packets to read // them from the inferior process. //---------------------------------------------------------------------- //---------------------------------------------------------------------- // "qQueryGDBServer" // // BRIEF // Ask the platform for the list of gdbservers we have to connect // // PRIORITY TO IMPLEMENT // Low. The packet is required to support connecting to gdbserver started // by the platform instance automatically. //---------------------------------------------------------------------- If the remote platform automatically started one or more gdbserver instance (without lldb asking it) then it have to return the list of port number or socket name for each of them what can be used by lldb to connect to those instances. The data in this packet is a JSON array of JSON objects with the following keys: "port": (optional) "socket_name": (optional) Example packet: [ { "port": 1234 }, { "port": 5432 }, { "socket_name": "foo" } ] Index: vendor/lldb/dist/include/lldb/Host/Host.h =================================================================== --- vendor/lldb/dist/include/lldb/Host/Host.h (revision 320966) +++ vendor/lldb/dist/include/lldb/Host/Host.h (revision 320967) @@ -1,258 +1,256 @@ //===-- Host.h --------------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -#ifndef liblldb_Host_h_ -#define liblldb_Host_h_ -#if defined(__cplusplus) +#ifndef LLDB_HOST_HOST_H +#define LLDB_HOST_HOST_H -#include - -#include -#include - #include "lldb/Host/File.h" #include "lldb/Host/HostThread.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/StringList.h" #include "lldb/lldb-private-forward.h" #include "lldb/lldb-private.h" +#include +#include +#include +#include +#include namespace lldb_private { class FileAction; class ProcessLaunchInfo; //---------------------------------------------------------------------- // Exit Type for inferior processes //---------------------------------------------------------------------- struct WaitStatus { enum Type : uint8_t { Exit, // The status represents the return code from normal // program exit (i.e. WIFEXITED() was true) Signal, // The status represents the signal number that caused // the program to exit (i.e. WIFSIGNALED() was true) Stop, // The status represents the signal number that caused the // program to stop (i.e. WIFSTOPPED() was true) }; Type type; uint8_t status; WaitStatus(Type type, uint8_t status) : type(type), status(status) {} static WaitStatus Decode(int wstatus); }; //---------------------------------------------------------------------- /// @class Host Host.h "lldb/Host/Host.h" /// @brief A class that provides host computer information. /// /// Host is a class that answers information about the host operating /// system. //---------------------------------------------------------------------- class Host { public: typedef std::function // Exit value of process if signal is zero MonitorChildProcessCallback; //------------------------------------------------------------------ /// Start monitoring a child process. /// /// Allows easy monitoring of child processes. \a callback will be /// called when the child process exits or if it gets a signal. The /// callback will only be called with signals if \a monitor_signals /// is \b true. \a callback will usually be called from another /// thread so the callback function must be thread safe. /// /// When the callback gets called, the return value indicates if /// monitoring should stop. If \b true is returned from \a callback /// the information will be removed. If \b false is returned then /// monitoring will continue. If the child process exits, the /// monitoring will automatically stop after the callback returned /// regardless of the callback return value. /// /// @param[in] callback /// A function callback to call when a child receives a signal /// (if \a monitor_signals is true) or a child exits. /// /// @param[in] pid /// The process ID of a child process to monitor, -1 for all /// processes. /// /// @param[in] monitor_signals /// If \b true the callback will get called when the child /// process gets a signal. If \b false, the callback will only /// get called if the child process exits. /// /// @return /// A thread handle that can be used to cancel the thread that /// was spawned to monitor \a pid. /// /// @see static void Host::StopMonitoringChildProcess (uint32_t) //------------------------------------------------------------------ static HostThread StartMonitoringChildProcess(const MonitorChildProcessCallback &callback, lldb::pid_t pid, bool monitor_signals); enum SystemLogType { eSystemLogWarning, eSystemLogError }; static void SystemLog(SystemLogType type, const char *format, ...) __attribute__((format(printf, 2, 3))); static void SystemLog(SystemLogType type, const char *format, va_list args); //------------------------------------------------------------------ /// Get the process ID for the calling process. /// /// @return /// The process ID for the current process. //------------------------------------------------------------------ static lldb::pid_t GetCurrentProcessID(); static void Kill(lldb::pid_t pid, int signo); //------------------------------------------------------------------ /// Get the thread token (the one returned by ThreadCreate when the thread was /// created) for the /// calling thread in the current process. /// /// @return /// The thread token for the calling thread in the current process. //------------------------------------------------------------------ static lldb::thread_t GetCurrentThread(); static const char *GetSignalAsCString(int signo); //------------------------------------------------------------------ /// Given an address in the current process (the process that /// is running the LLDB code), return the name of the module that /// it comes from. This can be useful when you need to know the /// path to the shared library that your code is running in for /// loading resources that are relative to your binary. /// /// @param[in] host_addr /// The pointer to some code in the current process. /// /// @return /// \b A file spec with the module that contains \a host_addr, /// which may be invalid if \a host_addr doesn't fall into /// any valid module address range. //------------------------------------------------------------------ static FileSpec GetModuleFileSpecForHostAddress(const void *host_addr); //------------------------------------------------------------------ /// If you have an executable that is in a bundle and want to get /// back to the bundle directory from the path itself, this /// function will change a path to a file within a bundle to the /// bundle directory itself. /// /// @param[in] file /// A file spec that might point to a file in a bundle. /// /// @param[out] bundle_directory /// An object will be filled in with the bundle directory for /// the bundle when \b true is returned. Otherwise \a file is /// left untouched and \b false is returned. /// /// @return /// \b true if \a file was resolved in \a bundle_directory, /// \b false otherwise. //------------------------------------------------------------------ static bool GetBundleDirectory(const FileSpec &file, FileSpec &bundle_directory); //------------------------------------------------------------------ /// When executable files may live within a directory, where the /// directory represents an executable bundle (like the MacOSX /// app bundles), then locate the executable within the containing /// bundle. /// /// @param[in,out] file /// A file spec that currently points to the bundle that will /// be filled in with the executable path within the bundle /// if \b true is returned. Otherwise \a file is left untouched. /// /// @return /// \b true if \a file was resolved, \b false if this function /// was not able to resolve the path. //------------------------------------------------------------------ static bool ResolveExecutableInBundle(FileSpec &file); static uint32_t FindProcesses(const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &proc_infos); typedef std::map TidMap; typedef std::pair TidPair; static bool FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach); static bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info); static const lldb::UnixSignalsSP &GetUnixSignals(); static Status LaunchProcess(ProcessLaunchInfo &launch_info); //------------------------------------------------------------------ /// Perform expansion of the command-line for this launch info /// This can potentially involve wildcard expansion // environment variable replacement, and whatever other // argument magic the platform defines as part of its typical // user experience //------------------------------------------------------------------ static Status ShellExpandArguments(ProcessLaunchInfo &launch_info); // TODO: Convert this function to take a StringRef. static Status RunShellCommand( const char *command, // Shouldn't be NULL const FileSpec &working_dir, // Pass empty FileSpec to use the current // working directory int *status_ptr, // Pass NULL if you don't want the process exit status int *signo_ptr, // Pass NULL if you don't want the signal that caused the // process to exit std::string *command_output, // Pass NULL if you don't want the command output uint32_t timeout_sec, bool run_in_default_shell = true); static Status RunShellCommand( const Args &args, const FileSpec &working_dir, // Pass empty FileSpec to use the current // working directory int *status_ptr, // Pass NULL if you don't want the process exit status int *signo_ptr, // Pass NULL if you don't want the signal that caused the // process to exit std::string *command_output, // Pass NULL if you don't want the command output uint32_t timeout_sec, bool run_in_default_shell = true); static bool OpenFileInExternalEditor(const FileSpec &file_spec, uint32_t line_no); static size_t GetEnvironment(StringList &env); static std::unique_ptr CreateDefaultConnection(llvm::StringRef url); }; } // namespace lldb_private namespace llvm { template <> struct format_provider { /// Options = "" gives a human readable description of the status /// Options = "g" gives a gdb-remote protocol status (e.g., X09) static void format(const lldb_private::WaitStatus &WS, raw_ostream &OS, llvm::StringRef Options); }; } // namespace llvm -#endif // #if defined(__cplusplus) -#endif // liblldb_Host_h_ +#endif // LLDB_HOST_HOST_H Index: vendor/lldb/dist/include/lldb/Host/common/NativeProcessProtocol.h =================================================================== --- vendor/lldb/dist/include/lldb/Host/common/NativeProcessProtocol.h (revision 320966) +++ vendor/lldb/dist/include/lldb/Host/common/NativeProcessProtocol.h (revision 320967) @@ -1,486 +1,477 @@ //===-- NativeProcessProtocol.h ---------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef liblldb_NativeProcessProtocol_h_ #define liblldb_NativeProcessProtocol_h_ #include "lldb/Host/Host.h" #include "lldb/Host/MainLoop.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/TraceOptions.h" #include "lldb/lldb-private-forward.h" #include "lldb/lldb-types.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" #include #include "NativeBreakpointList.h" #include "NativeWatchpointList.h" namespace lldb_private { class MemoryRegionInfo; class ResumeActionList; //------------------------------------------------------------------ // NativeProcessProtocol //------------------------------------------------------------------ class NativeProcessProtocol : public std::enable_shared_from_this { friend class SoftwareBreakpoint; public: virtual ~NativeProcessProtocol() {} virtual Status Resume(const ResumeActionList &resume_actions) = 0; virtual Status Halt() = 0; virtual Status Detach() = 0; //------------------------------------------------------------------ /// Sends a process a UNIX signal \a signal. /// /// @return /// Returns an error object. //------------------------------------------------------------------ virtual Status Signal(int signo) = 0; //------------------------------------------------------------------ /// Tells a process to interrupt all operations as if by a Ctrl-C. /// /// The default implementation will send a local host's equivalent of /// a SIGSTOP to the process via the NativeProcessProtocol::Signal() /// operation. /// /// @return /// Returns an error object. //------------------------------------------------------------------ virtual Status Interrupt(); virtual Status Kill() = 0; //------------------------------------------------------------------ // Tells a process not to stop the inferior on given signals // and just reinject them back. //------------------------------------------------------------------ virtual Status IgnoreSignals(llvm::ArrayRef signals); //---------------------------------------------------------------------- // Memory and memory region functions //---------------------------------------------------------------------- virtual Status GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info); virtual Status ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) = 0; virtual Status ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) = 0; virtual Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written) = 0; virtual Status AllocateMemory(size_t size, uint32_t permissions, lldb::addr_t &addr) = 0; virtual Status DeallocateMemory(lldb::addr_t addr) = 0; virtual lldb::addr_t GetSharedLibraryInfoAddress() = 0; virtual bool IsAlive() const; virtual size_t UpdateThreads() = 0; virtual bool GetArchitecture(ArchSpec &arch) const = 0; //---------------------------------------------------------------------- // Breakpoint functions //---------------------------------------------------------------------- virtual Status SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) = 0; virtual Status RemoveBreakpoint(lldb::addr_t addr, bool hardware = false); virtual Status EnableBreakpoint(lldb::addr_t addr); virtual Status DisableBreakpoint(lldb::addr_t addr); //---------------------------------------------------------------------- // Hardware Breakpoint functions //---------------------------------------------------------------------- virtual const HardwareBreakpointMap &GetHardwareBreakpointMap() const; virtual Status SetHardwareBreakpoint(lldb::addr_t addr, size_t size); virtual Status RemoveHardwareBreakpoint(lldb::addr_t addr); //---------------------------------------------------------------------- // Watchpoint functions //---------------------------------------------------------------------- virtual const NativeWatchpointList::WatchpointMap &GetWatchpointMap() const; virtual llvm::Optional> GetHardwareDebugSupportInfo() const; virtual Status SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware); virtual Status RemoveWatchpoint(lldb::addr_t addr); //---------------------------------------------------------------------- // Accessors //---------------------------------------------------------------------- lldb::pid_t GetID() const { return m_pid; } lldb::StateType GetState() const; bool IsRunning() const { return m_state == lldb::eStateRunning || IsStepping(); } bool IsStepping() const { return m_state == lldb::eStateStepping; } bool CanResume() const { return m_state == lldb::eStateStopped; } bool GetByteOrder(lldb::ByteOrder &byte_order) const; virtual llvm::ErrorOr> GetAuxvData() const = 0; //---------------------------------------------------------------------- // Exit Status //---------------------------------------------------------------------- virtual llvm::Optional GetExitStatus(); virtual bool SetExitStatus(WaitStatus status, bool bNotifyStateChange); //---------------------------------------------------------------------- // Access to threads //---------------------------------------------------------------------- NativeThreadProtocolSP GetThreadAtIndex(uint32_t idx); NativeThreadProtocolSP GetThreadByID(lldb::tid_t tid); void SetCurrentThreadID(lldb::tid_t tid) { m_current_thread_id = tid; } lldb::tid_t GetCurrentThreadID() { return m_current_thread_id; } NativeThreadProtocolSP GetCurrentThread() { return GetThreadByID(m_current_thread_id); } //---------------------------------------------------------------------- // Access to inferior stdio //---------------------------------------------------------------------- virtual int GetTerminalFileDescriptor() { return m_terminal_fd; } //---------------------------------------------------------------------- // Stop id interface //---------------------------------------------------------------------- uint32_t GetStopID() const; // --------------------------------------------------------------------- // Callbacks for low-level process state changes // --------------------------------------------------------------------- class NativeDelegate { public: virtual ~NativeDelegate() {} virtual void InitializeDelegate(NativeProcessProtocol *process) = 0; virtual void ProcessStateChanged(NativeProcessProtocol *process, lldb::StateType state) = 0; virtual void DidExec(NativeProcessProtocol *process) = 0; }; //------------------------------------------------------------------ /// Register a native delegate. /// /// Clients can register nofication callbacks by passing in a /// NativeDelegate impl and passing it into this function. /// /// Note: it is required that the lifetime of the /// native_delegate outlive the NativeProcessProtocol. /// /// @param[in] native_delegate /// A NativeDelegate impl to be called when certain events /// happen within the NativeProcessProtocol or related threads. /// /// @return /// true if the delegate was registered successfully; /// false if the delegate was already registered. /// /// @see NativeProcessProtocol::NativeDelegate. //------------------------------------------------------------------ bool RegisterNativeDelegate(NativeDelegate &native_delegate); //------------------------------------------------------------------ /// Unregister a native delegate previously registered. /// /// @param[in] native_delegate /// A NativeDelegate impl previously registered with this process. /// /// @return Returns \b true if the NativeDelegate was /// successfully removed from the process, \b false otherwise. /// /// @see NativeProcessProtocol::NativeDelegate //------------------------------------------------------------------ bool UnregisterNativeDelegate(NativeDelegate &native_delegate); virtual Status GetLoadedModuleFileSpec(const char *module_path, FileSpec &file_spec) = 0; virtual Status GetFileLoadAddress(const llvm::StringRef &file_name, lldb::addr_t &load_addr) = 0; - //------------------------------------------------------------------ - /// Launch a process for debugging. This method will create an concrete - /// instance of NativeProcessProtocol, based on the host platform. - /// (e.g. NativeProcessLinux on linux, etc.) - /// - /// @param[in] launch_info - /// Information required to launch the process. - /// - /// @param[in] native_delegate - /// The delegate that will receive messages regarding the - /// inferior. Must outlive the NativeProcessProtocol - /// instance. - /// - /// @param[in] mainloop - /// The mainloop instance with which the process can register - /// callbacks. Must outlive the NativeProcessProtocol - /// instance. - /// - /// @param[out] process_sp - /// On successful return from the method, this parameter - /// contains the shared pointer to the - /// NativeProcessProtocol that can be used to manipulate - /// the native process. - /// - /// @return - /// An error object indicating if the operation succeeded, - /// and if not, what error occurred. - //------------------------------------------------------------------ - static Status Launch(ProcessLaunchInfo &launch_info, - NativeDelegate &native_delegate, MainLoop &mainloop, - NativeProcessProtocolSP &process_sp); + class Factory { + public: + virtual ~Factory(); + //------------------------------------------------------------------ + /// Launch a process for debugging. + /// + /// @param[in] launch_info + /// Information required to launch the process. + /// + /// @param[in] native_delegate + /// The delegate that will receive messages regarding the + /// inferior. Must outlive the NativeProcessProtocol + /// instance. + /// + /// @param[in] mainloop + /// The mainloop instance with which the process can register + /// callbacks. Must outlive the NativeProcessProtocol + /// instance. + /// + /// @return + /// A NativeProcessProtocol shared pointer if the operation succeeded or + /// an error object if it failed. + //------------------------------------------------------------------ + virtual llvm::Expected + Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, + MainLoop &mainloop) const = 0; - //------------------------------------------------------------------ - /// Attach to an existing process. This method will create an concrete - /// instance of NativeProcessProtocol, based on the host platform. - /// (e.g. NativeProcessLinux on linux, etc.) - /// - /// @param[in] pid - /// pid of the process locatable - /// - /// @param[in] native_delegate - /// The delegate that will receive messages regarding the - /// inferior. Must outlive the NativeProcessProtocol - /// instance. - /// - /// @param[in] mainloop - /// The mainloop instance with which the process can register - /// callbacks. Must outlive the NativeProcessProtocol - /// instance. - /// - /// @param[out] process_sp - /// On successful return from the method, this parameter - /// contains the shared pointer to the - /// NativeProcessProtocol that can be used to manipulate - /// the native process. - /// - /// @return - /// An error object indicating if the operation succeeded, - /// and if not, what error occurred. - //------------------------------------------------------------------ - static Status Attach(lldb::pid_t pid, NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &process_sp); + //------------------------------------------------------------------ + /// Attach to an existing process. + /// + /// @param[in] pid + /// pid of the process locatable + /// + /// @param[in] native_delegate + /// The delegate that will receive messages regarding the + /// inferior. Must outlive the NativeProcessProtocol + /// instance. + /// + /// @param[in] mainloop + /// The mainloop instance with which the process can register + /// callbacks. Must outlive the NativeProcessProtocol + /// instance. + /// + /// @return + /// A NativeProcessProtocol shared pointer if the operation succeeded or + /// an error object if it failed. + //------------------------------------------------------------------ + virtual llvm::Expected + Attach(lldb::pid_t pid, NativeDelegate &native_delegate, + MainLoop &mainloop) const = 0; + }; //------------------------------------------------------------------ /// StartTracing API for starting a tracing instance with the /// TraceOptions on a specific thread or process. /// /// @param[in] config /// The configuration to use when starting tracing. /// /// @param[out] error /// Status indicates what went wrong. /// /// @return /// The API returns a user_id which can be used to get trace /// data, trace configuration or stopping the trace instance. /// The user_id is a key to identify and operate with a tracing /// instance. It may refer to the complete process or a single /// thread. //------------------------------------------------------------------ virtual lldb::user_id_t StartTrace(const TraceOptions &config, Status &error) { error.SetErrorString("Not implemented"); return LLDB_INVALID_UID; } //------------------------------------------------------------------ /// StopTracing API as the name suggests stops a tracing instance. /// /// @param[in] traceid /// The user id of the trace intended to be stopped. Now a /// user_id may map to multiple threads in which case this API /// could be used to stop the tracing for a specific thread by /// supplying its thread id. /// /// @param[in] thread /// Thread is needed when the complete process is being traced /// and the user wishes to stop tracing on a particular thread. /// /// @return /// Status indicating what went wrong. //------------------------------------------------------------------ virtual Status StopTrace(lldb::user_id_t traceid, lldb::tid_t thread = LLDB_INVALID_THREAD_ID) { return Status("Not implemented"); } //------------------------------------------------------------------ /// This API provides the trace data collected in the form of raw /// data. /// /// @param[in] traceid thread /// The traceid and thread provide the context for the trace /// instance. /// /// @param[in] buffer /// The buffer provides the destination buffer where the trace /// data would be read to. The buffer should be truncated to the /// filled length by this function. /// /// @param[in] offset /// There is possibility to read partially the trace data from /// a specified offset where in such cases the buffer provided /// may be smaller than the internal trace collection container. /// /// @return /// The size of the data actually read. //------------------------------------------------------------------ virtual Status GetData(lldb::user_id_t traceid, lldb::tid_t thread, llvm::MutableArrayRef &buffer, size_t offset = 0) { return Status("Not implemented"); } //------------------------------------------------------------------ /// Similar API as above except it aims to provide any extra data /// useful for decoding the actual trace data. //------------------------------------------------------------------ virtual Status GetMetaData(lldb::user_id_t traceid, lldb::tid_t thread, llvm::MutableArrayRef &buffer, size_t offset = 0) { return Status("Not implemented"); } //------------------------------------------------------------------ /// API to query the TraceOptions for a given user id /// /// @param[in] traceid /// The user id of the tracing instance. /// /// @param[in] config /// The thread id of the tracing instance, in case configuration /// for a specific thread is needed should be specified in the /// config. /// /// @param[out] error /// Status indicates what went wrong. /// /// @param[out] config /// The actual configuration being used for tracing. //------------------------------------------------------------------ virtual Status GetTraceConfig(lldb::user_id_t traceid, TraceOptions &config) { return Status("Not implemented"); } protected: lldb::pid_t m_pid; std::vector m_threads; - lldb::tid_t m_current_thread_id; + lldb::tid_t m_current_thread_id = LLDB_INVALID_THREAD_ID; mutable std::recursive_mutex m_threads_mutex; - lldb::StateType m_state; + lldb::StateType m_state = lldb::eStateInvalid; mutable std::recursive_mutex m_state_mutex; llvm::Optional m_exit_status; std::recursive_mutex m_delegates_mutex; std::vector m_delegates; NativeBreakpointList m_breakpoint_list; NativeWatchpointList m_watchpoint_list; HardwareBreakpointMap m_hw_breakpoints_map; int m_terminal_fd; - uint32_t m_stop_id; + uint32_t m_stop_id = 0; // Set of signal numbers that LLDB directly injects back to inferior // without stopping it. llvm::DenseSet m_signals_to_ignore; // lldb_private::Host calls should be used to launch a process for debugging, // and // then the process should be attached to. When attaching to a process // lldb_private::Host calls should be used to locate the process to attach to, // and then this function should be called. - NativeProcessProtocol(lldb::pid_t pid); + NativeProcessProtocol(lldb::pid_t pid, int terminal_fd, + NativeDelegate &delegate); // ----------------------------------------------------------- // Internal interface for state handling // ----------------------------------------------------------- void SetState(lldb::StateType state, bool notify_delegates = true); // Derived classes need not implement this. It can be used as a // hook to clear internal caches that should be invalidated when // stop ids change. // // Note this function is called with the state mutex obtained // by the caller. virtual void DoStopIDBumped(uint32_t newBumpId); // ----------------------------------------------------------- // Internal interface for software breakpoints // ----------------------------------------------------------- Status SetSoftwareBreakpoint(lldb::addr_t addr, uint32_t size_hint); virtual Status GetSoftwareBreakpointTrapOpcode(size_t trap_opcode_size_hint, size_t &actual_opcode_size, const uint8_t *&trap_opcode_bytes) = 0; // ----------------------------------------------------------- /// Notify the delegate that an exec occurred. /// /// Provide a mechanism for a delegate to clear out any exec- /// sensitive data. // ----------------------------------------------------------- void NotifyDidExec(); NativeThreadProtocolSP GetThreadByIDUnlocked(lldb::tid_t tid); // ----------------------------------------------------------- // Static helper methods for derived classes. // ----------------------------------------------------------- static Status ResolveProcessArchitecture(lldb::pid_t pid, ArchSpec &arch); private: void SynchronouslyNotifyProcessStateChanged(lldb::StateType state); }; } // namespace lldb_private #endif // #ifndef liblldb_NativeProcessProtocol_h_ Index: vendor/lldb/dist/lit/lit.cfg =================================================================== --- vendor/lldb/dist/lit/lit.cfg (revision 320966) +++ vendor/lldb/dist/lit/lit.cfg (revision 320967) @@ -1,223 +1,223 @@ # -*- Python -*- import os import platform import re import subprocess import locale import lit.formats import lit.util # Configuration file for the 'lit' test runner. # name: The name of this test suite. config.name = 'lldb' # testFormat: The test format to use to interpret tests. # # For now we require '&&' between commands, until they get globally killed and # the test runner updated. execute_external = (platform.system() != 'Windows' or lit_config.getBashPath() not in [None, ""]) config.test_format = lit.formats.ShTest(execute_external) # suffixes: We only support unit tests config.suffixes = [] # test_source_root: The root path where tests are located. config.test_source_root = os.path.dirname(__file__) # test_exec_root: The root path where tests should be run. lldb_obj_root = getattr(config, 'lldb_obj_root', None) if lldb_obj_root is not None: config.test_exec_root = os.path.join(lldb_obj_root, 'lit') # Set llvm_{src,obj}_root for use by others. config.llvm_src_root = getattr(config, 'llvm_src_root', None) config.llvm_obj_root = getattr(config, 'llvm_obj_root', None) # Tweak the PATH to include the tools dir and the scripts dir. if lldb_obj_root is not None: lldb_tools_dir = getattr(config, 'lldb_tools_dir', None) if not lldb_tools_dir: lit_config.fatal('No LLDB tools dir set!') llvm_tools_dir = getattr(config, 'llvm_tools_dir', None) if not llvm_tools_dir: lit_config.fatal('No LLVM tools dir set!') path = os.path.pathsep.join((lldb_tools_dir, llvm_tools_dir, config.environment['PATH'])) path = os.path.pathsep.join((os.path.join(getattr(config, 'llvm_src_root', None),'test','Scripts'),path)) config.environment['PATH'] = path lldb_libs_dir = getattr(config, 'lldb_libs_dir', None) if not lldb_libs_dir: lit_config.fatal('No LLDB libs dir set!') llvm_libs_dir = getattr(config, 'llvm_libs_dir', None) if not llvm_libs_dir: lit_config.fatal('No LLVM libs dir set!') path = os.path.pathsep.join((lldb_libs_dir, llvm_libs_dir, config.environment.get('LD_LIBRARY_PATH',''))) config.environment['LD_LIBRARY_PATH'] = path # Propagate LLVM_SRC_ROOT into the environment. config.environment['LLVM_SRC_ROOT'] = getattr(config, 'llvm_src_root', '') # Propagate PYTHON_EXECUTABLE into the environment config.environment['PYTHON_EXECUTABLE'] = getattr(config, 'python_executable', '') ### # Check that the object root is known. if config.test_exec_root is None: # Otherwise, we haven't loaded the site specific configuration (the user is # probably trying to run on a test file directly, and either the site # configuration hasn't been created by the build system, or we are in an # out-of-tree build situation). # Check for 'lldb_site_config' user parameter, and use that if available. site_cfg = lit_config.params.get('lldb_site_config', None) if site_cfg and os.path.exists(site_cfg): lit_config.load_config(config, site_cfg) raise SystemExit # Try to detect the situation where we are using an out-of-tree build by # looking for 'llvm-config'. # # FIXME: I debated (i.e., wrote and threw away) adding logic to # automagically generate the lit.site.cfg if we are in some kind of fresh # build situation. This means knowing how to invoke the build system though, # and I decided it was too much magic. We should solve this by just having # the .cfg files generated during the configuration step. llvm_config = lit.util.which('llvm-config', config.environment['PATH']) if not llvm_config: lit_config.fatal('No site specific configuration available!') # Get the source and object roots. - llvm_src_root = lit.util.capture(['llvm-config', '--src-root']).strip() - llvm_obj_root = lit.util.capture(['llvm-config', '--obj-root']).strip() + llvm_src_root = subprocess.check_output(['llvm-config', '--src-root']).strip() + llvm_obj_root = subprocess.check_output(['llvm-config', '--obj-root']).strip() lldb_src_root = os.path.join(llvm_src_root, "tools", "lldb") lldb_obj_root = os.path.join(llvm_obj_root, "tools", "lldb") # Validate that we got a tree which points to here, using the standard # tools/lldb layout. this_src_root = os.path.dirname(config.test_source_root) if os.path.realpath(lldb_src_root) != os.path.realpath(this_src_root): lit_config.fatal('No site specific configuration available!') # Check that the site specific configuration exists. site_cfg = os.path.join(lldb_obj_root, 'test', 'lit.site.cfg') if not os.path.exists(site_cfg): lit_config.fatal( 'No site specific configuration available! You may need to ' 'run "make test" in your lldb build directory.') # Okay, that worked. Notify the user of the automagic, and reconfigure. lit_config.note('using out-of-tree build at %r' % lldb_obj_root) lit_config.load_config(config, site_cfg) raise SystemExit # Register substitutions config.substitutions.append(('%python', config.python_executable)) debugserver = lit.util.which('debugserver', lldb_tools_dir) lldb = lit.util.which('lldb', lldb_tools_dir) if not os.path.exists(config.cc): config.cc = lit.util.which(config.cc, config.environment['PATH']) if not os.path.exists(config.cxx): config.cxx = lit.util.which(config.cxx, config.environment['PATH']) if platform.system() in ['Darwin']: try: - out = lit.util.capture(['xcrun', '--show-sdk-path']).strip() + out = subprocess.check_output(['xcrun', '--show-sdk-path']).strip() res = 0 except OSError: res = -1 if res == 0 and out: sdk_path = out lit_config.note('using SDKROOT: %r' % sdk_path) config.cc += " -isysroot %s" % sdk_path config.cxx += " -isysroot %s" % sdk_path config.substitutions.append(('%cc', config.cc)) config.substitutions.append(('%cxx', config.cxx)) config.substitutions.append(('%lldb', lldb)) if debugserver is not None: config.substitutions.append(('%debugserver', debugserver)) for pattern in [r"\bFileCheck\b", r"\| \bnot\b"]: tool_match = re.match(r"^(\\)?((\| )?)\W+b([0-9A-Za-z-_]+)\\b\W*$", pattern) tool_pipe = tool_match.group(2) tool_name = tool_match.group(4) tool_path = lit.util.which(tool_name, config.llvm_tools_dir) if not tool_path: # Warn, but still provide a substitution. lit_config.note( 'Did not find ' + tool_name + ' in ' + config.llvm_tools_dir) config.substitutions.append((pattern, tool_pipe + tool_path)) # Shell execution if platform.system() not in ['Windows'] or lit_config.getBashPath() != '': config.available_features.add('shell') # Running on Darwin OS if platform.system() in ['Darwin']: config.available_features.add('darwin') config.available_features.add('system-linker-mach-o') # Running on ELF based *nix if platform.system() in ['FreeBSD', 'Linux']: config.available_features.add('system-linker-elf') if platform.system() in ['FreeBSD']: config.available_features.add('freebsd') else: config.available_features.add('linux') if platform.system() in ['Windows']: config.available_features.add('windows') if re.match(r'^arm(hf.*-linux)|(.*-linux-gnuabihf)', config.target_triple): config.available_features.add("armhf-linux") if re.match(r'icc', config.cc): config.available_features.add("compiler-icc") elif re.match(r'clang', config.cc): config.available_features.add("compiler-clang") elif re.match(r'gcc', config.cc): config.available_features.add("compiler-gcc") elif re.match(r'cl', config.cc): config.available_features.add("compiler-msvc") # llvm-config knows whether it is compiled with asserts (and) # whether we are operating in release/debug mode. import subprocess try: llvm_config_cmd = \ subprocess.Popen([os.path.join(llvm_tools_dir, 'llvm-config'), '--build-mode', '--assertion-mode', '--targets-built'], stdout = subprocess.PIPE) except OSError as why: print("Could not find llvm-config in " + llvm_tools_dir) exit(42) llvm_config_output = llvm_config_cmd.stdout.read().decode('utf_8') llvm_config_output_list = llvm_config_output.split("\n") if re.search(r'DEBUG', llvm_config_output_list[0]): config.available_features.add('debug') if re.search(r'ON', llvm_config_output_list[1]): config.available_features.add('asserts') if re.search(r'ARM', llvm_config_output_list[2]): config.available_features.add('arm') if re.search(r'Mips', llvm_config_output_list[2]): config.available_features.add('mips') if re.search(r'X86', llvm_config_output_list[2]): config.available_features.add('x86') llvm_config_cmd.wait() Index: vendor/lldb/dist/lldb.xcodeproj/project.pbxproj =================================================================== --- vendor/lldb/dist/lldb.xcodeproj/project.pbxproj (revision 320966) +++ vendor/lldb/dist/lldb.xcodeproj/project.pbxproj (revision 320967) @@ -1,10540 +1,10562 @@ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXAggregateTarget section */ 26CEF3A914FD58BF007286B2 /* desktop_no_xpc */ = { isa = PBXAggregateTarget; buildConfigurationList = 26CEF3AD14FD58BF007286B2 /* Build configuration list for PBXAggregateTarget "desktop_no_xpc" */; buildPhases = ( AF90106415AB7D2900FF120D /* CopyFiles */, ); dependencies = ( 26B391F11A6DCCBE00456239 /* PBXTargetDependency */, 26CEF3B014FD591F007286B2 /* PBXTargetDependency */, 2687EACD1508115900DD8C2E /* PBXTargetDependency */, ); name = desktop_no_xpc; productName = snowleopard; }; 26CEF3B114FD592B007286B2 /* desktop */ = { isa = PBXAggregateTarget; buildConfigurationList = 26CEF3B214FD592B007286B2 /* Build configuration list for PBXAggregateTarget "desktop" */; buildPhases = ( AF90106415AB7D2900FF120D /* CopyFiles */, ); dependencies = ( 26CEF3BB14FD595B007286B2 /* PBXTargetDependency */, 26B391EF1A6DCCAF00456239 /* PBXTargetDependency */, 2687EACB1508115000DD8C2E /* PBXTargetDependency */, ); name = desktop; productName = desktop; }; 26CEF3BC14FD596A007286B2 /* ios */ = { isa = PBXAggregateTarget; buildConfigurationList = 26CEF3BD14FD596A007286B2 /* Build configuration list for PBXAggregateTarget "ios" */; buildPhases = ( AFF87C85150FF5CC000E1742 /* CopyFiles */, AF3059151B4B390800E25622 /* Run Script - remove unneeded Resources and Swift dirs from iOS LLDB.framework bundle */, ); dependencies = ( AFCA21D21D18E556004386B8 /* PBXTargetDependency */, 26CEF3C214FD5973007286B2 /* PBXTargetDependency */, 2687EACF1508116300DD8C2E /* PBXTargetDependency */, ); name = ios; productName = ios; }; /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ 23042D121976CA1D00621B2C /* PlatformKalimba.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23042D101976CA0A00621B2C /* PlatformKalimba.cpp */; }; 23059A0719532B96007B8189 /* LinuxSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23059A0519532B96007B8189 /* LinuxSignals.cpp */; }; 23059A101958B319007B8189 /* SBUnixSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23059A0F1958B319007B8189 /* SBUnixSignals.cpp */; }; 23059A121958B3B2007B8189 /* SBUnixSignals.h in Headers */ = {isa = PBXBuildFile; fileRef = 23059A111958B37B007B8189 /* SBUnixSignals.h */; settings = {ATTRIBUTES = (Public, ); }; }; 230EC45B1D63C3BA008DF59F /* ThreadPlanCallOnFunctionExit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 230EC4581D63C3A7008DF59F /* ThreadPlanCallOnFunctionExit.cpp */; }; 232CB615191E00CD00EF39FC /* NativeBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB60B191E00CC00EF39FC /* NativeBreakpoint.cpp */; }; 232CB617191E00CD00EF39FC /* NativeBreakpointList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB60D191E00CC00EF39FC /* NativeBreakpointList.cpp */; }; 232CB619191E00CD00EF39FC /* NativeProcessProtocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB60F191E00CC00EF39FC /* NativeProcessProtocol.cpp */; }; 232CB61B191E00CD00EF39FC /* NativeThreadProtocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB611191E00CC00EF39FC /* NativeThreadProtocol.cpp */; }; 232CB61D191E00CD00EF39FC /* SoftwareBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB613191E00CC00EF39FC /* SoftwareBreakpoint.cpp */; }; 233B007D1960C9F90090E598 /* ProcessInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 233B007B1960C9E60090E598 /* ProcessInfo.cpp */; }; 233B007F1960CB280090E598 /* ProcessLaunchInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 233B007E1960CB280090E598 /* ProcessLaunchInfo.cpp */; }; 236124A41986B4E2004EFC37 /* IOObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 236124A21986B4E2004EFC37 /* IOObject.cpp */; }; 236124A51986B4E2004EFC37 /* Socket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 236124A31986B4E2004EFC37 /* Socket.cpp */; }; 2374D7531D4BB2FF005C9575 /* GDBRemoteClientBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2374D74E1D4BB299005C9575 /* GDBRemoteClientBase.cpp */; }; 2377C2F819E613C100737875 /* PipePosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2377C2F719E613C100737875 /* PipePosix.cpp */; }; 237A8BAF1DEC9C7800CEBAFF /* RegisterInfoPOSIX_arm64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 237A8BAB1DEC9BBC00CEBAFF /* RegisterInfoPOSIX_arm64.cpp */; }; 238F2B9E1D2C82D0001FF92A /* StructuredDataPlugin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 238F2B9D1D2C82D0001FF92A /* StructuredDataPlugin.cpp */; }; 238F2BA11D2C835A001FF92A /* StructuredDataPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 238F2B9F1D2C835A001FF92A /* StructuredDataPlugin.h */; }; 238F2BA21D2C835A001FF92A /* SystemRuntime.h in Headers */ = {isa = PBXBuildFile; fileRef = 238F2BA01D2C835A001FF92A /* SystemRuntime.h */; }; 238F2BA81D2C85FA001FF92A /* StructuredDataDarwinLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 238F2BA61D2C85FA001FF92A /* StructuredDataDarwinLog.cpp */; }; 238F2BA91D2C85FA001FF92A /* StructuredDataDarwinLog.h in Headers */ = {isa = PBXBuildFile; fileRef = 238F2BA71D2C85FA001FF92A /* StructuredDataDarwinLog.h */; }; 239481861C59EBDD00DF7168 /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 239481851C59EBDD00DF7168 /* libncurses.dylib */; }; 23CB15331D66DA9300EDDDE1 /* GoParserTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEC6FF9F1BE970A2007882C1 /* GoParserTest.cpp */; }; 23CB15341D66DA9300EDDDE1 /* CPlusPlusLanguageTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23CB14FA1D66CCF100EDDDE1 /* CPlusPlusLanguageTest.cpp */; }; 23CB15351D66DA9300EDDDE1 /* UriParserTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2321F9461BDD346100BA9A93 /* UriParserTest.cpp */; }; 23CB15361D66DA9300EDDDE1 /* FileSpecTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23CB14FD1D66CD2400EDDDE1 /* FileSpecTest.cpp */; }; 23CB15371D66DA9300EDDDE1 /* PythonTestSuite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF45E1FC1BF57C8D000563EB /* PythonTestSuite.cpp */; }; 23CB15381D66DA9300EDDDE1 /* PythonExceptionStateTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FA093141BF65D3A0037DD08 /* PythonExceptionStateTests.cpp */; }; 23CB15391D66DA9300EDDDE1 /* DataExtractorTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23CB14E81D66CC0E00EDDDE1 /* DataExtractorTest.cpp */; }; 23CB153A1D66DA9300EDDDE1 /* GDBRemoteClientBaseTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2370A37D1D66C587000E7BE6 /* GDBRemoteClientBaseTest.cpp */; }; 23CB153B1D66DA9300EDDDE1 /* SocketTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2321F93A1BDD332400BA9A93 /* SocketTest.cpp */; }; 23CB153C1D66DA9300EDDDE1 /* TestArgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2321F93E1BDD33CE00BA9A93 /* TestArgs.cpp */; }; 23CB153D1D66DA9300EDDDE1 /* GDBRemoteCommunicationClientTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2370A37E1D66C587000E7BE6 /* GDBRemoteCommunicationClientTest.cpp */; }; 23CB153E1D66DA9300EDDDE1 /* PythonDataObjectsTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2321F94D1BDD360F00BA9A93 /* PythonDataObjectsTests.cpp */; }; 23CB153F1D66DA9300EDDDE1 /* SymbolsTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2321F93B1BDD332400BA9A93 /* SymbolsTest.cpp */; }; 23CB15401D66DA9300EDDDE1 /* TestClangASTContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23CB150C1D66CF5600EDDDE1 /* TestClangASTContext.cpp */; }; 23CB15411D66DA9300EDDDE1 /* StringExtractorTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2321F9441BDD346100BA9A93 /* StringExtractorTest.cpp */; }; 23CB15421D66DA9300EDDDE1 /* TaskPoolTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2321F9451BDD346100BA9A93 /* TaskPoolTest.cpp */; }; 23CB15431D66DA9300EDDDE1 /* BroadcasterTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23CB14E61D66CC0E00EDDDE1 /* BroadcasterTest.cpp */; }; 23CB15441D66DA9300EDDDE1 /* ScalarTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23CB14E91D66CC0E00EDDDE1 /* ScalarTest.cpp */; }; 23CB15451D66DA9300EDDDE1 /* SocketAddressTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2321F9391BDD332400BA9A93 /* SocketAddressTest.cpp */; }; 23CB15461D66DA9300EDDDE1 /* GDBRemoteTestUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2370A37F1D66C587000E7BE6 /* GDBRemoteTestUtils.cpp */; }; 23CB15471D66DA9300EDDDE1 /* EditlineTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2326CF511BDD693B00A5CEAC /* EditlineTest.cpp */; }; 23CB15491D66DA9300EDDDE1 /* libxml2.2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 23CB14E31D66CA2200EDDDE1 /* libxml2.2.dylib */; }; 23CB154A1D66DA9300EDDDE1 /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2326CF4E1BDD687800A5CEAC /* libpanel.dylib */; }; 23CB154B1D66DA9300EDDDE1 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2326CF4C1BDD684B00A5CEAC /* libedit.dylib */; }; 23CB154C1D66DA9300EDDDE1 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2326CF4A1BDD681800A5CEAC /* libz.dylib */; }; 23CB154D1D66DA9300EDDDE1 /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2326CF471BDD67C100A5CEAC /* libncurses.dylib */; }; 23CB154E1D66DA9300EDDDE1 /* liblldb-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2689FFCA13353D7A00698AC0 /* liblldb-core.a */; }; 23D0658F1D4A7BEE0008EDE6 /* RenderScriptExpressionOpts.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23D065821D4A7BDA0008EDE6 /* RenderScriptExpressionOpts.cpp */; }; 23D065901D4A7BEE0008EDE6 /* RenderScriptRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23D065841D4A7BDA0008EDE6 /* RenderScriptRuntime.cpp */; }; 23D065911D4A7BEE0008EDE6 /* RenderScriptx86ABIFixups.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23D065861D4A7BDA0008EDE6 /* RenderScriptx86ABIFixups.cpp */; }; 23D4007D1C2101F2000C3885 /* DWARFDebugMacro.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23E77CD61C20F29F007192AD /* DWARFDebugMacro.cpp */; }; 23D4007E1C210201000C3885 /* DebugMacros.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23E77CDB1C20F2F2007192AD /* DebugMacros.cpp */; }; 23DCBEA21D63E7190084C36B /* SBStructuredData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23DCBEA01D63E6440084C36B /* SBStructuredData.cpp */; }; 23DCBEA31D63E71F0084C36B /* SBStructuredData.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DCBE9F1D63E3800084C36B /* SBStructuredData.h */; settings = {ATTRIBUTES = (Public, ); }; }; 23DCEA461D1C4D0F00A602B4 /* SBMemoryRegionInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23DCEA421D1C4C6900A602B4 /* SBMemoryRegionInfo.cpp */; }; 23DCEA471D1C4D0F00A602B4 /* SBMemoryRegionInfoList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23DCEA431D1C4C6900A602B4 /* SBMemoryRegionInfoList.cpp */; }; 23DDF226196C3EE600BB8417 /* CommandOptionValidators.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23DDF224196C3EE600BB8417 /* CommandOptionValidators.cpp */; }; 23E2E5251D90373D006F38BB /* ArchSpecTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23E2E5161D903689006F38BB /* ArchSpecTest.cpp */; }; 23E2E5271D903782006F38BB /* MinidumpParserTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23E2E51A1D9036F2006F38BB /* MinidumpParserTest.cpp */; }; 23E2E5321D903832006F38BB /* BreakpointIDTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23E2E52D1D90382B006F38BB /* BreakpointIDTest.cpp */; }; 23E2E5441D904913006F38BB /* MinidumpParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23E2E5371D9048FB006F38BB /* MinidumpParser.cpp */; }; 23E2E5451D904913006F38BB /* MinidumpTypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23E2E5391D9048FB006F38BB /* MinidumpTypes.cpp */; }; 23EFE389193D1ABC00E54E54 /* SBTypeEnumMember.h in Headers */ = {isa = PBXBuildFile; fileRef = 23EFE388193D1ABC00E54E54 /* SBTypeEnumMember.h */; settings = {ATTRIBUTES = (Public, ); }; }; 23EFE38B193D1AEC00E54E54 /* SBTypeEnumMember.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23EFE38A193D1AEC00E54E54 /* SBTypeEnumMember.cpp */; }; 23F4034D1926E0F60046DC9B /* NativeRegisterContextRegisterInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23F403481926CC250046DC9B /* NativeRegisterContextRegisterInfo.cpp */; }; 250D6AE31A9679440049CC70 /* FileSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 250D6AE11A9679270049CC70 /* FileSystem.cpp */; }; 25420ECD1A6490B8009ADBCB /* OptionValueChar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25420ECC1A6490B8009ADBCB /* OptionValueChar.cpp */; }; 25420ED21A649D88009ADBCB /* PipeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25420ED11A649D88009ADBCB /* PipeBase.cpp */; }; 254FBB951A81AA7F00BD6378 /* SBLaunchInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 254FBB941A81AA7F00BD6378 /* SBLaunchInfo.cpp */; }; 254FBB971A81B03100BD6378 /* SBLaunchInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 254FBB961A81B03100BD6378 /* SBLaunchInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; 254FBBA31A9166F100BD6378 /* SBAttachInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 254FBBA21A9166F100BD6378 /* SBAttachInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; 254FBBA51A91670E00BD6378 /* SBAttachInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 254FBBA41A91670E00BD6378 /* SBAttachInfo.cpp */; }; 255EFF741AFABA720069F277 /* LockFileBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255EFF731AFABA720069F277 /* LockFileBase.cpp */; }; 255EFF761AFABA950069F277 /* LockFilePosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255EFF751AFABA950069F277 /* LockFilePosix.cpp */; }; 256CBDB41ADD0EFD00BC6CDC /* RegisterContextPOSIXCore_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 256CBDB21ADD0EFD00BC6CDC /* RegisterContextPOSIXCore_arm.cpp */; }; 256CBDBC1ADD107200BC6CDC /* RegisterContextLinux_mips64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 256CBDB81ADD107200BC6CDC /* RegisterContextLinux_mips64.cpp */; }; 256CBDC01ADD11C000BC6CDC /* RegisterContextPOSIX_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 256CBDBE1ADD11C000BC6CDC /* RegisterContextPOSIX_arm.cpp */; }; 2579065C1BD0488100178368 /* TCPSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2579065A1BD0488100178368 /* TCPSocket.cpp */; }; 2579065D1BD0488100178368 /* UDPSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2579065B1BD0488100178368 /* UDPSocket.cpp */; }; 2579065F1BD0488D00178368 /* DomainSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2579065E1BD0488D00178368 /* DomainSocket.cpp */; }; 257906641BD5AFD000178368 /* Acceptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 257906621BD5AFD000178368 /* Acceptor.cpp */; }; 257906651BD5AFD000178368 /* Acceptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 257906631BD5AFD000178368 /* Acceptor.h */; }; 25EF23781AC09B3700908DF0 /* AdbClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25EF23751AC09AD800908DF0 /* AdbClient.cpp */; }; 260157C61885F51C00F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; }; 260157C81885F53100F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; }; 2606EDDF184E68A10034641B /* liblldb-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2689FFCA13353D7A00698AC0 /* liblldb-core.a */; }; 260A63171861008E00FECF8E /* IOHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 260A63161861008E00FECF8E /* IOHandler.h */; }; 260A63191861009E00FECF8E /* IOHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260A63181861009E00FECF8E /* IOHandler.cpp */; }; 260CC64815D0440D002BF2E0 /* OptionValueArgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260CC63B15D0440D002BF2E0 /* OptionValueArgs.cpp */; }; 260CC64915D0440D002BF2E0 /* OptionValueArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260CC63C15D0440D002BF2E0 /* OptionValueArray.cpp */; }; 260CC64A15D0440D002BF2E0 /* OptionValueBoolean.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260CC63D15D0440D002BF2E0 /* OptionValueBoolean.cpp */; }; 260CC64B15D0440D002BF2E0 /* OptionValueProperties.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260CC63E15D0440D002BF2E0 /* OptionValueProperties.cpp */; }; 260CC64C15D0440D002BF2E0 /* OptionValueDictionary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260CC63F15D0440D002BF2E0 /* OptionValueDictionary.cpp */; }; 260CC64D15D0440D002BF2E0 /* OptionValueEnumeration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260CC64015D0440D002BF2E0 /* OptionValueEnumeration.cpp */; }; 260CC64E15D0440D002BF2E0 /* OptionValueFileSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260CC64115D0440D002BF2E0 /* OptionValueFileSpec.cpp */; }; 260CC64F15D0440D002BF2E0 /* OptionValueFileSpecLIst.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260CC64215D0440D002BF2E0 /* OptionValueFileSpecLIst.cpp */; }; 260CC65015D0440D002BF2E0 /* OptionValueFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260CC64315D0440D002BF2E0 /* OptionValueFormat.cpp */; }; 260CC65115D0440D002BF2E0 /* OptionValueSInt64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260CC64415D0440D002BF2E0 /* OptionValueSInt64.cpp */; }; 260CC65215D0440D002BF2E0 /* OptionValueString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260CC64515D0440D002BF2E0 /* OptionValueString.cpp */; }; 260CC65315D0440D002BF2E0 /* OptionValueUInt64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260CC64615D0440D002BF2E0 /* OptionValueUInt64.cpp */; }; 260CC65415D0440D002BF2E0 /* OptionValueUUID.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260CC64715D0440D002BF2E0 /* OptionValueUUID.cpp */; }; 260E07C6136FA69E00CF21D3 /* OptionGroupUUID.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260E07C5136FA69E00CF21D3 /* OptionGroupUUID.cpp */; }; 260E07C8136FAB9200CF21D3 /* OptionGroupFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260E07C7136FAB9200CF21D3 /* OptionGroupFile.cpp */; }; 26151DC31B41E4A200FF7F1C /* SharingPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 261B5A5311C3F2AD00AABD0A /* SharingPtr.h */; settings = {ATTRIBUTES = (Public, ); }; }; 261744781168585B005ADD65 /* SBType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 261744771168585B005ADD65 /* SBType.cpp */; }; 2617447A11685869005ADD65 /* SBType.h in Headers */ = {isa = PBXBuildFile; fileRef = 2617447911685869005ADD65 /* SBType.h */; settings = {ATTRIBUTES = (Public, ); }; }; 262173A318395D4600C52091 /* SectionLoadHistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 262173A218395D4600C52091 /* SectionLoadHistory.cpp */; }; 26274FA714030F79006BA130 /* DynamicLoaderDarwinKernel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26274FA514030F79006BA130 /* DynamicLoaderDarwinKernel.cpp */; }; 2628A4D513D4977900F5487A /* ThreadKDP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2628A4D313D4977900F5487A /* ThreadKDP.cpp */; }; 262CFC7711A4510000946C6C /* debugserver in Resources */ = {isa = PBXBuildFile; fileRef = 26CE05A0115C31E50022F371 /* debugserver */; }; 262ED0081631FA3A00879631 /* OptionGroupString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 262ED0071631FA3A00879631 /* OptionGroupString.cpp */; }; 262F12B51835468600AEB384 /* SBPlatform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 262F12B41835468600AEB384 /* SBPlatform.cpp */; }; 262F12B71835469C00AEB384 /* SBPlatform.h in Headers */ = {isa = PBXBuildFile; fileRef = 262F12B61835469C00AEB384 /* SBPlatform.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2635879417822FC2004C30BA /* SymbolVendorELF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2635879017822E56004C30BA /* SymbolVendorELF.cpp */; }; 263641191B34AEE200145B2F /* ABISysV_mips64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263641151B34AEE200145B2F /* ABISysV_mips64.cpp */; }; 26368A3C126B697600E8659F /* darwin-debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26368A3B126B697600E8659F /* darwin-debug.cpp */; }; 26368AF7126B960500E8659F /* darwin-debug in Resources */ = {isa = PBXBuildFile; fileRef = 26579F68126A25920007C5CB /* darwin-debug */; }; 263C4938178B50C40070F12D /* SBModuleSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263C4937178B50C40070F12D /* SBModuleSpec.cpp */; }; 263C493A178B50CF0070F12D /* SBModuleSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = 263C4939178B50CF0070F12D /* SBModuleSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; 263E949F13661AEA00E7D1CE /* UnwindAssembly-x86.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263E949D13661AE400E7D1CE /* UnwindAssembly-x86.cpp */; }; 263FDE601A79A01500E68013 /* FormatEntity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263FDE5F1A79A01500E68013 /* FormatEntity.cpp */; }; 2640E19F15DC78FD00F23B50 /* Property.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2640E19E15DC78FD00F23B50 /* Property.cpp */; }; 264297571D1DF247003F2BF4 /* SBMemoryRegionInfoList.h in Headers */ = {isa = PBXBuildFile; fileRef = 264297541D1DF209003F2BF4 /* SBMemoryRegionInfoList.h */; settings = {ATTRIBUTES = (Public, ); }; }; 264297581D1DF250003F2BF4 /* SBMemoryRegionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 264297531D1DF209003F2BF4 /* SBMemoryRegionInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2642FBAE13D003B400ED6808 /* CommunicationKDP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2642FBA813D003B400ED6808 /* CommunicationKDP.cpp */; }; 2642FBB013D003B400ED6808 /* ProcessKDP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2642FBAA13D003B400ED6808 /* ProcessKDP.cpp */; }; 2642FBB213D003B400ED6808 /* ProcessKDPLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2642FBAC13D003B400ED6808 /* ProcessKDPLog.cpp */; }; 26474CA818D0CB070073DEBA /* RegisterContextFreeBSD_i386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26474CA218D0CB070073DEBA /* RegisterContextFreeBSD_i386.cpp */; }; 26474CAA18D0CB070073DEBA /* RegisterContextFreeBSD_mips64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26474CA418D0CB070073DEBA /* RegisterContextFreeBSD_mips64.cpp */; }; 26474CAC18D0CB070073DEBA /* RegisterContextFreeBSD_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26474CA618D0CB070073DEBA /* RegisterContextFreeBSD_x86_64.cpp */; }; 26474CB218D0CB180073DEBA /* RegisterContextLinux_i386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26474CAE18D0CB180073DEBA /* RegisterContextLinux_i386.cpp */; }; 26474CB418D0CB180073DEBA /* RegisterContextLinux_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26474CB018D0CB180073DEBA /* RegisterContextLinux_x86_64.cpp */; }; 26474CBC18D0CB2D0073DEBA /* RegisterContextMach_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26474CB618D0CB2D0073DEBA /* RegisterContextMach_arm.cpp */; }; 26474CBE18D0CB2D0073DEBA /* RegisterContextMach_i386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26474CB818D0CB2D0073DEBA /* RegisterContextMach_i386.cpp */; }; 26474CC018D0CB2D0073DEBA /* RegisterContextMach_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26474CBA18D0CB2D0073DEBA /* RegisterContextMach_x86_64.cpp */; }; 26474CC918D0CB5B0073DEBA /* RegisterContextMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26474CC218D0CB5B0073DEBA /* RegisterContextMemory.cpp */; }; 26474CCB18D0CB5B0073DEBA /* RegisterContextPOSIX_mips64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26474CC418D0CB5B0073DEBA /* RegisterContextPOSIX_mips64.cpp */; }; 26474CCD18D0CB5B0073DEBA /* RegisterContextPOSIX_x86.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26474CC618D0CB5B0073DEBA /* RegisterContextPOSIX_x86.cpp */; }; 26491E3E15E1DB9F00CBFFC2 /* OptionValueRegex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26491E3D15E1DB9F00CBFFC2 /* OptionValueRegex.cpp */; }; 264A12FC1372522000875C42 /* EmulateInstructionARM64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264A12FA1372522000875C42 /* EmulateInstructionARM64.cpp */; }; 264A58EE1A7DBCAD00A6B1B0 /* OptionValueFormatEntity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264A58ED1A7DBCAD00A6B1B0 /* OptionValueFormatEntity.cpp */; }; 264A97BF133918BC0017F0BE /* PlatformRemoteGDBServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264A97BD133918BC0017F0BE /* PlatformRemoteGDBServer.cpp */; }; 264D8D5013661BD7003A368F /* UnwindAssembly.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264D8D4F13661BD7003A368F /* UnwindAssembly.cpp */; }; 265192C61BA8E905002F08F6 /* CompilerDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 265192C51BA8E905002F08F6 /* CompilerDecl.cpp */; }; 265205A813D3E3F700132FE2 /* RegisterContextKDP_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 265205A213D3E3F700132FE2 /* RegisterContextKDP_arm.cpp */; }; 265205AA13D3E3F700132FE2 /* RegisterContextKDP_i386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 265205A413D3E3F700132FE2 /* RegisterContextKDP_i386.cpp */; }; 265205AC13D3E3F700132FE2 /* RegisterContextKDP_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 265205A613D3E3F700132FE2 /* RegisterContextKDP_x86_64.cpp */; }; 2654A6801E54D59400DA1013 /* ModuleCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2654A67F1E54D59400DA1013 /* ModuleCache.cpp */; }; 2654A6831E54D5E200DA1013 /* RegisterNumber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2654A6821E54D5E200DA1013 /* RegisterNumber.cpp */; }; 2654A68D1E552D1500DA1013 /* PseudoTerminal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2654A68C1E552D1500DA1013 /* PseudoTerminal.cpp */; }; 2654A6901E552ED500DA1013 /* VASprintf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2654A68F1E552ED500DA1013 /* VASprintf.cpp */; }; 2656BBC31AE0739C00441749 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C32A10F3DFDD009D5894 /* libedit.dylib */; }; 2656BBC41AE073A800441749 /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2670F8111862B44A006B332C /* libncurses.dylib */; }; 2656BBC51AE073AD00441749 /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; }; 2656BBC61AE073B500441749 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 966C6B7818E6A56A0093F5EC /* libz.dylib */; }; 2657AFB71B86910100958979 /* CompilerDeclContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2657AFB61B86910100958979 /* CompilerDeclContext.cpp */; }; 2660AAB914622483003A9694 /* LLDBWrapPython.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A4EEB511682AAC007A372A /* LLDBWrapPython.cpp */; settings = {COMPILER_FLAGS = "-Dregister="; }; }; 26651A18133BF9E0005B64B7 /* Opcode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26651A17133BF9DF005B64B7 /* Opcode.cpp */; }; 2666ADC61B3CB675001FAFD3 /* DynamicLoaderHexagonDYLD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2666ADC11B3CB675001FAFD3 /* DynamicLoaderHexagonDYLD.cpp */; }; 2666ADC81B3CB675001FAFD3 /* HexagonDYLDRendezvous.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2666ADC31B3CB675001FAFD3 /* HexagonDYLDRendezvous.cpp */; }; 2668020E115FD12C008E1FE4 /* lldb-defines.h in Headers */ = {isa = PBXBuildFile; fileRef = 26BC7C2510F1B3BC00F91463 /* lldb-defines.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2668020F115FD12C008E1FE4 /* lldb-enumerations.h in Headers */ = {isa = PBXBuildFile; fileRef = 26BC7C2610F1B3BC00F91463 /* lldb-enumerations.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26680214115FD12C008E1FE4 /* lldb-types.h in Headers */ = {isa = PBXBuildFile; fileRef = 26BC7C2910F1B3BC00F91463 /* lldb-types.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26680219115FD13D008E1FE4 /* SBBreakpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 9AF16A9E11402D69007A7B3F /* SBBreakpoint.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2668021A115FD13D008E1FE4 /* SBBreakpointLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 9AF16CC611408686007A7B3F /* SBBreakpointLocation.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2668021B115FD13D008E1FE4 /* SBBroadcaster.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A9830F31125FC5800A56CB0 /* SBBroadcaster.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2668021D115FD13D008E1FE4 /* SBCommandInterpreter.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A9830F71125FC5800A56CB0 /* SBCommandInterpreter.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2668021E115FD13D008E1FE4 /* SBCommandReturnObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A9830F91125FC5800A56CB0 /* SBCommandReturnObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2668021F115FD13D008E1FE4 /* SBCommunication.h in Headers */ = {isa = PBXBuildFile; fileRef = 260223E7115F06D500A601A2 /* SBCommunication.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26680220115FD13D008E1FE4 /* SBDebugger.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A9830FB1125FC5800A56CB0 /* SBDebugger.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26680221115FD13D008E1FE4 /* SBDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A9830FC1125FC5800A56CB0 /* SBDefines.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26680222115FD13D008E1FE4 /* SBError.h in Headers */ = {isa = PBXBuildFile; fileRef = 2682F286115EF3BD00CCFF99 /* SBError.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26680223115FD13D008E1FE4 /* SBEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A9830FE1125FC5800A56CB0 /* SBEvent.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26680224115FD13D008E1FE4 /* SBFileSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = 26022531115F27FA00A601A2 /* SBFileSpec.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26680225115FD13D008E1FE4 /* SBFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A633FE8112DCE3C001A7E43 /* SBFrame.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26680227115FD13D008E1FE4 /* SBListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A9831021125FC5800A56CB0 /* SBListener.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2668022A115FD13D008E1FE4 /* SBProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A9831041125FC5800A56CB0 /* SBProcess.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2668022B115FD13D008E1FE4 /* SBSourceManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A9831061125FC5800A56CB0 /* SBSourceManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2668022C115FD13D008E1FE4 /* SBTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A9831081125FC5800A56CB0 /* SBTarget.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2668022E115FD13D008E1FE4 /* SBThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A98310A1125FC5800A56CB0 /* SBThread.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2668022F115FD19D008E1FE4 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C39010F3FA26009D5894 /* CoreFoundation.framework */; }; 26680233115FD1A7008E1FE4 /* libobjc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C37410F3F61B009D5894 /* libobjc.dylib */; }; 26680324116005D9008E1FE4 /* SBThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A9831091125FC5800A56CB0 /* SBThread.cpp */; }; 26680326116005DB008E1FE4 /* SBTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A9831071125FC5800A56CB0 /* SBTarget.cpp */; }; 26680327116005DC008E1FE4 /* SBSourceManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A9831051125FC5800A56CB0 /* SBSourceManager.cpp */; }; 26680328116005DE008E1FE4 /* SBProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A9831031125FC5800A56CB0 /* SBProcess.cpp */; }; 2668032A116005E0008E1FE4 /* SBListener.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A9831011125FC5800A56CB0 /* SBListener.cpp */; }; 2668032C116005E2008E1FE4 /* SBFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A633FE7112DCE3C001A7E43 /* SBFrame.cpp */; }; 2668032D116005E3008E1FE4 /* SBFileSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26022532115F281400A601A2 /* SBFileSpec.cpp */; }; 2668032E116005E5008E1FE4 /* SBEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A9830FD1125FC5800A56CB0 /* SBEvent.cpp */; }; 2668032F116005E6008E1FE4 /* SBError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2682F284115EF3A700CCFF99 /* SBError.cpp */; }; 26680330116005E7008E1FE4 /* SBDebugger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A9830FA1125FC5800A56CB0 /* SBDebugger.cpp */; }; 26680331116005E9008E1FE4 /* SBCommunication.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260223E8115F06E500A601A2 /* SBCommunication.cpp */; }; 26680332116005EA008E1FE4 /* SBCommandReturnObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A9830F81125FC5800A56CB0 /* SBCommandReturnObject.cpp */; }; 26680333116005EC008E1FE4 /* SBCommandInterpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A9830F61125FC5800A56CB0 /* SBCommandInterpreter.cpp */; }; 26680335116005EE008E1FE4 /* SBBroadcaster.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A9830F21125FC5800A56CB0 /* SBBroadcaster.cpp */; }; 26680336116005EF008E1FE4 /* SBBreakpointLocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AF16CC7114086A1007A7B3F /* SBBreakpointLocation.cpp */; }; 26680337116005F1008E1FE4 /* SBBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AF16A9C11402D5B007A7B3F /* SBBreakpoint.cpp */; }; 2668035C11601108008E1FE4 /* LLDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26680207115FD0ED008E1FE4 /* LLDB.framework */; }; 266942001A6DC2AC0063BE93 /* MICmdArgContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941601A6DC2AB0063BE93 /* MICmdArgContext.cpp */; }; 266942011A6DC2AC0063BE93 /* MICmdArgSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941621A6DC2AB0063BE93 /* MICmdArgSet.cpp */; }; 266942021A6DC2AC0063BE93 /* MICmdArgValBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941641A6DC2AB0063BE93 /* MICmdArgValBase.cpp */; }; 266942031A6DC2AC0063BE93 /* MICmdArgValConsume.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941661A6DC2AB0063BE93 /* MICmdArgValConsume.cpp */; }; 266942041A6DC2AC0063BE93 /* MICmdArgValFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941681A6DC2AB0063BE93 /* MICmdArgValFile.cpp */; }; 266942051A6DC2AC0063BE93 /* MICmdArgValListBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2669416A1A6DC2AC0063BE93 /* MICmdArgValListBase.cpp */; }; 266942061A6DC2AC0063BE93 /* MICmdArgValListOfN.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2669416C1A6DC2AC0063BE93 /* MICmdArgValListOfN.cpp */; }; 266942071A6DC2AC0063BE93 /* MICmdArgValNumber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2669416E1A6DC2AC0063BE93 /* MICmdArgValNumber.cpp */; }; 266942081A6DC2AC0063BE93 /* MICmdArgValOptionLong.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941701A6DC2AC0063BE93 /* MICmdArgValOptionLong.cpp */; }; 266942091A6DC2AC0063BE93 /* MICmdArgValOptionShort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941721A6DC2AC0063BE93 /* MICmdArgValOptionShort.cpp */; }; 2669420A1A6DC2AC0063BE93 /* MICmdArgValString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941741A6DC2AC0063BE93 /* MICmdArgValString.cpp */; }; 2669420B1A6DC2AC0063BE93 /* MICmdArgValThreadGrp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941761A6DC2AC0063BE93 /* MICmdArgValThreadGrp.cpp */; }; 2669420C1A6DC2AC0063BE93 /* MICmdBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941781A6DC2AC0063BE93 /* MICmdBase.cpp */; }; 2669420D1A6DC2AC0063BE93 /* MICmdCmd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2669417A1A6DC2AC0063BE93 /* MICmdCmd.cpp */; }; 2669420E1A6DC2AC0063BE93 /* MICmdCmdBreak.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2669417C1A6DC2AC0063BE93 /* MICmdCmdBreak.cpp */; }; 2669420F1A6DC2AC0063BE93 /* MICmdCmdData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2669417E1A6DC2AC0063BE93 /* MICmdCmdData.cpp */; }; 266942101A6DC2AC0063BE93 /* MICmdCmdEnviro.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941801A6DC2AC0063BE93 /* MICmdCmdEnviro.cpp */; }; 266942111A6DC2AC0063BE93 /* MICmdCmdExec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941821A6DC2AC0063BE93 /* MICmdCmdExec.cpp */; }; 266942121A6DC2AC0063BE93 /* MICmdCmdFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941841A6DC2AC0063BE93 /* MICmdCmdFile.cpp */; }; 266942131A6DC2AC0063BE93 /* MICmdCmdGdbInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941861A6DC2AC0063BE93 /* MICmdCmdGdbInfo.cpp */; }; 266942141A6DC2AC0063BE93 /* MICmdCmdGdbSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941881A6DC2AC0063BE93 /* MICmdCmdGdbSet.cpp */; }; 266942151A6DC2AC0063BE93 /* MICmdCmdGdbThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2669418A1A6DC2AC0063BE93 /* MICmdCmdGdbThread.cpp */; }; 266942161A6DC2AC0063BE93 /* MICmdCmdMiscellanous.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2669418C1A6DC2AC0063BE93 /* MICmdCmdMiscellanous.cpp */; }; 266942171A6DC2AC0063BE93 /* MICmdCmdStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2669418E1A6DC2AC0063BE93 /* MICmdCmdStack.cpp */; }; 266942181A6DC2AC0063BE93 /* MICmdCmdSupportInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941901A6DC2AC0063BE93 /* MICmdCmdSupportInfo.cpp */; }; 266942191A6DC2AC0063BE93 /* MICmdCmdSupportList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941921A6DC2AC0063BE93 /* MICmdCmdSupportList.cpp */; }; 2669421A1A6DC2AC0063BE93 /* MICmdCmdTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941941A6DC2AC0063BE93 /* MICmdCmdTarget.cpp */; }; 2669421B1A6DC2AC0063BE93 /* MICmdCmdThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941961A6DC2AC0063BE93 /* MICmdCmdThread.cpp */; }; 2669421C1A6DC2AC0063BE93 /* MICmdCmdTrace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941981A6DC2AC0063BE93 /* MICmdCmdTrace.cpp */; }; 2669421D1A6DC2AC0063BE93 /* MICmdCmdVar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2669419A1A6DC2AC0063BE93 /* MICmdCmdVar.cpp */; }; 2669421E1A6DC2AC0063BE93 /* MICmdCommands.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2669419C1A6DC2AC0063BE93 /* MICmdCommands.cpp */; }; 2669421F1A6DC2AC0063BE93 /* MICmdData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2669419E1A6DC2AC0063BE93 /* MICmdData.cpp */; }; 266942201A6DC2AC0063BE93 /* MICmdFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941A01A6DC2AC0063BE93 /* MICmdFactory.cpp */; }; 266942211A6DC2AC0063BE93 /* MICmdInterpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941A21A6DC2AC0063BE93 /* MICmdInterpreter.cpp */; }; 266942221A6DC2AC0063BE93 /* MICmdInvoker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941A41A6DC2AC0063BE93 /* MICmdInvoker.cpp */; }; 266942231A6DC2AC0063BE93 /* MICmdMgr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941A61A6DC2AC0063BE93 /* MICmdMgr.cpp */; }; 266942241A6DC2AC0063BE93 /* MICmdMgrSetCmdDeleteCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941A81A6DC2AC0063BE93 /* MICmdMgrSetCmdDeleteCallback.cpp */; }; 266942251A6DC2AC0063BE93 /* MICmnBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941AA1A6DC2AC0063BE93 /* MICmnBase.cpp */; }; 266942261A6DC2AC0063BE93 /* MICmnLLDBBroadcaster.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941AD1A6DC2AC0063BE93 /* MICmnLLDBBroadcaster.cpp */; }; 266942271A6DC2AC0063BE93 /* MICmnLLDBDebugger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941AF1A6DC2AC0063BE93 /* MICmnLLDBDebugger.cpp */; }; 266942281A6DC2AC0063BE93 /* MICmnLLDBDebuggerHandleEvents.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941B11A6DC2AC0063BE93 /* MICmnLLDBDebuggerHandleEvents.cpp */; }; 266942291A6DC2AC0063BE93 /* MICmnLLDBDebugSessionInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941B31A6DC2AC0063BE93 /* MICmnLLDBDebugSessionInfo.cpp */; }; 2669422A1A6DC2AC0063BE93 /* MICmnLLDBDebugSessionInfoVarObj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941B51A6DC2AC0063BE93 /* MICmnLLDBDebugSessionInfoVarObj.cpp */; }; 2669422B1A6DC2AC0063BE93 /* MICmnLLDBProxySBValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941B71A6DC2AC0063BE93 /* MICmnLLDBProxySBValue.cpp */; }; 2669422C1A6DC2AC0063BE93 /* MICmnLLDBUtilSBValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941B91A6DC2AC0063BE93 /* MICmnLLDBUtilSBValue.cpp */; }; 2669422D1A6DC2AC0063BE93 /* MICmnLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941BB1A6DC2AC0063BE93 /* MICmnLog.cpp */; }; 2669422E1A6DC2AC0063BE93 /* MICmnLogMediumFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941BD1A6DC2AC0063BE93 /* MICmnLogMediumFile.cpp */; }; 2669422F1A6DC2AC0063BE93 /* MICmnMIOutOfBandRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941BF1A6DC2AC0063BE93 /* MICmnMIOutOfBandRecord.cpp */; }; 266942301A6DC2AC0063BE93 /* MICmnMIResultRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941C11A6DC2AC0063BE93 /* MICmnMIResultRecord.cpp */; }; 266942311A6DC2AC0063BE93 /* MICmnMIValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941C31A6DC2AC0063BE93 /* MICmnMIValue.cpp */; }; 266942321A6DC2AC0063BE93 /* MICmnMIValueConst.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941C51A6DC2AC0063BE93 /* MICmnMIValueConst.cpp */; }; 266942331A6DC2AC0063BE93 /* MICmnMIValueList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941C71A6DC2AC0063BE93 /* MICmnMIValueList.cpp */; }; 266942341A6DC2AC0063BE93 /* MICmnMIValueResult.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941C91A6DC2AC0063BE93 /* MICmnMIValueResult.cpp */; }; 266942351A6DC2AC0063BE93 /* MICmnMIValueTuple.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941CB1A6DC2AC0063BE93 /* MICmnMIValueTuple.cpp */; }; 266942361A6DC2AC0063BE93 /* MICmnResources.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941CD1A6DC2AC0063BE93 /* MICmnResources.cpp */; }; 266942371A6DC2AC0063BE93 /* MICmnStreamStderr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941CF1A6DC2AC0063BE93 /* MICmnStreamStderr.cpp */; }; 266942381A6DC2AC0063BE93 /* MICmnStreamStdin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941D11A6DC2AC0063BE93 /* MICmnStreamStdin.cpp */; }; 2669423B1A6DC2AC0063BE93 /* MICmnStreamStdout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941D71A6DC2AC0063BE93 /* MICmnStreamStdout.cpp */; }; 2669423C1A6DC2AC0063BE93 /* MICmnThreadMgrStd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941D91A6DC2AC0063BE93 /* MICmnThreadMgrStd.cpp */; }; 2669423D1A6DC2AC0063BE93 /* MIDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941DC1A6DC2AC0063BE93 /* MIDriver.cpp */; }; 2669423E1A6DC2AC0063BE93 /* MIDriverBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941DE1A6DC2AC0063BE93 /* MIDriverBase.cpp */; }; 2669423F1A6DC2AC0063BE93 /* MIDriverMain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941E01A6DC2AC0063BE93 /* MIDriverMain.cpp */; }; 266942401A6DC2AC0063BE93 /* MIDriverMgr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941E11A6DC2AC0063BE93 /* MIDriverMgr.cpp */; }; 266942411A6DC2AC0063BE93 /* MIUtilDateTimeStd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941E41A6DC2AC0063BE93 /* MIUtilDateTimeStd.cpp */; }; 266942421A6DC2AC0063BE93 /* MIUtilDebug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941E61A6DC2AC0063BE93 /* MIUtilDebug.cpp */; }; 266942431A6DC2AC0063BE93 /* MIUtilFileStd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941E81A6DC2AC0063BE93 /* MIUtilFileStd.cpp */; }; 266942441A6DC2AC0063BE93 /* MIUtilMapIdToVariant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941EA1A6DC2AC0063BE93 /* MIUtilMapIdToVariant.cpp */; }; 266942451A6DC2AC0063BE93 /* MIUtilString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941EE1A6DC2AC0063BE93 /* MIUtilString.cpp */; }; 2669424A1A6DC2AC0063BE93 /* MIUtilThreadBaseStd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941F81A6DC2AC0063BE93 /* MIUtilThreadBaseStd.cpp */; }; 2669424B1A6DC2AC0063BE93 /* MIUtilVariant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941FA1A6DC2AC0063BE93 /* MIUtilVariant.cpp */; }; 2669424D1A6DC32B0063BE93 /* LLDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26680207115FD0ED008E1FE4 /* LLDB.framework */; }; 266DFE9713FD656E00D0C574 /* OperatingSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266DFE9613FD656E00D0C574 /* OperatingSystem.cpp */; }; 266E82971B8CE3AC008FCA06 /* DWARFDIE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266E82961B8CE3AC008FCA06 /* DWARFDIE.cpp */; }; 266E829D1B8E542C008FCA06 /* DWARFAttribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266E829C1B8E542C008FCA06 /* DWARFAttribute.cpp */; }; 2670F8121862B44A006B332C /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2670F8111862B44A006B332C /* libncurses.dylib */; }; 26744EF11338317700EF765A /* GDBRemoteCommunicationClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26744EED1338317700EF765A /* GDBRemoteCommunicationClient.cpp */; }; 26744EF31338317700EF765A /* GDBRemoteCommunicationServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26744EEF1338317700EF765A /* GDBRemoteCommunicationServer.cpp */; }; 26764C971E48F482008D3573 /* ConstString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26764C961E48F482008D3573 /* ConstString.cpp */; }; 26764C9E1E48F51E008D3573 /* Stream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26764C9D1E48F51E008D3573 /* Stream.cpp */; }; 26764CA01E48F528008D3573 /* RegularExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26764C9F1E48F528008D3573 /* RegularExpression.cpp */; }; 26764CA21E48F547008D3573 /* StreamString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26764CA11E48F547008D3573 /* StreamString.cpp */; }; 26780C611867C33D00234593 /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2670F8111862B44A006B332C /* libncurses.dylib */; }; 267A47FB1B1411C40021A5BC /* NativeRegisterContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267A47FA1B1411C40021A5BC /* NativeRegisterContext.cpp */; }; 267A47FF1B1411D90021A5BC /* NativeWatchpointList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267A47FE1B1411D90021A5BC /* NativeWatchpointList.cpp */; }; 267A48011B1411E40021A5BC /* XML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267A48001B1411E40021A5BC /* XML.cpp */; }; 267C012B136880DF006E963E /* OptionGroupValueObjectDisplay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267C012A136880DF006E963E /* OptionGroupValueObjectDisplay.cpp */; }; 267C01371368C49C006E963E /* OptionGroupOutputFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BCFC531368B3E4006DC050 /* OptionGroupOutputFile.cpp */; }; 267DFB461B06752A00000FB7 /* MICmdArgValPrintValues.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267DFB441B06752A00000FB7 /* MICmdArgValPrintValues.cpp */; }; 267F684A1CC02DED0086832B /* ABISysV_s390x.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267F68471CC02DED0086832B /* ABISysV_s390x.cpp */; }; 267F684B1CC02DED0086832B /* ABISysV_s390x.h in Headers */ = {isa = PBXBuildFile; fileRef = 267F68481CC02DED0086832B /* ABISysV_s390x.h */; }; 267F684F1CC02E270086832B /* RegisterContextPOSIXCore_s390x.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267F684D1CC02E270086832B /* RegisterContextPOSIXCore_s390x.cpp */; }; 267F68501CC02E270086832B /* RegisterContextPOSIXCore_s390x.h in Headers */ = {isa = PBXBuildFile; fileRef = 267F684E1CC02E270086832B /* RegisterContextPOSIXCore_s390x.h */; }; 267F68531CC02E920086832B /* RegisterContextLinux_s390x.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267F68511CC02E920086832B /* RegisterContextLinux_s390x.cpp */; }; 267F68541CC02E920086832B /* RegisterContextLinux_s390x.h in Headers */ = {isa = PBXBuildFile; fileRef = 267F68521CC02E920086832B /* RegisterContextLinux_s390x.h */; }; 267F68571CC02EAE0086832B /* RegisterContextPOSIX_s390x.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267F68551CC02EAE0086832B /* RegisterContextPOSIX_s390x.cpp */; }; 267F68581CC02EAE0086832B /* RegisterContextPOSIX_s390x.h in Headers */ = {isa = PBXBuildFile; fileRef = 267F68561CC02EAE0086832B /* RegisterContextPOSIX_s390x.h */; }; 267F685A1CC02EBE0086832B /* RegisterInfos_s390x.h in Headers */ = {isa = PBXBuildFile; fileRef = 267F68591CC02EBE0086832B /* RegisterInfos_s390x.h */; }; 268648C416531BF800F04704 /* com.apple.debugserver.posix.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 268648C116531BF800F04704 /* com.apple.debugserver.posix.plist */; }; 268648C516531BF800F04704 /* com.apple.debugserver.applist.internal.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 268648C216531BF800F04704 /* com.apple.debugserver.applist.internal.plist */; }; 268648C616531BF800F04704 /* com.apple.debugserver.internal.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 268648C316531BF800F04704 /* com.apple.debugserver.internal.plist */; }; 2686536C1370ACB200D186A3 /* OptionGroupBoolean.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2686536B1370ACB200D186A3 /* OptionGroupBoolean.cpp */; }; 268653701370AE7200D186A3 /* OptionGroupUInt64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2686536F1370AE7200D186A3 /* OptionGroupUInt64.cpp */; }; 2689000113353DB600698AC0 /* BreakpointResolverAddress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D0DD5310FE555900271C65 /* BreakpointResolverAddress.cpp */; }; 2689000313353DB600698AC0 /* BreakpointResolverFileLine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D0DD5410FE555900271C65 /* BreakpointResolverFileLine.cpp */; }; 2689000513353DB600698AC0 /* BreakpointResolverName.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D0DD5510FE555900271C65 /* BreakpointResolverName.cpp */; }; 2689000713353DB600698AC0 /* BreakpointSite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1310F1B83100F91463 /* BreakpointSite.cpp */; }; 2689000913353DB600698AC0 /* BreakpointSiteList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1410F1B83100F91463 /* BreakpointSiteList.cpp */; }; 2689000B13353DB600698AC0 /* Stoppoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1610F1B83100F91463 /* Stoppoint.cpp */; }; 2689000D13353DB600698AC0 /* StoppointCallbackContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E0910F1B83100F91463 /* StoppointCallbackContext.cpp */; }; 2689000F13353DB600698AC0 /* StoppointLocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1710F1B83100F91463 /* StoppointLocation.cpp */; }; 2689001113353DB600698AC0 /* Watchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1810F1B83100F91463 /* Watchpoint.cpp */; }; 2689001213353DDE00698AC0 /* CommandObjectApropos.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CA9637911B6E99A00780E28 /* CommandObjectApropos.cpp */; }; 2689001313353DDE00698AC0 /* CommandObjectArgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 499F381F11A5B3F300F5CE02 /* CommandObjectArgs.cpp */; }; 2689001413353DDE00698AC0 /* CommandObjectBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E2D10F1B84700F91463 /* CommandObjectBreakpoint.cpp */; }; 2689001513353DDE00698AC0 /* CommandObjectBreakpointCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A42976211861AA600FE05CD /* CommandObjectBreakpointCommand.cpp */; }; 2689001613353DDE00698AC0 /* CommandObjectCommands.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C5DBBC611E3FEC60035160F /* CommandObjectCommands.cpp */; }; 2689001713353DDE00698AC0 /* CommandObjectDisassemble.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E3010F1B84700F91463 /* CommandObjectDisassemble.cpp */; }; 2689001813353DDE00698AC0 /* CommandObjectExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E3110F1B84700F91463 /* CommandObjectExpression.cpp */; }; 2689001A13353DDE00698AC0 /* CommandObjectFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2672D8461189055500FF4019 /* CommandObjectFrame.cpp */; }; 2689001B13353DDE00698AC0 /* CommandObjectHelp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E3310F1B84700F91463 /* CommandObjectHelp.cpp */; }; 2689001D13353DDE00698AC0 /* CommandObjectLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264AD83711095BA600E0B039 /* CommandObjectLog.cpp */; }; 2689001E13353DDE00698AC0 /* CommandObjectMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E3610F1B84700F91463 /* CommandObjectMemory.cpp */; }; 2689001F13353DDE00698AC0 /* CommandObjectPlatform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26879CE71333F58B0012C1F8 /* CommandObjectPlatform.cpp */; }; 2689002013353DDE00698AC0 /* CommandObjectProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E3810F1B84700F91463 /* CommandObjectProcess.cpp */; }; 2689002113353DDE00698AC0 /* CommandObjectQuit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E3910F1B84700F91463 /* CommandObjectQuit.cpp */; }; 2689002213353DDE00698AC0 /* CommandObjectRegister.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E3B10F1B84700F91463 /* CommandObjectRegister.cpp */; }; 2689002313353DDE00698AC0 /* CommandObjectScript.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E3D10F1B84700F91463 /* CommandObjectScript.cpp */; }; 2689002413353DDE00698AC0 /* CommandObjectSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E4010F1B84700F91463 /* CommandObjectSettings.cpp */; }; 2689002513353DDE00698AC0 /* CommandObjectSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E4210F1B84700F91463 /* CommandObjectSource.cpp */; }; 2689002613353DDE00698AC0 /* CommandObjectSyntax.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E4510F1B84700F91463 /* CommandObjectSyntax.cpp */; }; 2689002713353DDE00698AC0 /* CommandObjectTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 269416AD119A024800FF2715 /* CommandObjectTarget.cpp */; }; 2689002813353DDE00698AC0 /* CommandObjectThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E4610F1B84700F91463 /* CommandObjectThread.cpp */; }; 2689002913353DDE00698AC0 /* CommandObjectVersion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B296983412C2FB2B002D92C3 /* CommandObjectVersion.cpp */; }; 2689002A13353E0400698AC0 /* Address.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E6910F1B85900F91463 /* Address.cpp */; }; 2689002B13353E0400698AC0 /* AddressRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E6A10F1B85900F91463 /* AddressRange.cpp */; }; 2689002C13353E0400698AC0 /* AddressResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC7034011752C6B0086C050 /* AddressResolver.cpp */; }; 2689002D13353E0400698AC0 /* AddressResolverFileLine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC7034211752C720086C050 /* AddressResolverFileLine.cpp */; }; 2689002E13353E0400698AC0 /* AddressResolverName.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC7034411752C790086C050 /* AddressResolverName.cpp */; }; 2689002F13353E0400698AC0 /* ArchSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E6B10F1B85900F91463 /* ArchSpec.cpp */; }; 2689003113353E0400698AC0 /* Broadcaster.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E6D10F1B85900F91463 /* Broadcaster.cpp */; }; 2689003213353E0400698AC0 /* Communication.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E6E10F1B85900F91463 /* Communication.cpp */; }; 2689003313353E0400698AC0 /* Connection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E6F10F1B85900F91463 /* Connection.cpp */; }; 2689003913353E0400698AC0 /* Debugger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263664921140A4930075843B /* Debugger.cpp */; }; 2689003A13353E0400698AC0 /* Disassembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E7610F1B85900F91463 /* Disassembler.cpp */; }; 2689003B13353E0400698AC0 /* EmulateInstruction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D9FDC812F784FD0003F2EE /* EmulateInstruction.cpp */; }; 2689003D13353E0400698AC0 /* Event.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E7910F1B85900F91463 /* Event.cpp */; }; 2689003E13353E0400698AC0 /* FileSpecList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E7B10F1B85900F91463 /* FileSpecList.cpp */; }; 2689004113353E0400698AC0 /* Listener.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E7E10F1B85900F91463 /* Listener.cpp */; }; 2689004213353E0400698AC0 /* Log.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E7F10F1B85900F91463 /* Log.cpp */; }; 2689004313353E0400698AC0 /* Mangled.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E8010F1B85900F91463 /* Mangled.cpp */; }; 2689004413353E0400698AC0 /* Module.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E8110F1B85900F91463 /* Module.cpp */; }; 2689004513353E0400698AC0 /* ModuleChild.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E8210F1B85900F91463 /* ModuleChild.cpp */; }; 2689004613353E0400698AC0 /* ModuleList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E8310F1B85900F91463 /* ModuleList.cpp */; }; 2689004713353E0400698AC0 /* PluginManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E8A10F1B85900F91463 /* PluginManager.cpp */; }; 2689004913353E0400698AC0 /* Scalar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E8D10F1B85900F91463 /* Scalar.cpp */; }; 2689004A13353E0400698AC0 /* SearchFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1510F1B83100F91463 /* SearchFilter.cpp */; }; 2689004B13353E0400698AC0 /* Section.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E8E10F1B85900F91463 /* Section.cpp */; }; 2689004C13353E0400698AC0 /* SourceManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E8F10F1B85900F91463 /* SourceManager.cpp */; }; 2689004D13353E0400698AC0 /* State.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E9010F1B85900F91463 /* State.cpp */; }; 2689004F13353E0400698AC0 /* StreamFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E9210F1B85900F91463 /* StreamFile.cpp */; }; 2689005113353E0400698AC0 /* StringList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A35765F116E76B900E8ED2F /* StringList.cpp */; }; 2689005213353E0400698AC0 /* Timer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E9610F1B85900F91463 /* Timer.cpp */; }; 2689005413353E0400698AC0 /* UserSettingsController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A4633DC11F65D9A00955CE1 /* UserSettingsController.cpp */; }; 2689005613353E0400698AC0 /* Value.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E9910F1B85900F91463 /* Value.cpp */; }; 2689005713353E0400698AC0 /* ValueObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E9A10F1B85900F91463 /* ValueObject.cpp */; }; 2689005813353E0400698AC0 /* ValueObjectChild.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E9B10F1B85900F91463 /* ValueObjectChild.cpp */; }; 2689005913353E0400698AC0 /* ValueObjectConstResult.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26424E3C125986CB0016D82C /* ValueObjectConstResult.cpp */; }; 2689005A13353E0400698AC0 /* ValueObjectList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E9C10F1B85900F91463 /* ValueObjectList.cpp */; }; 2689005B13353E0400698AC0 /* ValueObjectRegister.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264334381110F63100CDB6C6 /* ValueObjectRegister.cpp */; }; 2689005C13353E0400698AC0 /* ValueObjectVariable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E9D10F1B85900F91463 /* ValueObjectVariable.cpp */; }; 2689005E13353E0E00698AC0 /* ClangASTSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49D7072811B5AD11001AD875 /* ClangASTSource.cpp */; }; 2689005F13353E0E00698AC0 /* ClangFunctionCaller.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C98D3DA118FB96F00E575D0 /* ClangFunctionCaller.cpp */; }; 2689006013353E0E00698AC0 /* ClangExpressionDeclMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49F1A74511B3388F003ED505 /* ClangExpressionDeclMap.cpp */; }; 2689006113353E0E00698AC0 /* ClangExpressionParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49445C2512245E3600C11A81 /* ClangExpressionParser.cpp */; }; 2689006313353E0E00698AC0 /* ClangPersistentVariables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49D4FE871210B61C00CDB854 /* ClangPersistentVariables.cpp */; }; 2689006413353E0E00698AC0 /* ClangUserExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7ED510F1B86700F91463 /* ClangUserExpression.cpp */; }; 2689006513353E0E00698AC0 /* ClangUtilityFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 497C86BD122823D800B54702 /* ClangUtilityFunction.cpp */; }; 2689006613353E0E00698AC0 /* DWARFExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7ED810F1B86700F91463 /* DWARFExpression.cpp */; }; 2689006713353E0E00698AC0 /* ASTDumper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4906FD4012F2255300A2A77C /* ASTDumper.cpp */; }; 2689006813353E0E00698AC0 /* ASTResultSynthesizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49A8A39F11D568A300AD3B68 /* ASTResultSynthesizer.cpp */; }; 2689006913353E0E00698AC0 /* ASTStructExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 491193501226386000578B7F /* ASTStructExtractor.cpp */; }; 2689006A13353E0E00698AC0 /* IRDynamicChecks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49CF9829122C70BD007A0B96 /* IRDynamicChecks.cpp */; }; 2689006B13353E0E00698AC0 /* IRForTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49307AAD11DEA4D90081F992 /* IRForTarget.cpp */; }; 2689006D13353E0E00698AC0 /* IRExecutionUnit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C98D3DB118FB96F00E575D0 /* IRExecutionUnit.cpp */; }; 2689006E13353E1A00698AC0 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C6EA213011581005E16B0 /* File.cpp */; }; 2689006F13353E1A00698AC0 /* FileSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26FA43171301048600E71120 /* FileSpec.cpp */; }; 2689007113353E1A00698AC0 /* Host.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 69A01E1C1236C5D400C660B5 /* Host.cpp */; }; 2689007313353E1A00698AC0 /* Symbols.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 69A01E1F1236C5D400C660B5 /* Symbols.cpp */; }; 2689007413353E1A00698AC0 /* Terminal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 268DA873130095ED00C9483A /* Terminal.cpp */; }; 2689007613353E1A00698AC0 /* CFCBundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7EED10F1B8AD00F91463 /* CFCBundle.cpp */; }; 2689007713353E1A00698AC0 /* CFCData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7EEF10F1B8AD00F91463 /* CFCData.cpp */; }; 2689007813353E1A00698AC0 /* CFCMutableArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7EF110F1B8AD00F91463 /* CFCMutableArray.cpp */; }; 2689007913353E1A00698AC0 /* CFCMutableDictionary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7EF310F1B8AD00F91463 /* CFCMutableDictionary.cpp */; }; 2689007A13353E1A00698AC0 /* CFCMutableSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7EF510F1B8AD00F91463 /* CFCMutableSet.cpp */; }; 2689007B13353E1A00698AC0 /* CFCString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7EF810F1B8AD00F91463 /* CFCString.cpp */; }; 2689007C13353E1A00698AC0 /* Symbols.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2689B0B5113EE47E00A4AEDB /* Symbols.cpp */; }; 2689007D13353E2200698AC0 /* Args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E6C10F1B85900F91463 /* Args.cpp */; }; 2689007F13353E2200698AC0 /* CommandCompletions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C09CB74116BD98B00C7A725 /* CommandCompletions.cpp */; }; 2689008013353E2200698AC0 /* CommandInterpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F0810F1B8DD00F91463 /* CommandInterpreter.cpp */; }; 2689008113353E2200698AC0 /* CommandObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F0910F1B8DD00F91463 /* CommandObject.cpp */; }; 2689008313353E2200698AC0 /* CommandObjectMultiword.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DFBC58113B48F300DD817F /* CommandObjectMultiword.cpp */; }; 2689008413353E2200698AC0 /* CommandObjectRegexCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DFBC59113B48F300DD817F /* CommandObjectRegexCommand.cpp */; }; 2689008513353E2200698AC0 /* CommandReturnObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F0A10F1B8DD00F91463 /* CommandReturnObject.cpp */; }; 2689008613353E2200698AC0 /* Options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E8610F1B85900F91463 /* Options.cpp */; }; 2689008713353E2200698AC0 /* ScriptInterpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A82010B10FFB49800182560 /* ScriptInterpreter.cpp */; }; 2689008D13353E4200698AC0 /* DynamicLoaderMacOSXDYLD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C897A10F57C5600BB2B04 /* DynamicLoaderMacOSXDYLD.cpp */; }; 2689008E13353E4200698AC0 /* DynamicLoaderStatic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 268A683D1321B53B000E3FB8 /* DynamicLoaderStatic.cpp */; }; 2689009613353E4200698AC0 /* ObjectContainerBSDArchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A3B4AC1181454800381BC2 /* ObjectContainerBSDArchive.cpp */; }; 2689009713353E4200698AC0 /* ObjectContainerUniversalMachO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C898010F57C5600BB2B04 /* ObjectContainerUniversalMachO.cpp */; }; 2689009813353E4200698AC0 /* ELFHeader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D27C9D11ED3A4E0024D721 /* ELFHeader.cpp */; }; 2689009913353E4200698AC0 /* ObjectFileELF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C898510F57C5600BB2B04 /* ObjectFileELF.cpp */; }; 2689009A13353E4200698AC0 /* ObjectFileMachO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C898810F57C5600BB2B04 /* ObjectFileMachO.cpp */; }; 2689009B13353E4200698AC0 /* PlatformMacOSX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C5577B132575AD008FD8FE /* PlatformMacOSX.cpp */; }; 2689009C13353E4200698AC0 /* PlatformRemoteiOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2675F6FE1332BE690067997B /* PlatformRemoteiOS.cpp */; }; 2689009D13353E4200698AC0 /* GDBRemoteCommunication.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2618EE5B1315B29C001D6D71 /* GDBRemoteCommunication.cpp */; }; 2689009E13353E4200698AC0 /* GDBRemoteRegisterContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2618EE5D1315B29C001D6D71 /* GDBRemoteRegisterContext.cpp */; }; 2689009F13353E4200698AC0 /* ProcessGDBRemote.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2618EE5F1315B29C001D6D71 /* ProcessGDBRemote.cpp */; }; 268900A013353E4200698AC0 /* ProcessGDBRemoteLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2618EE611315B29C001D6D71 /* ProcessGDBRemoteLog.cpp */; }; 268900A113353E4200698AC0 /* ThreadGDBRemote.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2618EE631315B29C001D6D71 /* ThreadGDBRemote.cpp */; }; 268900AF13353E5000698AC0 /* UnwindLLDB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF68D32F1255A110002FF25B /* UnwindLLDB.cpp */; }; 268900B013353E5000698AC0 /* RegisterContextLLDB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF68D2541255416E002FF25B /* RegisterContextLLDB.cpp */; }; 268900B413353E5000698AC0 /* RegisterContextMacOSXFrameBackchain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E3EEF711A994E800FBADB6 /* RegisterContextMacOSXFrameBackchain.cpp */; }; 268900B513353E5000698AC0 /* StopInfoMachException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2615DBC81208B5FC0021781D /* StopInfoMachException.cpp */; }; 268900B613353E5000698AC0 /* UnwindMacOSXFrameBackchain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E3EEE311A9901300FBADB6 /* UnwindMacOSXFrameBackchain.cpp */; }; 268900B713353E5F00698AC0 /* DWARFAbbreviationDeclaration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89B310F57C5600BB2B04 /* DWARFAbbreviationDeclaration.cpp */; }; 268900B813353E5F00698AC0 /* DWARFCompileUnit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89B710F57C5600BB2B04 /* DWARFCompileUnit.cpp */; }; 268900B913353E5F00698AC0 /* DWARFDebugAbbrev.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89B910F57C5600BB2B04 /* DWARFDebugAbbrev.cpp */; }; 268900BA13353E5F00698AC0 /* DWARFDebugAranges.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89BB10F57C5600BB2B04 /* DWARFDebugAranges.cpp */; }; 268900BB13353E5F00698AC0 /* DWARFDebugArangeSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89BD10F57C5600BB2B04 /* DWARFDebugArangeSet.cpp */; }; 268900BC13353E5F00698AC0 /* DWARFDebugInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89BF10F57C5600BB2B04 /* DWARFDebugInfo.cpp */; }; 268900BD13353E5F00698AC0 /* DWARFDebugInfoEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89C110F57C5600BB2B04 /* DWARFDebugInfoEntry.cpp */; }; 268900BE13353E5F00698AC0 /* DWARFDebugLine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89C310F57C5600BB2B04 /* DWARFDebugLine.cpp */; }; 268900BF13353E5F00698AC0 /* DWARFDebugMacinfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89C510F57C5600BB2B04 /* DWARFDebugMacinfo.cpp */; }; 268900C013353E5F00698AC0 /* DWARFDebugMacinfoEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89C710F57C5600BB2B04 /* DWARFDebugMacinfoEntry.cpp */; }; 268900C113353E5F00698AC0 /* DWARFDebugPubnames.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89C910F57C5600BB2B04 /* DWARFDebugPubnames.cpp */; }; 268900C213353E5F00698AC0 /* DWARFDebugPubnamesSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89CB10F57C5600BB2B04 /* DWARFDebugPubnamesSet.cpp */; }; 268900C313353E5F00698AC0 /* DWARFDebugRanges.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89CD10F57C5600BB2B04 /* DWARFDebugRanges.cpp */; }; 268900C413353E5F00698AC0 /* DWARFDefines.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89CF10F57C5600BB2B04 /* DWARFDefines.cpp */; }; 268900C513353E5F00698AC0 /* DWARFDIECollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89D110F57C5600BB2B04 /* DWARFDIECollection.cpp */; }; 268900C613353E5F00698AC0 /* DWARFFormValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89D310F57C5600BB2B04 /* DWARFFormValue.cpp */; }; 268900C913353E5F00698AC0 /* NameToDIE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2618D9EA12406FE600F2B8FE /* NameToDIE.cpp */; }; 268900CA13353E5F00698AC0 /* SymbolFileDWARF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89D910F57C5600BB2B04 /* SymbolFileDWARF.cpp */; }; 268900CB13353E5F00698AC0 /* LogChannelDWARF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26109B3B1155D70100CC3529 /* LogChannelDWARF.cpp */; }; 268900CC13353E5F00698AC0 /* SymbolFileDWARFDebugMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89DB10F57C5600BB2B04 /* SymbolFileDWARFDebugMap.cpp */; }; 268900CD13353E5F00698AC0 /* UniqueDWARFASTType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26B8B42312EEC52A00A831B2 /* UniqueDWARFASTType.cpp */; }; 268900CE13353E5F00698AC0 /* SymbolFileSymtab.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89DE10F57C5600BB2B04 /* SymbolFileSymtab.cpp */; }; 268900CF13353E5F00698AC0 /* SymbolVendorMacOSX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89E210F57C5600BB2B04 /* SymbolVendorMacOSX.cpp */; }; 268900D013353E6F00698AC0 /* Block.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1310F1B8EC00F91463 /* Block.cpp */; }; 268900D113353E6F00698AC0 /* ClangASTContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1410F1B8EC00F91463 /* ClangASTContext.cpp */; }; 268900D213353E6F00698AC0 /* CompilerType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49E45FAD11F660FE008F7B28 /* CompilerType.cpp */; }; 268900D313353E6F00698AC0 /* ClangExternalASTSourceCallbacks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E69030129C6BEF00DDECD9 /* ClangExternalASTSourceCallbacks.cpp */; }; 268900D513353E6F00698AC0 /* CompileUnit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1510F1B8EC00F91463 /* CompileUnit.cpp */; }; 268900D613353E6F00698AC0 /* Declaration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1610F1B8EC00F91463 /* Declaration.cpp */; }; 268900D713353E6F00698AC0 /* DWARFCallFrameInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1710F1B8EC00F91463 /* DWARFCallFrameInfo.cpp */; }; 268900D813353E6F00698AC0 /* Function.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1810F1B8EC00F91463 /* Function.cpp */; }; 268900D913353E6F00698AC0 /* FuncUnwinders.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 961FABB81235DE1600F93A47 /* FuncUnwinders.cpp */; }; 268900DA13353E6F00698AC0 /* LineEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1910F1B8EC00F91463 /* LineEntry.cpp */; }; 268900DB13353E6F00698AC0 /* LineTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1A10F1B8EC00F91463 /* LineTable.cpp */; }; 268900DC13353E6F00698AC0 /* ObjectFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F4C10F1BC1A00F91463 /* ObjectFile.cpp */; }; 268900DD13353E6F00698AC0 /* Symbol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1B10F1B8EC00F91463 /* Symbol.cpp */; }; 268900DE13353E6F00698AC0 /* SymbolContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1C10F1B8EC00F91463 /* SymbolContext.cpp */; }; 268900DF13353E6F00698AC0 /* SymbolFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1D10F1B8EC00F91463 /* SymbolFile.cpp */; }; 268900E013353E6F00698AC0 /* SymbolVendor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF94005711C03F6500085DB9 /* SymbolVendor.cpp */; }; 268900E113353E6F00698AC0 /* Symtab.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1F10F1B8EC00F91463 /* Symtab.cpp */; }; 268900E213353E6F00698AC0 /* Type.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F2010F1B8EC00F91463 /* Type.cpp */; }; 268900E313353E6F00698AC0 /* TypeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F2110F1B8EC00F91463 /* TypeList.cpp */; }; 268900E413353E6F00698AC0 /* UnwindPlan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 961FABB91235DE1600F93A47 /* UnwindPlan.cpp */; }; 268900E513353E6F00698AC0 /* UnwindTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 961FABBA1235DE1600F93A47 /* UnwindTable.cpp */; }; 268900E613353E6F00698AC0 /* Variable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F2210F1B8EC00F91463 /* Variable.cpp */; }; 268900E713353E6F00698AC0 /* VariableList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F2310F1B8EC00F91463 /* VariableList.cpp */; }; 268900E813353E6F00698AC0 /* ABI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 497E7B9D1188F6690065CCA1 /* ABI.cpp */; }; 268900E913353E6F00698AC0 /* CPPLanguageRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CB443BC1249920C00C13DC2 /* CPPLanguageRuntime.cpp */; }; 268900EA13353E6F00698AC0 /* DynamicLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E7710F1B85900F91463 /* DynamicLoader.cpp */; }; 268900EB13353E6F00698AC0 /* ExecutionContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F3510F1B90C00F91463 /* ExecutionContext.cpp */; }; 268900EC13353E6F00698AC0 /* LanguageRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CB4430A12491DDA00C13DC2 /* LanguageRuntime.cpp */; }; 268900ED13353E6F00698AC0 /* ObjCLanguageRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CB443F212499B5000C13DC2 /* ObjCLanguageRuntime.cpp */; }; 268900EE13353E6F00698AC0 /* PathMappingList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 495BBACB119A0DBE00418BEA /* PathMappingList.cpp */; }; 268900EF13353E6F00698AC0 /* Platform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264A43BD1320BCEB005B4096 /* Platform.cpp */; }; 268900F013353E6F00698AC0 /* Process.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F3610F1B90C00F91463 /* Process.cpp */; }; 268900F113353E6F00698AC0 /* RegisterContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F3710F1B90C00F91463 /* RegisterContext.cpp */; }; 268900F213353E6F00698AC0 /* SectionLoadList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2618D7911240116900F2B8FE /* SectionLoadList.cpp */; }; 268900F313353E6F00698AC0 /* StackFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F3810F1B90C00F91463 /* StackFrame.cpp */; }; 268900F413353E6F00698AC0 /* StackFrameList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F3910F1B90C00F91463 /* StackFrameList.cpp */; }; 268900F513353E6F00698AC0 /* StackID.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F3A10F1B90C00F91463 /* StackID.cpp */; }; 268900F613353E6F00698AC0 /* StopInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2615DB861208A9E40021781D /* StopInfo.cpp */; }; 268900F713353E6F00698AC0 /* Target.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F3B10F1B90C00F91463 /* Target.cpp */; }; 268900F813353E6F00698AC0 /* TargetList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F3C10F1B90C00F91463 /* TargetList.cpp */; }; 268900F913353E6F00698AC0 /* Thread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F3D10F1B90C00F91463 /* Thread.cpp */; }; 268900FA13353E6F00698AC0 /* ThreadList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F3E10F1B90C00F91463 /* ThreadList.cpp */; }; 268900FB13353E6F00698AC0 /* ThreadPlan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F3F10F1B90C00F91463 /* ThreadPlan.cpp */; }; 268900FC13353E6F00698AC0 /* ThreadPlanBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C847110F50EFC00BB2B04 /* ThreadPlanBase.cpp */; }; 268900FD13353E6F00698AC0 /* ThreadPlanCallFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49EC3E98118F90AC00B1265E /* ThreadPlanCallFunction.cpp */; }; 268900FE13353E6F00698AC0 /* ThreadPlanCallUserExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C7CF7E51295E12B00B4FBB5 /* ThreadPlanCallUserExpression.cpp */; }; 268900FF13353E6F00698AC0 /* ThreadPlanShouldStopHere.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C43DEFA110641F300E55CBF /* ThreadPlanShouldStopHere.cpp */; }; 2689010013353E6F00698AC0 /* ThreadPlanStepInstruction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C847210F50EFC00BB2B04 /* ThreadPlanStepInstruction.cpp */; }; 2689010113353E6F00698AC0 /* ThreadPlanStepOut.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C847310F50EFC00BB2B04 /* ThreadPlanStepOut.cpp */; }; 2689010213353E6F00698AC0 /* ThreadPlanStepOverBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C847410F50EFC00BB2B04 /* ThreadPlanStepOverBreakpoint.cpp */; }; 2689010313353E6F00698AC0 /* ThreadPlanStepRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C847610F50EFC00BB2B04 /* ThreadPlanStepRange.cpp */; }; 2689010413353E6F00698AC0 /* ThreadPlanStepInRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C43DF8911069C3200E55CBF /* ThreadPlanStepInRange.cpp */; }; 2689010513353E6F00698AC0 /* ThreadPlanStepOverRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C43DF8A11069C3200E55CBF /* ThreadPlanStepOverRange.cpp */; }; 2689010613353E6F00698AC0 /* ThreadPlanRunToAddress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CAFCE031101218900CA63DB /* ThreadPlanRunToAddress.cpp */; }; 2689010713353E6F00698AC0 /* ThreadPlanStepThrough.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C847510F50EFC00BB2B04 /* ThreadPlanStepThrough.cpp */; }; 2689010813353E6F00698AC0 /* ThreadPlanStepUntil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2660D9FE11922A7F00958FBD /* ThreadPlanStepUntil.cpp */; }; 2689010A13353E6F00698AC0 /* ThreadPlanTracer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CC2A148128C73ED001531C4 /* ThreadPlanTracer.cpp */; }; 2689010B13353E6F00698AC0 /* ThreadSpec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C08CDE711C81EF8001610A8 /* ThreadSpec.cpp */; }; 2689010C13353E6F00698AC0 /* UnixSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C00987011500B4300F316B0 /* UnixSignals.cpp */; }; 2689011013353E8200698AC0 /* SharingPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 261B5A5211C3F2AD00AABD0A /* SharingPtr.cpp */; }; 2689011113353E8200698AC0 /* StringExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2660D9F611922A1300958FBD /* StringExtractor.cpp */; }; 2689011213353E8200698AC0 /* StringExtractorGDBRemote.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2676A093119C93C8008A98EF /* StringExtractorGDBRemote.cpp */; }; 268901161335BBC300698AC0 /* liblldb-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2689FFCA13353D7A00698AC0 /* liblldb-core.a */; }; 2689FFDA13353D9D00698AC0 /* lldb.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E7410F1B85900F91463 /* lldb.cpp */; }; 2689FFEF13353DB600698AC0 /* Breakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E0A10F1B83100F91463 /* Breakpoint.cpp */; }; 2689FFF113353DB600698AC0 /* BreakpointID.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E0B10F1B83100F91463 /* BreakpointID.cpp */; }; 2689FFF313353DB600698AC0 /* BreakpointIDList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E0C10F1B83100F91463 /* BreakpointIDList.cpp */; }; 2689FFF513353DB600698AC0 /* BreakpointList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E0D10F1B83100F91463 /* BreakpointList.cpp */; }; 2689FFF713353DB600698AC0 /* BreakpointLocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E0E10F1B83100F91463 /* BreakpointLocation.cpp */; }; 2689FFF913353DB600698AC0 /* BreakpointLocationCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E0F10F1B83100F91463 /* BreakpointLocationCollection.cpp */; }; 2689FFFB13353DB600698AC0 /* BreakpointLocationList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1010F1B83100F91463 /* BreakpointLocationList.cpp */; }; 2689FFFD13353DB600698AC0 /* BreakpointOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1110F1B83100F91463 /* BreakpointOptions.cpp */; }; 2689FFFF13353DB600698AC0 /* BreakpointResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1210F1B83100F91463 /* BreakpointResolver.cpp */; }; 268F9D53123AA15200B91E9B /* SBSymbolContextList.h in Headers */ = {isa = PBXBuildFile; fileRef = 268F9D52123AA15200B91E9B /* SBSymbolContextList.h */; settings = {ATTRIBUTES = (Public, ); }; }; 268F9D55123AA16600B91E9B /* SBSymbolContextList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 268F9D54123AA16600B91E9B /* SBSymbolContextList.cpp */; }; 2690B3711381D5C300ECFBAE /* Memory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2690B3701381D5C300ECFBAE /* Memory.cpp */; }; 2692BA15136610C100F9E14D /* UnwindAssemblyInstEmulation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2692BA13136610C100F9E14D /* UnwindAssemblyInstEmulation.cpp */; }; 2694E99D14FC0BB30076DE67 /* PlatformFreeBSD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2694E99A14FC0BB30076DE67 /* PlatformFreeBSD.cpp */; }; 2694E9A414FC0BBD0076DE67 /* PlatformLinux.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2694E9A114FC0BBD0076DE67 /* PlatformLinux.cpp */; }; 26954EBE1401EE8B00294D09 /* DynamicRegisterInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26954EBC1401EE8B00294D09 /* DynamicRegisterInfo.cpp */; }; 26957D9813D381C900670048 /* RegisterContextDarwin_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26957D9213D381C900670048 /* RegisterContextDarwin_arm.cpp */; }; 26957D9A13D381C900670048 /* RegisterContextDarwin_i386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26957D9413D381C900670048 /* RegisterContextDarwin_i386.cpp */; }; 26957D9C13D381C900670048 /* RegisterContextDarwin_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26957D9613D381C900670048 /* RegisterContextDarwin_x86_64.cpp */; }; 2697A39315E404B1003E682C /* OptionValueArch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2697A39215E404B1003E682C /* OptionValueArch.cpp */; }; 2697A54D133A6305004E4240 /* PlatformDarwin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2697A54B133A6305004E4240 /* PlatformDarwin.cpp */; }; 2698699B15E6CBD0002415FF /* OperatingSystemPython.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2698699815E6CBD0002415FF /* OperatingSystemPython.cpp */; }; 269DDD4A1B8FD1C300D0DBD8 /* DWARFASTParserClang.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 269DDD481B8FD1C300D0DBD8 /* DWARFASTParserClang.cpp */; }; 26A375811D59462700D6CBDB /* SelectHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A3757F1D59462700D6CBDB /* SelectHelper.cpp */; }; 26A527C114E24F5F00F3A14A /* ProcessMachCore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A527BD14E24F5F00F3A14A /* ProcessMachCore.cpp */; }; 26A527C314E24F5F00F3A14A /* ThreadMachCore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A527BF14E24F5F00F3A14A /* ThreadMachCore.cpp */; }; 26A69C5F137A17A500262477 /* RegisterValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C6886E137880C400407EDF /* RegisterValue.cpp */; }; 26A7A035135E6E4200FB369E /* OptionValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A7A034135E6E4200FB369E /* OptionValue.cpp */; }; 26AB92121819D74600E63F3E /* DWARFDataExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26AB92101819D74600E63F3E /* DWARFDataExtractor.cpp */; }; 26B1EFAE154638AF00E2DAC7 /* DWARFDeclContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26B1EFAC154638AF00E2DAC7 /* DWARFDeclContext.cpp */; }; 26B1FCC21338115F002886E2 /* Host.mm in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7EE810F1B88F00F91463 /* Host.mm */; }; 26B42C4D1187ABA50079C8C8 /* LLDB.h in Headers */ = {isa = PBXBuildFile; fileRef = 26B42C4C1187ABA50079C8C8 /* LLDB.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26B7564E14F89356008D9CB3 /* PlatformiOSSimulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26B7564C14F89356008D9CB3 /* PlatformiOSSimulator.cpp */; }; 26B75B441AD6E29A001F7A57 /* MipsLinuxSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26B75B421AD6E29A001F7A57 /* MipsLinuxSignals.cpp */; }; 26B8283D142D01E9002DBC64 /* SBSection.h in Headers */ = {isa = PBXBuildFile; fileRef = 26B8283C142D01E9002DBC64 /* SBSection.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26B82840142D020F002DBC64 /* SBSection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26B8283F142D020F002DBC64 /* SBSection.cpp */; }; 26BC179918C7F2B300D2196D /* JITLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC179718C7F2B300D2196D /* JITLoader.cpp */; }; 26BC179A18C7F2B300D2196D /* JITLoaderList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC179818C7F2B300D2196D /* JITLoaderList.cpp */; }; 26BC17AB18C7F4CB00D2196D /* ProcessElfCore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC17A218C7F4CB00D2196D /* ProcessElfCore.cpp */; }; 26BC17AD18C7F4CB00D2196D /* RegisterContextPOSIXCore_mips64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC17A418C7F4CB00D2196D /* RegisterContextPOSIXCore_mips64.cpp */; }; 26BC17AF18C7F4CB00D2196D /* RegisterContextPOSIXCore_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC17A618C7F4CB00D2196D /* RegisterContextPOSIXCore_x86_64.cpp */; }; 26BC17B118C7F4CB00D2196D /* ThreadElfCore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC17A818C7F4CB00D2196D /* ThreadElfCore.cpp */; }; 26BCFC521368AE38006DC050 /* OptionGroupFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BCFC511368AE38006DC050 /* OptionGroupFormat.cpp */; }; 26BD407F135D2AE000237D80 /* FileLineResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BD407E135D2ADF00237D80 /* FileLineResolver.cpp */; }; 26BF51F31B3C754400016294 /* ABISysV_hexagon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BF51EA1B3C754400016294 /* ABISysV_hexagon.cpp */; }; 26BF51F61B3C754400016294 /* ABISysV_i386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BF51EF1B3C754400016294 /* ABISysV_i386.cpp */; }; 26C72C94124322890068DC16 /* SBStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 26C72C93124322890068DC16 /* SBStream.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26C72C961243229A0068DC16 /* SBStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C72C951243229A0068DC16 /* SBStream.cpp */; }; 26C7C4831BFFEA7E009BD01F /* WindowsMiniDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C7C4811BFFEA7E009BD01F /* WindowsMiniDump.cpp */; }; 26C7C4841BFFEA7E009BD01F /* WindowsMiniDump.h in Headers */ = {isa = PBXBuildFile; fileRef = 26C7C4821BFFEA7E009BD01F /* WindowsMiniDump.h */; }; 26CA97A1172B1FD5005DC71B /* RegisterContextThreadMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26CA979F172B1FD5005DC71B /* RegisterContextThreadMemory.cpp */; }; 26CEB5EF18761CB2008F575A /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C32A10F3DFDD009D5894 /* libedit.dylib */; }; 26CEB5F218762056008F575A /* CommandObjectGUI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26CEB5F018762056008F575A /* CommandObjectGUI.cpp */; }; 26CFDCA3186163A4000E63E5 /* Editline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26CFDCA2186163A4000E63E5 /* Editline.cpp */; }; 26CFDCA818616473000E63E5 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C32A10F3DFDD009D5894 /* libedit.dylib */; }; 26D265BC136B4269002EEE45 /* lldb-public.h in Headers */ = {isa = PBXBuildFile; fileRef = 26651A14133BEC76005B64B7 /* lldb-public.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26D52C1F1A980FE300E5D2FB /* MICmdCmdSymbol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D52C1D1A980FE300E5D2FB /* MICmdCmdSymbol.cpp */; }; 26D55235159A7DB100708D8D /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26D55234159A7DB100708D8D /* libxml2.dylib */; }; 26D5E15F135BAEA2006EA0A7 /* OptionGroupArchitecture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D5E15E135BAEA2006EA0A7 /* OptionGroupArchitecture.cpp */; }; 26D5E163135BB054006EA0A7 /* OptionGroupPlatform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D5E162135BB054006EA0A7 /* OptionGroupPlatform.cpp */; }; 26D7E45D13D5E30A007FD12B /* SocketAddress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D7E45C13D5E30A007FD12B /* SocketAddress.cpp */; }; 26DAED6315D327C200E15819 /* OptionValuePathMappings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DAED6215D327C200E15819 /* OptionValuePathMappings.cpp */; }; 26DB3E161379E7AD0080DC73 /* ABIMacOSX_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DB3E071379E7AD0080DC73 /* ABIMacOSX_arm.cpp */; }; 26DB3E191379E7AD0080DC73 /* ABIMacOSX_arm64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DB3E0B1379E7AD0080DC73 /* ABIMacOSX_arm64.cpp */; }; 26DB3E1C1379E7AD0080DC73 /* ABIMacOSX_i386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DB3E0F1379E7AD0080DC73 /* ABIMacOSX_i386.cpp */; }; 26DB3E1F1379E7AD0080DC73 /* ABISysV_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DB3E131379E7AD0080DC73 /* ABISysV_x86_64.cpp */; }; 26DC6A1D1337FECA00FF7998 /* lldb-platform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DC6A1C1337FECA00FF7998 /* lldb-platform.cpp */; }; 26DE1E6C11616C2E00A093E2 /* lldb-forward.h in Headers */ = {isa = PBXBuildFile; fileRef = 26DE1E6A11616C2E00A093E2 /* lldb-forward.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26DE204111618AB900A093E2 /* SBSymbolContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 26DE204011618AB900A093E2 /* SBSymbolContext.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26DE204311618ACA00A093E2 /* SBAddress.h in Headers */ = {isa = PBXBuildFile; fileRef = 26DE204211618ACA00A093E2 /* SBAddress.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26DE204511618ADA00A093E2 /* SBAddress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DE204411618ADA00A093E2 /* SBAddress.cpp */; }; 26DE204711618AED00A093E2 /* SBSymbolContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DE204611618AED00A093E2 /* SBSymbolContext.cpp */; }; 26DE204D11618E7A00A093E2 /* SBModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DE204C11618E7A00A093E2 /* SBModule.cpp */; }; 26DE204F11618E9800A093E2 /* SBModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 26DE204E11618E9800A093E2 /* SBModule.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26DE205311618FAC00A093E2 /* SBFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 26DE205211618FAC00A093E2 /* SBFunction.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26DE205511618FB800A093E2 /* SBCompileUnit.h in Headers */ = {isa = PBXBuildFile; fileRef = 26DE205411618FB800A093E2 /* SBCompileUnit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26DE205711618FC500A093E2 /* SBBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 26DE205611618FC500A093E2 /* SBBlock.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26DE205911618FE700A093E2 /* SBLineEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = 26DE205811618FE700A093E2 /* SBLineEntry.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26DE205B11618FF600A093E2 /* SBSymbol.h in Headers */ = {isa = PBXBuildFile; fileRef = 26DE205A11618FF600A093E2 /* SBSymbol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26DE205D1161901400A093E2 /* SBFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DE205C1161901400A093E2 /* SBFunction.cpp */; }; 26DE205F1161901B00A093E2 /* SBCompileUnit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DE205E1161901B00A093E2 /* SBCompileUnit.cpp */; }; 26DE20611161902700A093E2 /* SBBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DE20601161902600A093E2 /* SBBlock.cpp */; }; 26DE20631161904200A093E2 /* SBLineEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DE20621161904200A093E2 /* SBLineEntry.cpp */; }; 26DE20651161904E00A093E2 /* SBSymbol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DE20641161904E00A093E2 /* SBSymbol.cpp */; }; 26E152261419CAD4007967D0 /* ObjectFilePECOFF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E152231419CACA007967D0 /* ObjectFilePECOFF.cpp */; }; 26ED3D6D13C563810017D45E /* OptionGroupVariable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26ED3D6C13C563810017D45E /* OptionGroupVariable.cpp */; }; 26EFB61B1BFE8D3E00544801 /* PlatformNetBSD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26EFB6181BFE8D3E00544801 /* PlatformNetBSD.cpp */; }; 26EFB61C1BFE8D3E00544801 /* PlatformNetBSD.h in Headers */ = {isa = PBXBuildFile; fileRef = 26EFB6191BFE8D3E00544801 /* PlatformNetBSD.h */; }; 26EFC4CD18CFAF0D00865D87 /* ObjectFileJIT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26EFC4CA18CFAF0D00865D87 /* ObjectFileJIT.cpp */; }; 26F006561B4DD86700B872E5 /* DynamicLoaderWindowsDYLD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F006541B4DD86700B872E5 /* DynamicLoaderWindowsDYLD.cpp */; }; 26F4A21C13FBA31A0064B613 /* ThreadMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F4A21A13FBA31A0064B613 /* ThreadMemory.cpp */; }; 26F5C27710F3D9E4009D5894 /* Driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F5C27310F3D9E4009D5894 /* Driver.cpp */; }; 26F5C32D10F3DFDD009D5894 /* libtermcap.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C32B10F3DFDD009D5894 /* libtermcap.dylib */; }; 26FFC19914FC072100087D58 /* AuxVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26FFC19314FC072100087D58 /* AuxVector.cpp */; }; 26FFC19B14FC072100087D58 /* DYLDRendezvous.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26FFC19514FC072100087D58 /* DYLDRendezvous.cpp */; }; 26FFC19D14FC072100087D58 /* DynamicLoaderPOSIXDYLD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26FFC19714FC072100087D58 /* DynamicLoaderPOSIXDYLD.cpp */; }; 304B2E461CAAA57B007829FE /* ClangUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3032B1B61CAAA3D1004BE1AB /* ClangUtil.cpp */; }; 30B38A001CAAA6D7009524E3 /* ClangUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 3032B1B91CAAA400004BE1AB /* ClangUtil.h */; }; 332CCB181AFF41620034D4C4 /* SBLanguageRuntime.h in Headers */ = {isa = PBXBuildFile; fileRef = 3392EBB71AFF402200858B9F /* SBLanguageRuntime.h */; settings = {ATTRIBUTES = (Public, ); }; }; 33E5E8471A674FB60024ED68 /* StringConvert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33E5E8411A672A240024ED68 /* StringConvert.cpp */; }; 3F8160A61AB9F7DD001DA9DF /* Logging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F8160A51AB9F7DD001DA9DF /* Logging.cpp */; }; 3F81691A1ABA2419001DA9DF /* NameMatches.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F8169181ABA2419001DA9DF /* NameMatches.cpp */; }; 3F81692C1ABB7A1E001DA9DF /* SystemInitializerFull.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F81692A1ABB7A16001DA9DF /* SystemInitializerFull.cpp */; }; 3F8169311ABB7A6D001DA9DF /* SystemInitializer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F81692E1ABB7A6D001DA9DF /* SystemInitializer.cpp */; }; 3F8169321ABB7A6D001DA9DF /* SystemInitializerCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F81692F1ABB7A6D001DA9DF /* SystemInitializerCommon.cpp */; }; 3F8169331ABB7A6D001DA9DF /* SystemLifetimeManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F8169301ABB7A6D001DA9DF /* SystemLifetimeManager.cpp */; }; 3FBA69E11B6067120008F44A /* ScriptInterpreterNone.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FBA69DD1B6067020008F44A /* ScriptInterpreterNone.cpp */; }; 3FBA69EC1B6067430008F44A /* PythonDataObjects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FBA69E31B60672A0008F44A /* PythonDataObjects.cpp */; }; 3FBA69ED1B60674B0008F44A /* ScriptInterpreterPython.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FBA69E51B60672A0008F44A /* ScriptInterpreterPython.cpp */; }; 3FDFDDBD199C3A06009756A7 /* FileAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFDDBC199C3A06009756A7 /* FileAction.cpp */; }; 3FDFDDBF199D345E009756A7 /* FileCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFDDBE199D345E009756A7 /* FileCache.cpp */; }; 3FDFDDC6199D37ED009756A7 /* FileSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFDDC5199D37ED009756A7 /* FileSystem.cpp */; }; 3FDFE52C19A2917A009756A7 /* HostInfoMacOSX.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFE52B19A2917A009756A7 /* HostInfoMacOSX.mm */; }; 3FDFE53119A292F0009756A7 /* HostInfoPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFE53019A292F0009756A7 /* HostInfoPosix.cpp */; }; 3FDFE53519A29327009756A7 /* HostInfoBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFE53419A29327009756A7 /* HostInfoBase.cpp */; }; 3FDFE56C19AF9C44009756A7 /* HostProcessPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFE56A19AF9C44009756A7 /* HostProcessPosix.cpp */; }; 3FDFE56D19AF9C44009756A7 /* HostThreadPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFE56B19AF9C44009756A7 /* HostThreadPosix.cpp */; }; 3FDFED0B19B7C8DE009756A7 /* HostThreadMacOSX.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFED0519B7C898009756A7 /* HostThreadMacOSX.mm */; }; 3FDFED2719BA6D96009756A7 /* HostNativeThreadBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFED2419BA6D96009756A7 /* HostNativeThreadBase.cpp */; }; 3FDFED2819BA6D96009756A7 /* HostThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFED2519BA6D96009756A7 /* HostThread.cpp */; }; 3FDFED2919BA6D96009756A7 /* ThreadLauncher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFED2619BA6D96009756A7 /* ThreadLauncher.cpp */; }; 3FDFED2D19C257A0009756A7 /* HostProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFED2C19C257A0009756A7 /* HostProcess.cpp */; }; 490A36C0180F0E6F00BA31F8 /* PlatformWindows.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 490A36BD180F0E6F00BA31F8 /* PlatformWindows.cpp */; }; 490A966B1628C3BF00F0002E /* SBDeclaration.h in Headers */ = {isa = PBXBuildFile; fileRef = 9452573816262CEF00325455 /* SBDeclaration.h */; settings = {ATTRIBUTES = (Public, ); }; }; 492DB7E71EC662B100B9E9AF /* Status.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 492DB7E61EC662B100B9E9AF /* Status.h */; }; 492DB7EB1EC662E200B9E9AF /* Status.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 492DB7E81EC662D100B9E9AF /* Status.cpp */; }; 4939EA8D1BD56B6D00084382 /* REPL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4939EA8C1BD56B6D00084382 /* REPL.cpp */; }; 494260DA14579144003C1C78 /* VerifyDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 494260D914579144003C1C78 /* VerifyDecl.cpp */; }; 4959511F1A1BC4BC00F6F8FC /* ClangModulesDeclVendor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4959511E1A1BC4BC00F6F8FC /* ClangModulesDeclVendor.cpp */; }; 4966DCC4148978A10028481B /* ClangExternalASTSourceCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4966DCC3148978A10028481B /* ClangExternalASTSourceCommon.cpp */; }; 4984BA131B978C55008658D4 /* ClangExpressionVariable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4984BA0E1B978C3E008658D4 /* ClangExpressionVariable.cpp */; }; 4984BA161B979973008658D4 /* ExpressionVariable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4984BA151B979973008658D4 /* ExpressionVariable.cpp */; }; 4984BA181B979C08008658D4 /* ExpressionVariable.h in Headers */ = {isa = PBXBuildFile; fileRef = 4984BA171B979C08008658D4 /* ExpressionVariable.h */; }; 49A1CAC51430E8DE00306AC9 /* ExpressionSourceCode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49A1CAC31430E8BD00306AC9 /* ExpressionSourceCode.cpp */; }; 49A71FE7141FFA5C00D59478 /* IRInterpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 496B01581406DE8900F830D5 /* IRInterpreter.cpp */; }; 49CA96FC1E6AACC900C03FEE /* DataBufferHeap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49CA96E61E6AAC6600C03FEE /* DataBufferHeap.cpp */; }; 49CA96FD1E6AACC900C03FEE /* DataBufferLLVM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49CA96E71E6AAC6600C03FEE /* DataBufferLLVM.cpp */; }; 49CA96FE1E6AACC900C03FEE /* DataEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49CA96E81E6AAC6600C03FEE /* DataEncoder.cpp */; }; 49CA96FF1E6AACC900C03FEE /* DataExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49CA96E91E6AAC6600C03FEE /* DataExtractor.cpp */; }; 49CA97001E6AACC900C03FEE /* UUID.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49CA96EA1E6AAC6600C03FEE /* UUID.cpp */; }; 49D8FB3913B5598F00411094 /* ClangASTImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49D8FB3513B558DE00411094 /* ClangASTImporter.cpp */; }; 49DA65031485C92A005FF180 /* AppleObjCDeclVendor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DA65021485C92A005FF180 /* AppleObjCDeclVendor.cpp */; }; 49DCF6FE170E6B4A0092F75E /* IRMemoryMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DCF6FD170E6B4A0092F75E /* IRMemoryMap.cpp */; }; 49DCF702170E70120092F75E /* Materializer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DCF700170E70120092F75E /* Materializer.cpp */; }; 49DEF1251CD7C6DF006A7C7D /* BlockPointer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DEF11F1CD7BD90006A7C7D /* BlockPointer.cpp */; }; 49E4F66B1C9CAD16008487EA /* DiagnosticManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49E4F6681C9CAD12008487EA /* DiagnosticManager.cpp */; }; 49F811F31E931B2100F4E163 /* CPlusPlusNameParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49F811EF1E931B1500F4E163 /* CPlusPlusNameParser.cpp */; }; 4C0083401B9F9BA900D5CF24 /* UtilityFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C00833F1B9F9BA900D5CF24 /* UtilityFunction.cpp */; }; 4C2479BD1BA39295009C9A7B /* FunctionCaller.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C0083321B9A5DE200D5CF24 /* FunctionCaller.cpp */; }; 4C3ADCD61810D88B00357218 /* BreakpointResolverFileRegex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CAA56141422D986001FFA01 /* BreakpointResolverFileRegex.cpp */; }; 4C4EB7811E6A4DCC002035C0 /* DumpDataExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C4EB77F1E6A4DB8002035C0 /* DumpDataExtractor.cpp */; }; 4C562CC71CC07DF700C52EAC /* PDBASTParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C562CC21CC07DDD00C52EAC /* PDBASTParser.cpp */; }; 4C56543119D1EFAA002E9C44 /* ThreadPlanPython.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C56543019D1EFAA002E9C44 /* ThreadPlanPython.cpp */; }; 4C56543519D2297A002E9C44 /* SBThreadPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C56543419D2297A002E9C44 /* SBThreadPlan.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4C56543719D22B32002E9C44 /* SBThreadPlan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C56543619D22B32002E9C44 /* SBThreadPlan.cpp */; }; 4C88BC2A1BA3722B00AA0964 /* Expression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C88BC291BA3722B00AA0964 /* Expression.cpp */; }; 4C88BC2D1BA391B000AA0964 /* UserExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C0083331B9A5DE200D5CF24 /* UserExpression.cpp */; }; 4CABA9E0134A8BCD00539BDD /* ValueObjectMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CABA9DF134A8BCD00539BDD /* ValueObjectMemory.cpp */; }; 4CC7C6501D5298F30076FF94 /* OCamlLanguage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7C64D1D5298E20076FF94 /* OCamlLanguage.cpp */; }; 4CC7C6571D52997A0076FF94 /* OCamlASTContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7C6551D52996C0076FF94 /* OCamlASTContext.cpp */; }; 4CC7C6581D529B950076FF94 /* DWARFASTParserOCaml.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7C6521D5299140076FF94 /* DWARFASTParserOCaml.cpp */; }; 4CCA644D13B40B82003BDF98 /* ItaniumABILanguageRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA643D13B40B82003BDF98 /* ItaniumABILanguageRuntime.cpp */; }; 4CCA645013B40B82003BDF98 /* AppleObjCRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA644213B40B82003BDF98 /* AppleObjCRuntime.cpp */; }; 4CCA645213B40B82003BDF98 /* AppleObjCRuntimeV1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA644413B40B82003BDF98 /* AppleObjCRuntimeV1.cpp */; }; 4CCA645413B40B82003BDF98 /* AppleObjCRuntimeV2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA644613B40B82003BDF98 /* AppleObjCRuntimeV2.cpp */; }; 4CCA645613B40B82003BDF98 /* AppleObjCTrampolineHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA644813B40B82003BDF98 /* AppleObjCTrampolineHandler.cpp */; }; 4CCA645813B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA644A13B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.cpp */; }; 4CD0BD0F134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CD0BD0E134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp */; }; 4CDB8D6D1DBA91B6006C5B13 /* LibStdcppUniquePointer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CDB8D671DBA91A6006C5B13 /* LibStdcppUniquePointer.cpp */; }; 4CDB8D6E1DBA91B6006C5B13 /* LibStdcppTuple.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CDB8D681DBA91A6006C5B13 /* LibStdcppTuple.cpp */; }; 4CE4EFAA1E8999B900A80C06 /* PlatformOpenBSD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4EFA61E8999B000A80C06 /* PlatformOpenBSD.cpp */; }; 4CE4EFB31E899A3400A80C06 /* RegisterContextOpenBSD_i386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4EFAB1E899A1200A80C06 /* RegisterContextOpenBSD_i386.cpp */; }; 4CE4EFB41E899A4000A80C06 /* RegisterContextOpenBSD_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4EFAD1E899A1200A80C06 /* RegisterContextOpenBSD_x86_64.cpp */; }; 4CE4F673162C971A00F75CB3 /* SBExpressionOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CE4F672162C971A00F75CB3 /* SBExpressionOptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4CE4F675162C973F00F75CB3 /* SBExpressionOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4F674162C973F00F75CB3 /* SBExpressionOptions.cpp */; }; 4CF3D80C15AF4DC800845BF3 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDB919B414F6F10D008FF64B /* Security.framework */; }; 4CF52AF51428291E0051E832 /* SBFileSpecList.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF52AF41428291E0051E832 /* SBFileSpecList.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4CF52AF8142829390051E832 /* SBFileSpecList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF52AF7142829390051E832 /* SBFileSpecList.cpp */; }; 54067BF11DF2041B00749AA5 /* UBSanRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 54067BEC1DF2034B00749AA5 /* UBSanRuntime.cpp */; }; 6D0F61431C80AAAE00A4ECEE /* JavaASTContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D0F61411C80AAAA00A4ECEE /* JavaASTContext.cpp */; }; 6D0F61481C80AAD600A4ECEE /* DWARFASTParserJava.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D0F61441C80AACF00A4ECEE /* DWARFASTParserJava.cpp */; }; 6D0F614E1C80AB0700A4ECEE /* JavaLanguageRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D0F614A1C80AB0400A4ECEE /* JavaLanguageRuntime.cpp */; }; 6D0F614F1C80AB0C00A4ECEE /* JavaLanguageRuntime.h in Headers */ = {isa = PBXBuildFile; fileRef = 6D0F614B1C80AB0400A4ECEE /* JavaLanguageRuntime.h */; }; 6D0F61591C80AB3500A4ECEE /* JavaFormatterFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D0F61511C80AB3000A4ECEE /* JavaFormatterFunctions.cpp */; }; 6D0F615A1C80AB3900A4ECEE /* JavaLanguage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D0F61531C80AB3000A4ECEE /* JavaLanguage.cpp */; }; 6D55B2901A8A806200A70529 /* GDBRemoteCommunicationServerCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D55B28D1A8A806200A70529 /* GDBRemoteCommunicationServerCommon.cpp */; }; 6D55B2911A8A806200A70529 /* GDBRemoteCommunicationServerLLGS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D55B28E1A8A806200A70529 /* GDBRemoteCommunicationServerLLGS.cpp */; }; 6D55B2921A8A806200A70529 /* GDBRemoteCommunicationServerPlatform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D55B28F1A8A806200A70529 /* GDBRemoteCommunicationServerPlatform.cpp */; }; 6D55BAED1A8CD0A800A70529 /* PlatformAndroid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D55BAE91A8CD08C00A70529 /* PlatformAndroid.cpp */; }; 6D55BAEE1A8CD0B200A70529 /* PlatformAndroidRemoteGDBServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D55BAEB1A8CD08C00A70529 /* PlatformAndroidRemoteGDBServer.cpp */; }; 6D762BEE1B1605D2006C929D /* LLDBServerUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D762BEC1B1605CD006C929D /* LLDBServerUtilities.cpp */; }; 6D86CEA01B440F8500A7FBFA /* CommandObjectBugreport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D86CE9E1B440F6B00A7FBFA /* CommandObjectBugreport.cpp */; }; 6D95DC001B9DC057000E318A /* DIERef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D95DBFD1B9DC057000E318A /* DIERef.cpp */; }; 6D95DC011B9DC057000E318A /* HashedNameToDIE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D95DBFE1B9DC057000E318A /* HashedNameToDIE.cpp */; }; 6D95DC021B9DC057000E318A /* SymbolFileDWARFDwo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D95DBFF1B9DC057000E318A /* SymbolFileDWARFDwo.cpp */; }; 6D99A3631BBC2F3200979793 /* ArmUnwindInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D99A3621BBC2F3200979793 /* ArmUnwindInfo.cpp */; }; 6D9AB3DD1BB2B74E003F2289 /* TypeMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D9AB3DC1BB2B74E003F2289 /* TypeMap.cpp */; }; 6DEC6F391BD66D750091ABA6 /* TaskPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6DEC6F381BD66D750091ABA6 /* TaskPool.cpp */; }; 8C26C4261C3EA5F90031DF7C /* TSanRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C26C4241C3EA4340031DF7C /* TSanRuntime.cpp */; }; 8C2D6A53197A1EAF006989C9 /* MemoryHistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C2D6A52197A1EAF006989C9 /* MemoryHistory.cpp */; }; 8C2D6A5E197A250F006989C9 /* MemoryHistoryASan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C2D6A5A197A1FDC006989C9 /* MemoryHistoryASan.cpp */; }; 8C3BD9961EF45DA50016C343 /* MainThreadCheckerRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C3BD9951EF45D9B0016C343 /* MainThreadCheckerRuntime.cpp */; }; 8CCB017E19BA28A80009FD44 /* ThreadCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CCB017A19BA283D0009FD44 /* ThreadCollection.cpp */; }; 8CCB018219BA4E270009FD44 /* SBThreadCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 8CCB018119BA4E210009FD44 /* SBThreadCollection.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8CCB018319BA51BF0009FD44 /* SBThreadCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CCB017F19BA4DD00009FD44 /* SBThreadCollection.cpp */; }; 8CF02AE919DCC01900B14BE0 /* InstrumentationRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CF02ADF19DCBF3B00B14BE0 /* InstrumentationRuntime.cpp */; }; 8CF02AEA19DCC02100B14BE0 /* ASanRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CF02AE519DCBF8400B14BE0 /* ASanRuntime.cpp */; }; 8CF02AEF19DD16B100B14BE0 /* InstrumentationRuntimeStopInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CF02AED19DD15CF00B14BE0 /* InstrumentationRuntimeStopInfo.cpp */; }; 9404957A1BEC497E00926025 /* NSError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940495781BEC497E00926025 /* NSError.cpp */; }; 9404957B1BEC497E00926025 /* NSException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940495791BEC497E00926025 /* NSException.cpp */; }; 94094C6B163B6F840083A547 /* ValueObjectCast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94094C69163B6CD90083A547 /* ValueObjectCast.cpp */; }; 940B02F619DC96E700AD0F52 /* SBExecutionContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940B02F519DC96E700AD0F52 /* SBExecutionContext.cpp */; }; 940B04D91A8984FF0045D5F7 /* argdumper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 940B04D81A8984FF0045D5F7 /* argdumper.cpp */; }; 940B04E41A8987680045D5F7 /* lldb-argdumper in CopyFiles */ = {isa = PBXBuildFile; fileRef = 942829C01A89835300521B30 /* lldb-argdumper */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 94145431175E63B500284436 /* lldb-versioning.h in Headers */ = {isa = PBXBuildFile; fileRef = 94145430175D7FDE00284436 /* lldb-versioning.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9418EBCD1AA910910058B02E /* VectorType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9418EBCC1AA910910058B02E /* VectorType.cpp */; }; 941BCC7F14E48C4000BB969C /* SBTypeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 9461568614E355F2003A195C /* SBTypeFilter.h */; settings = {ATTRIBUTES = (Public, ); }; }; 941BCC8014E48C4000BB969C /* SBTypeFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 9461568714E355F2003A195C /* SBTypeFormat.h */; settings = {ATTRIBUTES = (Public, ); }; }; 941BCC8114E48C4000BB969C /* SBTypeSummary.h in Headers */ = {isa = PBXBuildFile; fileRef = 9461568814E355F2003A195C /* SBTypeSummary.h */; settings = {ATTRIBUTES = (Public, ); }; }; 941BCC8214E48C4000BB969C /* SBTypeSynthetic.h in Headers */ = {isa = PBXBuildFile; fileRef = 9461568914E355F2003A195C /* SBTypeSynthetic.h */; settings = {ATTRIBUTES = (Public, ); }; }; 94235B9E1A8D667400EB2EED /* SBVariablesOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94235B9B1A8D5FF300EB2EED /* SBVariablesOptions.cpp */; }; 94235B9F1A8D66D600EB2EED /* SBVariablesOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 94235B9A1A8D5FD800EB2EED /* SBVariablesOptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 942612F71B95000000EF842E /* LanguageCategory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 942612F61B95000000EF842E /* LanguageCategory.cpp */; }; 942612F81B952C9B00EF842E /* ObjCLanguage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94B6385E1B8FB7A2004FE1E4 /* ObjCLanguage.cpp */; }; 942829561A89614C00521B30 /* JSON.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 942829551A89614C00521B30 /* JSON.cpp */; }; 942829CC1A89839300521B30 /* liblldb-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2689FFCA13353D7A00698AC0 /* liblldb-core.a */; }; 9428BC2C1C6E64E4002A24D7 /* LibCxxAtomic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9428BC291C6E64DC002A24D7 /* LibCxxAtomic.cpp */; }; 94380B8219940B0A00BFE4A8 /* StringLexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94380B8119940B0A00BFE4A8 /* StringLexer.cpp */; }; 943BDEFE1AA7B2F800789CE8 /* LLDBAssert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 943BDEFD1AA7B2F800789CE8 /* LLDBAssert.cpp */; }; 9441816E1C8F5EC900E5A8D9 /* CommandAlias.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9441816D1C8F5EC900E5A8D9 /* CommandAlias.cpp */; }; 944372DC171F6B4300E57C32 /* RegisterContextDummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 944372DA171F6B4300E57C32 /* RegisterContextDummy.cpp */; }; 9443B122140C18C40013457C /* SBData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9443B121140C18C10013457C /* SBData.cpp */; }; 9443B123140C26AB0013457C /* SBData.h in Headers */ = {isa = PBXBuildFile; fileRef = 9443B120140C18A90013457C /* SBData.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9447DE431BD5963300E67212 /* DumpValueObjectOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9447DE421BD5963300E67212 /* DumpValueObjectOptions.cpp */; }; 945215DF17F639EE00521C0B /* ValueObjectPrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945215DE17F639EE00521C0B /* ValueObjectPrinter.cpp */; }; 9452573A16262D0200325455 /* SBDeclaration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9452573916262D0200325455 /* SBDeclaration.cpp */; }; 945261BF1B9A11FC00BF138D /* CxxStringTypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261B31B9A11E800BF138D /* CxxStringTypes.cpp */; }; 945261C01B9A11FC00BF138D /* LibCxx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261B51B9A11E800BF138D /* LibCxx.cpp */; }; 945261C11B9A11FC00BF138D /* LibCxxInitializerList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261B71B9A11E800BF138D /* LibCxxInitializerList.cpp */; }; 945261C21B9A11FC00BF138D /* LibCxxList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261B81B9A11E800BF138D /* LibCxxList.cpp */; }; 945261C31B9A11FC00BF138D /* LibCxxMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261B91B9A11E800BF138D /* LibCxxMap.cpp */; }; 945261C41B9A11FC00BF138D /* LibCxxUnorderedMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261BA1B9A11E800BF138D /* LibCxxUnorderedMap.cpp */; }; 945261C51B9A11FC00BF138D /* LibCxxVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261BB1B9A11E800BF138D /* LibCxxVector.cpp */; }; 945261C61B9A11FC00BF138D /* LibStdcpp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261BC1B9A11E800BF138D /* LibStdcpp.cpp */; }; 945261C81B9A14D300BF138D /* CXXFunctionPointer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261C71B9A14D300BF138D /* CXXFunctionPointer.cpp */; }; 9455630F1BEAD0600073F75F /* PlatformAppleSimulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9455630A1BEAD0570073F75F /* PlatformAppleSimulator.cpp */; }; 945563101BEAD0650073F75F /* PlatformiOSSimulatorCoreSimulatorSupport.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9455630D1BEAD0570073F75F /* PlatformiOSSimulatorCoreSimulatorSupport.mm */; }; 945759671534941F005A9070 /* PlatformPOSIX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945759651534941F005A9070 /* PlatformPOSIX.cpp */; }; 9461569A14E358A6003A195C /* SBTypeFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9461568A14E35621003A195C /* SBTypeFilter.cpp */; }; 9461569B14E358A6003A195C /* SBTypeFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9461568B14E35621003A195C /* SBTypeFormat.cpp */; }; 9461569C14E358A6003A195C /* SBTypeSummary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9461568C14E35621003A195C /* SBTypeSummary.cpp */; }; 9461569D14E358A6003A195C /* SBTypeSynthetic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9461568D14E35621003A195C /* SBTypeSynthetic.cpp */; }; 946216C21A97C080006E19CC /* OptionValueLanguage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 946216C11A97C080006E19CC /* OptionValueLanguage.cpp */; }; 9463D4CD13B1798800C230D4 /* CommandObjectType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */; }; 9475C18814E5E9FA001BFC6D /* SBTypeCategory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9475C18714E5E9FA001BFC6D /* SBTypeCategory.cpp */; }; 9475C18914E5EA08001BFC6D /* SBTypeCategory.h in Headers */ = {isa = PBXBuildFile; fileRef = 9475C18514E5E9C5001BFC6D /* SBTypeCategory.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9475C18E14E5F834001BFC6D /* SBTypeNameSpecifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9475C18D14E5F834001BFC6D /* SBTypeNameSpecifier.cpp */; }; 9475C18F14E5F858001BFC6D /* SBTypeNameSpecifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 9475C18C14E5F826001BFC6D /* SBTypeNameSpecifier.h */; settings = {ATTRIBUTES = (Public, ); }; }; 947A1D641616476B0017C8D1 /* CommandObjectPlugin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 947A1D621616476A0017C8D1 /* CommandObjectPlugin.cpp */; }; 947CF7711DC7B1EE00EF980B /* ProcessMinidump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 947CF7701DC7B1EE00EF980B /* ProcessMinidump.cpp */; }; 947CF7761DC7B20D00EF980B /* RegisterContextMinidump_x86_32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 947CF7741DC7B20D00EF980B /* RegisterContextMinidump_x86_32.cpp */; }; 947CF7771DC7B20D00EF980B /* ThreadMinidump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 947CF7751DC7B20D00EF980B /* ThreadMinidump.cpp */; }; 9485545A1DCBAE3B00345FF5 /* RenderScriptScriptGroup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 948554591DCBAE3B00345FF5 /* RenderScriptScriptGroup.cpp */; }; 949ADF031406F648004833E1 /* ValueObjectConstResultImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 949ADF021406F648004833E1 /* ValueObjectConstResultImpl.cpp */; }; 949EEDA01BA74B6D008C63CF /* CoreMedia.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 949EED9E1BA74B64008C63CF /* CoreMedia.cpp */; }; 949EEDA31BA76577008C63CF /* Cocoa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 949EEDA11BA76571008C63CF /* Cocoa.cpp */; }; 949EEDAE1BA7671C008C63CF /* CF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 949EEDAC1BA76719008C63CF /* CF.cpp */; }; 949EEDAF1BA76729008C63CF /* NSArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 949EEDA41BA765B5008C63CF /* NSArray.cpp */; }; 949EEDB11BA7672D008C63CF /* NSDictionary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 949EEDA51BA765B5008C63CF /* NSDictionary.cpp */; }; 949EEDB21BA76731008C63CF /* NSIndexPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 949EEDA61BA765B5008C63CF /* NSIndexPath.cpp */; }; 949EEDB31BA76736008C63CF /* NSSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 949EEDA71BA765B5008C63CF /* NSSet.cpp */; }; 94A5B3971AB9FE8D00A5EE7F /* EmulateInstructionMIPS64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94A5B3951AB9FE8300A5EE7F /* EmulateInstructionMIPS64.cpp */; }; 94B638531B8F8E6C004FE1E4 /* Language.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94B638521B8F8E6C004FE1E4 /* Language.cpp */; }; 94B6385D1B8FB178004FE1E4 /* CPlusPlusLanguage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94B6385B1B8FB174004FE1E4 /* CPlusPlusLanguage.cpp */; }; 94B638631B8FB7F1004FE1E4 /* ObjCPlusPlusLanguage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94B638621B8FB7F1004FE1E4 /* ObjCPlusPlusLanguage.cpp */; }; 94B6E76213D88365005F417F /* ValueObjectSyntheticFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94B6E76113D88362005F417F /* ValueObjectSyntheticFilter.cpp */; }; 94B9E5121BBF20F4000A48DC /* NSString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94B9E5111BBF20F4000A48DC /* NSString.cpp */; }; 94BA8B6D176F8C9B005A91B5 /* Range.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94BA8B6C176F8C9B005A91B5 /* Range.cpp */; }; 94BA8B70176F97CE005A91B5 /* CommandHistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94BA8B6F176F97CE005A91B5 /* CommandHistory.cpp */; }; 94CB255C16B069770059775D /* DataVisualization.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CB255816B069770059775D /* DataVisualization.cpp */; }; 94CB255D16B069770059775D /* FormatClasses.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CB255916B069770059775D /* FormatClasses.cpp */; }; 94CB255E16B069770059775D /* FormatManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CB255A16B069770059775D /* FormatManager.cpp */; }; 94CB256616B096F10059775D /* TypeCategory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CB256416B096F10059775D /* TypeCategory.cpp */; }; 94CB256716B096F10059775D /* TypeCategoryMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CB256516B096F10059775D /* TypeCategoryMap.cpp */; }; 94CB257016B0A4270059775D /* TypeFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CB256D16B0A4260059775D /* TypeFormat.cpp */; }; 94CB257116B0A4270059775D /* TypeSummary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CB256E16B0A4260059775D /* TypeSummary.cpp */; }; 94CB257216B0A4270059775D /* TypeSynthetic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CB256F16B0A4270059775D /* TypeSynthetic.cpp */; }; 94CB257416B1D3880059775D /* FormatCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CB257316B1D3870059775D /* FormatCache.cpp */; }; 94CD131A19BA33B400DB7BED /* TypeValidator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CD131919BA33B400DB7BED /* TypeValidator.cpp */; }; 94CD7D0919A3FBA300908B7C /* AppleObjCClassDescriptorV2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CD7D0819A3FBA300908B7C /* AppleObjCClassDescriptorV2.cpp */; }; 94CD7D0C19A3FBCE00908B7C /* AppleObjCTypeEncodingParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CD7D0B19A3FBCE00908B7C /* AppleObjCTypeEncodingParser.cpp */; }; 94D0858C1B9675B8000D24BD /* FormattersHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D0858B1B9675B8000D24BD /* FormattersHelpers.cpp */; }; 94E829CA152D33C1006F96A3 /* lldb-server in Resources */ = {isa = PBXBuildFile; fileRef = 26DC6A101337FE6900FF7998 /* lldb-server */; }; 94F48F251A01C687005C0EC6 /* StringPrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94F48F241A01C687005C0EC6 /* StringPrinter.cpp */; }; 94FA3DE01405D50400833217 /* ValueObjectConstResultChild.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94FA3DDF1405D50300833217 /* ValueObjectConstResultChild.cpp */; }; 964381701C8D6B8200023D59 /* SBLanguageRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF20F76C1AF18FC700751A6E /* SBLanguageRuntime.cpp */; }; 964463EC1A330C0500154ED8 /* CompactUnwindInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 964463EB1A330C0500154ED8 /* CompactUnwindInfo.cpp */; }; 966C6B7918E6A56A0093F5EC /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 966C6B7818E6A56A0093F5EC /* libz.dylib */; }; 966C6B7A18E6A56A0093F5EC /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 966C6B7818E6A56A0093F5EC /* libz.dylib */; }; 966C6B7C18E6A56A0093F5EC /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 966C6B7818E6A56A0093F5EC /* libz.dylib */; }; 9694FA711B32AA64005EBB16 /* ABISysV_mips.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9694FA6F1B32AA64005EBB16 /* ABISysV_mips.cpp */; }; 9A0FDEA71E8EF5110086B2F5 /* RegisterContextLinux_mips.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A0FDE971E8EF5010086B2F5 /* RegisterContextLinux_mips.cpp */; }; + 9A1542F91F0EE48600DEA1D8 /* MockTildeExpressionResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A1542F51F0EE44000DEA1D8 /* MockTildeExpressionResolver.cpp */; }; + 9A1542FA1F0EE48600DEA1D8 /* TestUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A1542F71F0EE44000DEA1D8 /* TestUtilities.cpp */; }; 9A19A6AF1163BBB200E0D453 /* SBValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A19A6A51163BB7E00E0D453 /* SBValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9A19A6B01163BBB300E0D453 /* SBValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A19A6AD1163BB9800E0D453 /* SBValue.cpp */; }; 9A1E595C1EB2B141002206A5 /* SBTrace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A1E59521EB2B0B9002206A5 /* SBTrace.cpp */; }; 9A1E595D1EB2B141002206A5 /* SBTraceOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A1E59531EB2B0B9002206A5 /* SBTraceOptions.cpp */; }; 9A22A161135E30370024DDC3 /* EmulateInstructionARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A22A15D135E30370024DDC3 /* EmulateInstructionARM.cpp */; }; 9A22A163135E30370024DDC3 /* EmulationStateARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A22A15F135E30370024DDC3 /* EmulationStateARM.cpp */; }; 9A357583116CFDEE00E8ED2F /* SBValueList.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A357582116CFDEE00E8ED2F /* SBValueList.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9A35758E116CFE0F00E8ED2F /* SBValueList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A35758D116CFE0F00E8ED2F /* SBValueList.cpp */; }; 9A357671116E7B5200E8ED2F /* SBStringList.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A357670116E7B5200E8ED2F /* SBStringList.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9A357673116E7B6400E8ED2F /* SBStringList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A357672116E7B6400E8ED2F /* SBStringList.cpp */; }; 9A3576A8116E9AB700E8ED2F /* SBHostOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A3576A7116E9AB700E8ED2F /* SBHostOS.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9A3576AA116E9AC700E8ED2F /* SBHostOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A3576A9116E9AC700E8ED2F /* SBHostOS.cpp */; }; 9A36D24D1EB3BE7F00AAD9EA /* SBTrace.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A1E59581EB2B10D002206A5 /* SBTrace.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9A36D24E1EB3BE7F00AAD9EA /* SBTraceOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A1E59591EB2B10D002206A5 /* SBTraceOptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9A4F35101368A51A00823F52 /* StreamAsynchronousIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A4F350F1368A51A00823F52 /* StreamAsynchronousIO.cpp */; }; 9A77AD541E64E2760025CE04 /* RegisterInfoPOSIX_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A77AD501E64E24E0025CE04 /* RegisterInfoPOSIX_arm.cpp */; }; 9AC7038E117674FB0086C050 /* SBInstruction.h in Headers */ = {isa = PBXBuildFile; fileRef = 9AC7038D117674EB0086C050 /* SBInstruction.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9AC70390117675270086C050 /* SBInstructionList.h in Headers */ = {isa = PBXBuildFile; fileRef = 9AC7038F117675270086C050 /* SBInstructionList.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9AC703AF117675410086C050 /* SBInstruction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC703AE117675410086C050 /* SBInstruction.cpp */; }; 9AC703B1117675490086C050 /* SBInstructionList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC703B0117675490086C050 /* SBInstructionList.cpp */; }; 9AD9449F1E8DB26C004796ED /* RegisterContextNetBSD_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AD9449B1E8DB267004796ED /* RegisterContextNetBSD_x86_64.cpp */; }; A36FF33C17D8E94600244D40 /* OptionParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A36FF33B17D8E94600244D40 /* OptionParser.cpp */; }; AE44FB301BB07EB20033EB62 /* GoUserExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE44FB2C1BB07DD80033EB62 /* GoUserExpression.cpp */; }; AE44FB311BB07EB80033EB62 /* GoLexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE44FB2A1BB07DD80033EB62 /* GoLexer.cpp */; }; AE44FB321BB07EBC0033EB62 /* GoParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE44FB2B1BB07DD80033EB62 /* GoParser.cpp */; }; AE44FB3E1BB485960033EB62 /* GoLanguageRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE44FB3D1BB485960033EB62 /* GoLanguageRuntime.cpp */; }; AE44FB471BB4BB090033EB62 /* GoLanguage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE44FB451BB4BB090033EB62 /* GoLanguage.cpp */; }; AE44FB4C1BB4BB540033EB62 /* GoFormatterFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE44FB4A1BB4BB540033EB62 /* GoFormatterFunctions.cpp */; }; AE6897281B94F6DE0018845D /* DWARFASTParserGo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE6897261B94F6DE0018845D /* DWARFASTParserGo.cpp */; }; AE7F56291B8FE418001377A8 /* GoASTContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEFFBA7C1AC4835D0087B932 /* GoASTContext.cpp */; }; AE8F624919EF3E1E00326B21 /* OperatingSystemGo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE8F624719EF3E1E00326B21 /* OperatingSystemGo.cpp */; }; AEB0E4591BD6E9F800B24093 /* LLVMUserExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEB0E4581BD6E9F800B24093 /* LLVMUserExpression.cpp */; }; AEEA34051AC88A7400AB639D /* TypeSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEEA34041AC88A7400AB639D /* TypeSystem.cpp */; }; AF061F87182C97ED00B6A19C /* RegisterContextHistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF061F85182C97ED00B6A19C /* RegisterContextHistory.cpp */; }; AF0C112818580CD800C4C45B /* QueueItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF0C112718580CD800C4C45B /* QueueItem.cpp */; }; AF0E22F018A09FB20009B7D1 /* AppleGetItemInfoHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF0E22EE18A09FB20009B7D1 /* AppleGetItemInfoHandler.cpp */; }; AF0EBBE8185940FB0059E52F /* SBQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF0EBBE6185940FB0059E52F /* SBQueue.cpp */; }; AF0EBBE9185940FB0059E52F /* SBQueueItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF0EBBE7185940FB0059E52F /* SBQueueItem.cpp */; }; AF0EBBEC185941360059E52F /* SBQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = AF0EBBEA185941360059E52F /* SBQueue.h */; settings = {ATTRIBUTES = (Public, ); }; }; AF0EBBED185941360059E52F /* SBQueueItem.h in Headers */ = {isa = PBXBuildFile; fileRef = AF0EBBEB185941360059E52F /* SBQueueItem.h */; settings = {ATTRIBUTES = (Public, ); }; }; AF0F6E501739A76D009180FE /* RegisterContextKDP_arm64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF0F6E4E1739A76D009180FE /* RegisterContextKDP_arm64.cpp */; }; AF1729D6182C907200E0AB97 /* HistoryThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF1729D4182C907200E0AB97 /* HistoryThread.cpp */; }; AF1729D7182C907200E0AB97 /* HistoryUnwind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF1729D5182C907200E0AB97 /* HistoryUnwind.cpp */; }; AF1D88691B575E8D003CB899 /* ValueObjectConstResultCast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF94726E1B575E430063D65C /* ValueObjectConstResultCast.cpp */; }; AF1F7B07189C904B0087DB9C /* AppleGetPendingItemsHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF1F7B05189C904B0087DB9C /* AppleGetPendingItemsHandler.cpp */; }; AF20F7661AF18F8500751A6E /* ABISysV_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF20F7641AF18F8500751A6E /* ABISysV_arm.cpp */; }; AF20F76A1AF18F9000751A6E /* ABISysV_arm64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF20F7681AF18F9000751A6E /* ABISysV_arm64.cpp */; }; AF23B4DB19009C66003E2A58 /* FreeBSDSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF23B4D919009C66003E2A58 /* FreeBSDSignals.cpp */; }; AF248A4D1DA71C77000B814D /* TestArm64InstEmulation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF248A4C1DA71C77000B814D /* TestArm64InstEmulation.cpp */; }; AF254E31170CCC33007AE5C9 /* PlatformDarwinKernel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF254E2F170CCC33007AE5C9 /* PlatformDarwinKernel.cpp */; }; AF25AB26188F685C0030DEC3 /* AppleGetQueuesHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF25AB24188F685C0030DEC3 /* AppleGetQueuesHandler.cpp */; }; AF26703A1852D01E00B6CC36 /* Queue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF2670381852D01E00B6CC36 /* Queue.cpp */; }; AF26703B1852D01E00B6CC36 /* QueueList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF2670391852D01E00B6CC36 /* QueueList.cpp */; }; AF27AD551D3603EA00CF2833 /* DynamicLoaderDarwin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF27AD531D3603EA00CF2833 /* DynamicLoaderDarwin.cpp */; }; AF27AD561D3603EA00CF2833 /* DynamicLoaderDarwin.h in Headers */ = {isa = PBXBuildFile; fileRef = AF27AD541D3603EA00CF2833 /* DynamicLoaderDarwin.h */; }; AF2907BF1D3F082400E10654 /* DynamicLoaderMacOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF2907BD1D3F082400E10654 /* DynamicLoaderMacOS.cpp */; }; AF2BA6EC1A707E3400C5248A /* UriParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33064C991A5C7A330033D415 /* UriParser.cpp */; }; AF2BCA6C18C7EFDE005B4526 /* JITLoaderGDB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF2BCA6918C7EFDE005B4526 /* JITLoaderGDB.cpp */; }; AF33B4BE1C1FA441001B28D9 /* NetBSDSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF33B4BC1C1FA441001B28D9 /* NetBSDSignals.cpp */; }; AF33B4BF1C1FA441001B28D9 /* NetBSDSignals.h in Headers */ = {isa = PBXBuildFile; fileRef = AF33B4BD1C1FA441001B28D9 /* NetBSDSignals.h */; }; AF37E10A17C861F20061E18E /* ProcessRunLock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF37E10917C861F20061E18E /* ProcessRunLock.cpp */; }; AF3A4AD21EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF3A4AD01EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.cpp */; }; AF3A4AD31EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = AF3A4AD11EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.h */; }; AF415AE71D949E4400FCE0D4 /* x86AssemblyInspectionEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF415AE51D949E4400FCE0D4 /* x86AssemblyInspectionEngine.cpp */; }; AF415AE81D949E4400FCE0D4 /* x86AssemblyInspectionEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = AF415AE61D949E4400FCE0D4 /* x86AssemblyInspectionEngine.h */; }; AF45FDE518A1F3AC0007051C /* AppleGetThreadItemInfoHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF45FDE318A1F3AC0007051C /* AppleGetThreadItemInfoHandler.cpp */; }; AF6335E21C87B21E00F7D554 /* SymbolFilePDB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF6335E01C87B21E00F7D554 /* SymbolFilePDB.cpp */; }; AF6335E31C87B21E00F7D554 /* SymbolFilePDB.h in Headers */ = {isa = PBXBuildFile; fileRef = AF6335E11C87B21E00F7D554 /* SymbolFilePDB.h */; }; AF77E08F1A033C700096C0EA /* ABISysV_ppc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF77E08D1A033C700096C0EA /* ABISysV_ppc.cpp */; }; AF77E0931A033C7F0096C0EA /* ABISysV_ppc64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF77E0911A033C7F0096C0EA /* ABISysV_ppc64.cpp */; }; AF77E0A11A033D360096C0EA /* RegisterContextFreeBSD_powerpc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF77E09A1A033D360096C0EA /* RegisterContextFreeBSD_powerpc.cpp */; }; AF77E0A41A033D360096C0EA /* RegisterContextPOSIX_powerpc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF77E09D1A033D360096C0EA /* RegisterContextPOSIX_powerpc.cpp */; }; AF77E0A91A033D740096C0EA /* RegisterContextPOSIXCore_powerpc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF77E0A71A033D740096C0EA /* RegisterContextPOSIXCore_powerpc.cpp */; }; AF81DEFA1828A23F0042CF19 /* SystemRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF81DEF91828A23F0042CF19 /* SystemRuntime.cpp */; }; AF8AD62E1BEC28A400150209 /* PlatformAppleTVSimulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF8AD62A1BEC28A400150209 /* PlatformAppleTVSimulator.cpp */; }; AF8AD62F1BEC28A400150209 /* PlatformAppleTVSimulator.h in Headers */ = {isa = PBXBuildFile; fileRef = AF8AD62B1BEC28A400150209 /* PlatformAppleTVSimulator.h */; }; AF8AD6301BEC28A400150209 /* PlatformAppleWatchSimulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF8AD62C1BEC28A400150209 /* PlatformAppleWatchSimulator.cpp */; }; AF8AD6311BEC28A400150209 /* PlatformAppleWatchSimulator.h in Headers */ = {isa = PBXBuildFile; fileRef = AF8AD62D1BEC28A400150209 /* PlatformAppleWatchSimulator.h */; }; AF8AD6371BEC28C400150209 /* PlatformRemoteAppleTV.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF8AD6331BEC28C400150209 /* PlatformRemoteAppleTV.cpp */; }; AF8AD6381BEC28C400150209 /* PlatformRemoteAppleTV.h in Headers */ = {isa = PBXBuildFile; fileRef = AF8AD6341BEC28C400150209 /* PlatformRemoteAppleTV.h */; }; AF8AD6391BEC28C400150209 /* PlatformRemoteAppleWatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF8AD6351BEC28C400150209 /* PlatformRemoteAppleWatch.cpp */; }; AF8AD63A1BEC28C400150209 /* PlatformRemoteAppleWatch.h in Headers */ = {isa = PBXBuildFile; fileRef = AF8AD6361BEC28C400150209 /* PlatformRemoteAppleWatch.h */; }; AF90106515AB7D3600FF120D /* lldb.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = AF90106315AB7C5700FF120D /* lldb.1 */; }; AF9107EE168570D200DBCD3C /* RegisterContextDarwin_arm64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF9107EC168570D200DBCD3C /* RegisterContextDarwin_arm64.cpp */; }; AF9107EF168570D200DBCD3C /* RegisterContextDarwin_arm64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF9107EC168570D200DBCD3C /* RegisterContextDarwin_arm64.cpp */; }; AF9B8F33182DB52900DA866F /* SystemRuntimeMacOSX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF9B8F31182DB52900DA866F /* SystemRuntimeMacOSX.cpp */; }; AFAFD80A1E57E1B90017A14F /* ModuleCacheTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFAFD8091E57E1B90017A14F /* ModuleCacheTest.cpp */; }; AFB3D2801AC262AB003B4B30 /* MICmdCmdGdbShow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFB3D27E1AC262AB003B4B30 /* MICmdCmdGdbShow.cpp */; }; AFC234091AF85CE100CDE8B6 /* CommandObjectLanguage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFC234061AF85CE000CDE8B6 /* CommandObjectLanguage.cpp */; }; AFC2DCE71E6E2ED000283714 /* FastDemangle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFC2DCE61E6E2ED000283714 /* FastDemangle.cpp */; }; AFC2DCE91E6E2F2C00283714 /* Baton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFC2DCE81E6E2F2C00283714 /* Baton.cpp */; }; AFC2DCEB1E6E2F7D00283714 /* UserID.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFC2DCEA1E6E2F7D00283714 /* UserID.cpp */; }; AFC2DCF01E6E2FD200283714 /* VMRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFC2DCEF1E6E2FD200283714 /* VMRange.cpp */; }; AFC2DCF31E6E30CF00283714 /* History.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFC2DCF21E6E30CF00283714 /* History.cpp */; }; AFC2DCF61E6E316A00283714 /* StreamCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFC2DCF51E6E316A00283714 /* StreamCallback.cpp */; }; AFC2DCF91E6E318000283714 /* StreamGDBRemote.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFC2DCF81E6E318000283714 /* StreamGDBRemote.cpp */; }; AFCB2BBD1BF577F40018B553 /* PythonExceptionState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFCB2BBB1BF577F40018B553 /* PythonExceptionState.cpp */; }; AFCB2BBE1BF577F40018B553 /* PythonExceptionState.h in Headers */ = {isa = PBXBuildFile; fileRef = AFCB2BBC1BF577F40018B553 /* PythonExceptionState.h */; }; AFD65C811D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFD65C7F1D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.cpp */; }; AFD65C821D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = AFD65C801D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.h */; }; AFDCDBCB19DD0F42005EA55E /* SBExecutionContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 940B02F419DC96CB00AD0F52 /* SBExecutionContext.h */; settings = {ATTRIBUTES = (Public, ); }; }; AFDFDFD119E34D3400EAE509 /* ConnectionFileDescriptorPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFDFDFD019E34D3400EAE509 /* ConnectionFileDescriptorPosix.cpp */; }; AFEC3362194A8ABA00FF05C6 /* StructuredData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFEC3361194A8ABA00FF05C6 /* StructuredData.cpp */; }; AFEC5FD81D94F9380076A480 /* Testx86AssemblyInspectionEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFEC5FD51D94F9380076A480 /* Testx86AssemblyInspectionEngine.cpp */; }; AFF87C87150FF669000E1742 /* com.apple.debugserver.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = AFF87C86150FF669000E1742 /* com.apple.debugserver.plist */; }; AFF87C8F150FF688000E1742 /* com.apple.debugserver.applist.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = AFF87C8E150FF688000E1742 /* com.apple.debugserver.applist.plist */; }; AFF8FF0C1E779D4B003830EF /* TildeExpressionResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFF8FF0B1E779D4B003830EF /* TildeExpressionResolver.cpp */; }; B207C4931429607D00F36E4E /* CommandObjectWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B207C4921429607D00F36E4E /* CommandObjectWatchpoint.cpp */; }; B2462247141AD37D00F3D409 /* OptionGroupWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2462246141AD37D00F3D409 /* OptionGroupWatchpoint.cpp */; }; B27318421416AC12006039C8 /* WatchpointList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B27318411416AC12006039C8 /* WatchpointList.cpp */; }; B28058A1139988B0002D96D0 /* InferiorCallPOSIX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B28058A0139988B0002D96D0 /* InferiorCallPOSIX.cpp */; }; B299580B14F2FA1400050A04 /* DisassemblerLLVMC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B299580A14F2FA1400050A04 /* DisassemblerLLVMC.cpp */; }; B2A58722143119810092BFBA /* SBWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = B2A58721143119810092BFBA /* SBWatchpoint.h */; settings = {ATTRIBUTES = (Public, ); }; }; B2A58724143119D50092BFBA /* SBWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2A58723143119D50092BFBA /* SBWatchpoint.cpp */; }; B2B7CCEB15D1BD6700EEFB57 /* CommandObjectWatchpointCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2B7CCEA15D1BD6600EEFB57 /* CommandObjectWatchpointCommand.cpp */; }; B2B7CCF015D1C20F00EEFB57 /* WatchpointOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2B7CCEF15D1C20F00EEFB57 /* WatchpointOptions.cpp */; }; D67521381EA17C4200439694 /* MainLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D67521351EA17C3900439694 /* MainLoop.cpp */; }; E769331C1A94D15400C73337 /* lldb-gdbserver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D6F3F4183E7F9300194858 /* lldb-gdbserver.cpp */; }; E769331E1A94D18100C73337 /* lldb-server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E769331D1A94D18100C73337 /* lldb-server.cpp */; }; E7723D441AC4A7FB002BA082 /* RegisterContextPOSIXCore_arm64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E7723D421AC4A7FB002BA082 /* RegisterContextPOSIXCore_arm64.cpp */; }; E7723D4C1AC4A944002BA082 /* RegisterContextPOSIX_arm64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E7723D4A1AC4A944002BA082 /* RegisterContextPOSIX_arm64.cpp */; }; E778E9A21B062D1700247609 /* EmulateInstructionMIPS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E778E99F1B062D1700247609 /* EmulateInstructionMIPS.cpp */; }; E7E94ABC1B54961F00D0AE30 /* GDBRemoteSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E73A15A41B548EC500786197 /* GDBRemoteSignals.cpp */; }; EB8375E71B553DE800BA907D /* ThreadPlanCallFunctionUsingABI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EB8375E61B553DE800BA907D /* ThreadPlanCallFunctionUsingABI.cpp */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 239504C41BDD3FD700963CEA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 265E9BE1115C2BAA00D0DCCB /* debugserver.xcodeproj */; proxyType = 2; remoteGlobalIDString = 456F67721AD46CE9002850C2; remoteInfo = "debugserver-mini"; }; 23CB15311D66DA9300EDDDE1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 2689FFC913353D7A00698AC0; remoteInfo = "lldb-core"; }; 23E2E5471D904D72006F38BB /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 23CB152F1D66DA9300EDDDE1; remoteInfo = "lldb-gtest-for-debugging"; }; 262CFC7111A450CB00946C6C /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 265E9BE1115C2BAA00D0DCCB /* debugserver.xcodeproj */; proxyType = 1; remoteGlobalIDString = 26CE0593115C31C20022F371; remoteInfo = debugserver; }; 26368AF5126B95FA00E8659F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 26579F67126A25920007C5CB; remoteInfo = "darwin-debug"; }; 266803611160110D008E1FE4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 26680206115FD0ED008E1FE4; remoteInfo = LLDB; }; 2687EACA1508115000DD8C2E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 2687EAC51508110B00DD8C2E; remoteInfo = "install-headers"; }; 2687EACC1508115900DD8C2E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 2687EAC51508110B00DD8C2E; remoteInfo = "install-headers"; }; 2687EACE1508116300DD8C2E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 2687EAC51508110B00DD8C2E; remoteInfo = "install-headers"; }; 2689011413353E9B00698AC0 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 2689FFC913353D7A00698AC0; remoteInfo = "lldb-core"; }; 26B391EE1A6DCCAF00456239 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 2690CD161A6DC0D000E717C8; remoteInfo = "lldb-mi"; }; 26B391F01A6DCCBE00456239 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 2690CD161A6DC0D000E717C8; remoteInfo = "lldb-mi"; }; 26CE059F115C31E50022F371 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 265E9BE1115C2BAA00D0DCCB /* debugserver.xcodeproj */; proxyType = 2; remoteGlobalIDString = 26CE0594115C31C20022F371; remoteInfo = "lldb-debugserver"; }; 26CEF3AF14FD591F007286B2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 26F5C26910F3D9A4009D5894; remoteInfo = "lldb-tool"; }; 26CEF3BA14FD595B007286B2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 26F5C26910F3D9A4009D5894; remoteInfo = "lldb-tool"; }; 26CEF3C114FD5973007286B2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 26F5C26910F3D9A4009D5894; remoteInfo = "lldb-tool"; }; 26DC6A151337FE7300FF7998 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 2689FFC913353D7A00698AC0; remoteInfo = "lldb-core"; }; 26DF745F1A6DCDB300B85563 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 26680206115FD0ED008E1FE4; remoteInfo = LLDB; }; 942829C91A89836A00521B30 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 2689FFC913353D7A00698AC0; remoteInfo = "lldb-core"; }; 942829CD1A89842900521B30 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 942829BF1A89835300521B30; remoteInfo = argdumper; }; 94E829C8152D33B4006F96A3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 26DC6A0F1337FE6900FF7998; remoteInfo = "lldb-server"; }; AFCA21D11D18E556004386B8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 265E9BE1115C2BAA00D0DCCB /* debugserver.xcodeproj */; proxyType = 1; remoteGlobalIDString = 456F67431AD46CE9002850C2; remoteInfo = "debugserver-mini"; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ 239504D21BDD451400963CEA /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = /usr/share/man/man1/; dstSubfolderSpec = 0; files = ( ); runOnlyForDeploymentPostprocessing = 1; }; 23CB154F1D66DA9300EDDDE1 /* Copy Files */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = /usr/share/man/man1/; dstSubfolderSpec = 0; files = ( ); name = "Copy Files"; runOnlyForDeploymentPostprocessing = 1; }; 940B04E31A89875C0045D5F7 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 7; files = ( 940B04E41A8987680045D5F7 /* lldb-argdumper in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; 942829BE1A89835300521B30 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = /usr/share/man/man1/; dstSubfolderSpec = 0; files = ( ); runOnlyForDeploymentPostprocessing = 1; }; AF90106415AB7D2900FF120D /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; dstPath = "$(DEVELOPER_INSTALL_DIR)/usr/share/man/man1"; dstSubfolderSpec = 0; files = ( 492DB7E71EC662B100B9E9AF /* Status.h in CopyFiles */, AF90106515AB7D3600FF120D /* lldb.1 in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; AFF87C85150FF5CC000E1742 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; dstPath = /Developer/Library/Lockdown/ServiceAgents/; dstSubfolderSpec = 0; files = ( 268648C416531BF800F04704 /* com.apple.debugserver.posix.plist in CopyFiles */, 268648C516531BF800F04704 /* com.apple.debugserver.applist.internal.plist in CopyFiles */, 268648C616531BF800F04704 /* com.apple.debugserver.internal.plist in CopyFiles */, AFF87C87150FF669000E1742 /* com.apple.debugserver.plist in CopyFiles */, AFF87C8F150FF688000E1742 /* com.apple.debugserver.applist.plist in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 1; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 23042D101976CA0A00621B2C /* PlatformKalimba.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformKalimba.cpp; sourceTree = ""; }; 23042D111976CA0A00621B2C /* PlatformKalimba.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlatformKalimba.h; sourceTree = ""; }; 23059A0519532B96007B8189 /* LinuxSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LinuxSignals.cpp; path = Utility/LinuxSignals.cpp; sourceTree = ""; }; 23059A0619532B96007B8189 /* LinuxSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LinuxSignals.h; path = Utility/LinuxSignals.h; sourceTree = ""; }; 23059A0F1958B319007B8189 /* SBUnixSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBUnixSignals.cpp; path = source/API/SBUnixSignals.cpp; sourceTree = ""; }; 23059A111958B37B007B8189 /* SBUnixSignals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBUnixSignals.h; path = include/lldb/API/SBUnixSignals.h; sourceTree = ""; }; 230EC4571D63C3A7008DF59F /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = CMakeLists.txt; path = source/Target/CMakeLists.txt; sourceTree = ""; }; 230EC4581D63C3A7008DF59F /* ThreadPlanCallOnFunctionExit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanCallOnFunctionExit.cpp; path = source/Target/ThreadPlanCallOnFunctionExit.cpp; sourceTree = ""; }; 23173F8B192BA93F005C708F /* lldb-x86-register-enums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lldb-x86-register-enums.h"; path = "Utility/lldb-x86-register-enums.h"; sourceTree = ""; }; 2321F9381BDD332400BA9A93 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 2321F9391BDD332400BA9A93 /* SocketAddressTest.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SocketAddressTest.cpp; sourceTree = ""; }; 2321F93A1BDD332400BA9A93 /* SocketTest.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SocketTest.cpp; sourceTree = ""; }; 2321F93B1BDD332400BA9A93 /* SymbolsTest.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolsTest.cpp; sourceTree = ""; }; 2321F93D1BDD33CE00BA9A93 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 2321F93E1BDD33CE00BA9A93 /* TestArgs.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TestArgs.cpp; sourceTree = ""; }; 2321F9401BDD340D00BA9A93 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 2321F9431BDD346100BA9A93 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 2321F9441BDD346100BA9A93 /* StringExtractorTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringExtractorTest.cpp; sourceTree = ""; }; 2321F9451BDD346100BA9A93 /* TaskPoolTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TaskPoolTest.cpp; sourceTree = ""; }; 2321F9461BDD346100BA9A93 /* UriParserTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UriParserTest.cpp; sourceTree = ""; }; 2321F94C1BDD360F00BA9A93 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 2321F94D1BDD360F00BA9A93 /* PythonDataObjectsTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PythonDataObjectsTests.cpp; sourceTree = ""; }; 2326CF3F1BDD613E00A5CEAC /* Python.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Python.framework; path = System/Library/Frameworks/Python.framework; sourceTree = SDKROOT; }; 2326CF451BDD647400A5CEAC /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 2326CF471BDD67C100A5CEAC /* libncurses.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libncurses.dylib; path = ../../../../../../usr/lib/libncurses.dylib; sourceTree = ""; }; 2326CF4A1BDD681800A5CEAC /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = ../../../../../../usr/lib/libz.dylib; sourceTree = ""; }; 2326CF4C1BDD684B00A5CEAC /* libedit.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libedit.dylib; path = ../../../../../../usr/lib/libedit.dylib; sourceTree = ""; }; 2326CF4E1BDD687800A5CEAC /* libpanel.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpanel.dylib; path = ../../../../../../usr/lib/libpanel.dylib; sourceTree = ""; }; 2326CF511BDD693B00A5CEAC /* EditlineTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EditlineTest.cpp; sourceTree = ""; }; 232CB60B191E00CC00EF39FC /* NativeBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeBreakpoint.cpp; path = source/Host/common/NativeBreakpoint.cpp; sourceTree = ""; }; 232CB60D191E00CC00EF39FC /* NativeBreakpointList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeBreakpointList.cpp; path = source/Host/common/NativeBreakpointList.cpp; sourceTree = ""; }; 232CB60F191E00CC00EF39FC /* NativeProcessProtocol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = NativeProcessProtocol.cpp; path = source/Host/common/NativeProcessProtocol.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 232CB611191E00CC00EF39FC /* NativeThreadProtocol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeThreadProtocol.cpp; path = source/Host/common/NativeThreadProtocol.cpp; sourceTree = ""; }; 232CB613191E00CC00EF39FC /* SoftwareBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SoftwareBreakpoint.cpp; path = source/Host/common/SoftwareBreakpoint.cpp; sourceTree = ""; }; 233B007919609DB40090E598 /* ProcessLaunchInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ProcessLaunchInfo.h; path = include/lldb/Target/ProcessLaunchInfo.h; sourceTree = ""; }; 233B007A1960A0440090E598 /* ProcessInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ProcessInfo.h; path = include/lldb/Target/ProcessInfo.h; sourceTree = ""; }; 233B007B1960C9E60090E598 /* ProcessInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProcessInfo.cpp; path = source/Target/ProcessInfo.cpp; sourceTree = ""; }; 233B007E1960CB280090E598 /* ProcessLaunchInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProcessLaunchInfo.cpp; path = source/Target/ProcessLaunchInfo.cpp; sourceTree = ""; }; 233B009D19610D6B0090E598 /* Host.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Host.cpp; sourceTree = ""; }; 2360092C193FB21500189DB1 /* MemoryRegionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MemoryRegionInfo.h; path = include/lldb/Target/MemoryRegionInfo.h; sourceTree = ""; }; 236102981CF38A2B00B8E0B9 /* AddLLDB.cmake */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = AddLLDB.cmake; sourceTree = ""; }; 236102991CF38A2B00B8E0B9 /* LLDBConfig.cmake */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LLDBConfig.cmake; sourceTree = ""; }; 2361029A1CF38A2B00B8E0B9 /* LLDBStandalone.cmake */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LLDBStandalone.cmake; sourceTree = ""; }; 2361029E1CF38A3500B8E0B9 /* Android.cmake */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Android.cmake; sourceTree = ""; }; 236124A21986B4E2004EFC37 /* IOObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IOObject.cpp; path = source/Utility/IOObject.cpp; sourceTree = ""; }; 236124A31986B4E2004EFC37 /* Socket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Socket.cpp; sourceTree = ""; }; 236124A61986B50E004EFC37 /* IOObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = IOObject.h; path = include/lldb/Utility/IOObject.h; sourceTree = ""; }; 236124A71986B50E004EFC37 /* Socket.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Socket.h; path = include/lldb/Host/Socket.h; sourceTree = ""; }; 2370A37A1D66C57B000E7BE6 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 2370A37C1D66C587000E7BE6 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 2370A37D1D66C587000E7BE6 /* GDBRemoteClientBaseTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteClientBaseTest.cpp; sourceTree = ""; }; 2370A37E1D66C587000E7BE6 /* GDBRemoteCommunicationClientTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunicationClientTest.cpp; sourceTree = ""; }; 2370A37F1D66C587000E7BE6 /* GDBRemoteTestUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteTestUtils.cpp; sourceTree = ""; }; 2370A3801D66C587000E7BE6 /* GDBRemoteTestUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDBRemoteTestUtils.h; sourceTree = ""; }; 2374D7431D4BAA1D005C9575 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 2374D74E1D4BB299005C9575 /* GDBRemoteClientBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteClientBase.cpp; sourceTree = ""; }; 2374D74F1D4BB299005C9575 /* GDBRemoteClientBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDBRemoteClientBase.h; sourceTree = ""; }; 2377C2F719E613C100737875 /* PipePosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PipePosix.cpp; sourceTree = ""; }; 237A8BAB1DEC9BBC00CEBAFF /* RegisterInfoPOSIX_arm64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterInfoPOSIX_arm64.cpp; path = Utility/RegisterInfoPOSIX_arm64.cpp; sourceTree = ""; }; 237A8BAC1DEC9BBC00CEBAFF /* RegisterInfoPOSIX_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterInfoPOSIX_arm64.h; path = Utility/RegisterInfoPOSIX_arm64.h; sourceTree = ""; }; 237C577A19AF9D9F00213D59 /* HostInfoLinux.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HostInfoLinux.h; path = include/lldb/Host/linux/HostInfoLinux.h; sourceTree = SOURCE_ROOT; }; 238F2B9D1D2C82D0001FF92A /* StructuredDataPlugin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StructuredDataPlugin.cpp; path = source/Target/StructuredDataPlugin.cpp; sourceTree = ""; }; 238F2B9F1D2C835A001FF92A /* StructuredDataPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StructuredDataPlugin.h; path = include/lldb/Target/StructuredDataPlugin.h; sourceTree = ""; }; 238F2BA01D2C835A001FF92A /* SystemRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SystemRuntime.h; path = include/lldb/Target/SystemRuntime.h; sourceTree = ""; }; 238F2BA61D2C85FA001FF92A /* StructuredDataDarwinLog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StructuredDataDarwinLog.cpp; sourceTree = ""; }; 238F2BA71D2C85FA001FF92A /* StructuredDataDarwinLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructuredDataDarwinLog.h; sourceTree = ""; }; 239481851C59EBDD00DF7168 /* libncurses.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libncurses.dylib; path = ../../../../../usr/lib/libncurses.dylib; sourceTree = ""; }; 239504C21BDD3FD600963CEA /* gtest_common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = gtest_common.h; sourceTree = ""; }; 239504C61BDD3FF300963CEA /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 239504D41BDD451400963CEA /* lldb-gtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "lldb-gtest"; sourceTree = BUILT_PRODUCTS_DIR; }; 23AB052D199FF639003B8084 /* FreeBSDThread.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FreeBSDThread.cpp; sourceTree = ""; }; 23AB052E199FF639003B8084 /* FreeBSDThread.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FreeBSDThread.h; sourceTree = ""; }; 23AB052F199FF639003B8084 /* ProcessFreeBSD.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessFreeBSD.cpp; sourceTree = ""; }; 23AB0530199FF639003B8084 /* ProcessFreeBSD.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ProcessFreeBSD.h; sourceTree = ""; }; 23AB0531199FF639003B8084 /* ProcessMonitor.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessMonitor.cpp; sourceTree = ""; }; 23AB0532199FF639003B8084 /* ProcessMonitor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ProcessMonitor.h; sourceTree = ""; }; 23CB14E31D66CA2200EDDDE1 /* libxml2.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.2.dylib; path = usr/lib/libxml2.2.dylib; sourceTree = SDKROOT; }; 23CB14E61D66CC0E00EDDDE1 /* BroadcasterTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BroadcasterTest.cpp; sourceTree = ""; }; 23CB14E71D66CC0E00EDDDE1 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 23CB14E81D66CC0E00EDDDE1 /* DataExtractorTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DataExtractorTest.cpp; sourceTree = ""; }; 23CB14E91D66CC0E00EDDDE1 /* ScalarTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScalarTest.cpp; sourceTree = ""; }; 23CB14F11D66CC9000EDDDE1 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 23CB14F31D66CC9B00EDDDE1 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 23CB14F61D66CCD600EDDDE1 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 23CB14F91D66CCF100EDDDE1 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 23CB14FA1D66CCF100EDDDE1 /* CPlusPlusLanguageTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CPlusPlusLanguageTest.cpp; sourceTree = ""; }; 23CB14FD1D66CD2400EDDDE1 /* FileSpecTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileSpecTest.cpp; sourceTree = ""; }; 23CB15051D66CDB400EDDDE1 /* TestModule.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = TestModule.c; sourceTree = ""; }; 23CB15061D66CDB400EDDDE1 /* TestModule.so */ = {isa = PBXFileReference; lastKnownFileType = file; path = TestModule.so; sourceTree = ""; }; 23CB150B1D66CF5600EDDDE1 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 23CB150C1D66CF5600EDDDE1 /* TestClangASTContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestClangASTContext.cpp; sourceTree = ""; }; 23CB15101D66CF6900EDDDE1 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 23CB15131D66CF8700EDDDE1 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 23CB15141D66CF8700EDDDE1 /* SymbolFilePDBTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolFilePDBTests.cpp; sourceTree = ""; }; 23CB15191D66CFAC00EDDDE1 /* test-dwarf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "test-dwarf.cpp"; sourceTree = ""; }; 23CB151A1D66CFAC00EDDDE1 /* test-dwarf.exe */ = {isa = PBXFileReference; lastKnownFileType = file; path = "test-dwarf.exe"; sourceTree = ""; }; 23CB151B1D66CFAC00EDDDE1 /* test-pdb-alt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "test-pdb-alt.cpp"; sourceTree = ""; }; 23CB151C1D66CFAC00EDDDE1 /* test-pdb-nested.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "test-pdb-nested.h"; sourceTree = ""; }; 23CB151D1D66CFAC00EDDDE1 /* test-pdb-types.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "test-pdb-types.cpp"; sourceTree = ""; }; 23CB151E1D66CFAC00EDDDE1 /* test-pdb-types.exe */ = {isa = PBXFileReference; lastKnownFileType = file; path = "test-pdb-types.exe"; sourceTree = ""; }; 23CB151F1D66CFAC00EDDDE1 /* test-pdb-types.pdb */ = {isa = PBXFileReference; lastKnownFileType = file; path = "test-pdb-types.pdb"; sourceTree = ""; }; 23CB15201D66CFAC00EDDDE1 /* test-pdb.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "test-pdb.cpp"; sourceTree = ""; }; 23CB15211D66CFAC00EDDDE1 /* test-pdb.exe */ = {isa = PBXFileReference; lastKnownFileType = file; path = "test-pdb.exe"; sourceTree = ""; }; 23CB15221D66CFAC00EDDDE1 /* test-pdb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "test-pdb.h"; sourceTree = ""; }; 23CB15231D66CFAC00EDDDE1 /* test-pdb.pdb */ = {isa = PBXFileReference; lastKnownFileType = file; path = "test-pdb.pdb"; sourceTree = ""; }; 23CB15561D66DA9300EDDDE1 /* lldb-gtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "lldb-gtest"; sourceTree = BUILT_PRODUCTS_DIR; }; 23D065811D4A7BDA0008EDE6 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 23D065821D4A7BDA0008EDE6 /* RenderScriptExpressionOpts.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderScriptExpressionOpts.cpp; sourceTree = ""; }; 23D065831D4A7BDA0008EDE6 /* RenderScriptExpressionOpts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderScriptExpressionOpts.h; sourceTree = ""; }; 23D065841D4A7BDA0008EDE6 /* RenderScriptRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderScriptRuntime.cpp; sourceTree = ""; }; 23D065851D4A7BDA0008EDE6 /* RenderScriptRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderScriptRuntime.h; sourceTree = ""; }; 23D065861D4A7BDA0008EDE6 /* RenderScriptx86ABIFixups.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderScriptx86ABIFixups.cpp; sourceTree = ""; }; 23D065871D4A7BDA0008EDE6 /* RenderScriptx86ABIFixups.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderScriptx86ABIFixups.h; sourceTree = ""; }; 23DCBE971D63E14B0084C36B /* SBLanguageRuntime.i */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBLanguageRuntime.i; sourceTree = ""; }; 23DCBE981D63E14B0084C36B /* SBStructuredData.i */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBStructuredData.i; sourceTree = ""; }; 23DCBE991D63E14B0084C36B /* SBTypeEnumMember.i */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBTypeEnumMember.i; sourceTree = ""; }; 23DCBE9A1D63E14B0084C36B /* SBUnixSignals.i */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBUnixSignals.i; sourceTree = ""; }; 23DCBE9F1D63E3800084C36B /* SBStructuredData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBStructuredData.h; path = include/lldb/API/SBStructuredData.h; sourceTree = ""; }; 23DCBEA01D63E6440084C36B /* SBStructuredData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBStructuredData.cpp; path = source/API/SBStructuredData.cpp; sourceTree = ""; }; 23DCEA421D1C4C6900A602B4 /* SBMemoryRegionInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBMemoryRegionInfo.cpp; path = source/API/SBMemoryRegionInfo.cpp; sourceTree = ""; }; 23DCEA431D1C4C6900A602B4 /* SBMemoryRegionInfoList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBMemoryRegionInfoList.cpp; path = source/API/SBMemoryRegionInfoList.cpp; sourceTree = ""; }; 23DDF224196C3EE600BB8417 /* CommandOptionValidators.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandOptionValidators.cpp; path = source/Interpreter/CommandOptionValidators.cpp; sourceTree = ""; }; 23E2E5161D903689006F38BB /* ArchSpecTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArchSpecTest.cpp; sourceTree = ""; }; 23E2E5191D9036F2006F38BB /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 23E2E51A1D9036F2006F38BB /* MinidumpParserTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MinidumpParserTest.cpp; sourceTree = ""; }; 23E2E51E1D903726006F38BB /* fizzbuzz_no_heap.dmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fizzbuzz_no_heap.dmp; sourceTree = ""; }; 23E2E51F1D903726006F38BB /* linux-x86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "linux-x86_64.cpp"; sourceTree = ""; }; 23E2E5201D903726006F38BB /* linux-x86_64.dmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = "linux-x86_64.dmp"; sourceTree = ""; }; 23E2E52D1D90382B006F38BB /* BreakpointIDTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BreakpointIDTest.cpp; sourceTree = ""; }; 23E2E52E1D90382B006F38BB /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 23E2E5361D9048FB006F38BB /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 23E2E5371D9048FB006F38BB /* MinidumpParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MinidumpParser.cpp; sourceTree = ""; }; 23E2E5381D9048FB006F38BB /* MinidumpParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MinidumpParser.h; sourceTree = ""; }; 23E2E5391D9048FB006F38BB /* MinidumpTypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MinidumpTypes.cpp; sourceTree = ""; }; 23E2E53A1D9048FB006F38BB /* MinidumpTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MinidumpTypes.h; sourceTree = ""; }; 23E77CD61C20F29F007192AD /* DWARFDebugMacro.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFDebugMacro.cpp; sourceTree = ""; }; 23E77CD71C20F29F007192AD /* DWARFDebugMacro.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFDebugMacro.h; sourceTree = ""; }; 23E77CDB1C20F2F2007192AD /* DebugMacros.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DebugMacros.cpp; path = source/Symbol/DebugMacros.cpp; sourceTree = ""; }; 23EDE3301926839700F6A132 /* NativeRegisterContext.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = NativeRegisterContext.cpp; path = source/Host/common/NativeRegisterContext.cpp; sourceTree = ""; }; 23EDE3311926843600F6A132 /* NativeRegisterContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeRegisterContext.h; path = include/lldb/Host/common/NativeRegisterContext.h; sourceTree = ""; }; 23EDE3371926AAD500F6A132 /* RegisterInfoInterface.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RegisterInfoInterface.h; path = Utility/RegisterInfoInterface.h; sourceTree = ""; }; 23EFE388193D1ABC00E54E54 /* SBTypeEnumMember.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBTypeEnumMember.h; path = include/lldb/API/SBTypeEnumMember.h; sourceTree = ""; }; 23EFE38A193D1AEC00E54E54 /* SBTypeEnumMember.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SBTypeEnumMember.cpp; path = source/API/SBTypeEnumMember.cpp; sourceTree = ""; }; 23F403471926C8D50046DC9B /* NativeRegisterContextRegisterInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeRegisterContextRegisterInfo.h; path = Utility/NativeRegisterContextRegisterInfo.h; sourceTree = ""; }; 23F403481926CC250046DC9B /* NativeRegisterContextRegisterInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeRegisterContextRegisterInfo.cpp; path = Utility/NativeRegisterContextRegisterInfo.cpp; sourceTree = ""; }; 250D6AE11A9679270049CC70 /* FileSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileSystem.cpp; sourceTree = ""; }; 25420ECC1A6490B8009ADBCB /* OptionValueChar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueChar.cpp; path = source/Interpreter/OptionValueChar.cpp; sourceTree = ""; }; 25420ECE1A64911B009ADBCB /* OptionValueChar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionValueChar.h; path = include/lldb/Interpreter/OptionValueChar.h; sourceTree = ""; }; 25420ED11A649D88009ADBCB /* PipeBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PipeBase.cpp; sourceTree = ""; }; 254FBB921A81AA5200BD6378 /* SBLaunchInfo.i */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBLaunchInfo.i; sourceTree = ""; }; 254FBB941A81AA7F00BD6378 /* SBLaunchInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBLaunchInfo.cpp; path = source/API/SBLaunchInfo.cpp; sourceTree = ""; }; 254FBB961A81B03100BD6378 /* SBLaunchInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBLaunchInfo.h; path = include/lldb/API/SBLaunchInfo.h; sourceTree = ""; }; 254FBBA21A9166F100BD6378 /* SBAttachInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBAttachInfo.h; path = include/lldb/API/SBAttachInfo.h; sourceTree = ""; }; 254FBBA41A91670E00BD6378 /* SBAttachInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBAttachInfo.cpp; path = source/API/SBAttachInfo.cpp; sourceTree = ""; }; 254FBBA61A91672800BD6378 /* SBAttachInfo.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBAttachInfo.i; sourceTree = ""; }; 255EFF6F1AFABA320069F277 /* LockFileWindows.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LockFileWindows.h; path = include/lldb/Host/windows/LockFileWindows.h; sourceTree = ""; }; 255EFF701AFABA320069F277 /* PipeWindows.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PipeWindows.h; path = include/lldb/Host/windows/PipeWindows.h; sourceTree = ""; }; 255EFF711AFABA4D0069F277 /* LockFileWindows.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LockFileWindows.cpp; path = source/Host/windows/LockFileWindows.cpp; sourceTree = ""; }; 255EFF731AFABA720069F277 /* LockFileBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LockFileBase.cpp; sourceTree = ""; }; 255EFF751AFABA950069F277 /* LockFilePosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LockFilePosix.cpp; sourceTree = ""; }; 256CBDB21ADD0EFD00BC6CDC /* RegisterContextPOSIXCore_arm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextPOSIXCore_arm.cpp; sourceTree = ""; }; 256CBDB31ADD0EFD00BC6CDC /* RegisterContextPOSIXCore_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextPOSIXCore_arm.h; sourceTree = ""; }; 256CBDB81ADD107200BC6CDC /* RegisterContextLinux_mips64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextLinux_mips64.cpp; path = Utility/RegisterContextLinux_mips64.cpp; sourceTree = ""; }; 256CBDB91ADD107200BC6CDC /* RegisterContextLinux_mips64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextLinux_mips64.h; path = Utility/RegisterContextLinux_mips64.h; sourceTree = ""; }; 256CBDBE1ADD11C000BC6CDC /* RegisterContextPOSIX_arm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextPOSIX_arm.cpp; path = Utility/RegisterContextPOSIX_arm.cpp; sourceTree = ""; }; 256CBDBF1ADD11C000BC6CDC /* RegisterContextPOSIX_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextPOSIX_arm.h; path = Utility/RegisterContextPOSIX_arm.h; sourceTree = ""; }; 2579065A1BD0488100178368 /* TCPSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TCPSocket.cpp; sourceTree = ""; }; 2579065B1BD0488100178368 /* UDPSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UDPSocket.cpp; sourceTree = ""; }; 2579065E1BD0488D00178368 /* DomainSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DomainSocket.cpp; sourceTree = ""; }; 257906621BD5AFD000178368 /* Acceptor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Acceptor.cpp; path = "tools/lldb-server/Acceptor.cpp"; sourceTree = ""; }; 257906631BD5AFD000178368 /* Acceptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Acceptor.h; path = "tools/lldb-server/Acceptor.h"; sourceTree = ""; }; 25EF23751AC09AD800908DF0 /* AdbClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AdbClient.cpp; sourceTree = ""; }; 25EF23761AC09AD800908DF0 /* AdbClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdbClient.h; sourceTree = ""; }; 260157C41885F4FF00F875CF /* libpanel.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpanel.dylib; path = /usr/lib/libpanel.dylib; sourceTree = ""; }; 260223E7115F06D500A601A2 /* SBCommunication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBCommunication.h; path = include/lldb/API/SBCommunication.h; sourceTree = ""; }; 260223E8115F06E500A601A2 /* SBCommunication.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBCommunication.cpp; path = source/API/SBCommunication.cpp; sourceTree = ""; }; 26022531115F27FA00A601A2 /* SBFileSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBFileSpec.h; path = include/lldb/API/SBFileSpec.h; sourceTree = ""; }; 26022532115F281400A601A2 /* SBFileSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBFileSpec.cpp; path = source/API/SBFileSpec.cpp; sourceTree = ""; }; 260A248D15D06C4F009981B0 /* OptionValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValues.h; path = include/lldb/Interpreter/OptionValues.h; sourceTree = ""; }; 260A39A519647A3A004B4130 /* Pipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Pipe.h; path = include/lldb/Host/Pipe.h; sourceTree = ""; }; 260A63111860FDB600FECF8E /* Queue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Queue.h; path = include/lldb/Target/Queue.h; sourceTree = ""; }; 260A63121860FDBD00FECF8E /* QueueItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = QueueItem.h; path = include/lldb/Target/QueueItem.h; sourceTree = ""; }; 260A63131860FDC700FECF8E /* QueueList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = QueueList.h; path = include/lldb/Target/QueueList.h; sourceTree = ""; }; 260A63161861008E00FECF8E /* IOHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IOHandler.h; path = include/lldb/Core/IOHandler.h; sourceTree = ""; }; 260A63181861009E00FECF8E /* IOHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IOHandler.cpp; path = source/Core/IOHandler.cpp; sourceTree = ""; }; 260C6EA013011578005E16B0 /* File.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = File.h; path = include/lldb/Host/File.h; sourceTree = ""; }; 260C6EA213011581005E16B0 /* File.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = File.cpp; sourceTree = ""; }; 260C847110F50EFC00BB2B04 /* ThreadPlanBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanBase.cpp; path = source/Target/ThreadPlanBase.cpp; sourceTree = ""; }; 260C847210F50EFC00BB2B04 /* ThreadPlanStepInstruction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanStepInstruction.cpp; path = source/Target/ThreadPlanStepInstruction.cpp; sourceTree = ""; }; 260C847310F50EFC00BB2B04 /* ThreadPlanStepOut.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanStepOut.cpp; path = source/Target/ThreadPlanStepOut.cpp; sourceTree = ""; }; 260C847410F50EFC00BB2B04 /* ThreadPlanStepOverBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanStepOverBreakpoint.cpp; path = source/Target/ThreadPlanStepOverBreakpoint.cpp; sourceTree = ""; }; 260C847510F50EFC00BB2B04 /* ThreadPlanStepThrough.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanStepThrough.cpp; path = source/Target/ThreadPlanStepThrough.cpp; sourceTree = ""; }; 260C847610F50EFC00BB2B04 /* ThreadPlanStepRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanStepRange.cpp; path = source/Target/ThreadPlanStepRange.cpp; sourceTree = ""; }; 260C847F10F50F0A00BB2B04 /* ThreadPlanBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanBase.h; path = include/lldb/Target/ThreadPlanBase.h; sourceTree = ""; }; 260C848010F50F0A00BB2B04 /* ThreadPlanStepInstruction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanStepInstruction.h; path = include/lldb/Target/ThreadPlanStepInstruction.h; sourceTree = ""; }; 260C848110F50F0A00BB2B04 /* ThreadPlanStepOut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanStepOut.h; path = include/lldb/Target/ThreadPlanStepOut.h; sourceTree = ""; }; 260C848210F50F0A00BB2B04 /* ThreadPlanStepOverBreakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanStepOverBreakpoint.h; path = include/lldb/Target/ThreadPlanStepOverBreakpoint.h; sourceTree = ""; }; 260C848310F50F0A00BB2B04 /* ThreadPlanStepThrough.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanStepThrough.h; path = include/lldb/Target/ThreadPlanStepThrough.h; sourceTree = ""; }; 260C848410F50F0A00BB2B04 /* ThreadPlanStepRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanStepRange.h; path = include/lldb/Target/ThreadPlanStepRange.h; sourceTree = ""; }; 260C876910F538E700BB2B04 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; 260C897A10F57C5600BB2B04 /* DynamicLoaderMacOSXDYLD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLoaderMacOSXDYLD.cpp; sourceTree = ""; }; 260C897B10F57C5600BB2B04 /* DynamicLoaderMacOSXDYLD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderMacOSXDYLD.h; sourceTree = ""; }; 260C898010F57C5600BB2B04 /* ObjectContainerUniversalMachO.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectContainerUniversalMachO.cpp; sourceTree = ""; }; 260C898110F57C5600BB2B04 /* ObjectContainerUniversalMachO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectContainerUniversalMachO.h; sourceTree = ""; }; 260C898510F57C5600BB2B04 /* ObjectFileELF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectFileELF.cpp; sourceTree = ""; }; 260C898610F57C5600BB2B04 /* ObjectFileELF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectFileELF.h; sourceTree = ""; }; 260C898810F57C5600BB2B04 /* ObjectFileMachO.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectFileMachO.cpp; sourceTree = ""; }; 260C898910F57C5600BB2B04 /* ObjectFileMachO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectFileMachO.h; sourceTree = ""; }; 260C89B310F57C5600BB2B04 /* DWARFAbbreviationDeclaration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFAbbreviationDeclaration.cpp; sourceTree = ""; }; 260C89B410F57C5600BB2B04 /* DWARFAbbreviationDeclaration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFAbbreviationDeclaration.h; sourceTree = ""; }; 260C89B610F57C5600BB2B04 /* DWARFAttribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFAttribute.h; sourceTree = ""; }; 260C89B710F57C5600BB2B04 /* DWARFCompileUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFCompileUnit.cpp; sourceTree = ""; }; 260C89B810F57C5600BB2B04 /* DWARFCompileUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFCompileUnit.h; sourceTree = ""; }; 260C89B910F57C5600BB2B04 /* DWARFDebugAbbrev.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFDebugAbbrev.cpp; sourceTree = ""; }; 260C89BA10F57C5600BB2B04 /* DWARFDebugAbbrev.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFDebugAbbrev.h; sourceTree = ""; }; 260C89BB10F57C5600BB2B04 /* DWARFDebugAranges.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFDebugAranges.cpp; sourceTree = ""; }; 260C89BC10F57C5600BB2B04 /* DWARFDebugAranges.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFDebugAranges.h; sourceTree = ""; }; 260C89BD10F57C5600BB2B04 /* DWARFDebugArangeSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFDebugArangeSet.cpp; sourceTree = ""; }; 260C89BE10F57C5600BB2B04 /* DWARFDebugArangeSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFDebugArangeSet.h; sourceTree = ""; }; 260C89BF10F57C5600BB2B04 /* DWARFDebugInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFDebugInfo.cpp; sourceTree = ""; }; 260C89C010F57C5600BB2B04 /* DWARFDebugInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFDebugInfo.h; sourceTree = ""; }; 260C89C110F57C5600BB2B04 /* DWARFDebugInfoEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFDebugInfoEntry.cpp; sourceTree = ""; }; 260C89C210F57C5600BB2B04 /* DWARFDebugInfoEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFDebugInfoEntry.h; sourceTree = ""; }; 260C89C310F57C5600BB2B04 /* DWARFDebugLine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFDebugLine.cpp; sourceTree = ""; }; 260C89C410F57C5600BB2B04 /* DWARFDebugLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFDebugLine.h; sourceTree = ""; }; 260C89C510F57C5600BB2B04 /* DWARFDebugMacinfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFDebugMacinfo.cpp; sourceTree = ""; }; 260C89C610F57C5600BB2B04 /* DWARFDebugMacinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFDebugMacinfo.h; sourceTree = ""; }; 260C89C710F57C5600BB2B04 /* DWARFDebugMacinfoEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFDebugMacinfoEntry.cpp; sourceTree = ""; }; 260C89C810F57C5600BB2B04 /* DWARFDebugMacinfoEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFDebugMacinfoEntry.h; sourceTree = ""; }; 260C89C910F57C5600BB2B04 /* DWARFDebugPubnames.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFDebugPubnames.cpp; sourceTree = ""; }; 260C89CA10F57C5600BB2B04 /* DWARFDebugPubnames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFDebugPubnames.h; sourceTree = ""; }; 260C89CB10F57C5600BB2B04 /* DWARFDebugPubnamesSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFDebugPubnamesSet.cpp; sourceTree = ""; }; 260C89CC10F57C5600BB2B04 /* DWARFDebugPubnamesSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFDebugPubnamesSet.h; sourceTree = ""; }; 260C89CD10F57C5600BB2B04 /* DWARFDebugRanges.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFDebugRanges.cpp; sourceTree = ""; }; 260C89CE10F57C5600BB2B04 /* DWARFDebugRanges.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFDebugRanges.h; sourceTree = ""; }; 260C89CF10F57C5600BB2B04 /* DWARFDefines.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; path = DWARFDefines.cpp; sourceTree = ""; }; 260C89D010F57C5600BB2B04 /* DWARFDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFDefines.h; sourceTree = ""; }; 260C89D110F57C5600BB2B04 /* DWARFDIECollection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFDIECollection.cpp; sourceTree = ""; }; 260C89D210F57C5600BB2B04 /* DWARFDIECollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFDIECollection.h; sourceTree = ""; }; 260C89D310F57C5600BB2B04 /* DWARFFormValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFFormValue.cpp; sourceTree = ""; }; 260C89D410F57C5600BB2B04 /* DWARFFormValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFFormValue.h; sourceTree = ""; }; 260C89D910F57C5600BB2B04 /* SymbolFileDWARF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolFileDWARF.cpp; sourceTree = ""; }; 260C89DA10F57C5600BB2B04 /* SymbolFileDWARF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolFileDWARF.h; sourceTree = ""; }; 260C89DB10F57C5600BB2B04 /* SymbolFileDWARFDebugMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolFileDWARFDebugMap.cpp; sourceTree = ""; }; 260C89DC10F57C5600BB2B04 /* SymbolFileDWARFDebugMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolFileDWARFDebugMap.h; sourceTree = ""; }; 260C89DE10F57C5600BB2B04 /* SymbolFileSymtab.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolFileSymtab.cpp; sourceTree = ""; }; 260C89DF10F57C5600BB2B04 /* SymbolFileSymtab.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolFileSymtab.h; sourceTree = ""; }; 260C89E210F57C5600BB2B04 /* SymbolVendorMacOSX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolVendorMacOSX.cpp; sourceTree = ""; }; 260C89E310F57C5600BB2B04 /* SymbolVendorMacOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolVendorMacOSX.h; sourceTree = ""; }; 260CC62115D04377002BF2E0 /* OptionValueArgs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValueArgs.h; path = include/lldb/Interpreter/OptionValueArgs.h; sourceTree = ""; }; 260CC62215D04377002BF2E0 /* OptionValueArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValueArray.h; path = include/lldb/Interpreter/OptionValueArray.h; sourceTree = ""; }; 260CC62315D04377002BF2E0 /* OptionValueBoolean.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValueBoolean.h; path = include/lldb/Interpreter/OptionValueBoolean.h; sourceTree = ""; }; 260CC62415D04377002BF2E0 /* OptionValueProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValueProperties.h; path = include/lldb/Interpreter/OptionValueProperties.h; sourceTree = ""; }; 260CC62515D04377002BF2E0 /* OptionValueDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValueDictionary.h; path = include/lldb/Interpreter/OptionValueDictionary.h; sourceTree = ""; }; 260CC62615D04377002BF2E0 /* OptionValueEnumeration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValueEnumeration.h; path = include/lldb/Interpreter/OptionValueEnumeration.h; sourceTree = ""; }; 260CC62715D04377002BF2E0 /* OptionValueFileSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValueFileSpec.h; path = include/lldb/Interpreter/OptionValueFileSpec.h; sourceTree = ""; }; 260CC62815D04377002BF2E0 /* OptionValueFileSpecList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValueFileSpecList.h; path = include/lldb/Interpreter/OptionValueFileSpecList.h; sourceTree = ""; }; 260CC62915D04377002BF2E0 /* OptionValueFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValueFormat.h; path = include/lldb/Interpreter/OptionValueFormat.h; sourceTree = ""; }; 260CC62A15D04377002BF2E0 /* OptionValueSInt64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValueSInt64.h; path = include/lldb/Interpreter/OptionValueSInt64.h; sourceTree = ""; }; 260CC62B15D04377002BF2E0 /* OptionValueString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValueString.h; path = include/lldb/Interpreter/OptionValueString.h; sourceTree = ""; }; 260CC62C15D04377002BF2E0 /* OptionValueUInt64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValueUInt64.h; path = include/lldb/Interpreter/OptionValueUInt64.h; sourceTree = ""; }; 260CC62D15D04377002BF2E0 /* OptionValueUUID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValueUUID.h; path = include/lldb/Interpreter/OptionValueUUID.h; sourceTree = ""; }; 260CC63B15D0440D002BF2E0 /* OptionValueArgs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueArgs.cpp; path = source/Interpreter/OptionValueArgs.cpp; sourceTree = ""; }; 260CC63C15D0440D002BF2E0 /* OptionValueArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueArray.cpp; path = source/Interpreter/OptionValueArray.cpp; sourceTree = ""; }; 260CC63D15D0440D002BF2E0 /* OptionValueBoolean.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueBoolean.cpp; path = source/Interpreter/OptionValueBoolean.cpp; sourceTree = ""; }; 260CC63E15D0440D002BF2E0 /* OptionValueProperties.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueProperties.cpp; path = source/Interpreter/OptionValueProperties.cpp; sourceTree = ""; }; 260CC63F15D0440D002BF2E0 /* OptionValueDictionary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueDictionary.cpp; path = source/Interpreter/OptionValueDictionary.cpp; sourceTree = ""; }; 260CC64015D0440D002BF2E0 /* OptionValueEnumeration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueEnumeration.cpp; path = source/Interpreter/OptionValueEnumeration.cpp; sourceTree = ""; }; 260CC64115D0440D002BF2E0 /* OptionValueFileSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueFileSpec.cpp; path = source/Interpreter/OptionValueFileSpec.cpp; sourceTree = ""; }; 260CC64215D0440D002BF2E0 /* OptionValueFileSpecLIst.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueFileSpecLIst.cpp; path = source/Interpreter/OptionValueFileSpecLIst.cpp; sourceTree = ""; }; 260CC64315D0440D002BF2E0 /* OptionValueFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueFormat.cpp; path = source/Interpreter/OptionValueFormat.cpp; sourceTree = ""; }; 260CC64415D0440D002BF2E0 /* OptionValueSInt64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueSInt64.cpp; path = source/Interpreter/OptionValueSInt64.cpp; sourceTree = ""; }; 260CC64515D0440D002BF2E0 /* OptionValueString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueString.cpp; path = source/Interpreter/OptionValueString.cpp; sourceTree = ""; }; 260CC64615D0440D002BF2E0 /* OptionValueUInt64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueUInt64.cpp; path = source/Interpreter/OptionValueUInt64.cpp; sourceTree = ""; }; 260CC64715D0440D002BF2E0 /* OptionValueUUID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueUUID.cpp; path = source/Interpreter/OptionValueUUID.cpp; sourceTree = ""; }; 260D9B2615EC369500960137 /* ModuleSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ModuleSpec.h; path = include/lldb/Core/ModuleSpec.h; sourceTree = ""; }; 260E07C3136FA68900CF21D3 /* OptionGroupUUID.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupUUID.h; path = include/lldb/Interpreter/OptionGroupUUID.h; sourceTree = ""; }; 260E07C5136FA69E00CF21D3 /* OptionGroupUUID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupUUID.cpp; path = source/Interpreter/OptionGroupUUID.cpp; sourceTree = ""; }; 260E07C7136FAB9200CF21D3 /* OptionGroupFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupFile.cpp; path = source/Interpreter/OptionGroupFile.cpp; sourceTree = ""; }; 260E07C9136FABAC00CF21D3 /* OptionGroupFile.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupFile.h; path = include/lldb/Interpreter/OptionGroupFile.h; sourceTree = ""; }; 26109B3B1155D70100CC3529 /* LogChannelDWARF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LogChannelDWARF.cpp; sourceTree = ""; }; 26109B3C1155D70100CC3529 /* LogChannelDWARF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LogChannelDWARF.h; sourceTree = ""; }; 2611FEEF142D83060017FEA3 /* SBAddress.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBAddress.i; sourceTree = ""; }; 2611FEF0142D83060017FEA3 /* SBBlock.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBBlock.i; sourceTree = ""; }; 2611FEF1142D83060017FEA3 /* SBBreakpoint.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBBreakpoint.i; sourceTree = ""; }; 2611FEF2142D83060017FEA3 /* SBBreakpointLocation.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBBreakpointLocation.i; sourceTree = ""; }; 2611FEF3142D83060017FEA3 /* SBBroadcaster.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBBroadcaster.i; sourceTree = ""; }; 2611FEF4142D83060017FEA3 /* SBCommandInterpreter.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBCommandInterpreter.i; sourceTree = ""; }; 2611FEF5142D83060017FEA3 /* SBCommandReturnObject.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBCommandReturnObject.i; sourceTree = ""; }; 2611FEF6142D83060017FEA3 /* SBCommunication.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBCommunication.i; sourceTree = ""; }; 2611FEF7142D83060017FEA3 /* SBCompileUnit.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBCompileUnit.i; sourceTree = ""; }; 2611FEF8142D83060017FEA3 /* SBData.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBData.i; sourceTree = ""; }; 2611FEF9142D83060017FEA3 /* SBDebugger.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBDebugger.i; sourceTree = ""; }; 2611FEFA142D83060017FEA3 /* SBError.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBError.i; sourceTree = ""; }; 2611FEFB142D83060017FEA3 /* SBEvent.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBEvent.i; sourceTree = ""; }; 2611FEFC142D83060017FEA3 /* SBFileSpec.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBFileSpec.i; sourceTree = ""; }; 2611FEFD142D83060017FEA3 /* SBFileSpecList.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBFileSpecList.i; sourceTree = ""; }; 2611FEFE142D83060017FEA3 /* SBFrame.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBFrame.i; sourceTree = ""; }; 2611FEFF142D83060017FEA3 /* SBFunction.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBFunction.i; sourceTree = ""; }; 2611FF00142D83060017FEA3 /* SBHostOS.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBHostOS.i; sourceTree = ""; }; 2611FF02142D83060017FEA3 /* SBInstruction.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBInstruction.i; sourceTree = ""; }; 2611FF03142D83060017FEA3 /* SBInstructionList.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBInstructionList.i; sourceTree = ""; }; 2611FF04142D83060017FEA3 /* SBLineEntry.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBLineEntry.i; sourceTree = ""; }; 2611FF05142D83060017FEA3 /* SBListener.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBListener.i; sourceTree = ""; }; 2611FF06142D83060017FEA3 /* SBModule.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBModule.i; sourceTree = ""; }; 2611FF07142D83060017FEA3 /* SBProcess.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBProcess.i; sourceTree = ""; }; 2611FF08142D83060017FEA3 /* SBSection.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBSection.i; sourceTree = ""; }; 2611FF09142D83060017FEA3 /* SBSourceManager.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBSourceManager.i; sourceTree = ""; }; 2611FF0A142D83060017FEA3 /* SBStream.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBStream.i; sourceTree = ""; }; 2611FF0B142D83060017FEA3 /* SBStringList.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBStringList.i; sourceTree = ""; }; 2611FF0C142D83060017FEA3 /* SBSymbol.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBSymbol.i; sourceTree = ""; }; 2611FF0D142D83060017FEA3 /* SBSymbolContext.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBSymbolContext.i; sourceTree = ""; }; 2611FF0E142D83060017FEA3 /* SBSymbolContextList.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBSymbolContextList.i; sourceTree = ""; }; 2611FF0F142D83060017FEA3 /* SBTarget.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBTarget.i; sourceTree = ""; }; 2611FF10142D83060017FEA3 /* SBThread.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBThread.i; sourceTree = ""; }; 2611FF11142D83060017FEA3 /* SBType.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBType.i; sourceTree = ""; }; 2611FF12142D83060017FEA3 /* SBValue.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBValue.i; sourceTree = ""; }; 2611FF13142D83060017FEA3 /* SBValueList.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBValueList.i; sourceTree = ""; }; 2615DB841208A9C90021781D /* StopInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StopInfo.h; path = include/lldb/Target/StopInfo.h; sourceTree = ""; }; 2615DB861208A9E40021781D /* StopInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StopInfo.cpp; path = source/Target/StopInfo.cpp; sourceTree = ""; }; 2615DBC81208B5FC0021781D /* StopInfoMachException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StopInfoMachException.cpp; path = Utility/StopInfoMachException.cpp; sourceTree = ""; }; 2615DBC91208B5FC0021781D /* StopInfoMachException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StopInfoMachException.h; path = Utility/StopInfoMachException.h; sourceTree = ""; }; 261744771168585B005ADD65 /* SBType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBType.cpp; path = source/API/SBType.cpp; sourceTree = ""; }; 2617447911685869005ADD65 /* SBType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBType.h; path = include/lldb/API/SBType.h; sourceTree = ""; }; 2618D78F1240115500F2B8FE /* SectionLoadList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SectionLoadList.h; path = include/lldb/Target/SectionLoadList.h; sourceTree = ""; }; 2618D7911240116900F2B8FE /* SectionLoadList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SectionLoadList.cpp; path = source/Target/SectionLoadList.cpp; sourceTree = ""; }; 2618D957124056C700F2B8FE /* NameToDIE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NameToDIE.h; sourceTree = ""; }; 2618D9EA12406FE600F2B8FE /* NameToDIE.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NameToDIE.cpp; sourceTree = ""; }; 2618EE5B1315B29C001D6D71 /* GDBRemoteCommunication.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunication.cpp; sourceTree = ""; }; 2618EE5C1315B29C001D6D71 /* GDBRemoteCommunication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDBRemoteCommunication.h; sourceTree = ""; }; 2618EE5D1315B29C001D6D71 /* GDBRemoteRegisterContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteRegisterContext.cpp; sourceTree = ""; }; 2618EE5E1315B29C001D6D71 /* GDBRemoteRegisterContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDBRemoteRegisterContext.h; sourceTree = ""; }; 2618EE5F1315B29C001D6D71 /* ProcessGDBRemote.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessGDBRemote.cpp; sourceTree = ""; }; 2618EE601315B29C001D6D71 /* ProcessGDBRemote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessGDBRemote.h; sourceTree = ""; }; 2618EE611315B29C001D6D71 /* ProcessGDBRemoteLog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessGDBRemoteLog.cpp; sourceTree = ""; }; 2618EE621315B29C001D6D71 /* ProcessGDBRemoteLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessGDBRemoteLog.h; sourceTree = ""; }; 2618EE631315B29C001D6D71 /* ThreadGDBRemote.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadGDBRemote.cpp; sourceTree = ""; }; 2618EE641315B29C001D6D71 /* ThreadGDBRemote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadGDBRemote.h; sourceTree = ""; }; 261B5A5211C3F2AD00AABD0A /* SharingPtr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SharingPtr.cpp; path = source/Utility/SharingPtr.cpp; sourceTree = ""; }; 261B5A5311C3F2AD00AABD0A /* SharingPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SharingPtr.h; path = include/lldb/Utility/SharingPtr.h; sourceTree = ""; }; 262173A018395D3800C52091 /* SectionLoadHistory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SectionLoadHistory.h; path = include/lldb/Target/SectionLoadHistory.h; sourceTree = ""; }; 262173A218395D4600C52091 /* SectionLoadHistory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SectionLoadHistory.cpp; path = source/Target/SectionLoadHistory.cpp; sourceTree = ""; }; 26217930133BC8640083B112 /* lldb-private-types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-private-types.h"; path = "include/lldb/lldb-private-types.h"; sourceTree = ""; }; 26217932133BCB850083B112 /* lldb-private-enumerations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-private-enumerations.h"; path = "include/lldb/lldb-private-enumerations.h"; sourceTree = ""; }; 2623096E13D0EFFB006381D9 /* StreamBuffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StreamBuffer.h; path = include/lldb/Core/StreamBuffer.h; sourceTree = ""; }; 2626B6AD143E1BEA00EF935C /* RangeMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RangeMap.h; path = include/lldb/Core/RangeMap.h; sourceTree = ""; }; 26274FA514030F79006BA130 /* DynamicLoaderDarwinKernel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLoaderDarwinKernel.cpp; sourceTree = ""; }; 26274FA614030F79006BA130 /* DynamicLoaderDarwinKernel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderDarwinKernel.h; sourceTree = ""; }; 2628A4D313D4977900F5487A /* ThreadKDP.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadKDP.cpp; sourceTree = ""; }; 2628A4D413D4977900F5487A /* ThreadKDP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadKDP.h; sourceTree = ""; }; 262D24E413FB8710002D1960 /* RegisterContextMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextMemory.cpp; path = Utility/RegisterContextMemory.cpp; sourceTree = ""; }; 262D24E513FB8710002D1960 /* RegisterContextMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextMemory.h; path = Utility/RegisterContextMemory.h; sourceTree = ""; }; 262ED0041631FA2800879631 /* OptionGroupString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionGroupString.h; path = include/lldb/Interpreter/OptionGroupString.h; sourceTree = ""; }; 262ED0071631FA3A00879631 /* OptionGroupString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupString.cpp; path = source/Interpreter/OptionGroupString.cpp; sourceTree = ""; }; 262F12B41835468600AEB384 /* SBPlatform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBPlatform.cpp; path = source/API/SBPlatform.cpp; sourceTree = ""; }; 262F12B61835469C00AEB384 /* SBPlatform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBPlatform.h; path = include/lldb/API/SBPlatform.h; sourceTree = ""; }; 262F12B8183546C900AEB384 /* SBPlatform.i */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBPlatform.i; sourceTree = ""; }; 2635879017822E56004C30BA /* SymbolVendorELF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolVendorELF.cpp; sourceTree = ""; }; 2635879117822E56004C30BA /* SymbolVendorELF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolVendorELF.h; sourceTree = ""; }; 263641151B34AEE200145B2F /* ABISysV_mips64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ABISysV_mips64.cpp; sourceTree = ""; }; 263641161B34AEE200145B2F /* ABISysV_mips64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ABISysV_mips64.h; sourceTree = ""; }; 263664921140A4930075843B /* Debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = Debugger.cpp; path = source/Core/Debugger.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 263664941140A4C10075843B /* Debugger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = Debugger.h; path = include/lldb/Core/Debugger.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 26368A3B126B697600E8659F /* darwin-debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "darwin-debug.cpp"; path = "tools/darwin-debug/darwin-debug.cpp"; sourceTree = ""; }; 263C4937178B50C40070F12D /* SBModuleSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBModuleSpec.cpp; path = source/API/SBModuleSpec.cpp; sourceTree = ""; }; 263C4939178B50CF0070F12D /* SBModuleSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBModuleSpec.h; path = include/lldb/API/SBModuleSpec.h; sourceTree = ""; }; 263C493B178B61CC0070F12D /* SBModuleSpec.i */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBModuleSpec.i; sourceTree = ""; }; 263E949D13661AE400E7D1CE /* UnwindAssembly-x86.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "UnwindAssembly-x86.cpp"; sourceTree = ""; }; 263E949E13661AE400E7D1CE /* UnwindAssembly-x86.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UnwindAssembly-x86.h"; sourceTree = ""; }; 263FDE5D1A799F2D00E68013 /* FormatEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FormatEntity.h; path = include/lldb/Core/FormatEntity.h; sourceTree = ""; }; 263FDE5F1A79A01500E68013 /* FormatEntity.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FormatEntity.cpp; path = source/Core/FormatEntity.cpp; sourceTree = ""; }; 263FEDA5112CC1DA00E4C208 /* ThreadSafeSTLMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadSafeSTLMap.h; path = include/lldb/Core/ThreadSafeSTLMap.h; sourceTree = ""; }; 2640E19E15DC78FD00F23B50 /* Property.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Property.cpp; path = source/Interpreter/Property.cpp; sourceTree = ""; }; 26424E3C125986CB0016D82C /* ValueObjectConstResult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectConstResult.cpp; path = source/Core/ValueObjectConstResult.cpp; sourceTree = ""; }; 26424E3E125986D30016D82C /* ValueObjectConstResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectConstResult.h; path = include/lldb/Core/ValueObjectConstResult.h; sourceTree = ""; }; 264297531D1DF209003F2BF4 /* SBMemoryRegionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBMemoryRegionInfo.h; path = include/lldb/API/SBMemoryRegionInfo.h; sourceTree = ""; }; 264297541D1DF209003F2BF4 /* SBMemoryRegionInfoList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBMemoryRegionInfoList.h; path = include/lldb/API/SBMemoryRegionInfoList.h; sourceTree = ""; }; 264297591D1DF2AA003F2BF4 /* SBMemoryRegionInfo.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBMemoryRegionInfo.i; sourceTree = ""; }; 2642975A1D1DF2AA003F2BF4 /* SBMemoryRegionInfoList.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBMemoryRegionInfoList.i; sourceTree = ""; }; 2642FBA813D003B400ED6808 /* CommunicationKDP.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CommunicationKDP.cpp; sourceTree = ""; }; 2642FBA913D003B400ED6808 /* CommunicationKDP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommunicationKDP.h; sourceTree = ""; }; 2642FBAA13D003B400ED6808 /* ProcessKDP.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessKDP.cpp; sourceTree = ""; }; 2642FBAB13D003B400ED6808 /* ProcessKDP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessKDP.h; sourceTree = ""; }; 2642FBAC13D003B400ED6808 /* ProcessKDPLog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessKDPLog.cpp; sourceTree = ""; }; 2642FBAD13D003B400ED6808 /* ProcessKDPLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessKDPLog.h; sourceTree = ""; }; 264334381110F63100CDB6C6 /* ValueObjectRegister.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectRegister.cpp; path = source/Core/ValueObjectRegister.cpp; sourceTree = ""; }; 2643343A1110F63C00CDB6C6 /* ValueObjectRegister.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectRegister.h; path = include/lldb/Core/ValueObjectRegister.h; sourceTree = ""; }; 264723A511FA076E00DE380C /* CleanUp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CleanUp.h; path = include/lldb/Utility/CleanUp.h; sourceTree = ""; }; 26474C9F18D0CAEC0073DEBA /* RegisterContext_x86.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContext_x86.h; path = Utility/RegisterContext_x86.h; sourceTree = ""; }; 26474CA218D0CB070073DEBA /* RegisterContextFreeBSD_i386.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextFreeBSD_i386.cpp; path = Utility/RegisterContextFreeBSD_i386.cpp; sourceTree = ""; }; 26474CA318D0CB070073DEBA /* RegisterContextFreeBSD_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextFreeBSD_i386.h; path = Utility/RegisterContextFreeBSD_i386.h; sourceTree = ""; }; 26474CA418D0CB070073DEBA /* RegisterContextFreeBSD_mips64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextFreeBSD_mips64.cpp; path = Utility/RegisterContextFreeBSD_mips64.cpp; sourceTree = ""; }; 26474CA518D0CB070073DEBA /* RegisterContextFreeBSD_mips64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextFreeBSD_mips64.h; path = Utility/RegisterContextFreeBSD_mips64.h; sourceTree = ""; }; 26474CA618D0CB070073DEBA /* RegisterContextFreeBSD_x86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextFreeBSD_x86_64.cpp; path = Utility/RegisterContextFreeBSD_x86_64.cpp; sourceTree = ""; }; 26474CA718D0CB070073DEBA /* RegisterContextFreeBSD_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextFreeBSD_x86_64.h; path = Utility/RegisterContextFreeBSD_x86_64.h; sourceTree = ""; }; 26474CAE18D0CB180073DEBA /* RegisterContextLinux_i386.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextLinux_i386.cpp; path = Utility/RegisterContextLinux_i386.cpp; sourceTree = ""; }; 26474CAF18D0CB180073DEBA /* RegisterContextLinux_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextLinux_i386.h; path = Utility/RegisterContextLinux_i386.h; sourceTree = ""; }; 26474CB018D0CB180073DEBA /* RegisterContextLinux_x86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextLinux_x86_64.cpp; path = Utility/RegisterContextLinux_x86_64.cpp; sourceTree = ""; }; 26474CB118D0CB180073DEBA /* RegisterContextLinux_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextLinux_x86_64.h; path = Utility/RegisterContextLinux_x86_64.h; sourceTree = ""; }; 26474CB618D0CB2D0073DEBA /* RegisterContextMach_arm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextMach_arm.cpp; path = Utility/RegisterContextMach_arm.cpp; sourceTree = ""; }; 26474CB718D0CB2D0073DEBA /* RegisterContextMach_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextMach_arm.h; path = Utility/RegisterContextMach_arm.h; sourceTree = ""; }; 26474CB818D0CB2D0073DEBA /* RegisterContextMach_i386.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextMach_i386.cpp; path = Utility/RegisterContextMach_i386.cpp; sourceTree = ""; }; 26474CB918D0CB2D0073DEBA /* RegisterContextMach_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextMach_i386.h; path = Utility/RegisterContextMach_i386.h; sourceTree = ""; }; 26474CBA18D0CB2D0073DEBA /* RegisterContextMach_x86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextMach_x86_64.cpp; path = Utility/RegisterContextMach_x86_64.cpp; sourceTree = ""; }; 26474CBB18D0CB2D0073DEBA /* RegisterContextMach_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextMach_x86_64.h; path = Utility/RegisterContextMach_x86_64.h; sourceTree = ""; }; 26474CC218D0CB5B0073DEBA /* RegisterContextMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextMemory.cpp; path = Utility/RegisterContextMemory.cpp; sourceTree = ""; }; 26474CC318D0CB5B0073DEBA /* RegisterContextMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextMemory.h; path = Utility/RegisterContextMemory.h; sourceTree = ""; }; 26474CC418D0CB5B0073DEBA /* RegisterContextPOSIX_mips64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextPOSIX_mips64.cpp; path = Utility/RegisterContextPOSIX_mips64.cpp; sourceTree = ""; }; 26474CC518D0CB5B0073DEBA /* RegisterContextPOSIX_mips64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextPOSIX_mips64.h; path = Utility/RegisterContextPOSIX_mips64.h; sourceTree = ""; }; 26474CC618D0CB5B0073DEBA /* RegisterContextPOSIX_x86.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextPOSIX_x86.cpp; path = Utility/RegisterContextPOSIX_x86.cpp; sourceTree = ""; }; 26474CC718D0CB5B0073DEBA /* RegisterContextPOSIX_x86.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextPOSIX_x86.h; path = Utility/RegisterContextPOSIX_x86.h; sourceTree = ""; }; 26474CC818D0CB5B0073DEBA /* RegisterContextPOSIX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextPOSIX.h; sourceTree = ""; }; 26474CD018D0CB700073DEBA /* RegisterInfos_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterInfos_i386.h; path = Utility/RegisterInfos_i386.h; sourceTree = ""; }; 26474CD118D0CB710073DEBA /* RegisterInfos_mips64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterInfos_mips64.h; path = Utility/RegisterInfos_mips64.h; sourceTree = ""; }; 26474CD218D0CB710073DEBA /* RegisterInfos_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterInfos_x86_64.h; path = Utility/RegisterInfos_x86_64.h; sourceTree = ""; }; 26491E3A15E1DB8600CBFFC2 /* OptionValueRegex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValueRegex.h; path = include/lldb/Interpreter/OptionValueRegex.h; sourceTree = ""; }; 26491E3D15E1DB9F00CBFFC2 /* OptionValueRegex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueRegex.cpp; path = source/Interpreter/OptionValueRegex.cpp; sourceTree = ""; }; 264A12FA1372522000875C42 /* EmulateInstructionARM64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EmulateInstructionARM64.cpp; sourceTree = ""; }; 264A12FB1372522000875C42 /* EmulateInstructionARM64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EmulateInstructionARM64.h; sourceTree = ""; }; 264A12FF137252C700875C42 /* ARM64_DWARF_Registers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ARM64_DWARF_Registers.h; path = source/Utility/ARM64_DWARF_Registers.h; sourceTree = ""; }; 264A43BB1320B3B4005B4096 /* Platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Platform.h; path = include/lldb/Target/Platform.h; sourceTree = ""; }; 264A43BD1320BCEB005B4096 /* Platform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Platform.cpp; path = source/Target/Platform.cpp; sourceTree = ""; }; 264A58EB1A7DBC8C00A6B1B0 /* OptionValueFormatEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValueFormatEntity.h; path = include/lldb/Interpreter/OptionValueFormatEntity.h; sourceTree = ""; }; 264A58ED1A7DBCAD00A6B1B0 /* OptionValueFormatEntity.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueFormatEntity.cpp; path = source/Interpreter/OptionValueFormatEntity.cpp; sourceTree = ""; }; 264A97BD133918BC0017F0BE /* PlatformRemoteGDBServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PlatformRemoteGDBServer.cpp; path = "gdb-server/PlatformRemoteGDBServer.cpp"; sourceTree = ""; }; 264A97BE133918BC0017F0BE /* PlatformRemoteGDBServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlatformRemoteGDBServer.h; path = "gdb-server/PlatformRemoteGDBServer.h"; sourceTree = ""; }; 264AD83711095BA600E0B039 /* CommandObjectLog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectLog.cpp; path = source/Commands/CommandObjectLog.cpp; sourceTree = ""; }; 264AD83911095BBD00E0B039 /* CommandObjectLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectLog.h; path = source/Commands/CommandObjectLog.h; sourceTree = ""; }; 264D8D4E13661BCC003A368F /* UnwindAssembly.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = UnwindAssembly.h; path = include/lldb/Target/UnwindAssembly.h; sourceTree = ""; }; 264D8D4F13661BD7003A368F /* UnwindAssembly.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindAssembly.cpp; path = source/Target/UnwindAssembly.cpp; sourceTree = ""; }; 265192C41BA8E8F8002F08F6 /* CompilerDecl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CompilerDecl.h; path = include/lldb/Symbol/CompilerDecl.h; sourceTree = ""; }; 265192C51BA8E905002F08F6 /* CompilerDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompilerDecl.cpp; path = source/Symbol/CompilerDecl.cpp; sourceTree = ""; }; 265205A213D3E3F700132FE2 /* RegisterContextKDP_arm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextKDP_arm.cpp; sourceTree = ""; }; 265205A313D3E3F700132FE2 /* RegisterContextKDP_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextKDP_arm.h; sourceTree = ""; }; 265205A413D3E3F700132FE2 /* RegisterContextKDP_i386.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextKDP_i386.cpp; sourceTree = ""; }; 265205A513D3E3F700132FE2 /* RegisterContextKDP_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextKDP_i386.h; sourceTree = ""; }; 265205A613D3E3F700132FE2 /* RegisterContextKDP_x86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextKDP_x86_64.cpp; sourceTree = ""; }; 265205A713D3E3F700132FE2 /* RegisterContextKDP_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextKDP_x86_64.h; sourceTree = ""; }; 2654A67F1E54D59400DA1013 /* ModuleCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ModuleCache.cpp; path = source/Target/ModuleCache.cpp; sourceTree = ""; }; 2654A6811E54D5A200DA1013 /* ModuleCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ModuleCache.h; path = include/lldb/Target/ModuleCache.h; sourceTree = ""; }; 2654A6821E54D5E200DA1013 /* RegisterNumber.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterNumber.cpp; path = source/Target/RegisterNumber.cpp; sourceTree = ""; }; 2654A6841E54D5EE00DA1013 /* RegisterNumber.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RegisterNumber.h; path = include/lldb/Target/RegisterNumber.h; sourceTree = ""; }; 2654A68C1E552D1500DA1013 /* PseudoTerminal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PseudoTerminal.cpp; path = source/Host/common/PseudoTerminal.cpp; sourceTree = ""; }; 2654A68E1E552D2400DA1013 /* PseudoTerminal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PseudoTerminal.h; path = include/lldb/Host/PseudoTerminal.h; sourceTree = ""; }; 2654A68F1E552ED500DA1013 /* VASprintf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VASprintf.cpp; path = source/Utility/VASprintf.cpp; sourceTree = ""; }; 2654A6911E552F3C00DA1013 /* UriParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = UriParser.h; path = include/lldb/Utility/UriParser.h; sourceTree = ""; }; 2654A6921E552F4600DA1013 /* VASPrintf.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = VASPrintf.h; path = include/lldb/Utility/VASPrintf.h; sourceTree = ""; }; 26579F68126A25920007C5CB /* darwin-debug */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "darwin-debug"; sourceTree = BUILT_PRODUCTS_DIR; }; 2657AFB51B8690EC00958979 /* CompilerDeclContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CompilerDeclContext.h; path = include/lldb/Symbol/CompilerDeclContext.h; sourceTree = ""; }; 2657AFB61B86910100958979 /* CompilerDeclContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompilerDeclContext.cpp; path = source/Symbol/CompilerDeclContext.cpp; sourceTree = ""; }; 265ABF6210F42EE900531910 /* DebugSymbols.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DebugSymbols.framework; path = /System/Library/PrivateFrameworks/DebugSymbols.framework; sourceTree = ""; }; 265E9BE1115C2BAA00D0DCCB /* debugserver.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = debugserver.xcodeproj; path = tools/debugserver/debugserver.xcodeproj; sourceTree = ""; }; 2660D9F611922A1300958FBD /* StringExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringExtractor.cpp; path = source/Utility/StringExtractor.cpp; sourceTree = ""; }; 2660D9FE11922A7F00958FBD /* ThreadPlanStepUntil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanStepUntil.cpp; path = source/Target/ThreadPlanStepUntil.cpp; sourceTree = ""; }; 26651A14133BEC76005B64B7 /* lldb-public.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-public.h"; path = "include/lldb/lldb-public.h"; sourceTree = ""; }; 26651A15133BF9CC005B64B7 /* Opcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Opcode.h; path = include/lldb/Core/Opcode.h; sourceTree = ""; }; 26651A17133BF9DF005B64B7 /* Opcode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Opcode.cpp; path = source/Core/Opcode.cpp; sourceTree = ""; }; 2665CD0D15080846002C8FAE /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; 2666ADC11B3CB675001FAFD3 /* DynamicLoaderHexagonDYLD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLoaderHexagonDYLD.cpp; sourceTree = ""; }; 2666ADC21B3CB675001FAFD3 /* DynamicLoaderHexagonDYLD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderHexagonDYLD.h; sourceTree = ""; }; 2666ADC31B3CB675001FAFD3 /* HexagonDYLDRendezvous.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HexagonDYLDRendezvous.cpp; sourceTree = ""; }; 2666ADC41B3CB675001FAFD3 /* HexagonDYLDRendezvous.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HexagonDYLDRendezvous.h; sourceTree = ""; }; 26680207115FD0ED008E1FE4 /* LLDB.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LLDB.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 2669415B1A6DC2AB0063BE93 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = CMakeLists.txt; path = "tools/lldb-mi/CMakeLists.txt"; sourceTree = SOURCE_ROOT; }; 2669415E1A6DC2AB0063BE93 /* lldb-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "lldb-Info.plist"; path = "tools/lldb-mi/lldb-Info.plist"; sourceTree = SOURCE_ROOT; }; 2669415F1A6DC2AB0063BE93 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; name = Makefile; path = "tools/lldb-mi/Makefile"; sourceTree = SOURCE_ROOT; }; 266941601A6DC2AB0063BE93 /* MICmdArgContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdArgContext.cpp; path = "tools/lldb-mi/MICmdArgContext.cpp"; sourceTree = SOURCE_ROOT; }; 266941611A6DC2AB0063BE93 /* MICmdArgContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdArgContext.h; path = "tools/lldb-mi/MICmdArgContext.h"; sourceTree = SOURCE_ROOT; }; 266941621A6DC2AB0063BE93 /* MICmdArgSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdArgSet.cpp; path = "tools/lldb-mi/MICmdArgSet.cpp"; sourceTree = SOURCE_ROOT; }; 266941631A6DC2AB0063BE93 /* MICmdArgSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdArgSet.h; path = "tools/lldb-mi/MICmdArgSet.h"; sourceTree = SOURCE_ROOT; }; 266941641A6DC2AB0063BE93 /* MICmdArgValBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdArgValBase.cpp; path = "tools/lldb-mi/MICmdArgValBase.cpp"; sourceTree = SOURCE_ROOT; }; 266941651A6DC2AB0063BE93 /* MICmdArgValBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdArgValBase.h; path = "tools/lldb-mi/MICmdArgValBase.h"; sourceTree = SOURCE_ROOT; }; 266941661A6DC2AB0063BE93 /* MICmdArgValConsume.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdArgValConsume.cpp; path = "tools/lldb-mi/MICmdArgValConsume.cpp"; sourceTree = SOURCE_ROOT; }; 266941671A6DC2AB0063BE93 /* MICmdArgValConsume.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdArgValConsume.h; path = "tools/lldb-mi/MICmdArgValConsume.h"; sourceTree = SOURCE_ROOT; }; 266941681A6DC2AB0063BE93 /* MICmdArgValFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdArgValFile.cpp; path = "tools/lldb-mi/MICmdArgValFile.cpp"; sourceTree = SOURCE_ROOT; }; 266941691A6DC2AB0063BE93 /* MICmdArgValFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdArgValFile.h; path = "tools/lldb-mi/MICmdArgValFile.h"; sourceTree = SOURCE_ROOT; }; 2669416A1A6DC2AC0063BE93 /* MICmdArgValListBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdArgValListBase.cpp; path = "tools/lldb-mi/MICmdArgValListBase.cpp"; sourceTree = SOURCE_ROOT; }; 2669416B1A6DC2AC0063BE93 /* MICmdArgValListBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdArgValListBase.h; path = "tools/lldb-mi/MICmdArgValListBase.h"; sourceTree = SOURCE_ROOT; }; 2669416C1A6DC2AC0063BE93 /* MICmdArgValListOfN.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdArgValListOfN.cpp; path = "tools/lldb-mi/MICmdArgValListOfN.cpp"; sourceTree = SOURCE_ROOT; }; 2669416D1A6DC2AC0063BE93 /* MICmdArgValListOfN.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdArgValListOfN.h; path = "tools/lldb-mi/MICmdArgValListOfN.h"; sourceTree = SOURCE_ROOT; }; 2669416E1A6DC2AC0063BE93 /* MICmdArgValNumber.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdArgValNumber.cpp; path = "tools/lldb-mi/MICmdArgValNumber.cpp"; sourceTree = SOURCE_ROOT; }; 2669416F1A6DC2AC0063BE93 /* MICmdArgValNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdArgValNumber.h; path = "tools/lldb-mi/MICmdArgValNumber.h"; sourceTree = SOURCE_ROOT; }; 266941701A6DC2AC0063BE93 /* MICmdArgValOptionLong.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdArgValOptionLong.cpp; path = "tools/lldb-mi/MICmdArgValOptionLong.cpp"; sourceTree = SOURCE_ROOT; }; 266941711A6DC2AC0063BE93 /* MICmdArgValOptionLong.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdArgValOptionLong.h; path = "tools/lldb-mi/MICmdArgValOptionLong.h"; sourceTree = SOURCE_ROOT; }; 266941721A6DC2AC0063BE93 /* MICmdArgValOptionShort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdArgValOptionShort.cpp; path = "tools/lldb-mi/MICmdArgValOptionShort.cpp"; sourceTree = SOURCE_ROOT; }; 266941731A6DC2AC0063BE93 /* MICmdArgValOptionShort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdArgValOptionShort.h; path = "tools/lldb-mi/MICmdArgValOptionShort.h"; sourceTree = SOURCE_ROOT; }; 266941741A6DC2AC0063BE93 /* MICmdArgValString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdArgValString.cpp; path = "tools/lldb-mi/MICmdArgValString.cpp"; sourceTree = SOURCE_ROOT; }; 266941751A6DC2AC0063BE93 /* MICmdArgValString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdArgValString.h; path = "tools/lldb-mi/MICmdArgValString.h"; sourceTree = SOURCE_ROOT; }; 266941761A6DC2AC0063BE93 /* MICmdArgValThreadGrp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdArgValThreadGrp.cpp; path = "tools/lldb-mi/MICmdArgValThreadGrp.cpp"; sourceTree = SOURCE_ROOT; }; 266941771A6DC2AC0063BE93 /* MICmdArgValThreadGrp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdArgValThreadGrp.h; path = "tools/lldb-mi/MICmdArgValThreadGrp.h"; sourceTree = SOURCE_ROOT; }; 266941781A6DC2AC0063BE93 /* MICmdBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdBase.cpp; path = "tools/lldb-mi/MICmdBase.cpp"; sourceTree = SOURCE_ROOT; }; 266941791A6DC2AC0063BE93 /* MICmdBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdBase.h; path = "tools/lldb-mi/MICmdBase.h"; sourceTree = SOURCE_ROOT; }; 2669417A1A6DC2AC0063BE93 /* MICmdCmd.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCmd.cpp; path = "tools/lldb-mi/MICmdCmd.cpp"; sourceTree = SOURCE_ROOT; }; 2669417B1A6DC2AC0063BE93 /* MICmdCmd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCmd.h; path = "tools/lldb-mi/MICmdCmd.h"; sourceTree = SOURCE_ROOT; }; 2669417C1A6DC2AC0063BE93 /* MICmdCmdBreak.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCmdBreak.cpp; path = "tools/lldb-mi/MICmdCmdBreak.cpp"; sourceTree = SOURCE_ROOT; }; 2669417D1A6DC2AC0063BE93 /* MICmdCmdBreak.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCmdBreak.h; path = "tools/lldb-mi/MICmdCmdBreak.h"; sourceTree = SOURCE_ROOT; }; 2669417E1A6DC2AC0063BE93 /* MICmdCmdData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCmdData.cpp; path = "tools/lldb-mi/MICmdCmdData.cpp"; sourceTree = SOURCE_ROOT; }; 2669417F1A6DC2AC0063BE93 /* MICmdCmdData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCmdData.h; path = "tools/lldb-mi/MICmdCmdData.h"; sourceTree = SOURCE_ROOT; }; 266941801A6DC2AC0063BE93 /* MICmdCmdEnviro.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCmdEnviro.cpp; path = "tools/lldb-mi/MICmdCmdEnviro.cpp"; sourceTree = SOURCE_ROOT; }; 266941811A6DC2AC0063BE93 /* MICmdCmdEnviro.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCmdEnviro.h; path = "tools/lldb-mi/MICmdCmdEnviro.h"; sourceTree = SOURCE_ROOT; }; 266941821A6DC2AC0063BE93 /* MICmdCmdExec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCmdExec.cpp; path = "tools/lldb-mi/MICmdCmdExec.cpp"; sourceTree = SOURCE_ROOT; }; 266941831A6DC2AC0063BE93 /* MICmdCmdExec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCmdExec.h; path = "tools/lldb-mi/MICmdCmdExec.h"; sourceTree = SOURCE_ROOT; }; 266941841A6DC2AC0063BE93 /* MICmdCmdFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCmdFile.cpp; path = "tools/lldb-mi/MICmdCmdFile.cpp"; sourceTree = SOURCE_ROOT; }; 266941851A6DC2AC0063BE93 /* MICmdCmdFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCmdFile.h; path = "tools/lldb-mi/MICmdCmdFile.h"; sourceTree = SOURCE_ROOT; }; 266941861A6DC2AC0063BE93 /* MICmdCmdGdbInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCmdGdbInfo.cpp; path = "tools/lldb-mi/MICmdCmdGdbInfo.cpp"; sourceTree = SOURCE_ROOT; }; 266941871A6DC2AC0063BE93 /* MICmdCmdGdbInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCmdGdbInfo.h; path = "tools/lldb-mi/MICmdCmdGdbInfo.h"; sourceTree = SOURCE_ROOT; }; 266941881A6DC2AC0063BE93 /* MICmdCmdGdbSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCmdGdbSet.cpp; path = "tools/lldb-mi/MICmdCmdGdbSet.cpp"; sourceTree = SOURCE_ROOT; }; 266941891A6DC2AC0063BE93 /* MICmdCmdGdbSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCmdGdbSet.h; path = "tools/lldb-mi/MICmdCmdGdbSet.h"; sourceTree = SOURCE_ROOT; }; 2669418A1A6DC2AC0063BE93 /* MICmdCmdGdbThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCmdGdbThread.cpp; path = "tools/lldb-mi/MICmdCmdGdbThread.cpp"; sourceTree = SOURCE_ROOT; }; 2669418B1A6DC2AC0063BE93 /* MICmdCmdGdbThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCmdGdbThread.h; path = "tools/lldb-mi/MICmdCmdGdbThread.h"; sourceTree = SOURCE_ROOT; }; 2669418C1A6DC2AC0063BE93 /* MICmdCmdMiscellanous.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCmdMiscellanous.cpp; path = "tools/lldb-mi/MICmdCmdMiscellanous.cpp"; sourceTree = SOURCE_ROOT; }; 2669418D1A6DC2AC0063BE93 /* MICmdCmdMiscellanous.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCmdMiscellanous.h; path = "tools/lldb-mi/MICmdCmdMiscellanous.h"; sourceTree = SOURCE_ROOT; }; 2669418E1A6DC2AC0063BE93 /* MICmdCmdStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCmdStack.cpp; path = "tools/lldb-mi/MICmdCmdStack.cpp"; sourceTree = SOURCE_ROOT; }; 2669418F1A6DC2AC0063BE93 /* MICmdCmdStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCmdStack.h; path = "tools/lldb-mi/MICmdCmdStack.h"; sourceTree = SOURCE_ROOT; }; 266941901A6DC2AC0063BE93 /* MICmdCmdSupportInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCmdSupportInfo.cpp; path = "tools/lldb-mi/MICmdCmdSupportInfo.cpp"; sourceTree = SOURCE_ROOT; }; 266941911A6DC2AC0063BE93 /* MICmdCmdSupportInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCmdSupportInfo.h; path = "tools/lldb-mi/MICmdCmdSupportInfo.h"; sourceTree = SOURCE_ROOT; }; 266941921A6DC2AC0063BE93 /* MICmdCmdSupportList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCmdSupportList.cpp; path = "tools/lldb-mi/MICmdCmdSupportList.cpp"; sourceTree = SOURCE_ROOT; }; 266941931A6DC2AC0063BE93 /* MICmdCmdSupportList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCmdSupportList.h; path = "tools/lldb-mi/MICmdCmdSupportList.h"; sourceTree = SOURCE_ROOT; }; 266941941A6DC2AC0063BE93 /* MICmdCmdTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCmdTarget.cpp; path = "tools/lldb-mi/MICmdCmdTarget.cpp"; sourceTree = SOURCE_ROOT; }; 266941951A6DC2AC0063BE93 /* MICmdCmdTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCmdTarget.h; path = "tools/lldb-mi/MICmdCmdTarget.h"; sourceTree = SOURCE_ROOT; }; 266941961A6DC2AC0063BE93 /* MICmdCmdThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCmdThread.cpp; path = "tools/lldb-mi/MICmdCmdThread.cpp"; sourceTree = SOURCE_ROOT; }; 266941971A6DC2AC0063BE93 /* MICmdCmdThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCmdThread.h; path = "tools/lldb-mi/MICmdCmdThread.h"; sourceTree = SOURCE_ROOT; }; 266941981A6DC2AC0063BE93 /* MICmdCmdTrace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCmdTrace.cpp; path = "tools/lldb-mi/MICmdCmdTrace.cpp"; sourceTree = SOURCE_ROOT; }; 266941991A6DC2AC0063BE93 /* MICmdCmdTrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCmdTrace.h; path = "tools/lldb-mi/MICmdCmdTrace.h"; sourceTree = SOURCE_ROOT; }; 2669419A1A6DC2AC0063BE93 /* MICmdCmdVar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCmdVar.cpp; path = "tools/lldb-mi/MICmdCmdVar.cpp"; sourceTree = SOURCE_ROOT; }; 2669419B1A6DC2AC0063BE93 /* MICmdCmdVar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCmdVar.h; path = "tools/lldb-mi/MICmdCmdVar.h"; sourceTree = SOURCE_ROOT; }; 2669419C1A6DC2AC0063BE93 /* MICmdCommands.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCommands.cpp; path = "tools/lldb-mi/MICmdCommands.cpp"; sourceTree = SOURCE_ROOT; }; 2669419D1A6DC2AC0063BE93 /* MICmdCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCommands.h; path = "tools/lldb-mi/MICmdCommands.h"; sourceTree = SOURCE_ROOT; }; 2669419E1A6DC2AC0063BE93 /* MICmdData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdData.cpp; path = "tools/lldb-mi/MICmdData.cpp"; sourceTree = SOURCE_ROOT; }; 2669419F1A6DC2AC0063BE93 /* MICmdData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdData.h; path = "tools/lldb-mi/MICmdData.h"; sourceTree = SOURCE_ROOT; }; 266941A01A6DC2AC0063BE93 /* MICmdFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdFactory.cpp; path = "tools/lldb-mi/MICmdFactory.cpp"; sourceTree = SOURCE_ROOT; }; 266941A11A6DC2AC0063BE93 /* MICmdFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdFactory.h; path = "tools/lldb-mi/MICmdFactory.h"; sourceTree = SOURCE_ROOT; }; 266941A21A6DC2AC0063BE93 /* MICmdInterpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdInterpreter.cpp; path = "tools/lldb-mi/MICmdInterpreter.cpp"; sourceTree = SOURCE_ROOT; }; 266941A31A6DC2AC0063BE93 /* MICmdInterpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdInterpreter.h; path = "tools/lldb-mi/MICmdInterpreter.h"; sourceTree = SOURCE_ROOT; }; 266941A41A6DC2AC0063BE93 /* MICmdInvoker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdInvoker.cpp; path = "tools/lldb-mi/MICmdInvoker.cpp"; sourceTree = SOURCE_ROOT; }; 266941A51A6DC2AC0063BE93 /* MICmdInvoker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdInvoker.h; path = "tools/lldb-mi/MICmdInvoker.h"; sourceTree = SOURCE_ROOT; }; 266941A61A6DC2AC0063BE93 /* MICmdMgr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdMgr.cpp; path = "tools/lldb-mi/MICmdMgr.cpp"; sourceTree = SOURCE_ROOT; }; 266941A71A6DC2AC0063BE93 /* MICmdMgr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdMgr.h; path = "tools/lldb-mi/MICmdMgr.h"; sourceTree = SOURCE_ROOT; }; 266941A81A6DC2AC0063BE93 /* MICmdMgrSetCmdDeleteCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdMgrSetCmdDeleteCallback.cpp; path = "tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.cpp"; sourceTree = SOURCE_ROOT; }; 266941A91A6DC2AC0063BE93 /* MICmdMgrSetCmdDeleteCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdMgrSetCmdDeleteCallback.h; path = "tools/lldb-mi/MICmdMgrSetCmdDeleteCallback.h"; sourceTree = SOURCE_ROOT; }; 266941AA1A6DC2AC0063BE93 /* MICmnBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnBase.cpp; path = "tools/lldb-mi/MICmnBase.cpp"; sourceTree = SOURCE_ROOT; }; 266941AB1A6DC2AC0063BE93 /* MICmnBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnBase.h; path = "tools/lldb-mi/MICmnBase.h"; sourceTree = SOURCE_ROOT; }; 266941AC1A6DC2AC0063BE93 /* MICmnConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnConfig.h; path = "tools/lldb-mi/MICmnConfig.h"; sourceTree = SOURCE_ROOT; }; 266941AD1A6DC2AC0063BE93 /* MICmnLLDBBroadcaster.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnLLDBBroadcaster.cpp; path = "tools/lldb-mi/MICmnLLDBBroadcaster.cpp"; sourceTree = SOURCE_ROOT; }; 266941AE1A6DC2AC0063BE93 /* MICmnLLDBBroadcaster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnLLDBBroadcaster.h; path = "tools/lldb-mi/MICmnLLDBBroadcaster.h"; sourceTree = SOURCE_ROOT; }; 266941AF1A6DC2AC0063BE93 /* MICmnLLDBDebugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnLLDBDebugger.cpp; path = "tools/lldb-mi/MICmnLLDBDebugger.cpp"; sourceTree = SOURCE_ROOT; }; 266941B01A6DC2AC0063BE93 /* MICmnLLDBDebugger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnLLDBDebugger.h; path = "tools/lldb-mi/MICmnLLDBDebugger.h"; sourceTree = SOURCE_ROOT; }; 266941B11A6DC2AC0063BE93 /* MICmnLLDBDebuggerHandleEvents.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnLLDBDebuggerHandleEvents.cpp; path = "tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp"; sourceTree = SOURCE_ROOT; }; 266941B21A6DC2AC0063BE93 /* MICmnLLDBDebuggerHandleEvents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnLLDBDebuggerHandleEvents.h; path = "tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.h"; sourceTree = SOURCE_ROOT; }; 266941B31A6DC2AC0063BE93 /* MICmnLLDBDebugSessionInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnLLDBDebugSessionInfo.cpp; path = "tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp"; sourceTree = SOURCE_ROOT; }; 266941B41A6DC2AC0063BE93 /* MICmnLLDBDebugSessionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnLLDBDebugSessionInfo.h; path = "tools/lldb-mi/MICmnLLDBDebugSessionInfo.h"; sourceTree = SOURCE_ROOT; }; 266941B51A6DC2AC0063BE93 /* MICmnLLDBDebugSessionInfoVarObj.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnLLDBDebugSessionInfoVarObj.cpp; path = "tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.cpp"; sourceTree = SOURCE_ROOT; }; 266941B61A6DC2AC0063BE93 /* MICmnLLDBDebugSessionInfoVarObj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnLLDBDebugSessionInfoVarObj.h; path = "tools/lldb-mi/MICmnLLDBDebugSessionInfoVarObj.h"; sourceTree = SOURCE_ROOT; }; 266941B71A6DC2AC0063BE93 /* MICmnLLDBProxySBValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnLLDBProxySBValue.cpp; path = "tools/lldb-mi/MICmnLLDBProxySBValue.cpp"; sourceTree = SOURCE_ROOT; }; 266941B81A6DC2AC0063BE93 /* MICmnLLDBProxySBValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnLLDBProxySBValue.h; path = "tools/lldb-mi/MICmnLLDBProxySBValue.h"; sourceTree = SOURCE_ROOT; }; 266941B91A6DC2AC0063BE93 /* MICmnLLDBUtilSBValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnLLDBUtilSBValue.cpp; path = "tools/lldb-mi/MICmnLLDBUtilSBValue.cpp"; sourceTree = SOURCE_ROOT; }; 266941BA1A6DC2AC0063BE93 /* MICmnLLDBUtilSBValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnLLDBUtilSBValue.h; path = "tools/lldb-mi/MICmnLLDBUtilSBValue.h"; sourceTree = SOURCE_ROOT; }; 266941BB1A6DC2AC0063BE93 /* MICmnLog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnLog.cpp; path = "tools/lldb-mi/MICmnLog.cpp"; sourceTree = SOURCE_ROOT; }; 266941BC1A6DC2AC0063BE93 /* MICmnLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnLog.h; path = "tools/lldb-mi/MICmnLog.h"; sourceTree = SOURCE_ROOT; }; 266941BD1A6DC2AC0063BE93 /* MICmnLogMediumFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnLogMediumFile.cpp; path = "tools/lldb-mi/MICmnLogMediumFile.cpp"; sourceTree = SOURCE_ROOT; }; 266941BE1A6DC2AC0063BE93 /* MICmnLogMediumFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnLogMediumFile.h; path = "tools/lldb-mi/MICmnLogMediumFile.h"; sourceTree = SOURCE_ROOT; }; 266941BF1A6DC2AC0063BE93 /* MICmnMIOutOfBandRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnMIOutOfBandRecord.cpp; path = "tools/lldb-mi/MICmnMIOutOfBandRecord.cpp"; sourceTree = SOURCE_ROOT; }; 266941C01A6DC2AC0063BE93 /* MICmnMIOutOfBandRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnMIOutOfBandRecord.h; path = "tools/lldb-mi/MICmnMIOutOfBandRecord.h"; sourceTree = SOURCE_ROOT; }; 266941C11A6DC2AC0063BE93 /* MICmnMIResultRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnMIResultRecord.cpp; path = "tools/lldb-mi/MICmnMIResultRecord.cpp"; sourceTree = SOURCE_ROOT; }; 266941C21A6DC2AC0063BE93 /* MICmnMIResultRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnMIResultRecord.h; path = "tools/lldb-mi/MICmnMIResultRecord.h"; sourceTree = SOURCE_ROOT; }; 266941C31A6DC2AC0063BE93 /* MICmnMIValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnMIValue.cpp; path = "tools/lldb-mi/MICmnMIValue.cpp"; sourceTree = SOURCE_ROOT; }; 266941C41A6DC2AC0063BE93 /* MICmnMIValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnMIValue.h; path = "tools/lldb-mi/MICmnMIValue.h"; sourceTree = SOURCE_ROOT; }; 266941C51A6DC2AC0063BE93 /* MICmnMIValueConst.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnMIValueConst.cpp; path = "tools/lldb-mi/MICmnMIValueConst.cpp"; sourceTree = SOURCE_ROOT; }; 266941C61A6DC2AC0063BE93 /* MICmnMIValueConst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnMIValueConst.h; path = "tools/lldb-mi/MICmnMIValueConst.h"; sourceTree = SOURCE_ROOT; }; 266941C71A6DC2AC0063BE93 /* MICmnMIValueList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnMIValueList.cpp; path = "tools/lldb-mi/MICmnMIValueList.cpp"; sourceTree = SOURCE_ROOT; }; 266941C81A6DC2AC0063BE93 /* MICmnMIValueList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnMIValueList.h; path = "tools/lldb-mi/MICmnMIValueList.h"; sourceTree = SOURCE_ROOT; }; 266941C91A6DC2AC0063BE93 /* MICmnMIValueResult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnMIValueResult.cpp; path = "tools/lldb-mi/MICmnMIValueResult.cpp"; sourceTree = SOURCE_ROOT; }; 266941CA1A6DC2AC0063BE93 /* MICmnMIValueResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnMIValueResult.h; path = "tools/lldb-mi/MICmnMIValueResult.h"; sourceTree = SOURCE_ROOT; }; 266941CB1A6DC2AC0063BE93 /* MICmnMIValueTuple.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnMIValueTuple.cpp; path = "tools/lldb-mi/MICmnMIValueTuple.cpp"; sourceTree = SOURCE_ROOT; }; 266941CC1A6DC2AC0063BE93 /* MICmnMIValueTuple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnMIValueTuple.h; path = "tools/lldb-mi/MICmnMIValueTuple.h"; sourceTree = SOURCE_ROOT; }; 266941CD1A6DC2AC0063BE93 /* MICmnResources.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnResources.cpp; path = "tools/lldb-mi/MICmnResources.cpp"; sourceTree = SOURCE_ROOT; }; 266941CE1A6DC2AC0063BE93 /* MICmnResources.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnResources.h; path = "tools/lldb-mi/MICmnResources.h"; sourceTree = SOURCE_ROOT; }; 266941CF1A6DC2AC0063BE93 /* MICmnStreamStderr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnStreamStderr.cpp; path = "tools/lldb-mi/MICmnStreamStderr.cpp"; sourceTree = SOURCE_ROOT; }; 266941D01A6DC2AC0063BE93 /* MICmnStreamStderr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnStreamStderr.h; path = "tools/lldb-mi/MICmnStreamStderr.h"; sourceTree = SOURCE_ROOT; }; 266941D11A6DC2AC0063BE93 /* MICmnStreamStdin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnStreamStdin.cpp; path = "tools/lldb-mi/MICmnStreamStdin.cpp"; sourceTree = SOURCE_ROOT; }; 266941D21A6DC2AC0063BE93 /* MICmnStreamStdin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnStreamStdin.h; path = "tools/lldb-mi/MICmnStreamStdin.h"; sourceTree = SOURCE_ROOT; }; 266941D71A6DC2AC0063BE93 /* MICmnStreamStdout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnStreamStdout.cpp; path = "tools/lldb-mi/MICmnStreamStdout.cpp"; sourceTree = SOURCE_ROOT; }; 266941D81A6DC2AC0063BE93 /* MICmnStreamStdout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnStreamStdout.h; path = "tools/lldb-mi/MICmnStreamStdout.h"; sourceTree = SOURCE_ROOT; }; 266941D91A6DC2AC0063BE93 /* MICmnThreadMgrStd.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmnThreadMgrStd.cpp; path = "tools/lldb-mi/MICmnThreadMgrStd.cpp"; sourceTree = SOURCE_ROOT; }; 266941DA1A6DC2AC0063BE93 /* MICmnThreadMgrStd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmnThreadMgrStd.h; path = "tools/lldb-mi/MICmnThreadMgrStd.h"; sourceTree = SOURCE_ROOT; }; 266941DB1A6DC2AC0063BE93 /* MIDataTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MIDataTypes.h; path = "tools/lldb-mi/MIDataTypes.h"; sourceTree = SOURCE_ROOT; }; 266941DC1A6DC2AC0063BE93 /* MIDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MIDriver.cpp; path = "tools/lldb-mi/MIDriver.cpp"; sourceTree = SOURCE_ROOT; }; 266941DD1A6DC2AC0063BE93 /* MIDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MIDriver.h; path = "tools/lldb-mi/MIDriver.h"; sourceTree = SOURCE_ROOT; }; 266941DE1A6DC2AC0063BE93 /* MIDriverBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MIDriverBase.cpp; path = "tools/lldb-mi/MIDriverBase.cpp"; sourceTree = SOURCE_ROOT; }; 266941DF1A6DC2AC0063BE93 /* MIDriverBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MIDriverBase.h; path = "tools/lldb-mi/MIDriverBase.h"; sourceTree = SOURCE_ROOT; }; 266941E01A6DC2AC0063BE93 /* MIDriverMain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MIDriverMain.cpp; path = "tools/lldb-mi/MIDriverMain.cpp"; sourceTree = SOURCE_ROOT; }; 266941E11A6DC2AC0063BE93 /* MIDriverMgr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MIDriverMgr.cpp; path = "tools/lldb-mi/MIDriverMgr.cpp"; sourceTree = SOURCE_ROOT; }; 266941E21A6DC2AC0063BE93 /* MIDriverMgr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MIDriverMgr.h; path = "tools/lldb-mi/MIDriverMgr.h"; sourceTree = SOURCE_ROOT; }; 266941E31A6DC2AC0063BE93 /* MIReadMe.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = MIReadMe.txt; path = "tools/lldb-mi/MIReadMe.txt"; sourceTree = SOURCE_ROOT; }; 266941E41A6DC2AC0063BE93 /* MIUtilDateTimeStd.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MIUtilDateTimeStd.cpp; path = "tools/lldb-mi/MIUtilDateTimeStd.cpp"; sourceTree = SOURCE_ROOT; }; 266941E51A6DC2AC0063BE93 /* MIUtilDateTimeStd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MIUtilDateTimeStd.h; path = "tools/lldb-mi/MIUtilDateTimeStd.h"; sourceTree = SOURCE_ROOT; }; 266941E61A6DC2AC0063BE93 /* MIUtilDebug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MIUtilDebug.cpp; path = "tools/lldb-mi/MIUtilDebug.cpp"; sourceTree = SOURCE_ROOT; }; 266941E71A6DC2AC0063BE93 /* MIUtilDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MIUtilDebug.h; path = "tools/lldb-mi/MIUtilDebug.h"; sourceTree = SOURCE_ROOT; }; 266941E81A6DC2AC0063BE93 /* MIUtilFileStd.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MIUtilFileStd.cpp; path = "tools/lldb-mi/MIUtilFileStd.cpp"; sourceTree = SOURCE_ROOT; }; 266941E91A6DC2AC0063BE93 /* MIUtilFileStd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MIUtilFileStd.h; path = "tools/lldb-mi/MIUtilFileStd.h"; sourceTree = SOURCE_ROOT; }; 266941EA1A6DC2AC0063BE93 /* MIUtilMapIdToVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MIUtilMapIdToVariant.cpp; path = "tools/lldb-mi/MIUtilMapIdToVariant.cpp"; sourceTree = SOURCE_ROOT; }; 266941EB1A6DC2AC0063BE93 /* MIUtilMapIdToVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MIUtilMapIdToVariant.h; path = "tools/lldb-mi/MIUtilMapIdToVariant.h"; sourceTree = SOURCE_ROOT; }; 266941EC1A6DC2AC0063BE93 /* MIUtilSingletonBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MIUtilSingletonBase.h; path = "tools/lldb-mi/MIUtilSingletonBase.h"; sourceTree = SOURCE_ROOT; }; 266941ED1A6DC2AC0063BE93 /* MIUtilSingletonHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MIUtilSingletonHelper.h; path = "tools/lldb-mi/MIUtilSingletonHelper.h"; sourceTree = SOURCE_ROOT; }; 266941EE1A6DC2AC0063BE93 /* MIUtilString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MIUtilString.cpp; path = "tools/lldb-mi/MIUtilString.cpp"; sourceTree = SOURCE_ROOT; }; 266941EF1A6DC2AC0063BE93 /* MIUtilString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MIUtilString.h; path = "tools/lldb-mi/MIUtilString.h"; sourceTree = SOURCE_ROOT; }; 266941F81A6DC2AC0063BE93 /* MIUtilThreadBaseStd.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MIUtilThreadBaseStd.cpp; path = "tools/lldb-mi/MIUtilThreadBaseStd.cpp"; sourceTree = SOURCE_ROOT; }; 266941F91A6DC2AC0063BE93 /* MIUtilThreadBaseStd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MIUtilThreadBaseStd.h; path = "tools/lldb-mi/MIUtilThreadBaseStd.h"; sourceTree = SOURCE_ROOT; }; 266941FA1A6DC2AC0063BE93 /* MIUtilVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MIUtilVariant.cpp; path = "tools/lldb-mi/MIUtilVariant.cpp"; sourceTree = SOURCE_ROOT; }; 266941FB1A6DC2AC0063BE93 /* MIUtilVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MIUtilVariant.h; path = "tools/lldb-mi/MIUtilVariant.h"; sourceTree = SOURCE_ROOT; }; 266941FD1A6DC2AC0063BE93 /* Platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Platform.h; path = "tools/lldb-mi/Platform.h"; sourceTree = SOURCE_ROOT; }; 266960591199F4230075C61A /* build-llvm.pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = "build-llvm.pl"; sourceTree = ""; }; 2669605A1199F4230075C61A /* build-swig-wrapper-classes.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "build-swig-wrapper-classes.sh"; sourceTree = ""; }; 2669605B1199F4230075C61A /* checkpoint-llvm.pl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = "checkpoint-llvm.pl"; sourceTree = ""; }; 2669605C1199F4230075C61A /* finish-swig-wrapper-classes.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "finish-swig-wrapper-classes.sh"; sourceTree = ""; }; 2669605D1199F4230075C61A /* install-lldb.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "install-lldb.sh"; sourceTree = ""; }; 2669605E1199F4230075C61A /* lldb.swig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = lldb.swig; sourceTree = ""; }; 266960601199F4230075C61A /* build-swig-Python.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "build-swig-Python.sh"; sourceTree = ""; }; 266960611199F4230075C61A /* edit-swig-python-wrapper-file.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = "edit-swig-python-wrapper-file.py"; sourceTree = ""; }; 266960631199F4230075C61A /* sed-sources */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.perl; path = "sed-sources"; sourceTree = ""; }; 266DFE9613FD656E00D0C574 /* OperatingSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OperatingSystem.cpp; path = source/Target/OperatingSystem.cpp; sourceTree = ""; }; 266DFE9813FD658300D0C574 /* OperatingSystem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OperatingSystem.h; path = include/lldb/Target/OperatingSystem.h; sourceTree = ""; }; 266E82951B8CE346008FCA06 /* DWARFDIE.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DWARFDIE.h; sourceTree = ""; }; 266E82961B8CE3AC008FCA06 /* DWARFDIE.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFDIE.cpp; sourceTree = ""; }; 266E829C1B8E542C008FCA06 /* DWARFAttribute.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFAttribute.cpp; sourceTree = ""; }; 266F5CBB12FC846200DFCE33 /* Config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Config.h; path = include/lldb/Host/Config.h; sourceTree = ""; }; 26709E311964A34000B94724 /* LaunchServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LaunchServices.framework; path = /System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework; sourceTree = ""; }; 2670F8111862B44A006B332C /* libncurses.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libncurses.dylib; path = /usr/lib/libncurses.dylib; sourceTree = ""; }; 2672D8461189055500FF4019 /* CommandObjectFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectFrame.cpp; path = source/Commands/CommandObjectFrame.cpp; sourceTree = ""; }; 2672D8471189055500FF4019 /* CommandObjectFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectFrame.h; path = source/Commands/CommandObjectFrame.h; sourceTree = ""; }; 26744EED1338317700EF765A /* GDBRemoteCommunicationClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunicationClient.cpp; sourceTree = ""; }; 26744EEE1338317700EF765A /* GDBRemoteCommunicationClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDBRemoteCommunicationClient.h; sourceTree = ""; }; 26744EEF1338317700EF765A /* GDBRemoteCommunicationServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunicationServer.cpp; sourceTree = ""; }; 26744EF01338317700EF765A /* GDBRemoteCommunicationServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDBRemoteCommunicationServer.h; sourceTree = ""; }; 2675F6FE1332BE690067997B /* PlatformRemoteiOS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformRemoteiOS.cpp; sourceTree = ""; }; 2675F6FF1332BE690067997B /* PlatformRemoteiOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformRemoteiOS.h; sourceTree = ""; }; 26764C951E48F46F008D3573 /* ConstString.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ConstString.h; path = include/lldb/Utility/ConstString.h; sourceTree = ""; }; 26764C961E48F482008D3573 /* ConstString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConstString.cpp; path = source/Utility/ConstString.cpp; sourceTree = ""; }; 26764C9B1E48F50C008D3573 /* Stream.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Stream.h; path = include/lldb/Utility/Stream.h; sourceTree = ""; }; 26764C9C1E48F516008D3573 /* RegularExpression.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RegularExpression.h; path = include/lldb/Utility/RegularExpression.h; sourceTree = ""; }; 26764C9D1E48F51E008D3573 /* Stream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Stream.cpp; path = source/Utility/Stream.cpp; sourceTree = ""; }; 26764C9F1E48F528008D3573 /* RegularExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegularExpression.cpp; path = source/Utility/RegularExpression.cpp; sourceTree = ""; }; 26764CA11E48F547008D3573 /* StreamString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StreamString.cpp; path = source/Utility/StreamString.cpp; sourceTree = ""; }; 26764CA31E48F550008D3573 /* StreamString.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StreamString.h; path = include/lldb/Utility/StreamString.h; sourceTree = ""; }; 26764CA41E48F566008D3573 /* StreamTee.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StreamTee.h; path = include/lldb/Utility/StreamTee.h; sourceTree = ""; }; 2676A093119C93C8008A98EF /* StringExtractorGDBRemote.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringExtractorGDBRemote.cpp; path = source/Utility/StringExtractorGDBRemote.cpp; sourceTree = ""; }; 2676A094119C93C8008A98EF /* StringExtractorGDBRemote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringExtractorGDBRemote.h; path = source/Utility/StringExtractorGDBRemote.h; sourceTree = ""; }; 267A47F21B14115A0021A5BC /* SoftwareBreakpoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SoftwareBreakpoint.h; path = include/lldb/Host/common/SoftwareBreakpoint.h; sourceTree = ""; }; 267A47F31B14116E0021A5BC /* NativeBreakpoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeBreakpoint.h; path = include/lldb/Host/common/NativeBreakpoint.h; sourceTree = ""; }; 267A47F41B1411750021A5BC /* NativeBreakpointList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeBreakpointList.h; path = include/lldb/Host/common/NativeBreakpointList.h; sourceTree = ""; }; 267A47F51B14117F0021A5BC /* NativeProcessProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeProcessProtocol.h; path = include/lldb/Host/common/NativeProcessProtocol.h; sourceTree = ""; }; 267A47F61B14118F0021A5BC /* NativeRegisterContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeRegisterContext.h; path = include/lldb/Host/common/NativeRegisterContext.h; sourceTree = ""; }; 267A47F81B1411A40021A5BC /* NativeThreadProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeThreadProtocol.h; path = include/lldb/Host/common/NativeThreadProtocol.h; sourceTree = ""; }; 267A47F91B1411AC0021A5BC /* NativeWatchpointList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeWatchpointList.h; path = include/lldb/Host/common/NativeWatchpointList.h; sourceTree = ""; }; 267A47FA1B1411C40021A5BC /* NativeRegisterContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeRegisterContext.cpp; path = source/Host/common/NativeRegisterContext.cpp; sourceTree = ""; }; 267A47FE1B1411D90021A5BC /* NativeWatchpointList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeWatchpointList.cpp; path = source/Host/common/NativeWatchpointList.cpp; sourceTree = ""; }; 267A48001B1411E40021A5BC /* XML.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = XML.cpp; path = source/Host/common/XML.cpp; sourceTree = ""; }; 267A48031B1416080021A5BC /* XML.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = XML.h; path = include/lldb/Host/XML.h; sourceTree = ""; }; 267C0128136880C7006E963E /* OptionGroupValueObjectDisplay.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupValueObjectDisplay.h; path = include/lldb/Interpreter/OptionGroupValueObjectDisplay.h; sourceTree = ""; }; 267C012A136880DF006E963E /* OptionGroupValueObjectDisplay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupValueObjectDisplay.cpp; path = source/Interpreter/OptionGroupValueObjectDisplay.cpp; sourceTree = ""; }; 267DFB441B06752A00000FB7 /* MICmdArgValPrintValues.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdArgValPrintValues.cpp; path = "tools/lldb-mi/MICmdArgValPrintValues.cpp"; sourceTree = SOURCE_ROOT; }; 267DFB451B06752A00000FB7 /* MICmdArgValPrintValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdArgValPrintValues.h; path = "tools/lldb-mi/MICmdArgValPrintValues.h"; sourceTree = SOURCE_ROOT; }; 267F68471CC02DED0086832B /* ABISysV_s390x.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ABISysV_s390x.cpp; sourceTree = ""; }; 267F68481CC02DED0086832B /* ABISysV_s390x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ABISysV_s390x.h; sourceTree = ""; }; 267F684D1CC02E270086832B /* RegisterContextPOSIXCore_s390x.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextPOSIXCore_s390x.cpp; sourceTree = ""; }; 267F684E1CC02E270086832B /* RegisterContextPOSIXCore_s390x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextPOSIXCore_s390x.h; sourceTree = ""; }; 267F68511CC02E920086832B /* RegisterContextLinux_s390x.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextLinux_s390x.cpp; path = Utility/RegisterContextLinux_s390x.cpp; sourceTree = ""; }; 267F68521CC02E920086832B /* RegisterContextLinux_s390x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextLinux_s390x.h; path = Utility/RegisterContextLinux_s390x.h; sourceTree = ""; }; 267F68551CC02EAE0086832B /* RegisterContextPOSIX_s390x.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextPOSIX_s390x.cpp; path = Utility/RegisterContextPOSIX_s390x.cpp; sourceTree = ""; }; 267F68561CC02EAE0086832B /* RegisterContextPOSIX_s390x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextPOSIX_s390x.h; path = Utility/RegisterContextPOSIX_s390x.h; sourceTree = ""; }; 267F68591CC02EBE0086832B /* RegisterInfos_s390x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterInfos_s390x.h; path = Utility/RegisterInfos_s390x.h; sourceTree = ""; }; 2682100C143A59AE004BCF2D /* MappedHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MappedHash.h; path = include/lldb/Core/MappedHash.h; sourceTree = ""; }; 2682F284115EF3A700CCFF99 /* SBError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBError.cpp; path = source/API/SBError.cpp; sourceTree = ""; }; 2682F286115EF3BD00CCFF99 /* SBError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBError.h; path = include/lldb/API/SBError.h; sourceTree = ""; }; 268648C116531BF800F04704 /* com.apple.debugserver.posix.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.debugserver.posix.plist; path = tools/debugserver/source/com.apple.debugserver.posix.plist; sourceTree = ""; }; 268648C216531BF800F04704 /* com.apple.debugserver.applist.internal.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.debugserver.applist.internal.plist; path = tools/debugserver/source/com.apple.debugserver.applist.internal.plist; sourceTree = ""; }; 268648C316531BF800F04704 /* com.apple.debugserver.internal.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.debugserver.internal.plist; path = tools/debugserver/source/com.apple.debugserver.internal.plist; sourceTree = ""; }; 2686536B1370ACB200D186A3 /* OptionGroupBoolean.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupBoolean.cpp; path = source/Interpreter/OptionGroupBoolean.cpp; sourceTree = ""; }; 2686536D1370ACC600D186A3 /* OptionGroupBoolean.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupBoolean.h; path = include/lldb/Interpreter/OptionGroupBoolean.h; sourceTree = ""; }; 2686536E1370AE5A00D186A3 /* OptionGroupUInt64.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupUInt64.h; path = include/lldb/Interpreter/OptionGroupUInt64.h; sourceTree = ""; }; 2686536F1370AE7200D186A3 /* OptionGroupUInt64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupUInt64.cpp; path = source/Interpreter/OptionGroupUInt64.cpp; sourceTree = ""; }; 26879CE51333F5750012C1F8 /* CommandObjectPlatform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectPlatform.h; path = source/Commands/CommandObjectPlatform.h; sourceTree = ""; }; 26879CE71333F58B0012C1F8 /* CommandObjectPlatform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectPlatform.cpp; path = source/Commands/CommandObjectPlatform.cpp; sourceTree = ""; }; 2689B0A4113EE3CD00A4AEDB /* Symbols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Symbols.h; path = include/lldb/Host/Symbols.h; sourceTree = ""; }; 2689B0B5113EE47E00A4AEDB /* Symbols.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Symbols.cpp; path = source/Host/macosx/Symbols.cpp; sourceTree = ""; }; 2689FFCA13353D7A00698AC0 /* liblldb-core.a */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = "liblldb-core.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 268A683D1321B53B000E3FB8 /* DynamicLoaderStatic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLoaderStatic.cpp; sourceTree = ""; }; 268A683E1321B53B000E3FB8 /* DynamicLoaderStatic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderStatic.h; sourceTree = ""; }; 268A813F115B19D000F645B0 /* UniqueCStringMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UniqueCStringMap.h; path = include/lldb/Core/UniqueCStringMap.h; sourceTree = ""; }; 268DA871130095D000C9483A /* Terminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Terminal.h; path = include/lldb/Host/Terminal.h; sourceTree = ""; }; 268DA873130095ED00C9483A /* Terminal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Terminal.cpp; sourceTree = ""; }; 268F9D52123AA15200B91E9B /* SBSymbolContextList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBSymbolContextList.h; path = include/lldb/API/SBSymbolContextList.h; sourceTree = ""; }; 268F9D54123AA16600B91E9B /* SBSymbolContextList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBSymbolContextList.cpp; path = source/API/SBSymbolContextList.cpp; sourceTree = ""; }; 2690B36F1381D5B600ECFBAE /* Memory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Memory.h; path = include/lldb/Target/Memory.h; sourceTree = ""; }; 2690B3701381D5C300ECFBAE /* Memory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Memory.cpp; path = source/Target/Memory.cpp; sourceTree = ""; }; 2690CD171A6DC0D000E717C8 /* lldb-mi */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "lldb-mi"; sourceTree = BUILT_PRODUCTS_DIR; }; 2692BA13136610C100F9E14D /* UnwindAssemblyInstEmulation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UnwindAssemblyInstEmulation.cpp; sourceTree = ""; }; 2692BA14136610C100F9E14D /* UnwindAssemblyInstEmulation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnwindAssemblyInstEmulation.h; sourceTree = ""; }; 269416AD119A024800FF2715 /* CommandObjectTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectTarget.cpp; path = source/Commands/CommandObjectTarget.cpp; sourceTree = ""; }; 269416AE119A024800FF2715 /* CommandObjectTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectTarget.h; path = source/Commands/CommandObjectTarget.h; sourceTree = ""; }; 2694E99A14FC0BB30076DE67 /* PlatformFreeBSD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformFreeBSD.cpp; sourceTree = ""; }; 2694E99B14FC0BB30076DE67 /* PlatformFreeBSD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformFreeBSD.h; sourceTree = ""; }; 2694E9A114FC0BBD0076DE67 /* PlatformLinux.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformLinux.cpp; sourceTree = ""; }; 2694E9A214FC0BBD0076DE67 /* PlatformLinux.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformLinux.h; sourceTree = ""; }; 26954EBC1401EE8B00294D09 /* DynamicRegisterInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DynamicRegisterInfo.cpp; path = Utility/DynamicRegisterInfo.cpp; sourceTree = ""; }; 26954EBD1401EE8B00294D09 /* DynamicRegisterInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DynamicRegisterInfo.h; path = Utility/DynamicRegisterInfo.h; sourceTree = ""; }; 26957D9213D381C900670048 /* RegisterContextDarwin_arm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextDarwin_arm.cpp; path = Utility/RegisterContextDarwin_arm.cpp; sourceTree = ""; }; 26957D9313D381C900670048 /* RegisterContextDarwin_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextDarwin_arm.h; path = Utility/RegisterContextDarwin_arm.h; sourceTree = ""; }; 26957D9413D381C900670048 /* RegisterContextDarwin_i386.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextDarwin_i386.cpp; path = Utility/RegisterContextDarwin_i386.cpp; sourceTree = ""; }; 26957D9513D381C900670048 /* RegisterContextDarwin_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextDarwin_i386.h; path = Utility/RegisterContextDarwin_i386.h; sourceTree = ""; }; 26957D9613D381C900670048 /* RegisterContextDarwin_x86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextDarwin_x86_64.cpp; path = Utility/RegisterContextDarwin_x86_64.cpp; sourceTree = ""; }; 26957D9713D381C900670048 /* RegisterContextDarwin_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextDarwin_x86_64.h; path = Utility/RegisterContextDarwin_x86_64.h; sourceTree = ""; }; 2697A39215E404B1003E682C /* OptionValueArch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueArch.cpp; path = source/Interpreter/OptionValueArch.cpp; sourceTree = ""; }; 2697A39415E404BA003E682C /* OptionValueArch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValueArch.h; path = include/lldb/Interpreter/OptionValueArch.h; sourceTree = ""; }; 2697A54B133A6305004E4240 /* PlatformDarwin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformDarwin.cpp; sourceTree = ""; }; 2697A54C133A6305004E4240 /* PlatformDarwin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformDarwin.h; sourceTree = ""; }; 2698699815E6CBD0002415FF /* OperatingSystemPython.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OperatingSystemPython.cpp; sourceTree = ""; }; 2698699915E6CBD0002415FF /* OperatingSystemPython.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OperatingSystemPython.h; sourceTree = ""; }; 269DDD451B8FD01A00D0DBD8 /* DWARFASTParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFASTParser.h; sourceTree = ""; }; 269DDD481B8FD1C300D0DBD8 /* DWARFASTParserClang.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFASTParserClang.cpp; sourceTree = ""; }; 269DDD491B8FD1C300D0DBD8 /* DWARFASTParserClang.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFASTParserClang.h; sourceTree = ""; }; 269FF07D12494F7D00225026 /* FuncUnwinders.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FuncUnwinders.h; path = include/lldb/Symbol/FuncUnwinders.h; sourceTree = ""; }; 269FF07F12494F8E00225026 /* UnwindPlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UnwindPlan.h; path = include/lldb/Symbol/UnwindPlan.h; sourceTree = ""; }; 269FF08112494FC200225026 /* UnwindTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UnwindTable.h; path = include/lldb/Symbol/UnwindTable.h; sourceTree = ""; }; 26A0DA4D140F721D006DA411 /* HashedNameToDIE.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HashedNameToDIE.h; sourceTree = ""; }; 26A3757F1D59462700D6CBDB /* SelectHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SelectHelper.cpp; path = source/Utility/SelectHelper.cpp; sourceTree = ""; }; 26A375831D59486000D6CBDB /* StringExtractor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StringExtractor.h; path = include/lldb/Utility/StringExtractor.h; sourceTree = ""; }; 26A375841D59487700D6CBDB /* SelectHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SelectHelper.h; path = include/lldb/Utility/SelectHelper.h; sourceTree = ""; }; 26A3B4AC1181454800381BC2 /* ObjectContainerBSDArchive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectContainerBSDArchive.cpp; sourceTree = ""; }; 26A3B4AD1181454800381BC2 /* ObjectContainerBSDArchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectContainerBSDArchive.h; sourceTree = ""; }; 26A4EEB511682AAC007A372A /* LLDBWrapPython.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = LLDBWrapPython.cpp; sourceTree = BUILT_PRODUCTS_DIR; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 26A527BD14E24F5F00F3A14A /* ProcessMachCore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessMachCore.cpp; sourceTree = ""; }; 26A527BE14E24F5F00F3A14A /* ProcessMachCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessMachCore.h; sourceTree = ""; }; 26A527BF14E24F5F00F3A14A /* ThreadMachCore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadMachCore.cpp; sourceTree = ""; }; 26A527C014E24F5F00F3A14A /* ThreadMachCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadMachCore.h; sourceTree = ""; }; 26A7A034135E6E4200FB369E /* OptionValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValue.cpp; path = source/Interpreter/OptionValue.cpp; sourceTree = ""; }; 26A7A036135E6E5300FB369E /* OptionValue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionValue.h; path = include/lldb/Interpreter/OptionValue.h; sourceTree = ""; }; 26AB54111832DC3400EADFF3 /* RegisterCheckpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterCheckpoint.h; path = include/lldb/Target/RegisterCheckpoint.h; sourceTree = ""; }; 26AB92101819D74600E63F3E /* DWARFDataExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFDataExtractor.cpp; sourceTree = ""; }; 26AB92111819D74600E63F3E /* DWARFDataExtractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFDataExtractor.h; sourceTree = ""; }; 26ACEC2715E077AE00E94760 /* Property.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Property.h; path = include/lldb/Interpreter/Property.h; sourceTree = ""; }; 26B167A41123BF5500DC7B4F /* ThreadSafeValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadSafeValue.h; path = include/lldb/Core/ThreadSafeValue.h; sourceTree = ""; }; 26B1EFAC154638AF00E2DAC7 /* DWARFDeclContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFDeclContext.cpp; sourceTree = ""; }; 26B1EFAD154638AF00E2DAC7 /* DWARFDeclContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFDeclContext.h; sourceTree = ""; }; 26B42C4C1187ABA50079C8C8 /* LLDB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLDB.h; path = include/lldb/API/LLDB.h; sourceTree = ""; }; 26B7564C14F89356008D9CB3 /* PlatformiOSSimulator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformiOSSimulator.cpp; sourceTree = ""; }; 26B7564D14F89356008D9CB3 /* PlatformiOSSimulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformiOSSimulator.h; sourceTree = ""; }; 26B75B421AD6E29A001F7A57 /* MipsLinuxSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MipsLinuxSignals.cpp; path = Utility/MipsLinuxSignals.cpp; sourceTree = ""; }; 26B75B431AD6E29A001F7A57 /* MipsLinuxSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MipsLinuxSignals.h; path = Utility/MipsLinuxSignals.h; sourceTree = ""; }; 26B8283C142D01E9002DBC64 /* SBSection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBSection.h; path = include/lldb/API/SBSection.h; sourceTree = ""; }; 26B8283F142D020F002DBC64 /* SBSection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBSection.cpp; path = source/API/SBSection.cpp; sourceTree = ""; }; 26B8B42212EEC52A00A831B2 /* UniqueDWARFASTType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UniqueDWARFASTType.h; sourceTree = ""; }; 26B8B42312EEC52A00A831B2 /* UniqueDWARFASTType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UniqueDWARFASTType.cpp; sourceTree = ""; }; 26BC179718C7F2B300D2196D /* JITLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JITLoader.cpp; path = source/Target/JITLoader.cpp; sourceTree = ""; }; 26BC179818C7F2B300D2196D /* JITLoaderList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JITLoaderList.cpp; path = source/Target/JITLoaderList.cpp; sourceTree = ""; }; 26BC179B18C7F2CB00D2196D /* JITLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JITLoader.h; path = include/lldb/Target/JITLoader.h; sourceTree = ""; }; 26BC179C18C7F2CB00D2196D /* JITLoaderList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JITLoaderList.h; path = include/lldb/Target/JITLoaderList.h; sourceTree = ""; }; 26BC17A218C7F4CB00D2196D /* ProcessElfCore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessElfCore.cpp; sourceTree = ""; }; 26BC17A318C7F4CB00D2196D /* ProcessElfCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessElfCore.h; sourceTree = ""; }; 26BC17A418C7F4CB00D2196D /* RegisterContextPOSIXCore_mips64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextPOSIXCore_mips64.cpp; sourceTree = ""; }; 26BC17A518C7F4CB00D2196D /* RegisterContextPOSIXCore_mips64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextPOSIXCore_mips64.h; sourceTree = ""; }; 26BC17A618C7F4CB00D2196D /* RegisterContextPOSIXCore_x86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextPOSIXCore_x86_64.cpp; sourceTree = ""; }; 26BC17A718C7F4CB00D2196D /* RegisterContextPOSIXCore_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextPOSIXCore_x86_64.h; sourceTree = ""; }; 26BC17A818C7F4CB00D2196D /* ThreadElfCore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadElfCore.cpp; sourceTree = ""; }; 26BC17A918C7F4CB00D2196D /* ThreadElfCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadElfCore.h; sourceTree = ""; }; 26BC17BA18C7F4FA00D2196D /* ProcessMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessMessage.cpp; sourceTree = ""; }; 26BC17BB18C7F4FA00D2196D /* ProcessMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessMessage.h; sourceTree = ""; }; 26BC17BE18C7F4FA00D2196D /* ProcessPOSIXLog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessPOSIXLog.cpp; sourceTree = ""; }; 26BC17BF18C7F4FA00D2196D /* ProcessPOSIXLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessPOSIXLog.h; sourceTree = ""; }; 26BC7C2510F1B3BC00F91463 /* lldb-defines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lldb-defines.h"; path = "include/lldb/lldb-defines.h"; sourceTree = ""; }; 26BC7C2610F1B3BC00F91463 /* lldb-enumerations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lldb-enumerations.h"; path = "include/lldb/lldb-enumerations.h"; sourceTree = ""; }; 26BC7C2810F1B3BC00F91463 /* lldb-private-interfaces.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lldb-private-interfaces.h"; path = "include/lldb/lldb-private-interfaces.h"; sourceTree = ""; }; 26BC7C2910F1B3BC00F91463 /* lldb-types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lldb-types.h"; path = "include/lldb/lldb-types.h"; sourceTree = ""; }; 26BC7C2A10F1B3BC00F91463 /* lldb-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lldb-private.h"; path = "include/lldb/lldb-private.h"; sourceTree = ""; }; 26BC7C5510F1B6E900F91463 /* Block.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Block.h; path = include/lldb/Symbol/Block.h; sourceTree = ""; }; 26BC7C5610F1B6E900F91463 /* ClangASTContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangASTContext.h; path = include/lldb/Symbol/ClangASTContext.h; sourceTree = ""; }; 26BC7C5710F1B6E900F91463 /* CompileUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompileUnit.h; path = include/lldb/Symbol/CompileUnit.h; sourceTree = ""; }; 26BC7C5810F1B6E900F91463 /* Declaration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Declaration.h; path = include/lldb/Symbol/Declaration.h; sourceTree = ""; }; 26BC7C5910F1B6E900F91463 /* DWARFCallFrameInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DWARFCallFrameInfo.h; path = include/lldb/Symbol/DWARFCallFrameInfo.h; sourceTree = ""; }; 26BC7C5A10F1B6E900F91463 /* Function.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Function.h; path = include/lldb/Symbol/Function.h; sourceTree = ""; }; 26BC7C5B10F1B6E900F91463 /* LineEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LineEntry.h; path = include/lldb/Symbol/LineEntry.h; sourceTree = ""; }; 26BC7C5C10F1B6E900F91463 /* LineTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LineTable.h; path = include/lldb/Symbol/LineTable.h; sourceTree = ""; }; 26BC7C5D10F1B6E900F91463 /* ObjectContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ObjectContainer.h; path = include/lldb/Symbol/ObjectContainer.h; sourceTree = ""; }; 26BC7C5E10F1B6E900F91463 /* ObjectFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ObjectFile.h; path = include/lldb/Symbol/ObjectFile.h; sourceTree = ""; }; 26BC7C5F10F1B6E900F91463 /* Symbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Symbol.h; path = include/lldb/Symbol/Symbol.h; sourceTree = ""; }; 26BC7C6010F1B6E900F91463 /* SymbolContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SymbolContext.h; path = include/lldb/Symbol/SymbolContext.h; sourceTree = ""; }; 26BC7C6110F1B6E900F91463 /* SymbolContextScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SymbolContextScope.h; path = include/lldb/Symbol/SymbolContextScope.h; sourceTree = ""; }; 26BC7C6210F1B6E900F91463 /* SymbolFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SymbolFile.h; path = include/lldb/Symbol/SymbolFile.h; sourceTree = ""; }; 26BC7C6310F1B6E900F91463 /* SymbolVendor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SymbolVendor.h; path = include/lldb/Symbol/SymbolVendor.h; sourceTree = ""; }; 26BC7C6410F1B6E900F91463 /* Symtab.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Symtab.h; path = include/lldb/Symbol/Symtab.h; sourceTree = ""; }; 26BC7C6510F1B6E900F91463 /* Type.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Type.h; path = include/lldb/Symbol/Type.h; sourceTree = ""; }; 26BC7C6610F1B6E900F91463 /* TypeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypeList.h; path = include/lldb/Symbol/TypeList.h; sourceTree = ""; }; 26BC7C6710F1B6E900F91463 /* Variable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Variable.h; path = include/lldb/Symbol/Variable.h; sourceTree = ""; }; 26BC7C6810F1B6E900F91463 /* VariableList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VariableList.h; path = include/lldb/Symbol/VariableList.h; sourceTree = ""; }; 26BC7CED10F1B71400F91463 /* StoppointCallbackContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StoppointCallbackContext.h; path = include/lldb/Breakpoint/StoppointCallbackContext.h; sourceTree = ""; }; 26BC7CEE10F1B71400F91463 /* Breakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Breakpoint.h; path = include/lldb/Breakpoint/Breakpoint.h; sourceTree = ""; }; 26BC7CEF10F1B71400F91463 /* BreakpointID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointID.h; path = include/lldb/Breakpoint/BreakpointID.h; sourceTree = ""; }; 26BC7CF010F1B71400F91463 /* BreakpointIDList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointIDList.h; path = include/lldb/Breakpoint/BreakpointIDList.h; sourceTree = ""; }; 26BC7CF110F1B71400F91463 /* BreakpointList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointList.h; path = include/lldb/Breakpoint/BreakpointList.h; sourceTree = ""; }; 26BC7CF210F1B71400F91463 /* BreakpointLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointLocation.h; path = include/lldb/Breakpoint/BreakpointLocation.h; sourceTree = ""; }; 26BC7CF310F1B71400F91463 /* BreakpointLocationCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointLocationCollection.h; path = include/lldb/Breakpoint/BreakpointLocationCollection.h; sourceTree = ""; }; 26BC7CF410F1B71400F91463 /* BreakpointLocationList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointLocationList.h; path = include/lldb/Breakpoint/BreakpointLocationList.h; sourceTree = ""; }; 26BC7CF510F1B71400F91463 /* BreakpointOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointOptions.h; path = include/lldb/Breakpoint/BreakpointOptions.h; sourceTree = ""; }; 26BC7CF610F1B71400F91463 /* BreakpointResolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointResolver.h; path = include/lldb/Breakpoint/BreakpointResolver.h; sourceTree = ""; }; 26BC7CF710F1B71400F91463 /* BreakpointSite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointSite.h; path = include/lldb/Breakpoint/BreakpointSite.h; sourceTree = ""; }; 26BC7CF810F1B71400F91463 /* BreakpointSiteList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointSiteList.h; path = include/lldb/Breakpoint/BreakpointSiteList.h; sourceTree = ""; }; 26BC7CF910F1B71400F91463 /* SearchFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SearchFilter.h; path = include/lldb/Core/SearchFilter.h; sourceTree = ""; }; 26BC7CFA10F1B71400F91463 /* Stoppoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Stoppoint.h; path = include/lldb/Breakpoint/Stoppoint.h; sourceTree = ""; }; 26BC7CFB10F1B71400F91463 /* StoppointLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StoppointLocation.h; path = include/lldb/Breakpoint/StoppointLocation.h; sourceTree = ""; }; 26BC7CFC10F1B71400F91463 /* Watchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Watchpoint.h; path = include/lldb/Breakpoint/Watchpoint.h; sourceTree = ""; }; 26BC7D1410F1B76300F91463 /* CommandObjectBreakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectBreakpoint.h; path = source/Commands/CommandObjectBreakpoint.h; sourceTree = ""; }; 26BC7D1710F1B76300F91463 /* CommandObjectDisassemble.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectDisassemble.h; path = source/Commands/CommandObjectDisassemble.h; sourceTree = ""; }; 26BC7D1810F1B76300F91463 /* CommandObjectExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectExpression.h; path = source/Commands/CommandObjectExpression.h; sourceTree = ""; }; 26BC7D1A10F1B76300F91463 /* CommandObjectHelp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectHelp.h; path = source/Commands/CommandObjectHelp.h; sourceTree = ""; }; 26BC7D1D10F1B76300F91463 /* CommandObjectMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectMemory.h; path = source/Commands/CommandObjectMemory.h; sourceTree = ""; }; 26BC7D1F10F1B76300F91463 /* CommandObjectProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectProcess.h; path = source/Commands/CommandObjectProcess.h; sourceTree = ""; }; 26BC7D2010F1B76300F91463 /* CommandObjectQuit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectQuit.h; path = source/Commands/CommandObjectQuit.h; sourceTree = ""; }; 26BC7D2210F1B76300F91463 /* CommandObjectRegister.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectRegister.h; path = source/Commands/CommandObjectRegister.h; sourceTree = ""; }; 26BC7D2410F1B76300F91463 /* CommandObjectScript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectScript.h; path = source/Interpreter/CommandObjectScript.h; sourceTree = ""; }; 26BC7D2710F1B76300F91463 /* CommandObjectSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectSettings.h; path = source/Commands/CommandObjectSettings.h; sourceTree = ""; }; 26BC7D2910F1B76300F91463 /* CommandObjectSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectSource.h; path = source/Commands/CommandObjectSource.h; sourceTree = ""; }; 26BC7D2C10F1B76300F91463 /* CommandObjectSyntax.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectSyntax.h; path = source/Commands/CommandObjectSyntax.h; sourceTree = ""; }; 26BC7D2D10F1B76300F91463 /* CommandObjectThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectThread.h; path = source/Commands/CommandObjectThread.h; sourceTree = ""; }; 26BC7D5010F1B77400F91463 /* Address.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Address.h; path = include/lldb/Core/Address.h; sourceTree = ""; }; 26BC7D5110F1B77400F91463 /* AddressRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AddressRange.h; path = include/lldb/Core/AddressRange.h; sourceTree = ""; }; 26BC7D5210F1B77400F91463 /* ArchSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ArchSpec.h; path = include/lldb/Core/ArchSpec.h; sourceTree = ""; }; 26BC7D5310F1B77400F91463 /* Args.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Args.h; path = include/lldb/Interpreter/Args.h; sourceTree = ""; }; 26BC7D5410F1B77400F91463 /* Broadcaster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Broadcaster.h; path = include/lldb/Core/Broadcaster.h; sourceTree = ""; }; 26BC7D5510F1B77400F91463 /* ClangForward.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangForward.h; path = include/lldb/Core/ClangForward.h; sourceTree = ""; }; 26BC7D5610F1B77400F91463 /* Communication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Communication.h; path = include/lldb/Core/Communication.h; sourceTree = ""; }; 26BC7D5710F1B77400F91463 /* Connection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Connection.h; path = include/lldb/Utility/Connection.h; sourceTree = ""; }; 26BC7D5E10F1B77400F91463 /* Disassembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Disassembler.h; path = include/lldb/Core/Disassembler.h; sourceTree = ""; }; 26BC7D5F10F1B77400F91463 /* dwarf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf.h; path = include/lldb/Core/dwarf.h; sourceTree = ""; }; 26BC7D6110F1B77400F91463 /* Event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Event.h; path = include/lldb/Core/Event.h; sourceTree = ""; }; 26BC7D6310F1B77400F91463 /* FileSpecList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileSpecList.h; path = include/lldb/Core/FileSpecList.h; sourceTree = ""; }; 26BC7D6510F1B77400F91463 /* IOStreamMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IOStreamMacros.h; path = include/lldb/Core/IOStreamMacros.h; sourceTree = ""; }; 26BC7D6710F1B77400F91463 /* Listener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Listener.h; path = include/lldb/Core/Listener.h; sourceTree = ""; }; 26BC7D6810F1B77400F91463 /* Log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Log.h; path = include/lldb/Utility/Log.h; sourceTree = ""; }; 26BC7D6910F1B77400F91463 /* Mangled.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Mangled.h; path = include/lldb/Core/Mangled.h; sourceTree = ""; }; 26BC7D6A10F1B77400F91463 /* Module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Module.h; path = include/lldb/Core/Module.h; sourceTree = ""; }; 26BC7D6B10F1B77400F91463 /* ModuleChild.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ModuleChild.h; path = include/lldb/Core/ModuleChild.h; sourceTree = ""; }; 26BC7D6C10F1B77400F91463 /* ModuleList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ModuleList.h; path = include/lldb/Core/ModuleList.h; sourceTree = ""; }; 26BC7D6D10F1B77400F91463 /* Options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Options.h; path = include/lldb/Interpreter/Options.h; sourceTree = ""; }; 26BC7D7010F1B77400F91463 /* PluginInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PluginInterface.h; path = include/lldb/Core/PluginInterface.h; sourceTree = ""; }; 26BC7D7110F1B77400F91463 /* PluginManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PluginManager.h; path = include/lldb/Core/PluginManager.h; sourceTree = ""; }; 26BC7D7410F1B77400F91463 /* Scalar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Scalar.h; path = include/lldb/Core/Scalar.h; sourceTree = ""; }; 26BC7D7510F1B77400F91463 /* Section.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Section.h; path = include/lldb/Core/Section.h; sourceTree = ""; }; 26BC7D7610F1B77400F91463 /* SourceManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SourceManager.h; path = include/lldb/Core/SourceManager.h; sourceTree = ""; }; 26BC7D7710F1B77400F91463 /* State.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = State.h; path = include/lldb/Core/State.h; sourceTree = ""; }; 26BC7D7810F1B77400F91463 /* STLUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = STLUtils.h; path = include/lldb/Core/STLUtils.h; sourceTree = ""; }; 26BC7D7A10F1B77400F91463 /* StreamFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StreamFile.h; path = include/lldb/Core/StreamFile.h; sourceTree = ""; }; 26BC7D7E10F1B77400F91463 /* Timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Timer.h; path = include/lldb/Utility/Timer.h; sourceTree = ""; }; 26BC7D8110F1B77400F91463 /* Value.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Value.h; path = include/lldb/Core/Value.h; sourceTree = ""; }; 26BC7D8210F1B77400F91463 /* ValueObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObject.h; path = include/lldb/Core/ValueObject.h; sourceTree = ""; }; 26BC7D8310F1B77400F91463 /* ValueObjectChild.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectChild.h; path = include/lldb/Core/ValueObjectChild.h; sourceTree = ""; }; 26BC7D8410F1B77400F91463 /* ValueObjectList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectList.h; path = include/lldb/Core/ValueObjectList.h; sourceTree = ""; }; 26BC7D8510F1B77400F91463 /* ValueObjectVariable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectVariable.h; path = include/lldb/Core/ValueObjectVariable.h; sourceTree = ""; }; 26BC7DC010F1B79500F91463 /* ClangExpressionHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangExpressionHelper.h; path = ExpressionParser/Clang/ClangExpressionHelper.h; sourceTree = ""; }; 26BC7DC310F1B79500F91463 /* DWARFExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DWARFExpression.h; path = include/lldb/Expression/DWARFExpression.h; sourceTree = ""; }; 26BC7DD310F1B7D500F91463 /* Endian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Endian.h; path = include/lldb/Utility/Endian.h; sourceTree = ""; }; 26BC7DD410F1B7D500F91463 /* Host.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Host.h; path = include/lldb/Host/Host.h; sourceTree = ""; }; 26BC7DD610F1B7D500F91463 /* Predicate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Predicate.h; path = include/lldb/Host/Predicate.h; sourceTree = ""; }; 26BC7DE210F1B7F900F91463 /* CommandInterpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandInterpreter.h; path = include/lldb/Interpreter/CommandInterpreter.h; sourceTree = ""; }; 26BC7DE310F1B7F900F91463 /* CommandObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObject.h; path = include/lldb/Interpreter/CommandObject.h; sourceTree = ""; }; 26BC7DE410F1B7F900F91463 /* CommandReturnObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandReturnObject.h; path = include/lldb/Interpreter/CommandReturnObject.h; sourceTree = ""; }; 26BC7DE510F1B7F900F91463 /* ScriptInterpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScriptInterpreter.h; path = include/lldb/Interpreter/ScriptInterpreter.h; sourceTree = ""; }; 26BC7DF110F1B81A00F91463 /* DynamicLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DynamicLoader.h; path = include/lldb/Target/DynamicLoader.h; sourceTree = ""; }; 26BC7DF210F1B81A00F91463 /* ExecutionContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExecutionContext.h; path = include/lldb/Target/ExecutionContext.h; sourceTree = ""; }; 26BC7DF310F1B81A00F91463 /* Process.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Process.h; path = include/lldb/Target/Process.h; sourceTree = ""; }; 26BC7DF410F1B81A00F91463 /* RegisterContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContext.h; path = include/lldb/Target/RegisterContext.h; sourceTree = ""; }; 26BC7DF510F1B81A00F91463 /* StackFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StackFrame.h; path = include/lldb/Target/StackFrame.h; sourceTree = ""; }; 26BC7DF610F1B81A00F91463 /* StackFrameList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StackFrameList.h; path = include/lldb/Target/StackFrameList.h; sourceTree = ""; }; 26BC7DF710F1B81A00F91463 /* StackID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StackID.h; path = include/lldb/Target/StackID.h; sourceTree = ""; }; 26BC7DF810F1B81A00F91463 /* Target.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Target.h; path = include/lldb/Target/Target.h; sourceTree = ""; }; 26BC7DF910F1B81A00F91463 /* TargetList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TargetList.h; path = include/lldb/Target/TargetList.h; sourceTree = ""; }; 26BC7DFA10F1B81A00F91463 /* Thread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Thread.h; path = include/lldb/Target/Thread.h; sourceTree = ""; }; 26BC7DFB10F1B81A00F91463 /* ThreadList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadList.h; path = include/lldb/Target/ThreadList.h; sourceTree = ""; }; 26BC7DFC10F1B81A00F91463 /* ThreadPlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlan.h; path = include/lldb/Target/ThreadPlan.h; sourceTree = ""; }; 26BC7E0910F1B83100F91463 /* StoppointCallbackContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StoppointCallbackContext.cpp; path = source/Breakpoint/StoppointCallbackContext.cpp; sourceTree = ""; }; 26BC7E0A10F1B83100F91463 /* Breakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Breakpoint.cpp; path = source/Breakpoint/Breakpoint.cpp; sourceTree = ""; }; 26BC7E0B10F1B83100F91463 /* BreakpointID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointID.cpp; path = source/Breakpoint/BreakpointID.cpp; sourceTree = ""; }; 26BC7E0C10F1B83100F91463 /* BreakpointIDList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointIDList.cpp; path = source/Breakpoint/BreakpointIDList.cpp; sourceTree = ""; }; 26BC7E0D10F1B83100F91463 /* BreakpointList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointList.cpp; path = source/Breakpoint/BreakpointList.cpp; sourceTree = ""; }; 26BC7E0E10F1B83100F91463 /* BreakpointLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointLocation.cpp; path = source/Breakpoint/BreakpointLocation.cpp; sourceTree = ""; }; 26BC7E0F10F1B83100F91463 /* BreakpointLocationCollection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointLocationCollection.cpp; path = source/Breakpoint/BreakpointLocationCollection.cpp; sourceTree = ""; }; 26BC7E1010F1B83100F91463 /* BreakpointLocationList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointLocationList.cpp; path = source/Breakpoint/BreakpointLocationList.cpp; sourceTree = ""; }; 26BC7E1110F1B83100F91463 /* BreakpointOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointOptions.cpp; path = source/Breakpoint/BreakpointOptions.cpp; sourceTree = ""; }; 26BC7E1210F1B83100F91463 /* BreakpointResolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointResolver.cpp; path = source/Breakpoint/BreakpointResolver.cpp; sourceTree = ""; }; 26BC7E1310F1B83100F91463 /* BreakpointSite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointSite.cpp; path = source/Breakpoint/BreakpointSite.cpp; sourceTree = ""; }; 26BC7E1410F1B83100F91463 /* BreakpointSiteList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointSiteList.cpp; path = source/Breakpoint/BreakpointSiteList.cpp; sourceTree = ""; }; 26BC7E1510F1B83100F91463 /* SearchFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SearchFilter.cpp; path = source/Core/SearchFilter.cpp; sourceTree = ""; }; 26BC7E1610F1B83100F91463 /* Stoppoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Stoppoint.cpp; path = source/Breakpoint/Stoppoint.cpp; sourceTree = ""; }; 26BC7E1710F1B83100F91463 /* StoppointLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StoppointLocation.cpp; path = source/Breakpoint/StoppointLocation.cpp; sourceTree = ""; }; 26BC7E1810F1B83100F91463 /* Watchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Watchpoint.cpp; path = source/Breakpoint/Watchpoint.cpp; sourceTree = ""; }; 26BC7E2D10F1B84700F91463 /* CommandObjectBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectBreakpoint.cpp; path = source/Commands/CommandObjectBreakpoint.cpp; sourceTree = ""; }; 26BC7E3010F1B84700F91463 /* CommandObjectDisassemble.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectDisassemble.cpp; path = source/Commands/CommandObjectDisassemble.cpp; sourceTree = ""; }; 26BC7E3110F1B84700F91463 /* CommandObjectExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectExpression.cpp; path = source/Commands/CommandObjectExpression.cpp; sourceTree = ""; }; 26BC7E3310F1B84700F91463 /* CommandObjectHelp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectHelp.cpp; path = source/Commands/CommandObjectHelp.cpp; sourceTree = ""; }; 26BC7E3610F1B84700F91463 /* CommandObjectMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectMemory.cpp; path = source/Commands/CommandObjectMemory.cpp; sourceTree = ""; }; 26BC7E3810F1B84700F91463 /* CommandObjectProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectProcess.cpp; path = source/Commands/CommandObjectProcess.cpp; sourceTree = ""; }; 26BC7E3910F1B84700F91463 /* CommandObjectQuit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectQuit.cpp; path = source/Commands/CommandObjectQuit.cpp; sourceTree = ""; }; 26BC7E3B10F1B84700F91463 /* CommandObjectRegister.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectRegister.cpp; path = source/Commands/CommandObjectRegister.cpp; sourceTree = ""; }; 26BC7E3D10F1B84700F91463 /* CommandObjectScript.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectScript.cpp; path = source/Interpreter/CommandObjectScript.cpp; sourceTree = ""; }; 26BC7E4010F1B84700F91463 /* CommandObjectSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectSettings.cpp; path = source/Commands/CommandObjectSettings.cpp; sourceTree = ""; }; 26BC7E4210F1B84700F91463 /* CommandObjectSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectSource.cpp; path = source/Commands/CommandObjectSource.cpp; sourceTree = ""; }; 26BC7E4510F1B84700F91463 /* CommandObjectSyntax.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectSyntax.cpp; path = source/Commands/CommandObjectSyntax.cpp; sourceTree = ""; }; 26BC7E4610F1B84700F91463 /* CommandObjectThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectThread.cpp; path = source/Commands/CommandObjectThread.cpp; sourceTree = ""; }; 26BC7E6910F1B85900F91463 /* Address.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Address.cpp; path = source/Core/Address.cpp; sourceTree = ""; }; 26BC7E6A10F1B85900F91463 /* AddressRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AddressRange.cpp; path = source/Core/AddressRange.cpp; sourceTree = ""; }; 26BC7E6B10F1B85900F91463 /* ArchSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ArchSpec.cpp; path = source/Core/ArchSpec.cpp; sourceTree = ""; }; 26BC7E6C10F1B85900F91463 /* Args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Args.cpp; path = source/Interpreter/Args.cpp; sourceTree = ""; }; 26BC7E6D10F1B85900F91463 /* Broadcaster.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Broadcaster.cpp; path = source/Core/Broadcaster.cpp; sourceTree = ""; }; 26BC7E6E10F1B85900F91463 /* Communication.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Communication.cpp; path = source/Core/Communication.cpp; sourceTree = ""; }; 26BC7E6F10F1B85900F91463 /* Connection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Connection.cpp; path = source/Utility/Connection.cpp; sourceTree = ""; }; 26BC7E7410F1B85900F91463 /* lldb.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lldb.cpp; path = source/lldb.cpp; sourceTree = ""; }; 26BC7E7610F1B85900F91463 /* Disassembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Disassembler.cpp; path = source/Core/Disassembler.cpp; sourceTree = ""; }; 26BC7E7710F1B85900F91463 /* DynamicLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DynamicLoader.cpp; path = source/Core/DynamicLoader.cpp; sourceTree = ""; }; 26BC7E7910F1B85900F91463 /* Event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Event.cpp; path = source/Core/Event.cpp; sourceTree = ""; }; 26BC7E7B10F1B85900F91463 /* FileSpecList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FileSpecList.cpp; path = source/Core/FileSpecList.cpp; sourceTree = ""; }; 26BC7E7E10F1B85900F91463 /* Listener.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Listener.cpp; path = source/Core/Listener.cpp; sourceTree = ""; }; 26BC7E7F10F1B85900F91463 /* Log.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Log.cpp; path = source/Utility/Log.cpp; sourceTree = ""; }; 26BC7E8010F1B85900F91463 /* Mangled.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Mangled.cpp; path = source/Core/Mangled.cpp; sourceTree = ""; }; 26BC7E8110F1B85900F91463 /* Module.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Module.cpp; path = source/Core/Module.cpp; sourceTree = ""; }; 26BC7E8210F1B85900F91463 /* ModuleChild.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ModuleChild.cpp; path = source/Core/ModuleChild.cpp; sourceTree = ""; }; 26BC7E8310F1B85900F91463 /* ModuleList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ModuleList.cpp; path = source/Core/ModuleList.cpp; sourceTree = ""; }; 26BC7E8610F1B85900F91463 /* Options.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Options.cpp; path = source/Interpreter/Options.cpp; sourceTree = ""; }; 26BC7E8A10F1B85900F91463 /* PluginManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginManager.cpp; path = source/Core/PluginManager.cpp; sourceTree = ""; }; 26BC7E8D10F1B85900F91463 /* Scalar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Scalar.cpp; path = source/Core/Scalar.cpp; sourceTree = ""; }; 26BC7E8E10F1B85900F91463 /* Section.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Section.cpp; path = source/Core/Section.cpp; sourceTree = ""; }; 26BC7E8F10F1B85900F91463 /* SourceManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SourceManager.cpp; path = source/Core/SourceManager.cpp; sourceTree = ""; }; 26BC7E9010F1B85900F91463 /* State.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = State.cpp; path = source/Core/State.cpp; sourceTree = ""; }; 26BC7E9210F1B85900F91463 /* StreamFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StreamFile.cpp; path = source/Core/StreamFile.cpp; sourceTree = ""; }; 26BC7E9610F1B85900F91463 /* Timer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Timer.cpp; path = source/Utility/Timer.cpp; sourceTree = ""; }; 26BC7E9910F1B85900F91463 /* Value.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Value.cpp; path = source/Core/Value.cpp; sourceTree = ""; }; 26BC7E9A10F1B85900F91463 /* ValueObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObject.cpp; path = source/Core/ValueObject.cpp; sourceTree = ""; }; 26BC7E9B10F1B85900F91463 /* ValueObjectChild.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectChild.cpp; path = source/Core/ValueObjectChild.cpp; sourceTree = ""; }; 26BC7E9C10F1B85900F91463 /* ValueObjectList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectList.cpp; path = source/Core/ValueObjectList.cpp; sourceTree = ""; }; 26BC7E9D10F1B85900F91463 /* ValueObjectVariable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectVariable.cpp; path = source/Core/ValueObjectVariable.cpp; sourceTree = ""; }; 26BC7ED510F1B86700F91463 /* ClangUserExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangUserExpression.cpp; path = ExpressionParser/Clang/ClangUserExpression.cpp; sourceTree = ""; }; 26BC7ED810F1B86700F91463 /* DWARFExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DWARFExpression.cpp; path = source/Expression/DWARFExpression.cpp; sourceTree = ""; }; 26BC7EE810F1B88F00F91463 /* Host.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Host.mm; path = source/Host/macosx/Host.mm; sourceTree = ""; }; 26BC7EED10F1B8AD00F91463 /* CFCBundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CFCBundle.cpp; path = source/Host/macosx/cfcpp/CFCBundle.cpp; sourceTree = ""; }; 26BC7EEE10F1B8AD00F91463 /* CFCBundle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CFCBundle.h; path = source/Host/macosx/cfcpp/CFCBundle.h; sourceTree = ""; }; 26BC7EEF10F1B8AD00F91463 /* CFCData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CFCData.cpp; path = source/Host/macosx/cfcpp/CFCData.cpp; sourceTree = ""; }; 26BC7EF010F1B8AD00F91463 /* CFCData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CFCData.h; path = source/Host/macosx/cfcpp/CFCData.h; sourceTree = ""; }; 26BC7EF110F1B8AD00F91463 /* CFCMutableArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CFCMutableArray.cpp; path = source/Host/macosx/cfcpp/CFCMutableArray.cpp; sourceTree = ""; }; 26BC7EF210F1B8AD00F91463 /* CFCMutableArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CFCMutableArray.h; path = source/Host/macosx/cfcpp/CFCMutableArray.h; sourceTree = ""; }; 26BC7EF310F1B8AD00F91463 /* CFCMutableDictionary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CFCMutableDictionary.cpp; path = source/Host/macosx/cfcpp/CFCMutableDictionary.cpp; sourceTree = ""; }; 26BC7EF410F1B8AD00F91463 /* CFCMutableDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CFCMutableDictionary.h; path = source/Host/macosx/cfcpp/CFCMutableDictionary.h; sourceTree = ""; }; 26BC7EF510F1B8AD00F91463 /* CFCMutableSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CFCMutableSet.cpp; path = source/Host/macosx/cfcpp/CFCMutableSet.cpp; sourceTree = ""; }; 26BC7EF610F1B8AD00F91463 /* CFCMutableSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CFCMutableSet.h; path = source/Host/macosx/cfcpp/CFCMutableSet.h; sourceTree = ""; }; 26BC7EF710F1B8AD00F91463 /* CFCReleaser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CFCReleaser.h; path = source/Host/macosx/cfcpp/CFCReleaser.h; sourceTree = ""; }; 26BC7EF810F1B8AD00F91463 /* CFCString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CFCString.cpp; path = source/Host/macosx/cfcpp/CFCString.cpp; sourceTree = ""; }; 26BC7EF910F1B8AD00F91463 /* CFCString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CFCString.h; path = source/Host/macosx/cfcpp/CFCString.h; sourceTree = ""; }; 26BC7F0810F1B8DD00F91463 /* CommandInterpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandInterpreter.cpp; path = source/Interpreter/CommandInterpreter.cpp; sourceTree = ""; }; 26BC7F0910F1B8DD00F91463 /* CommandObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObject.cpp; path = source/Interpreter/CommandObject.cpp; sourceTree = ""; }; 26BC7F0A10F1B8DD00F91463 /* CommandReturnObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandReturnObject.cpp; path = source/Interpreter/CommandReturnObject.cpp; sourceTree = ""; }; 26BC7F1310F1B8EC00F91463 /* Block.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Block.cpp; path = source/Symbol/Block.cpp; sourceTree = ""; }; 26BC7F1410F1B8EC00F91463 /* ClangASTContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangASTContext.cpp; path = source/Symbol/ClangASTContext.cpp; sourceTree = ""; }; 26BC7F1510F1B8EC00F91463 /* CompileUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompileUnit.cpp; path = source/Symbol/CompileUnit.cpp; sourceTree = ""; }; 26BC7F1610F1B8EC00F91463 /* Declaration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Declaration.cpp; path = source/Symbol/Declaration.cpp; sourceTree = ""; }; 26BC7F1710F1B8EC00F91463 /* DWARFCallFrameInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DWARFCallFrameInfo.cpp; path = source/Symbol/DWARFCallFrameInfo.cpp; sourceTree = ""; }; 26BC7F1810F1B8EC00F91463 /* Function.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Function.cpp; path = source/Symbol/Function.cpp; sourceTree = ""; }; 26BC7F1910F1B8EC00F91463 /* LineEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LineEntry.cpp; path = source/Symbol/LineEntry.cpp; sourceTree = ""; }; 26BC7F1A10F1B8EC00F91463 /* LineTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LineTable.cpp; path = source/Symbol/LineTable.cpp; sourceTree = ""; }; 26BC7F1B10F1B8EC00F91463 /* Symbol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Symbol.cpp; path = source/Symbol/Symbol.cpp; sourceTree = ""; }; 26BC7F1C10F1B8EC00F91463 /* SymbolContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SymbolContext.cpp; path = source/Symbol/SymbolContext.cpp; sourceTree = ""; }; 26BC7F1D10F1B8EC00F91463 /* SymbolFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SymbolFile.cpp; path = source/Symbol/SymbolFile.cpp; sourceTree = ""; }; 26BC7F1F10F1B8EC00F91463 /* Symtab.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Symtab.cpp; path = source/Symbol/Symtab.cpp; sourceTree = ""; }; 26BC7F2010F1B8EC00F91463 /* Type.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Type.cpp; path = source/Symbol/Type.cpp; sourceTree = ""; }; 26BC7F2110F1B8EC00F91463 /* TypeList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeList.cpp; path = source/Symbol/TypeList.cpp; sourceTree = ""; }; 26BC7F2210F1B8EC00F91463 /* Variable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Variable.cpp; path = source/Symbol/Variable.cpp; sourceTree = ""; }; 26BC7F2310F1B8EC00F91463 /* VariableList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VariableList.cpp; path = source/Symbol/VariableList.cpp; sourceTree = ""; }; 26BC7F3510F1B90C00F91463 /* ExecutionContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ExecutionContext.cpp; path = source/Target/ExecutionContext.cpp; sourceTree = ""; }; 26BC7F3610F1B90C00F91463 /* Process.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Process.cpp; path = source/Target/Process.cpp; sourceTree = ""; }; 26BC7F3710F1B90C00F91463 /* RegisterContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContext.cpp; path = source/Target/RegisterContext.cpp; sourceTree = ""; }; 26BC7F3810F1B90C00F91463 /* StackFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StackFrame.cpp; path = source/Target/StackFrame.cpp; sourceTree = ""; }; 26BC7F3910F1B90C00F91463 /* StackFrameList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StackFrameList.cpp; path = source/Target/StackFrameList.cpp; sourceTree = ""; }; 26BC7F3A10F1B90C00F91463 /* StackID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StackID.cpp; path = source/Target/StackID.cpp; sourceTree = ""; }; 26BC7F3B10F1B90C00F91463 /* Target.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Target.cpp; path = source/Target/Target.cpp; sourceTree = ""; }; 26BC7F3C10F1B90C00F91463 /* TargetList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TargetList.cpp; path = source/Target/TargetList.cpp; sourceTree = ""; }; 26BC7F3D10F1B90C00F91463 /* Thread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Thread.cpp; path = source/Target/Thread.cpp; sourceTree = ""; }; 26BC7F3E10F1B90C00F91463 /* ThreadList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadList.cpp; path = source/Target/ThreadList.cpp; sourceTree = ""; }; 26BC7F3F10F1B90C00F91463 /* ThreadPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlan.cpp; path = source/Target/ThreadPlan.cpp; sourceTree = ""; }; 26BC7F4C10F1BC1A00F91463 /* ObjectFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ObjectFile.cpp; path = source/Symbol/ObjectFile.cpp; sourceTree = ""; }; 26BCFC4F1368ADF7006DC050 /* OptionGroupFormat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupFormat.h; path = include/lldb/Interpreter/OptionGroupFormat.h; sourceTree = ""; }; 26BCFC511368AE38006DC050 /* OptionGroupFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupFormat.cpp; path = source/Interpreter/OptionGroupFormat.cpp; sourceTree = ""; }; 26BCFC531368B3E4006DC050 /* OptionGroupOutputFile.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupOutputFile.cpp; path = source/Interpreter/OptionGroupOutputFile.cpp; sourceTree = ""; }; 26BCFC541368B4B8006DC050 /* OptionGroupOutputFile.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupOutputFile.h; path = include/lldb/Interpreter/OptionGroupOutputFile.h; sourceTree = ""; }; 26BD407D135D2AC400237D80 /* FileLineResolver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FileLineResolver.h; path = include/lldb/Core/FileLineResolver.h; sourceTree = ""; }; 26BD407E135D2ADF00237D80 /* FileLineResolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FileLineResolver.cpp; path = source/Core/FileLineResolver.cpp; sourceTree = ""; }; 26BF51EA1B3C754400016294 /* ABISysV_hexagon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ABISysV_hexagon.cpp; sourceTree = ""; }; 26BF51EB1B3C754400016294 /* ABISysV_hexagon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ABISysV_hexagon.h; sourceTree = ""; }; 26BF51EF1B3C754400016294 /* ABISysV_i386.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ABISysV_i386.cpp; sourceTree = ""; }; 26BF51F01B3C754400016294 /* ABISysV_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ABISysV_i386.h; sourceTree = ""; }; 26C5577B132575AD008FD8FE /* PlatformMacOSX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformMacOSX.cpp; sourceTree = ""; }; 26C5577C132575AD008FD8FE /* PlatformMacOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformMacOSX.h; sourceTree = ""; }; 26C6886D137880B900407EDF /* RegisterValue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RegisterValue.h; path = include/lldb/Core/RegisterValue.h; sourceTree = ""; }; 26C6886E137880C400407EDF /* RegisterValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterValue.cpp; path = source/Core/RegisterValue.cpp; sourceTree = ""; }; 26C72C93124322890068DC16 /* SBStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBStream.h; path = include/lldb/API/SBStream.h; sourceTree = ""; }; 26C72C951243229A0068DC16 /* SBStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBStream.cpp; path = source/API/SBStream.cpp; sourceTree = ""; }; 26C7C4811BFFEA7E009BD01F /* WindowsMiniDump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WindowsMiniDump.cpp; sourceTree = ""; }; 26C7C4821BFFEA7E009BD01F /* WindowsMiniDump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowsMiniDump.h; sourceTree = ""; }; 26CA979F172B1FD5005DC71B /* RegisterContextThreadMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextThreadMemory.cpp; path = Utility/RegisterContextThreadMemory.cpp; sourceTree = ""; }; 26CA97A0172B1FD5005DC71B /* RegisterContextThreadMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextThreadMemory.h; path = Utility/RegisterContextThreadMemory.h; sourceTree = ""; }; 26CEB5F018762056008F575A /* CommandObjectGUI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectGUI.cpp; path = source/Commands/CommandObjectGUI.cpp; sourceTree = ""; }; 26CEB5F118762056008F575A /* CommandObjectGUI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectGUI.h; path = source/Commands/CommandObjectGUI.h; sourceTree = ""; }; 26CF992414428766001E4138 /* AnsiTerminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AnsiTerminal.h; path = include/lldb/Utility/AnsiTerminal.h; sourceTree = ""; }; 26CFDCA01861638D000E63E5 /* Editline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Editline.h; path = include/lldb/Host/Editline.h; sourceTree = ""; }; 26CFDCA2186163A4000E63E5 /* Editline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Editline.cpp; sourceTree = ""; }; 26D0DD5010FE554D00271C65 /* BreakpointResolverAddress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointResolverAddress.h; path = include/lldb/Breakpoint/BreakpointResolverAddress.h; sourceTree = ""; }; 26D0DD5110FE554D00271C65 /* BreakpointResolverFileLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointResolverFileLine.h; path = include/lldb/Breakpoint/BreakpointResolverFileLine.h; sourceTree = ""; }; 26D0DD5210FE554D00271C65 /* BreakpointResolverName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointResolverName.h; path = include/lldb/Breakpoint/BreakpointResolverName.h; sourceTree = ""; }; 26D0DD5310FE555900271C65 /* BreakpointResolverAddress.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointResolverAddress.cpp; path = source/Breakpoint/BreakpointResolverAddress.cpp; sourceTree = ""; }; 26D0DD5410FE555900271C65 /* BreakpointResolverFileLine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointResolverFileLine.cpp; path = source/Breakpoint/BreakpointResolverFileLine.cpp; sourceTree = ""; }; 26D0DD5510FE555900271C65 /* BreakpointResolverName.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointResolverName.cpp; path = source/Breakpoint/BreakpointResolverName.cpp; sourceTree = ""; }; 26D27C9D11ED3A4E0024D721 /* ELFHeader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ELFHeader.cpp; sourceTree = ""; }; 26D27C9E11ED3A4E0024D721 /* ELFHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ELFHeader.h; sourceTree = ""; }; 26D52C1D1A980FE300E5D2FB /* MICmdCmdSymbol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCmdSymbol.cpp; path = "tools/lldb-mi/MICmdCmdSymbol.cpp"; sourceTree = SOURCE_ROOT; }; 26D52C1E1A980FE300E5D2FB /* MICmdCmdSymbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCmdSymbol.h; path = "tools/lldb-mi/MICmdCmdSymbol.h"; sourceTree = SOURCE_ROOT; }; 26D55234159A7DB100708D8D /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = /usr/lib/libxml2.dylib; sourceTree = ""; }; 26D5E15E135BAEA2006EA0A7 /* OptionGroupArchitecture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupArchitecture.cpp; path = source/Interpreter/OptionGroupArchitecture.cpp; sourceTree = ""; }; 26D5E160135BAEB0006EA0A7 /* OptionGroupArchitecture.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupArchitecture.h; path = include/lldb/Interpreter/OptionGroupArchitecture.h; sourceTree = ""; }; 26D5E161135BB040006EA0A7 /* OptionGroupPlatform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupPlatform.h; path = include/lldb/Interpreter/OptionGroupPlatform.h; sourceTree = ""; }; 26D5E162135BB054006EA0A7 /* OptionGroupPlatform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupPlatform.cpp; path = source/Interpreter/OptionGroupPlatform.cpp; sourceTree = ""; }; 26D6F3F4183E7F9300194858 /* lldb-gdbserver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "lldb-gdbserver.cpp"; path = "tools/lldb-server/lldb-gdbserver.cpp"; sourceTree = ""; }; 26D7E45B13D5E2F9007FD12B /* SocketAddress.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SocketAddress.h; path = include/lldb/Host/SocketAddress.h; sourceTree = ""; }; 26D7E45C13D5E30A007FD12B /* SocketAddress.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SocketAddress.cpp; path = source/Host/common/SocketAddress.cpp; sourceTree = ""; }; 26D9FDC612F784E60003F2EE /* EmulateInstruction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EmulateInstruction.h; path = include/lldb/Core/EmulateInstruction.h; sourceTree = ""; }; 26D9FDC812F784FD0003F2EE /* EmulateInstruction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = EmulateInstruction.cpp; path = source/Core/EmulateInstruction.cpp; sourceTree = ""; }; 26DAED5F15D327A200E15819 /* OptionValuePathMappings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValuePathMappings.h; path = include/lldb/Interpreter/OptionValuePathMappings.h; sourceTree = ""; }; 26DAED6215D327C200E15819 /* OptionValuePathMappings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValuePathMappings.cpp; path = source/Interpreter/OptionValuePathMappings.cpp; sourceTree = ""; }; 26DAFD9711529BC7005A394E /* ExecutionContextScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExecutionContextScope.h; path = include/lldb/Target/ExecutionContextScope.h; sourceTree = ""; }; 26DB3E071379E7AD0080DC73 /* ABIMacOSX_arm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ABIMacOSX_arm.cpp; sourceTree = ""; }; 26DB3E081379E7AD0080DC73 /* ABIMacOSX_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ABIMacOSX_arm.h; sourceTree = ""; }; 26DB3E0B1379E7AD0080DC73 /* ABIMacOSX_arm64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ABIMacOSX_arm64.cpp; sourceTree = ""; }; 26DB3E0C1379E7AD0080DC73 /* ABIMacOSX_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ABIMacOSX_arm64.h; sourceTree = ""; }; 26DB3E0F1379E7AD0080DC73 /* ABIMacOSX_i386.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ABIMacOSX_i386.cpp; sourceTree = ""; }; 26DB3E101379E7AD0080DC73 /* ABIMacOSX_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ABIMacOSX_i386.h; sourceTree = ""; }; 26DB3E131379E7AD0080DC73 /* ABISysV_x86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ABISysV_x86_64.cpp; sourceTree = ""; }; 26DB3E141379E7AD0080DC73 /* ABISysV_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ABISysV_x86_64.h; sourceTree = ""; }; 26DC6A101337FE6900FF7998 /* lldb-server */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "lldb-server"; sourceTree = BUILT_PRODUCTS_DIR; }; 26DC6A1C1337FECA00FF7998 /* lldb-platform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "lldb-platform.cpp"; path = "tools/lldb-server/lldb-platform.cpp"; sourceTree = ""; }; 26DE1E6A11616C2E00A093E2 /* lldb-forward.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = "lldb-forward.h"; path = "include/lldb/lldb-forward.h"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 26DE204011618AB900A093E2 /* SBSymbolContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBSymbolContext.h; path = include/lldb/API/SBSymbolContext.h; sourceTree = ""; }; 26DE204211618ACA00A093E2 /* SBAddress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBAddress.h; path = include/lldb/API/SBAddress.h; sourceTree = ""; }; 26DE204411618ADA00A093E2 /* SBAddress.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBAddress.cpp; path = source/API/SBAddress.cpp; sourceTree = ""; }; 26DE204611618AED00A093E2 /* SBSymbolContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBSymbolContext.cpp; path = source/API/SBSymbolContext.cpp; sourceTree = ""; }; 26DE204C11618E7A00A093E2 /* SBModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBModule.cpp; path = source/API/SBModule.cpp; sourceTree = ""; }; 26DE204E11618E9800A093E2 /* SBModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBModule.h; path = include/lldb/API/SBModule.h; sourceTree = ""; }; 26DE205211618FAC00A093E2 /* SBFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBFunction.h; path = include/lldb/API/SBFunction.h; sourceTree = ""; }; 26DE205411618FB800A093E2 /* SBCompileUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBCompileUnit.h; path = include/lldb/API/SBCompileUnit.h; sourceTree = ""; }; 26DE205611618FC500A093E2 /* SBBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBBlock.h; path = include/lldb/API/SBBlock.h; sourceTree = ""; }; 26DE205811618FE700A093E2 /* SBLineEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBLineEntry.h; path = include/lldb/API/SBLineEntry.h; sourceTree = ""; }; 26DE205A11618FF600A093E2 /* SBSymbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBSymbol.h; path = include/lldb/API/SBSymbol.h; sourceTree = ""; }; 26DE205C1161901400A093E2 /* SBFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBFunction.cpp; path = source/API/SBFunction.cpp; sourceTree = ""; }; 26DE205E1161901B00A093E2 /* SBCompileUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBCompileUnit.cpp; path = source/API/SBCompileUnit.cpp; sourceTree = ""; }; 26DE20601161902600A093E2 /* SBBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBBlock.cpp; path = source/API/SBBlock.cpp; sourceTree = ""; }; 26DE20621161904200A093E2 /* SBLineEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBLineEntry.cpp; path = source/API/SBLineEntry.cpp; sourceTree = ""; }; 26DE20641161904E00A093E2 /* SBSymbol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBSymbol.cpp; path = source/API/SBSymbol.cpp; sourceTree = ""; }; 26DFBC51113B48D600DD817F /* CommandObjectMultiword.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectMultiword.h; path = include/lldb/Interpreter/CommandObjectMultiword.h; sourceTree = ""; }; 26DFBC52113B48D600DD817F /* CommandObjectRegexCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectRegexCommand.h; path = include/lldb/Interpreter/CommandObjectRegexCommand.h; sourceTree = ""; }; 26DFBC58113B48F300DD817F /* CommandObjectMultiword.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectMultiword.cpp; path = source/Commands/CommandObjectMultiword.cpp; sourceTree = ""; }; 26DFBC59113B48F300DD817F /* CommandObjectRegexCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectRegexCommand.cpp; path = source/Interpreter/CommandObjectRegexCommand.cpp; sourceTree = ""; }; 26E152231419CACA007967D0 /* ObjectFilePECOFF.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectFilePECOFF.cpp; sourceTree = ""; }; 26E152241419CACA007967D0 /* ObjectFilePECOFF.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ObjectFilePECOFF.h; sourceTree = ""; }; 26E3EEBD11A9870400FBADB6 /* Unwind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Unwind.h; path = include/lldb/Target/Unwind.h; sourceTree = ""; }; 26E3EEE311A9901300FBADB6 /* UnwindMacOSXFrameBackchain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindMacOSXFrameBackchain.cpp; path = Utility/UnwindMacOSXFrameBackchain.cpp; sourceTree = ""; }; 26E3EEE411A9901300FBADB6 /* UnwindMacOSXFrameBackchain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UnwindMacOSXFrameBackchain.h; path = Utility/UnwindMacOSXFrameBackchain.h; sourceTree = ""; }; 26E3EEF711A994E800FBADB6 /* RegisterContextMacOSXFrameBackchain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextMacOSXFrameBackchain.cpp; path = Utility/RegisterContextMacOSXFrameBackchain.cpp; sourceTree = ""; }; 26E3EEF811A994E800FBADB6 /* RegisterContextMacOSXFrameBackchain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextMacOSXFrameBackchain.h; path = Utility/RegisterContextMacOSXFrameBackchain.h; sourceTree = ""; }; 26E6902E129C6BD500DDECD9 /* ClangExternalASTSourceCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangExternalASTSourceCallbacks.h; path = include/lldb/Symbol/ClangExternalASTSourceCallbacks.h; sourceTree = ""; }; 26E69030129C6BEF00DDECD9 /* ClangExternalASTSourceCallbacks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangExternalASTSourceCallbacks.cpp; path = source/Symbol/ClangExternalASTSourceCallbacks.cpp; sourceTree = ""; }; 26ED3D6C13C563810017D45E /* OptionGroupVariable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupVariable.cpp; path = source/Interpreter/OptionGroupVariable.cpp; sourceTree = ""; }; 26ED3D6F13C5638A0017D45E /* OptionGroupVariable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupVariable.h; path = include/lldb/Interpreter/OptionGroupVariable.h; sourceTree = ""; }; 26EFB6181BFE8D3E00544801 /* PlatformNetBSD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformNetBSD.cpp; sourceTree = ""; }; 26EFB6191BFE8D3E00544801 /* PlatformNetBSD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformNetBSD.h; sourceTree = ""; }; 26EFC4CA18CFAF0D00865D87 /* ObjectFileJIT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectFileJIT.cpp; sourceTree = ""; }; 26EFC4CB18CFAF0D00865D87 /* ObjectFileJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectFileJIT.h; sourceTree = ""; }; 26F006541B4DD86700B872E5 /* DynamicLoaderWindowsDYLD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLoaderWindowsDYLD.cpp; sourceTree = ""; }; 26F006551B4DD86700B872E5 /* DynamicLoaderWindowsDYLD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderWindowsDYLD.h; sourceTree = ""; }; 26F2F8FD1B156678007857DE /* StructuredData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StructuredData.h; path = include/lldb/Utility/StructuredData.h; sourceTree = ""; }; 26F4A21A13FBA31A0064B613 /* ThreadMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadMemory.cpp; path = Utility/ThreadMemory.cpp; sourceTree = ""; }; 26F4A21B13FBA31A0064B613 /* ThreadMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadMemory.h; path = Utility/ThreadMemory.h; sourceTree = ""; }; 26F5C26A10F3D9A4009D5894 /* lldb */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = lldb; sourceTree = BUILT_PRODUCTS_DIR; }; 26F5C27210F3D9E4009D5894 /* lldb-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "lldb-Info.plist"; path = "tools/driver/lldb-Info.plist"; sourceTree = ""; }; 26F5C27310F3D9E4009D5894 /* Driver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Driver.cpp; path = tools/driver/Driver.cpp; sourceTree = ""; }; 26F5C27410F3D9E4009D5894 /* Driver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Driver.h; path = tools/driver/Driver.h; sourceTree = ""; }; 26F5C32410F3DF23009D5894 /* libpython.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpython.dylib; path = /usr/lib/libpython.dylib; sourceTree = ""; }; 26F5C32A10F3DFDD009D5894 /* libedit.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libedit.dylib; path = /usr/lib/libedit.dylib; sourceTree = ""; }; 26F5C32B10F3DFDD009D5894 /* libtermcap.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtermcap.dylib; path = /usr/lib/libtermcap.dylib; sourceTree = ""; }; 26F5C37410F3F61B009D5894 /* libobjc.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libobjc.dylib; path = /usr/lib/libobjc.dylib; sourceTree = ""; }; 26F5C39010F3FA26009D5894 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; 26F996A7119B79C300412154 /* ARM_DWARF_Registers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ARM_DWARF_Registers.h; path = source/Utility/ARM_DWARF_Registers.h; sourceTree = ""; }; 26FA4315130103F400E71120 /* FileSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileSpec.h; path = include/lldb/Utility/FileSpec.h; sourceTree = ""; }; 26FA43171301048600E71120 /* FileSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FileSpec.cpp; path = source/Utility/FileSpec.cpp; sourceTree = ""; }; 26FFC19314FC072100087D58 /* AuxVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AuxVector.cpp; sourceTree = ""; }; 26FFC19414FC072100087D58 /* AuxVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AuxVector.h; sourceTree = ""; }; 26FFC19514FC072100087D58 /* DYLDRendezvous.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DYLDRendezvous.cpp; sourceTree = ""; }; 26FFC19614FC072100087D58 /* DYLDRendezvous.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DYLDRendezvous.h; sourceTree = ""; }; 26FFC19714FC072100087D58 /* DynamicLoaderPOSIXDYLD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLoaderPOSIXDYLD.cpp; sourceTree = ""; }; 26FFC19814FC072100087D58 /* DynamicLoaderPOSIXDYLD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderPOSIXDYLD.h; sourceTree = ""; }; 3032B1B61CAAA3D1004BE1AB /* ClangUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangUtil.cpp; path = source/Symbol/ClangUtil.cpp; sourceTree = ""; }; 3032B1B91CAAA400004BE1AB /* ClangUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangUtil.h; path = include/lldb/Symbol/ClangUtil.h; sourceTree = ""; }; 33064C991A5C7A330033D415 /* UriParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UriParser.cpp; path = source/Utility/UriParser.cpp; sourceTree = ""; }; 3392EBB71AFF402200858B9F /* SBLanguageRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBLanguageRuntime.h; path = include/lldb/API/SBLanguageRuntime.h; sourceTree = ""; }; 33E5E8411A672A240024ED68 /* StringConvert.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringConvert.cpp; sourceTree = ""; }; 33E5E8451A6736D30024ED68 /* StringConvert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringConvert.h; path = include/lldb/Host/StringConvert.h; sourceTree = SOURCE_ROOT; }; 3F5E8AF31A40D4A500A73232 /* PipeBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PipeBase.h; path = include/lldb/Host/PipeBase.h; sourceTree = ""; }; 3F8160A51AB9F7DD001DA9DF /* Logging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Logging.cpp; path = source/Utility/Logging.cpp; sourceTree = ""; }; 3F8160A71AB9F809001DA9DF /* Logging.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = include/lldb/Utility/Logging.h; sourceTree = ""; }; 3F8169181ABA2419001DA9DF /* NameMatches.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NameMatches.cpp; path = source/Utility/NameMatches.cpp; sourceTree = ""; }; 3F81691C1ABA242B001DA9DF /* NameMatches.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NameMatches.h; path = include/lldb/Utility/NameMatches.h; sourceTree = ""; }; 3F81692A1ABB7A16001DA9DF /* SystemInitializerFull.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SystemInitializerFull.cpp; path = source/API/SystemInitializerFull.cpp; sourceTree = ""; }; 3F81692D1ABB7A40001DA9DF /* SystemInitializerFull.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SystemInitializerFull.h; path = include/lldb/API/SystemInitializerFull.h; sourceTree = ""; }; 3F81692E1ABB7A6D001DA9DF /* SystemInitializer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SystemInitializer.cpp; path = source/Initialization/SystemInitializer.cpp; sourceTree = ""; }; 3F81692F1ABB7A6D001DA9DF /* SystemInitializerCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SystemInitializerCommon.cpp; path = source/Initialization/SystemInitializerCommon.cpp; sourceTree = ""; }; 3F8169301ABB7A6D001DA9DF /* SystemLifetimeManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SystemLifetimeManager.cpp; path = source/Initialization/SystemLifetimeManager.cpp; sourceTree = ""; }; 3F8169341ABB7A80001DA9DF /* SystemInitializer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SystemInitializer.h; path = include/lldb/Initialization/SystemInitializer.h; sourceTree = ""; }; 3F8169351ABB7A80001DA9DF /* SystemInitializerCommon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SystemInitializerCommon.h; path = include/lldb/Initialization/SystemInitializerCommon.h; sourceTree = ""; }; 3F8169361ABB7A80001DA9DF /* SystemLifetimeManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SystemLifetimeManager.h; path = include/lldb/Initialization/SystemLifetimeManager.h; sourceTree = ""; }; 3FA093141BF65D3A0037DD08 /* PythonExceptionStateTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PythonExceptionStateTests.cpp; sourceTree = ""; }; 3FBA69DD1B6067020008F44A /* ScriptInterpreterNone.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ScriptInterpreterNone.cpp; path = ScriptInterpreter/None/ScriptInterpreterNone.cpp; sourceTree = ""; }; 3FBA69DE1B6067020008F44A /* ScriptInterpreterNone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScriptInterpreterNone.h; path = ScriptInterpreter/None/ScriptInterpreterNone.h; sourceTree = ""; }; 3FBA69E21B60672A0008F44A /* lldb-python.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lldb-python.h"; path = "ScriptInterpreter/Python/lldb-python.h"; sourceTree = ""; }; 3FBA69E31B60672A0008F44A /* PythonDataObjects.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PythonDataObjects.cpp; path = ScriptInterpreter/Python/PythonDataObjects.cpp; sourceTree = ""; }; 3FBA69E41B60672A0008F44A /* PythonDataObjects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PythonDataObjects.h; path = ScriptInterpreter/Python/PythonDataObjects.h; sourceTree = ""; }; 3FBA69E51B60672A0008F44A /* ScriptInterpreterPython.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ScriptInterpreterPython.cpp; path = ScriptInterpreter/Python/ScriptInterpreterPython.cpp; sourceTree = ""; }; 3FBA69E61B60672A0008F44A /* ScriptInterpreterPython.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScriptInterpreterPython.h; path = ScriptInterpreter/Python/ScriptInterpreterPython.h; sourceTree = ""; }; 3FDFD6C3199C396E009756A7 /* FileAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileAction.h; path = include/lldb/Target/FileAction.h; sourceTree = ""; }; 3FDFDDBC199C3A06009756A7 /* FileAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FileAction.cpp; path = source/Target/FileAction.cpp; sourceTree = ""; }; 3FDFDDBE199D345E009756A7 /* FileCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FileCache.cpp; path = source/Host/common/FileCache.cpp; sourceTree = ""; }; 3FDFDDC0199D34E2009756A7 /* FileCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FileCache.h; path = include/lldb/Host/FileCache.h; sourceTree = ""; }; 3FDFDDC1199D34E2009756A7 /* FileSystem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FileSystem.h; path = include/lldb/Host/FileSystem.h; sourceTree = ""; }; 3FDFDDC5199D37ED009756A7 /* FileSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FileSystem.cpp; sourceTree = ""; }; 3FDFE52B19A2917A009756A7 /* HostInfoMacOSX.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = HostInfoMacOSX.mm; path = source/Host/macosx/HostInfoMacOSX.mm; sourceTree = ""; }; 3FDFE52D19A291AF009756A7 /* HostInfoMacOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HostInfoMacOSX.h; path = include/lldb/Host/macosx/HostInfoMacOSX.h; sourceTree = ""; }; 3FDFE53019A292F0009756A7 /* HostInfoPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HostInfoPosix.cpp; sourceTree = ""; }; 3FDFE53219A29304009756A7 /* HostInfoPosix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HostInfoPosix.h; path = ../../../include/lldb/Host/posix/HostInfoPosix.h; sourceTree = ""; }; 3FDFE53419A29327009756A7 /* HostInfoBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HostInfoBase.cpp; sourceTree = ""; }; 3FDFE53619A2933E009756A7 /* HostInfoLinux.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = HostInfoLinux.cpp; sourceTree = ""; }; 3FDFE53719A2936B009756A7 /* HostInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HostInfo.h; path = include/lldb/Host/HostInfo.h; sourceTree = ""; }; 3FDFE53819A2936B009756A7 /* HostInfoBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HostInfoBase.h; path = include/lldb/Host/HostInfoBase.h; sourceTree = ""; }; 3FDFE53B19A293B3009756A7 /* HostInfoFreeBSD.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = HostInfoFreeBSD.cpp; path = source/Host/freebsd/HostInfoFreeBSD.cpp; sourceTree = ""; }; 3FDFE53C19A293CA009756A7 /* Config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Config.h; path = include/lldb/Host/freebsd/Config.h; sourceTree = ""; }; 3FDFE53D19A293CA009756A7 /* HostInfoFreeBSD.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HostInfoFreeBSD.h; path = include/lldb/Host/freebsd/HostInfoFreeBSD.h; sourceTree = ""; }; 3FDFE54019A29448009756A7 /* EditLineWin.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = EditLineWin.cpp; path = source/Host/windows/EditLineWin.cpp; sourceTree = ""; }; 3FDFE54119A29448009756A7 /* FileSystem.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FileSystem.cpp; path = source/Host/windows/FileSystem.cpp; sourceTree = ""; }; 3FDFE54219A29448009756A7 /* Host.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Host.cpp; path = source/Host/windows/Host.cpp; sourceTree = ""; }; 3FDFE54319A29448009756A7 /* HostInfoWindows.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = HostInfoWindows.cpp; path = source/Host/windows/HostInfoWindows.cpp; sourceTree = ""; }; 3FDFE54519A29448009756A7 /* ProcessRunLock.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ProcessRunLock.cpp; path = source/Host/windows/ProcessRunLock.cpp; sourceTree = ""; }; 3FDFE54619A29448009756A7 /* Windows.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Windows.cpp; path = source/Host/windows/Windows.cpp; sourceTree = ""; }; 3FDFE54719A2946B009756A7 /* AutoHandle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AutoHandle.h; path = include/lldb/Host/windows/AutoHandle.h; sourceTree = ""; }; 3FDFE54819A2946B009756A7 /* editlinewin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = editlinewin.h; path = include/lldb/Host/windows/editlinewin.h; sourceTree = ""; }; 3FDFE54919A2946B009756A7 /* HostInfoWindows.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HostInfoWindows.h; path = include/lldb/Host/windows/HostInfoWindows.h; sourceTree = ""; }; 3FDFE54A19A2946B009756A7 /* win32.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = win32.h; path = include/lldb/Host/windows/win32.h; sourceTree = ""; }; 3FDFE54B19A2946B009756A7 /* windows.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = windows.h; path = include/lldb/Host/windows/windows.h; sourceTree = ""; }; 3FDFE55E19AF9B14009756A7 /* Host.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Host.cpp; path = source/Host/freebsd/Host.cpp; sourceTree = ""; }; 3FDFE55F19AF9B14009756A7 /* HostThreadFreeBSD.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = HostThreadFreeBSD.cpp; path = source/Host/freebsd/HostThreadFreeBSD.cpp; sourceTree = ""; }; 3FDFE56019AF9B39009756A7 /* HostThreadFreeBSD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HostThreadFreeBSD.h; path = include/lldb/Host/freebsd/HostThreadFreeBSD.h; sourceTree = ""; }; 3FDFE56219AF9B60009756A7 /* HostThreadLinux.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = HostThreadLinux.cpp; sourceTree = ""; }; 3FDFE56319AF9B77009756A7 /* Config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Config.h; path = include/lldb/Host/linux/Config.h; sourceTree = SOURCE_ROOT; }; 3FDFE56419AF9B77009756A7 /* HostInfoLinux.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HostInfoLinux.h; path = include/lldb/Host/linux/HostInfoLinux.h; sourceTree = SOURCE_ROOT; }; 3FDFE56519AF9B77009756A7 /* HostThreadLinux.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HostThreadLinux.h; path = include/lldb/Host/linux/HostThreadLinux.h; sourceTree = SOURCE_ROOT; }; 3FDFE56719AF9BB2009756A7 /* HostThreadMacOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HostThreadMacOSX.h; path = include/lldb/Host/macosx/HostThreadMacOSX.h; sourceTree = ""; }; 3FDFE56A19AF9C44009756A7 /* HostProcessPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HostProcessPosix.cpp; sourceTree = ""; }; 3FDFE56B19AF9C44009756A7 /* HostThreadPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HostThreadPosix.cpp; sourceTree = ""; }; 3FDFE56E19AF9C5A009756A7 /* HostProcessPosix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HostProcessPosix.h; path = ../../../include/lldb/Host/posix/HostProcessPosix.h; sourceTree = ""; }; 3FDFE56F19AF9C5A009756A7 /* HostThreadPosix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HostThreadPosix.h; path = ../../../include/lldb/Host/posix/HostThreadPosix.h; sourceTree = ""; }; 3FDFE57019AF9CA0009756A7 /* HostProcessWindows.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = HostProcessWindows.cpp; path = source/Host/windows/HostProcessWindows.cpp; sourceTree = ""; }; 3FDFE57119AF9CA0009756A7 /* HostThreadWindows.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = HostThreadWindows.cpp; path = source/Host/windows/HostThreadWindows.cpp; sourceTree = ""; }; 3FDFE57219AF9CD3009756A7 /* HostProcessWindows.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HostProcessWindows.h; path = include/lldb/Host/windows/HostProcessWindows.h; sourceTree = ""; }; 3FDFE57319AF9CD3009756A7 /* HostThreadWindows.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HostThreadWindows.h; path = include/lldb/Host/windows/HostThreadWindows.h; sourceTree = ""; }; 3FDFE57419AFABFD009756A7 /* HostProcess.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HostProcess.h; path = include/lldb/Host/HostProcess.h; sourceTree = ""; }; 3FDFE57519AFABFD009756A7 /* HostThread.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HostThread.h; path = include/lldb/Host/HostThread.h; sourceTree = ""; }; 3FDFED0519B7C898009756A7 /* HostThreadMacOSX.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = HostThreadMacOSX.mm; path = source/Host/macosx/HostThreadMacOSX.mm; sourceTree = ""; }; 3FDFED1E19BA6D55009756A7 /* Debug.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Debug.h; path = include/lldb/Host/Debug.h; sourceTree = ""; }; 3FDFED1F19BA6D55009756A7 /* HostGetOpt.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HostGetOpt.h; path = include/lldb/Host/HostGetOpt.h; sourceTree = ""; }; 3FDFED2019BA6D55009756A7 /* HostNativeThread.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HostNativeThread.h; path = include/lldb/Host/HostNativeThread.h; sourceTree = ""; }; 3FDFED2119BA6D55009756A7 /* HostNativeThreadBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HostNativeThreadBase.h; path = include/lldb/Host/HostNativeThreadBase.h; sourceTree = ""; }; 3FDFED2219BA6D55009756A7 /* ProcessRunLock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ProcessRunLock.h; path = include/lldb/Host/ProcessRunLock.h; sourceTree = ""; }; 3FDFED2319BA6D55009756A7 /* ThreadLauncher.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ThreadLauncher.h; path = include/lldb/Host/ThreadLauncher.h; sourceTree = ""; }; 3FDFED2419BA6D96009756A7 /* HostNativeThreadBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HostNativeThreadBase.cpp; sourceTree = ""; }; 3FDFED2519BA6D96009756A7 /* HostThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HostThread.cpp; sourceTree = ""; }; 3FDFED2619BA6D96009756A7 /* ThreadLauncher.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadLauncher.cpp; sourceTree = ""; }; 3FDFED2C19C257A0009756A7 /* HostProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HostProcess.cpp; sourceTree = ""; }; 4906FD4012F2255300A2A77C /* ASTDumper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ASTDumper.cpp; path = ExpressionParser/Clang/ASTDumper.cpp; sourceTree = ""; }; 4906FD4412F2257600A2A77C /* ASTDumper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTDumper.h; path = ExpressionParser/Clang/ASTDumper.h; sourceTree = ""; }; 490A36BD180F0E6F00BA31F8 /* PlatformWindows.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformWindows.cpp; sourceTree = ""; }; 490A36BE180F0E6F00BA31F8 /* PlatformWindows.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformWindows.h; sourceTree = ""; }; 4911934B1226383D00578B7F /* ASTStructExtractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTStructExtractor.h; path = ExpressionParser/Clang/ASTStructExtractor.h; sourceTree = ""; }; 491193501226386000578B7F /* ASTStructExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ASTStructExtractor.cpp; path = ExpressionParser/Clang/ASTStructExtractor.cpp; sourceTree = ""; }; 492DB7E61EC662B100B9E9AF /* Status.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Status.h; path = include/lldb/Utility/Status.h; sourceTree = ""; }; 492DB7E81EC662D100B9E9AF /* Status.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Status.cpp; path = source/Utility/Status.cpp; sourceTree = ""; }; 49307AAD11DEA4D90081F992 /* IRForTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRForTarget.cpp; path = ExpressionParser/Clang/IRForTarget.cpp; sourceTree = ""; }; 49307AB111DEA4F20081F992 /* IRForTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IRForTarget.h; path = ExpressionParser/Clang/IRForTarget.h; sourceTree = ""; }; 4939EA8B1BD56B3700084382 /* REPL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = REPL.h; path = include/lldb/Expression/REPL.h; sourceTree = ""; }; 4939EA8C1BD56B6D00084382 /* REPL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = REPL.cpp; path = source/Expression/REPL.cpp; sourceTree = ""; }; 494260D7145790D5003C1C78 /* VerifyDecl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = VerifyDecl.h; path = include/lldb/Symbol/VerifyDecl.h; sourceTree = ""; }; 494260D914579144003C1C78 /* VerifyDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VerifyDecl.cpp; path = source/Symbol/VerifyDecl.cpp; sourceTree = ""; }; 49445C2512245E3600C11A81 /* ClangExpressionParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangExpressionParser.cpp; path = ExpressionParser/Clang/ClangExpressionParser.cpp; sourceTree = ""; }; 49445C2912245E5500C11A81 /* ClangExpressionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangExpressionParser.h; path = ExpressionParser/Clang/ClangExpressionParser.h; sourceTree = ""; }; 49445E341225AB6A00C11A81 /* ClangUserExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangUserExpression.h; path = ExpressionParser/Clang/ClangUserExpression.h; sourceTree = ""; }; 4959511B1A1BC48100F6F8FC /* ClangModulesDeclVendor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangModulesDeclVendor.h; path = ExpressionParser/Clang/ClangModulesDeclVendor.h; sourceTree = ""; }; 4959511E1A1BC4BC00F6F8FC /* ClangModulesDeclVendor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangModulesDeclVendor.cpp; path = ExpressionParser/Clang/ClangModulesDeclVendor.cpp; sourceTree = ""; }; 495B38431489714C002708C5 /* ClangExternalASTSourceCommon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ClangExternalASTSourceCommon.h; path = include/lldb/Symbol/ClangExternalASTSourceCommon.h; sourceTree = ""; }; 495BBACB119A0DBE00418BEA /* PathMappingList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PathMappingList.cpp; path = source/Target/PathMappingList.cpp; sourceTree = ""; }; 495BBACF119A0DE700418BEA /* PathMappingList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PathMappingList.h; path = include/lldb/Target/PathMappingList.h; sourceTree = ""; }; 4966DCC3148978A10028481B /* ClangExternalASTSourceCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangExternalASTSourceCommon.cpp; path = source/Symbol/ClangExternalASTSourceCommon.cpp; sourceTree = ""; }; 496B01581406DE8900F830D5 /* IRInterpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRInterpreter.cpp; path = source/Expression/IRInterpreter.cpp; sourceTree = ""; }; 496B015A1406DEB100F830D5 /* IRInterpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IRInterpreter.h; path = include/lldb/Expression/IRInterpreter.h; sourceTree = ""; }; 497C86BD122823D800B54702 /* ClangUtilityFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangUtilityFunction.cpp; path = ExpressionParser/Clang/ClangUtilityFunction.cpp; sourceTree = ""; }; 497C86C1122823F300B54702 /* ClangUtilityFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangUtilityFunction.h; path = ExpressionParser/Clang/ClangUtilityFunction.h; sourceTree = ""; }; 497E7B331188ED300065CCA1 /* ABI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ABI.h; path = include/lldb/Target/ABI.h; sourceTree = ""; }; 497E7B9D1188F6690065CCA1 /* ABI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ABI.cpp; path = source/Target/ABI.cpp; sourceTree = ""; }; 4984BA0E1B978C3E008658D4 /* ClangExpressionVariable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangExpressionVariable.cpp; path = ExpressionParser/Clang/ClangExpressionVariable.cpp; sourceTree = ""; }; 4984BA0F1B978C3E008658D4 /* ClangExpressionVariable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangExpressionVariable.h; path = ExpressionParser/Clang/ClangExpressionVariable.h; sourceTree = ""; }; 4984BA151B979973008658D4 /* ExpressionVariable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ExpressionVariable.cpp; path = source/Expression/ExpressionVariable.cpp; sourceTree = ""; }; 4984BA171B979C08008658D4 /* ExpressionVariable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExpressionVariable.h; path = include/lldb/Expression/ExpressionVariable.h; sourceTree = ""; }; 499F381E11A5B3F300F5CE02 /* CommandObjectArgs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectArgs.h; path = source/Commands/CommandObjectArgs.h; sourceTree = ""; }; 499F381F11A5B3F300F5CE02 /* CommandObjectArgs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectArgs.cpp; path = source/Commands/CommandObjectArgs.cpp; sourceTree = ""; }; 49A1CAC11430E21D00306AC9 /* ExpressionSourceCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExpressionSourceCode.h; path = include/lldb/Expression/ExpressionSourceCode.h; sourceTree = ""; }; 49A1CAC31430E8BD00306AC9 /* ExpressionSourceCode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ExpressionSourceCode.cpp; path = source/Expression/ExpressionSourceCode.cpp; sourceTree = ""; }; 49A8A39F11D568A300AD3B68 /* ASTResultSynthesizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ASTResultSynthesizer.cpp; path = ExpressionParser/Clang/ASTResultSynthesizer.cpp; sourceTree = ""; }; 49A8A3A311D568BF00AD3B68 /* ASTResultSynthesizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTResultSynthesizer.h; path = ExpressionParser/Clang/ASTResultSynthesizer.h; sourceTree = ""; }; 49B01A2D15F67B1700666829 /* DeclVendor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DeclVendor.h; path = include/lldb/Symbol/DeclVendor.h; sourceTree = ""; }; 49BB309511F79450001A4197 /* TaggedASTType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TaggedASTType.h; path = include/lldb/Symbol/TaggedASTType.h; sourceTree = ""; }; 49C66B1C17011A43004D1922 /* IRMemoryMap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = IRMemoryMap.h; path = include/lldb/Expression/IRMemoryMap.h; sourceTree = ""; }; 49CA96E61E6AAC6600C03FEE /* DataBufferHeap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DataBufferHeap.cpp; path = source/Utility/DataBufferHeap.cpp; sourceTree = ""; }; 49CA96E71E6AAC6600C03FEE /* DataBufferLLVM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DataBufferLLVM.cpp; path = source/Utility/DataBufferLLVM.cpp; sourceTree = ""; }; 49CA96E81E6AAC6600C03FEE /* DataEncoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DataEncoder.cpp; path = source/Utility/DataEncoder.cpp; sourceTree = ""; }; 49CA96E91E6AAC6600C03FEE /* DataExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DataExtractor.cpp; path = source/Utility/DataExtractor.cpp; sourceTree = ""; }; 49CA96EA1E6AAC6600C03FEE /* UUID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UUID.cpp; path = source/Utility/UUID.cpp; sourceTree = ""; }; 49CA96F01E6AAC8E00C03FEE /* DataBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DataBuffer.h; path = include/lldb/Utility/DataBuffer.h; sourceTree = ""; }; 49CA96F11E6AAC8E00C03FEE /* DataBufferHeap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DataBufferHeap.h; path = include/lldb/Utility/DataBufferHeap.h; sourceTree = ""; }; 49CA96F21E6AAC8E00C03FEE /* DataBufferLLVM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DataBufferLLVM.h; path = include/lldb/Utility/DataBufferLLVM.h; sourceTree = ""; }; 49CA96F31E6AAC8E00C03FEE /* DataEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DataEncoder.h; path = include/lldb/Utility/DataEncoder.h; sourceTree = ""; }; 49CA96F41E6AAC8E00C03FEE /* DataExtractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DataExtractor.h; path = include/lldb/Utility/DataExtractor.h; sourceTree = ""; }; 49CA96F51E6AAC8E00C03FEE /* UUID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UUID.h; path = include/lldb/Utility/UUID.h; sourceTree = ""; }; 49CF9829122C70BD007A0B96 /* IRDynamicChecks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRDynamicChecks.cpp; path = source/Expression/IRDynamicChecks.cpp; sourceTree = ""; }; 49CF9833122C718B007A0B96 /* IRDynamicChecks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IRDynamicChecks.h; path = include/lldb/Expression/IRDynamicChecks.h; sourceTree = ""; }; 49D4FE821210B5FB00CDB854 /* ClangPersistentVariables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangPersistentVariables.h; path = ExpressionParser/Clang/ClangPersistentVariables.h; sourceTree = ""; }; 49D4FE871210B61C00CDB854 /* ClangPersistentVariables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangPersistentVariables.cpp; path = ExpressionParser/Clang/ClangPersistentVariables.cpp; sourceTree = ""; }; 49D7072611B5AD03001AD875 /* ClangASTSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangASTSource.h; path = ExpressionParser/Clang/ClangASTSource.h; sourceTree = ""; }; 49D7072811B5AD11001AD875 /* ClangASTSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangASTSource.cpp; path = ExpressionParser/Clang/ClangASTSource.cpp; sourceTree = ""; }; 49D8FB3513B558DE00411094 /* ClangASTImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangASTImporter.cpp; path = source/Symbol/ClangASTImporter.cpp; sourceTree = ""; }; 49D8FB3713B5594900411094 /* ClangASTImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangASTImporter.h; path = include/lldb/Symbol/ClangASTImporter.h; sourceTree = ""; }; 49DA65021485C92A005FF180 /* AppleObjCDeclVendor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = AppleObjCDeclVendor.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 49DA65041485C942005FF180 /* AppleObjCDeclVendor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleObjCDeclVendor.h; sourceTree = ""; }; 49DCF6FD170E6B4A0092F75E /* IRMemoryMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRMemoryMap.cpp; path = source/Expression/IRMemoryMap.cpp; sourceTree = ""; }; 49DCF6FF170E6FD90092F75E /* Materializer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Materializer.h; path = include/lldb/Expression/Materializer.h; sourceTree = ""; }; 49DCF700170E70120092F75E /* Materializer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Materializer.cpp; path = source/Expression/Materializer.cpp; sourceTree = ""; }; 49DEF11F1CD7BD90006A7C7D /* BlockPointer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BlockPointer.cpp; path = Language/CPlusPlus/BlockPointer.cpp; sourceTree = ""; }; 49DEF1201CD7BD90006A7C7D /* BlockPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BlockPointer.h; path = Language/CPlusPlus/BlockPointer.h; sourceTree = ""; }; 49E45FA911F660DC008F7B28 /* CompilerType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompilerType.h; path = include/lldb/Symbol/CompilerType.h; sourceTree = ""; }; 49E45FAD11F660FE008F7B28 /* CompilerType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompilerType.cpp; path = source/Symbol/CompilerType.cpp; sourceTree = ""; }; 49E4F6681C9CAD12008487EA /* DiagnosticManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DiagnosticManager.cpp; path = source/Expression/DiagnosticManager.cpp; sourceTree = ""; }; 49E4F66C1C9CAD2D008487EA /* DiagnosticManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DiagnosticManager.h; path = include/lldb/Expression/DiagnosticManager.h; sourceTree = ""; }; 49EC3E98118F90AC00B1265E /* ThreadPlanCallFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanCallFunction.cpp; path = source/Target/ThreadPlanCallFunction.cpp; sourceTree = ""; }; 49EC3E9C118F90D400B1265E /* ThreadPlanCallFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanCallFunction.h; path = include/lldb/Target/ThreadPlanCallFunction.h; sourceTree = ""; }; 49F1A74511B3388F003ED505 /* ClangExpressionDeclMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangExpressionDeclMap.cpp; path = ExpressionParser/Clang/ClangExpressionDeclMap.cpp; sourceTree = ""; }; 49F1A74911B338AE003ED505 /* ClangExpressionDeclMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangExpressionDeclMap.h; path = ExpressionParser/Clang/ClangExpressionDeclMap.h; sourceTree = ""; }; 49F811EF1E931B1500F4E163 /* CPlusPlusNameParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CPlusPlusNameParser.cpp; path = Language/CPlusPlus/CPlusPlusNameParser.cpp; sourceTree = ""; }; 49F811F01E931B1500F4E163 /* CPlusPlusNameParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CPlusPlusNameParser.h; path = Language/CPlusPlus/CPlusPlusNameParser.h; sourceTree = ""; }; 4C00832C1B9A58A700D5CF24 /* Expression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Expression.h; path = include/lldb/Expression/Expression.h; sourceTree = ""; }; 4C00832D1B9A58A700D5CF24 /* FunctionCaller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FunctionCaller.h; path = include/lldb/Expression/FunctionCaller.h; sourceTree = ""; }; 4C00832E1B9A58A700D5CF24 /* UserExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UserExpression.h; path = include/lldb/Expression/UserExpression.h; sourceTree = ""; }; 4C0083321B9A5DE200D5CF24 /* FunctionCaller.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FunctionCaller.cpp; path = source/Expression/FunctionCaller.cpp; sourceTree = ""; }; 4C0083331B9A5DE200D5CF24 /* UserExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UserExpression.cpp; path = source/Expression/UserExpression.cpp; sourceTree = ""; }; 4C00833D1B9F9B8400D5CF24 /* UtilityFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UtilityFunction.h; path = include/lldb/Expression/UtilityFunction.h; sourceTree = ""; }; 4C00833F1B9F9BA900D5CF24 /* UtilityFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UtilityFunction.cpp; path = source/Expression/UtilityFunction.cpp; sourceTree = ""; }; 4C00986F11500B4300F316B0 /* UnixSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UnixSignals.h; path = include/lldb/Target/UnixSignals.h; sourceTree = ""; }; 4C00987011500B4300F316B0 /* UnixSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnixSignals.cpp; path = source/Target/UnixSignals.cpp; sourceTree = ""; }; 4C08CDE711C81EF8001610A8 /* ThreadSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadSpec.cpp; path = source/Target/ThreadSpec.cpp; sourceTree = ""; }; 4C08CDEB11C81F1E001610A8 /* ThreadSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadSpec.h; path = include/lldb/Target/ThreadSpec.h; sourceTree = ""; }; 4C09CB73116BD98B00C7A725 /* CommandCompletions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandCompletions.h; path = include/lldb/Interpreter/CommandCompletions.h; sourceTree = ""; }; 4C09CB74116BD98B00C7A725 /* CommandCompletions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandCompletions.cpp; path = source/Commands/CommandCompletions.cpp; sourceTree = ""; }; 4C2479BE1BA39843009C9A7B /* ExpressionParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ExpressionParser.h; path = include/lldb/Expression/ExpressionParser.h; sourceTree = ""; }; 4C29E77D1BA2403F00DFF855 /* ExpressionTypeSystemHelper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; name = ExpressionTypeSystemHelper.h; path = include/lldb/Expression/ExpressionTypeSystemHelper.h; sourceTree = ""; }; 4C2FAE2E135E3A70001EDE44 /* SharedCluster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SharedCluster.h; path = include/lldb/Utility/SharedCluster.h; sourceTree = ""; }; 4C3DA2301CA0BFB800CEB1D4 /* ClangDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangDiagnostic.h; path = ExpressionParser/Clang/ClangDiagnostic.h; sourceTree = ""; }; 4C43DEF9110641F300E55CBF /* ThreadPlanShouldStopHere.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanShouldStopHere.h; path = include/lldb/Target/ThreadPlanShouldStopHere.h; sourceTree = ""; }; 4C43DEFA110641F300E55CBF /* ThreadPlanShouldStopHere.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanShouldStopHere.cpp; path = source/Target/ThreadPlanShouldStopHere.cpp; sourceTree = ""; }; 4C43DF8511069BFD00E55CBF /* ThreadPlanStepInRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanStepInRange.h; path = include/lldb/Target/ThreadPlanStepInRange.h; sourceTree = ""; }; 4C43DF8611069BFD00E55CBF /* ThreadPlanStepOverRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanStepOverRange.h; path = include/lldb/Target/ThreadPlanStepOverRange.h; sourceTree = ""; }; 4C43DF8911069C3200E55CBF /* ThreadPlanStepInRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanStepInRange.cpp; path = source/Target/ThreadPlanStepInRange.cpp; sourceTree = ""; }; 4C43DF8A11069C3200E55CBF /* ThreadPlanStepOverRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanStepOverRange.cpp; path = source/Target/ThreadPlanStepOverRange.cpp; sourceTree = ""; }; 4C4EB77F1E6A4DB8002035C0 /* DumpDataExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DumpDataExtractor.cpp; path = source/Core/DumpDataExtractor.cpp; sourceTree = ""; }; 4C4EB7821E6A4DE7002035C0 /* DumpDataExtractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DumpDataExtractor.h; path = include/lldb/Core/DumpDataExtractor.h; sourceTree = ""; }; 4C562CC21CC07DDD00C52EAC /* PDBASTParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PDBASTParser.cpp; path = PDB/PDBASTParser.cpp; sourceTree = ""; }; 4C562CC31CC07DDD00C52EAC /* PDBASTParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PDBASTParser.h; path = PDB/PDBASTParser.h; sourceTree = ""; }; 4C56543019D1EFAA002E9C44 /* ThreadPlanPython.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanPython.cpp; path = source/Target/ThreadPlanPython.cpp; sourceTree = ""; }; 4C56543219D1EFB5002E9C44 /* ThreadPlanPython.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanPython.h; path = include/lldb/Target/ThreadPlanPython.h; sourceTree = ""; }; 4C56543419D2297A002E9C44 /* SBThreadPlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBThreadPlan.h; path = include/lldb/API/SBThreadPlan.h; sourceTree = ""; }; 4C56543619D22B32002E9C44 /* SBThreadPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBThreadPlan.cpp; path = source/API/SBThreadPlan.cpp; sourceTree = ""; }; 4C56543819D22FD9002E9C44 /* SBThreadPlan.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBThreadPlan.i; sourceTree = ""; }; 4C5DBBC611E3FEC60035160F /* CommandObjectCommands.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectCommands.cpp; path = source/Commands/CommandObjectCommands.cpp; sourceTree = ""; }; 4C5DBBC711E3FEC60035160F /* CommandObjectCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectCommands.h; path = source/Commands/CommandObjectCommands.h; sourceTree = ""; }; 4C73152119B7D71700F865A4 /* Iterable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Iterable.h; path = include/lldb/Utility/Iterable.h; sourceTree = ""; }; 4C7CF7E31295E10E00B4FBB5 /* ThreadPlanCallUserExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanCallUserExpression.h; path = include/lldb/Target/ThreadPlanCallUserExpression.h; sourceTree = ""; }; 4C7CF7E51295E12B00B4FBB5 /* ThreadPlanCallUserExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanCallUserExpression.cpp; path = source/Target/ThreadPlanCallUserExpression.cpp; sourceTree = ""; }; 4C88BC291BA3722B00AA0964 /* Expression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Expression.cpp; path = source/Expression/Expression.cpp; sourceTree = ""; }; 4C98D3DA118FB96F00E575D0 /* ClangFunctionCaller.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangFunctionCaller.cpp; path = ExpressionParser/Clang/ClangFunctionCaller.cpp; sourceTree = ""; }; 4C98D3DB118FB96F00E575D0 /* IRExecutionUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRExecutionUnit.cpp; path = source/Expression/IRExecutionUnit.cpp; sourceTree = ""; }; 4C98D3E0118FB98F00E575D0 /* ClangFunctionCaller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangFunctionCaller.h; path = ExpressionParser/Clang/ClangFunctionCaller.h; sourceTree = ""; }; 4C98D3E1118FB98F00E575D0 /* IRExecutionUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IRExecutionUnit.h; path = include/lldb/Expression/IRExecutionUnit.h; sourceTree = ""; }; 4CA9637911B6E99A00780E28 /* CommandObjectApropos.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectApropos.cpp; path = source/Commands/CommandObjectApropos.cpp; sourceTree = ""; }; 4CA9637A11B6E99A00780E28 /* CommandObjectApropos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectApropos.h; path = source/Commands/CommandObjectApropos.h; sourceTree = ""; }; 4CAA56121422D96A001FFA01 /* BreakpointResolverFileRegex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointResolverFileRegex.h; path = include/lldb/Breakpoint/BreakpointResolverFileRegex.h; sourceTree = ""; }; 4CAA56141422D986001FFA01 /* BreakpointResolverFileRegex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointResolverFileRegex.cpp; path = source/Breakpoint/BreakpointResolverFileRegex.cpp; sourceTree = ""; }; 4CAB257C18EC9DB800BAD33E /* SafeMachO.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SafeMachO.h; path = include/lldb/Utility/SafeMachO.h; sourceTree = ""; }; 4CABA9DC134A8BA700539BDD /* ValueObjectMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectMemory.h; path = include/lldb/Core/ValueObjectMemory.h; sourceTree = ""; }; 4CABA9DF134A8BCD00539BDD /* ValueObjectMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectMemory.cpp; path = source/Core/ValueObjectMemory.cpp; sourceTree = ""; }; 4CAFCE001101216B00CA63DB /* ThreadPlanRunToAddress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanRunToAddress.h; path = include/lldb/Target/ThreadPlanRunToAddress.h; sourceTree = ""; }; 4CAFCE031101218900CA63DB /* ThreadPlanRunToAddress.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanRunToAddress.cpp; path = source/Target/ThreadPlanRunToAddress.cpp; sourceTree = ""; }; 4CB4430912491DDA00C13DC2 /* LanguageRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LanguageRuntime.h; path = include/lldb/Target/LanguageRuntime.h; sourceTree = ""; }; 4CB4430A12491DDA00C13DC2 /* LanguageRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LanguageRuntime.cpp; path = source/Target/LanguageRuntime.cpp; sourceTree = ""; }; 4CB443BB1249920C00C13DC2 /* CPPLanguageRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CPPLanguageRuntime.h; path = include/lldb/Target/CPPLanguageRuntime.h; sourceTree = ""; }; 4CB443BC1249920C00C13DC2 /* CPPLanguageRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CPPLanguageRuntime.cpp; path = source/Target/CPPLanguageRuntime.cpp; sourceTree = ""; }; 4CB443F212499B5000C13DC2 /* ObjCLanguageRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ObjCLanguageRuntime.cpp; path = source/Target/ObjCLanguageRuntime.cpp; sourceTree = ""; }; 4CB443F612499B6E00C13DC2 /* ObjCLanguageRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ObjCLanguageRuntime.h; path = include/lldb/Target/ObjCLanguageRuntime.h; sourceTree = ""; }; 4CC2A148128C73ED001531C4 /* ThreadPlanTracer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanTracer.cpp; path = source/Target/ThreadPlanTracer.cpp; sourceTree = ""; }; 4CC2A14C128C7409001531C4 /* ThreadPlanTracer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanTracer.h; path = include/lldb/Target/ThreadPlanTracer.h; sourceTree = ""; }; 4CC7C64C1D5298E20076FF94 /* OCamlLanguage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OCamlLanguage.h; path = Language/OCaml/OCamlLanguage.h; sourceTree = ""; }; 4CC7C64D1D5298E20076FF94 /* OCamlLanguage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OCamlLanguage.cpp; path = Language/OCaml/OCamlLanguage.cpp; sourceTree = ""; }; 4CC7C6511D5299140076FF94 /* DWARFASTParserOCaml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFASTParserOCaml.h; sourceTree = ""; }; 4CC7C6521D5299140076FF94 /* DWARFASTParserOCaml.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFASTParserOCaml.cpp; sourceTree = ""; }; 4CC7C6551D52996C0076FF94 /* OCamlASTContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OCamlASTContext.cpp; path = source/Symbol/OCamlASTContext.cpp; sourceTree = ""; }; 4CCA643D13B40B82003BDF98 /* ItaniumABILanguageRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ItaniumABILanguageRuntime.cpp; sourceTree = ""; }; 4CCA643E13B40B82003BDF98 /* ItaniumABILanguageRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ItaniumABILanguageRuntime.h; sourceTree = ""; }; 4CCA644213B40B82003BDF98 /* AppleObjCRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppleObjCRuntime.cpp; sourceTree = ""; }; 4CCA644313B40B82003BDF98 /* AppleObjCRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppleObjCRuntime.h; sourceTree = ""; }; 4CCA644413B40B82003BDF98 /* AppleObjCRuntimeV1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = AppleObjCRuntimeV1.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 4CCA644513B40B82003BDF98 /* AppleObjCRuntimeV1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = AppleObjCRuntimeV1.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 4CCA644613B40B82003BDF98 /* AppleObjCRuntimeV2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = AppleObjCRuntimeV2.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 4CCA644713B40B82003BDF98 /* AppleObjCRuntimeV2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = AppleObjCRuntimeV2.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 4CCA644813B40B82003BDF98 /* AppleObjCTrampolineHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppleObjCTrampolineHandler.cpp; sourceTree = ""; }; 4CCA644913B40B82003BDF98 /* AppleObjCTrampolineHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppleObjCTrampolineHandler.h; sourceTree = ""; }; 4CCA644A13B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppleThreadPlanStepThroughObjCTrampoline.cpp; sourceTree = ""; }; 4CCA644B13B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppleThreadPlanStepThroughObjCTrampoline.h; sourceTree = ""; }; 4CD0BD0C134BFAB600CB44D4 /* ValueObjectDynamicValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectDynamicValue.h; path = include/lldb/Core/ValueObjectDynamicValue.h; sourceTree = ""; }; 4CD0BD0E134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectDynamicValue.cpp; path = source/Core/ValueObjectDynamicValue.cpp; sourceTree = ""; }; 4CDB8D671DBA91A6006C5B13 /* LibStdcppUniquePointer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibStdcppUniquePointer.cpp; path = Language/CPlusPlus/LibStdcppUniquePointer.cpp; sourceTree = ""; }; 4CDB8D681DBA91A6006C5B13 /* LibStdcppTuple.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibStdcppTuple.cpp; path = Language/CPlusPlus/LibStdcppTuple.cpp; sourceTree = ""; }; 4CE4EFA61E8999B000A80C06 /* PlatformOpenBSD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformOpenBSD.cpp; sourceTree = ""; }; 4CE4EFA71E8999B000A80C06 /* PlatformOpenBSD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformOpenBSD.h; sourceTree = ""; }; 4CE4EFAB1E899A1200A80C06 /* RegisterContextOpenBSD_i386.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextOpenBSD_i386.cpp; path = Utility/RegisterContextOpenBSD_i386.cpp; sourceTree = ""; }; 4CE4EFAC1E899A1200A80C06 /* RegisterContextOpenBSD_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextOpenBSD_i386.h; path = Utility/RegisterContextOpenBSD_i386.h; sourceTree = ""; }; 4CE4EFAD1E899A1200A80C06 /* RegisterContextOpenBSD_x86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextOpenBSD_x86_64.cpp; path = Utility/RegisterContextOpenBSD_x86_64.cpp; sourceTree = ""; }; 4CE4EFAE1E899A1200A80C06 /* RegisterContextOpenBSD_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextOpenBSD_x86_64.h; path = Utility/RegisterContextOpenBSD_x86_64.h; sourceTree = ""; }; 4CE4F672162C971A00F75CB3 /* SBExpressionOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBExpressionOptions.h; path = include/lldb/API/SBExpressionOptions.h; sourceTree = ""; }; 4CE4F674162C973F00F75CB3 /* SBExpressionOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBExpressionOptions.cpp; path = source/API/SBExpressionOptions.cpp; sourceTree = ""; }; 4CE4F676162CE1E100F75CB3 /* SBExpressionOptions.i */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBExpressionOptions.i; sourceTree = ""; }; 4CEDAED311754F5E00E875A6 /* ThreadPlanStepUntil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanStepUntil.h; path = include/lldb/Target/ThreadPlanStepUntil.h; sourceTree = ""; }; 4CF52AF41428291E0051E832 /* SBFileSpecList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBFileSpecList.h; path = include/lldb/API/SBFileSpecList.h; sourceTree = ""; }; 4CF52AF7142829390051E832 /* SBFileSpecList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBFileSpecList.cpp; path = source/API/SBFileSpecList.cpp; sourceTree = ""; }; 54067BEC1DF2034B00749AA5 /* UBSanRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = UBSanRuntime.cpp; sourceTree = ""; }; 54067BED1DF2034B00749AA5 /* UBSanRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UBSanRuntime.h; sourceTree = ""; }; 69A01E1C1236C5D400C660B5 /* Host.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Host.cpp; sourceTree = ""; }; 69A01E1F1236C5D400C660B5 /* Symbols.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Symbols.cpp; sourceTree = ""; }; 6D0F613C1C80AA8900A4ECEE /* DebugMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DebugMacros.h; path = include/lldb/Symbol/DebugMacros.h; sourceTree = ""; }; 6D0F613D1C80AA8900A4ECEE /* JavaASTContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JavaASTContext.h; path = include/lldb/Symbol/JavaASTContext.h; sourceTree = ""; }; 6D0F61411C80AAAA00A4ECEE /* JavaASTContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JavaASTContext.cpp; path = source/Symbol/JavaASTContext.cpp; sourceTree = ""; }; 6D0F61441C80AACF00A4ECEE /* DWARFASTParserJava.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFASTParserJava.cpp; sourceTree = ""; }; 6D0F61451C80AACF00A4ECEE /* DWARFASTParserJava.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFASTParserJava.h; sourceTree = ""; }; 6D0F614A1C80AB0400A4ECEE /* JavaLanguageRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JavaLanguageRuntime.cpp; path = Java/JavaLanguageRuntime.cpp; sourceTree = ""; }; 6D0F614B1C80AB0400A4ECEE /* JavaLanguageRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JavaLanguageRuntime.h; path = Java/JavaLanguageRuntime.h; sourceTree = ""; }; 6D0F61511C80AB3000A4ECEE /* JavaFormatterFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JavaFormatterFunctions.cpp; path = Language/Java/JavaFormatterFunctions.cpp; sourceTree = ""; }; 6D0F61521C80AB3000A4ECEE /* JavaFormatterFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JavaFormatterFunctions.h; path = Language/Java/JavaFormatterFunctions.h; sourceTree = ""; }; 6D0F61531C80AB3000A4ECEE /* JavaLanguage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JavaLanguage.cpp; path = Language/Java/JavaLanguage.cpp; sourceTree = ""; }; 6D0F61541C80AB3000A4ECEE /* JavaLanguage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JavaLanguage.h; path = Language/Java/JavaLanguage.h; sourceTree = ""; }; 6D55B28D1A8A806200A70529 /* GDBRemoteCommunicationServerCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunicationServerCommon.cpp; sourceTree = ""; }; 6D55B28E1A8A806200A70529 /* GDBRemoteCommunicationServerLLGS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunicationServerLLGS.cpp; sourceTree = ""; }; 6D55B28F1A8A806200A70529 /* GDBRemoteCommunicationServerPlatform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunicationServerPlatform.cpp; sourceTree = ""; }; 6D55B2931A8A808400A70529 /* GDBRemoteCommunicationServerCommon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GDBRemoteCommunicationServerCommon.h; sourceTree = ""; }; 6D55B2941A8A808400A70529 /* GDBRemoteCommunicationServerLLGS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GDBRemoteCommunicationServerLLGS.h; sourceTree = ""; }; 6D55B2951A8A808400A70529 /* GDBRemoteCommunicationServerPlatform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GDBRemoteCommunicationServerPlatform.h; sourceTree = ""; }; 6D55BAE01A8CD03D00A70529 /* HostInfoAndroid.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = HostInfoAndroid.cpp; path = source/Host/android/HostInfoAndroid.cpp; sourceTree = ""; }; 6D55BAE21A8CD06000A70529 /* Android.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Android.h; path = include/lldb/Host/android/Android.h; sourceTree = ""; }; 6D55BAE31A8CD06000A70529 /* Config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Config.h; path = include/lldb/Host/android/Config.h; sourceTree = ""; }; 6D55BAE41A8CD06000A70529 /* HostInfoAndroid.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HostInfoAndroid.h; path = include/lldb/Host/android/HostInfoAndroid.h; sourceTree = ""; }; 6D55BAE91A8CD08C00A70529 /* PlatformAndroid.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformAndroid.cpp; sourceTree = ""; }; 6D55BAEA1A8CD08C00A70529 /* PlatformAndroid.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlatformAndroid.h; sourceTree = ""; }; 6D55BAEB1A8CD08C00A70529 /* PlatformAndroidRemoteGDBServer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformAndroidRemoteGDBServer.cpp; sourceTree = ""; }; 6D55BAEC1A8CD08C00A70529 /* PlatformAndroidRemoteGDBServer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlatformAndroidRemoteGDBServer.h; sourceTree = ""; }; 6D762BEC1B1605CD006C929D /* LLDBServerUtilities.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LLDBServerUtilities.cpp; path = "tools/lldb-server/LLDBServerUtilities.cpp"; sourceTree = ""; }; 6D762BED1B1605CD006C929D /* LLDBServerUtilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LLDBServerUtilities.h; path = "tools/lldb-server/LLDBServerUtilities.h"; sourceTree = ""; }; 6D86CE9E1B440F6B00A7FBFA /* CommandObjectBugreport.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectBugreport.cpp; path = source/Commands/CommandObjectBugreport.cpp; sourceTree = ""; }; 6D86CE9F1B440F6B00A7FBFA /* CommandObjectBugreport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CommandObjectBugreport.h; path = source/Commands/CommandObjectBugreport.h; sourceTree = ""; }; 6D95DBFD1B9DC057000E318A /* DIERef.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DIERef.cpp; sourceTree = ""; }; 6D95DBFE1B9DC057000E318A /* HashedNameToDIE.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HashedNameToDIE.cpp; sourceTree = ""; }; 6D95DBFF1B9DC057000E318A /* SymbolFileDWARFDwo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolFileDWARFDwo.cpp; sourceTree = ""; }; 6D95DC031B9DC06F000E318A /* DIERef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DIERef.h; sourceTree = ""; }; 6D95DC041B9DC06F000E318A /* SymbolFileDWARFDwo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolFileDWARFDwo.h; sourceTree = ""; }; 6D99A3611BBC2F1600979793 /* ArmUnwindInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ArmUnwindInfo.h; path = include/lldb/Symbol/ArmUnwindInfo.h; sourceTree = ""; }; 6D99A3621BBC2F3200979793 /* ArmUnwindInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ArmUnwindInfo.cpp; path = source/Symbol/ArmUnwindInfo.cpp; sourceTree = ""; }; 6D9AB3DC1BB2B74E003F2289 /* TypeMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeMap.cpp; path = source/Symbol/TypeMap.cpp; sourceTree = ""; }; 6D9AB3DE1BB2B76B003F2289 /* TypeMap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TypeMap.h; path = include/lldb/Symbol/TypeMap.h; sourceTree = ""; }; 6DEC6F381BD66D750091ABA6 /* TaskPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TaskPool.cpp; path = source/Utility/TaskPool.cpp; sourceTree = ""; }; 6DEC6F3A1BD66D950091ABA6 /* TaskPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TaskPool.h; path = include/lldb/Utility/TaskPool.h; sourceTree = ""; }; 8C26C4241C3EA4340031DF7C /* TSanRuntime.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = TSanRuntime.cpp; path = TSan/TSanRuntime.cpp; sourceTree = ""; }; 8C26C4251C3EA4340031DF7C /* TSanRuntime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TSanRuntime.h; path = TSan/TSanRuntime.h; sourceTree = ""; }; 8C2D6A52197A1EAF006989C9 /* MemoryHistory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MemoryHistory.cpp; path = source/Target/MemoryHistory.cpp; sourceTree = ""; }; 8C2D6A54197A1EBE006989C9 /* MemoryHistory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MemoryHistory.h; path = include/lldb/Target/MemoryHistory.h; sourceTree = ""; }; 8C2D6A5A197A1FDC006989C9 /* MemoryHistoryASan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryHistoryASan.cpp; sourceTree = ""; }; 8C2D6A5B197A1FDC006989C9 /* MemoryHistoryASan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryHistoryASan.h; sourceTree = ""; }; 8C3BD9931EF45D9B0016C343 /* MainThreadCheckerRuntime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MainThreadCheckerRuntime.h; sourceTree = ""; }; 8C3BD9951EF45D9B0016C343 /* MainThreadCheckerRuntime.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MainThreadCheckerRuntime.cpp; sourceTree = ""; }; 8CCB017A19BA283D0009FD44 /* ThreadCollection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadCollection.cpp; path = source/Target/ThreadCollection.cpp; sourceTree = ""; }; 8CCB017C19BA289B0009FD44 /* ThreadCollection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ThreadCollection.h; path = include/lldb/Target/ThreadCollection.h; sourceTree = ""; }; 8CCB017F19BA4DD00009FD44 /* SBThreadCollection.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SBThreadCollection.cpp; path = source/API/SBThreadCollection.cpp; sourceTree = ""; }; 8CCB018119BA4E210009FD44 /* SBThreadCollection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBThreadCollection.h; path = include/lldb/API/SBThreadCollection.h; sourceTree = ""; }; 8CCB018419BA54930009FD44 /* SBThreadCollection.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBThreadCollection.i; sourceTree = ""; }; 8CF02ADF19DCBF3B00B14BE0 /* InstrumentationRuntime.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = InstrumentationRuntime.cpp; path = source/Target/InstrumentationRuntime.cpp; sourceTree = ""; }; 8CF02AE019DCBF3B00B14BE0 /* InstrumentationRuntime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = InstrumentationRuntime.h; path = include/lldb/Target/InstrumentationRuntime.h; sourceTree = ""; }; 8CF02AE519DCBF8400B14BE0 /* ASanRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ASanRuntime.cpp; sourceTree = ""; }; 8CF02AE619DCBF8400B14BE0 /* ASanRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASanRuntime.h; sourceTree = ""; }; 8CF02AED19DD15CF00B14BE0 /* InstrumentationRuntimeStopInfo.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = InstrumentationRuntimeStopInfo.cpp; path = source/Target/InstrumentationRuntimeStopInfo.cpp; sourceTree = ""; }; 8CF02AEE19DD15CF00B14BE0 /* InstrumentationRuntimeStopInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = InstrumentationRuntimeStopInfo.h; path = include/lldb/Target/InstrumentationRuntimeStopInfo.h; sourceTree = ""; }; 94005E0313F438DF001EF42D /* python-wrapper.swig */ = {isa = PBXFileReference; lastKnownFileType = text; path = "python-wrapper.swig"; sourceTree = ""; }; 94005E0513F45A1B001EF42D /* embedded_interpreter.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = embedded_interpreter.py; path = source/Interpreter/embedded_interpreter.py; sourceTree = ""; }; 940495781BEC497E00926025 /* NSError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSError.cpp; path = Language/ObjC/NSError.cpp; sourceTree = ""; }; 940495791BEC497E00926025 /* NSException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSException.cpp; path = Language/ObjC/NSException.cpp; sourceTree = ""; }; 94094C68163B6CCC0083A547 /* ValueObjectCast.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ValueObjectCast.h; path = include/lldb/Core/ValueObjectCast.h; sourceTree = ""; }; 94094C69163B6CD90083A547 /* ValueObjectCast.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectCast.cpp; path = source/Core/ValueObjectCast.cpp; sourceTree = ""; }; 940B01FE1D2D82220058795E /* ThreadSafeSTLVector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ThreadSafeSTLVector.h; path = include/lldb/Core/ThreadSafeSTLVector.h; sourceTree = ""; }; 940B02F419DC96CB00AD0F52 /* SBExecutionContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBExecutionContext.h; path = include/lldb/API/SBExecutionContext.h; sourceTree = ""; }; 940B02F519DC96E700AD0F52 /* SBExecutionContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBExecutionContext.cpp; path = source/API/SBExecutionContext.cpp; sourceTree = ""; }; 940B02F719DC970900AD0F52 /* SBExecutionContext.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBExecutionContext.i; sourceTree = ""; }; 940B04D81A8984FF0045D5F7 /* argdumper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = argdumper.cpp; path = tools/argdumper/argdumper.cpp; sourceTree = ""; }; 94145430175D7FDE00284436 /* lldb-versioning.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-versioning.h"; path = "include/lldb/lldb-versioning.h"; sourceTree = ""; }; 9418EBCB1AA9108B0058B02E /* VectorType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = VectorType.h; path = include/lldb/DataFormatters/VectorType.h; sourceTree = ""; }; 9418EBCC1AA910910058B02E /* VectorType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VectorType.cpp; path = source/DataFormatters/VectorType.cpp; sourceTree = ""; }; 94235B9A1A8D5FD800EB2EED /* SBVariablesOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBVariablesOptions.h; path = include/lldb/API/SBVariablesOptions.h; sourceTree = ""; }; 94235B9B1A8D5FF300EB2EED /* SBVariablesOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBVariablesOptions.cpp; path = source/API/SBVariablesOptions.cpp; sourceTree = ""; }; 94235B9D1A8D601A00EB2EED /* SBVariablesOptions.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBVariablesOptions.i; sourceTree = ""; }; 942612F51B94FFE900EF842E /* LanguageCategory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LanguageCategory.h; path = include/lldb/DataFormatters/LanguageCategory.h; sourceTree = ""; }; 942612F61B95000000EF842E /* LanguageCategory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LanguageCategory.cpp; path = source/DataFormatters/LanguageCategory.cpp; sourceTree = ""; }; 942829541A89614000521B30 /* JSON.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = JSON.h; path = include/lldb/Utility/JSON.h; sourceTree = ""; }; 942829551A89614C00521B30 /* JSON.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSON.cpp; path = source/Utility/JSON.cpp; sourceTree = ""; }; 942829C01A89835300521B30 /* lldb-argdumper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "lldb-argdumper"; sourceTree = BUILT_PRODUCTS_DIR; }; 9428BC291C6E64DC002A24D7 /* LibCxxAtomic.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxAtomic.cpp; path = Language/CPlusPlus/LibCxxAtomic.cpp; sourceTree = ""; }; 9428BC2A1C6E64DC002A24D7 /* LibCxxAtomic.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LibCxxAtomic.h; path = Language/CPlusPlus/LibCxxAtomic.h; sourceTree = ""; }; 94380B8019940B0300BFE4A8 /* StringLexer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StringLexer.h; path = include/lldb/Utility/StringLexer.h; sourceTree = ""; }; 94380B8119940B0A00BFE4A8 /* StringLexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringLexer.cpp; path = source/Utility/StringLexer.cpp; sourceTree = ""; }; 943B90FC1B991586007BA499 /* VectorIterator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = VectorIterator.h; path = include/lldb/DataFormatters/VectorIterator.h; sourceTree = ""; }; 943BDEFC1AA7B2DE00789CE8 /* LLDBAssert.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LLDBAssert.h; path = include/lldb/Utility/LLDBAssert.h; sourceTree = ""; }; 943BDEFD1AA7B2F800789CE8 /* LLDBAssert.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLDBAssert.cpp; path = source/Utility/LLDBAssert.cpp; sourceTree = ""; }; 9441816B1C8F5EB000E5A8D9 /* CommandAlias.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CommandAlias.h; path = include/lldb/Interpreter/CommandAlias.h; sourceTree = ""; }; 9441816D1C8F5EC900E5A8D9 /* CommandAlias.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandAlias.cpp; path = source/Interpreter/CommandAlias.cpp; sourceTree = ""; }; 944372DA171F6B4300E57C32 /* RegisterContextDummy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextDummy.cpp; path = Utility/RegisterContextDummy.cpp; sourceTree = ""; }; 944372DB171F6B4300E57C32 /* RegisterContextDummy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextDummy.h; path = Utility/RegisterContextDummy.h; sourceTree = ""; }; 9443B120140C18A90013457C /* SBData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBData.h; path = include/lldb/API/SBData.h; sourceTree = ""; }; 9443B121140C18C10013457C /* SBData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBData.cpp; path = source/API/SBData.cpp; sourceTree = ""; }; 9447DE411BD5962900E67212 /* DumpValueObjectOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DumpValueObjectOptions.h; path = include/lldb/DataFormatters/DumpValueObjectOptions.h; sourceTree = ""; }; 9447DE421BD5963300E67212 /* DumpValueObjectOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DumpValueObjectOptions.cpp; path = source/DataFormatters/DumpValueObjectOptions.cpp; sourceTree = ""; }; 9449B8031B30E0690019342B /* ThreadSafeDenseSet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ThreadSafeDenseSet.h; path = include/lldb/Core/ThreadSafeDenseSet.h; sourceTree = ""; }; 944DC3481774C99000D7D884 /* python-swigsafecast.swig */ = {isa = PBXFileReference; lastKnownFileType = text; path = "python-swigsafecast.swig"; sourceTree = ""; }; 945215DD17F639E600521C0B /* ValueObjectPrinter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ValueObjectPrinter.h; path = include/lldb/DataFormatters/ValueObjectPrinter.h; sourceTree = ""; }; 945215DE17F639EE00521C0B /* ValueObjectPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectPrinter.cpp; path = source/DataFormatters/ValueObjectPrinter.cpp; sourceTree = ""; }; 9452573616262CD000325455 /* SBDeclaration.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBDeclaration.i; sourceTree = ""; }; 9452573816262CEF00325455 /* SBDeclaration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBDeclaration.h; path = include/lldb/API/SBDeclaration.h; sourceTree = ""; }; 9452573916262D0200325455 /* SBDeclaration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBDeclaration.cpp; path = source/API/SBDeclaration.cpp; sourceTree = ""; }; 945261B31B9A11E800BF138D /* CxxStringTypes.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CxxStringTypes.cpp; path = Language/CPlusPlus/CxxStringTypes.cpp; sourceTree = ""; }; 945261B41B9A11E800BF138D /* CxxStringTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CxxStringTypes.h; path = Language/CPlusPlus/CxxStringTypes.h; sourceTree = ""; }; 945261B51B9A11E800BF138D /* LibCxx.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxx.cpp; path = Language/CPlusPlus/LibCxx.cpp; sourceTree = ""; }; 945261B61B9A11E800BF138D /* LibCxx.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LibCxx.h; path = Language/CPlusPlus/LibCxx.h; sourceTree = ""; }; 945261B71B9A11E800BF138D /* LibCxxInitializerList.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxInitializerList.cpp; path = Language/CPlusPlus/LibCxxInitializerList.cpp; sourceTree = ""; }; 945261B81B9A11E800BF138D /* LibCxxList.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxList.cpp; path = Language/CPlusPlus/LibCxxList.cpp; sourceTree = ""; }; 945261B91B9A11E800BF138D /* LibCxxMap.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxMap.cpp; path = Language/CPlusPlus/LibCxxMap.cpp; sourceTree = ""; }; 945261BA1B9A11E800BF138D /* LibCxxUnorderedMap.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxUnorderedMap.cpp; path = Language/CPlusPlus/LibCxxUnorderedMap.cpp; sourceTree = ""; }; 945261BB1B9A11E800BF138D /* LibCxxVector.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxVector.cpp; path = Language/CPlusPlus/LibCxxVector.cpp; sourceTree = ""; }; 945261BC1B9A11E800BF138D /* LibStdcpp.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LibStdcpp.cpp; path = Language/CPlusPlus/LibStdcpp.cpp; sourceTree = ""; }; 945261BD1B9A11E800BF138D /* LibStdcpp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LibStdcpp.h; path = Language/CPlusPlus/LibStdcpp.h; sourceTree = ""; }; 945261C71B9A14D300BF138D /* CXXFunctionPointer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CXXFunctionPointer.cpp; path = source/DataFormatters/CXXFunctionPointer.cpp; sourceTree = ""; }; 945261C91B9A14E000BF138D /* CXXFunctionPointer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CXXFunctionPointer.h; path = include/lldb/DataFormatters/CXXFunctionPointer.h; sourceTree = ""; }; 9455630A1BEAD0570073F75F /* PlatformAppleSimulator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformAppleSimulator.cpp; sourceTree = ""; }; 9455630B1BEAD0570073F75F /* PlatformAppleSimulator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlatformAppleSimulator.h; sourceTree = ""; }; 9455630C1BEAD0570073F75F /* PlatformiOSSimulatorCoreSimulatorSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlatformiOSSimulatorCoreSimulatorSupport.h; sourceTree = ""; }; 9455630D1BEAD0570073F75F /* PlatformiOSSimulatorCoreSimulatorSupport.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformiOSSimulatorCoreSimulatorSupport.mm; sourceTree = ""; }; 945759651534941F005A9070 /* PlatformPOSIX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PlatformPOSIX.cpp; path = POSIX/PlatformPOSIX.cpp; sourceTree = ""; }; 945759661534941F005A9070 /* PlatformPOSIX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlatformPOSIX.h; path = POSIX/PlatformPOSIX.h; sourceTree = ""; }; 9461568614E355F2003A195C /* SBTypeFilter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBTypeFilter.h; path = include/lldb/API/SBTypeFilter.h; sourceTree = ""; }; 9461568714E355F2003A195C /* SBTypeFormat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBTypeFormat.h; path = include/lldb/API/SBTypeFormat.h; sourceTree = ""; }; 9461568814E355F2003A195C /* SBTypeSummary.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBTypeSummary.h; path = include/lldb/API/SBTypeSummary.h; sourceTree = ""; }; 9461568914E355F2003A195C /* SBTypeSynthetic.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBTypeSynthetic.h; path = include/lldb/API/SBTypeSynthetic.h; sourceTree = ""; }; 9461568A14E35621003A195C /* SBTypeFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBTypeFilter.cpp; path = source/API/SBTypeFilter.cpp; sourceTree = ""; }; 9461568B14E35621003A195C /* SBTypeFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBTypeFormat.cpp; path = source/API/SBTypeFormat.cpp; sourceTree = ""; }; 9461568C14E35621003A195C /* SBTypeSummary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBTypeSummary.cpp; path = source/API/SBTypeSummary.cpp; sourceTree = ""; }; 9461568D14E35621003A195C /* SBTypeSynthetic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBTypeSynthetic.cpp; path = source/API/SBTypeSynthetic.cpp; sourceTree = ""; }; 9461569214E3567F003A195C /* SBTypeFilter.i */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBTypeFilter.i; sourceTree = ""; }; 9461569314E3567F003A195C /* SBTypeFormat.i */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBTypeFormat.i; sourceTree = ""; }; 9461569414E3567F003A195C /* SBTypeSummary.i */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBTypeSummary.i; sourceTree = ""; }; 9461569514E3567F003A195C /* SBTypeSynthetic.i */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBTypeSynthetic.i; sourceTree = ""; }; 946216BF1A97C055006E19CC /* OptionValueLanguage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValueLanguage.h; path = include/lldb/Interpreter/OptionValueLanguage.h; sourceTree = ""; }; 946216C11A97C080006E19CC /* OptionValueLanguage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValueLanguage.cpp; path = source/Interpreter/OptionValueLanguage.cpp; sourceTree = ""; }; 9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = CommandObjectType.cpp; path = source/Commands/CommandObjectType.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 9463D4CE13B179A500C230D4 /* CommandObjectType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CommandObjectType.h; path = source/Commands/CommandObjectType.h; sourceTree = ""; }; 9475C18514E5E9C5001BFC6D /* SBTypeCategory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBTypeCategory.h; path = include/lldb/API/SBTypeCategory.h; sourceTree = ""; }; 9475C18714E5E9FA001BFC6D /* SBTypeCategory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBTypeCategory.cpp; path = source/API/SBTypeCategory.cpp; sourceTree = ""; }; 9475C18A14E5EA1C001BFC6D /* SBTypeCategory.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBTypeCategory.i; sourceTree = ""; }; 9475C18B14E5F818001BFC6D /* SBTypeNameSpecifier.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBTypeNameSpecifier.i; sourceTree = ""; }; 9475C18C14E5F826001BFC6D /* SBTypeNameSpecifier.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBTypeNameSpecifier.h; path = include/lldb/API/SBTypeNameSpecifier.h; sourceTree = ""; }; 9475C18D14E5F834001BFC6D /* SBTypeNameSpecifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBTypeNameSpecifier.cpp; path = source/API/SBTypeNameSpecifier.cpp; sourceTree = ""; }; 947A1D621616476A0017C8D1 /* CommandObjectPlugin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectPlugin.cpp; path = source/Commands/CommandObjectPlugin.cpp; sourceTree = ""; }; 947A1D631616476A0017C8D1 /* CommandObjectPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectPlugin.h; path = source/Commands/CommandObjectPlugin.h; sourceTree = ""; }; 947CF76F1DC7B1E300EF980B /* ProcessMinidump.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ProcessMinidump.h; sourceTree = ""; }; 947CF7701DC7B1EE00EF980B /* ProcessMinidump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessMinidump.cpp; sourceTree = ""; }; 947CF7721DC7B20300EF980B /* RegisterContextMinidump_x86_32.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RegisterContextMinidump_x86_32.h; sourceTree = ""; }; 947CF7731DC7B20300EF980B /* ThreadMinidump.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ThreadMinidump.h; sourceTree = ""; }; 947CF7741DC7B20D00EF980B /* RegisterContextMinidump_x86_32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextMinidump_x86_32.cpp; sourceTree = ""; }; 947CF7751DC7B20D00EF980B /* ThreadMinidump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadMinidump.cpp; sourceTree = ""; }; 9481FE6B1B5F2D9200DED357 /* Either.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Either.h; path = include/lldb/Utility/Either.h; sourceTree = ""; }; 948554581DCBAE3200345FF5 /* RenderScriptScriptGroup.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderScriptScriptGroup.h; sourceTree = ""; }; 948554591DCBAE3B00345FF5 /* RenderScriptScriptGroup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderScriptScriptGroup.cpp; sourceTree = ""; }; 949ADF001406F62E004833E1 /* ValueObjectConstResultImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ValueObjectConstResultImpl.h; path = include/lldb/Core/ValueObjectConstResultImpl.h; sourceTree = ""; }; 949ADF021406F648004833E1 /* ValueObjectConstResultImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectConstResultImpl.cpp; path = source/Core/ValueObjectConstResultImpl.cpp; sourceTree = ""; }; 949EED9E1BA74B64008C63CF /* CoreMedia.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CoreMedia.cpp; path = Language/ObjC/CoreMedia.cpp; sourceTree = ""; }; 949EED9F1BA74B64008C63CF /* CoreMedia.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CoreMedia.h; path = Language/ObjC/CoreMedia.h; sourceTree = ""; }; 949EEDA11BA76571008C63CF /* Cocoa.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Cocoa.cpp; path = Language/ObjC/Cocoa.cpp; sourceTree = ""; }; 949EEDA21BA76571008C63CF /* Cocoa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Cocoa.h; path = Language/ObjC/Cocoa.h; sourceTree = ""; }; 949EEDA41BA765B5008C63CF /* NSArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSArray.cpp; path = Language/ObjC/NSArray.cpp; sourceTree = ""; }; 949EEDA51BA765B5008C63CF /* NSDictionary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSDictionary.cpp; path = Language/ObjC/NSDictionary.cpp; sourceTree = ""; }; 949EEDA61BA765B5008C63CF /* NSIndexPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSIndexPath.cpp; path = Language/ObjC/NSIndexPath.cpp; sourceTree = ""; }; 949EEDA71BA765B5008C63CF /* NSSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSSet.cpp; path = Language/ObjC/NSSet.cpp; sourceTree = ""; }; 949EEDAC1BA76719008C63CF /* CF.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CF.cpp; path = Language/ObjC/CF.cpp; sourceTree = ""; }; 949EEDAD1BA76719008C63CF /* CF.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CF.h; path = Language/ObjC/CF.h; sourceTree = ""; }; 94A5B3951AB9FE8300A5EE7F /* EmulateInstructionMIPS64.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = EmulateInstructionMIPS64.cpp; path = MIPS64/EmulateInstructionMIPS64.cpp; sourceTree = ""; }; 94A5B3961AB9FE8300A5EE7F /* EmulateInstructionMIPS64.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = EmulateInstructionMIPS64.h; path = MIPS64/EmulateInstructionMIPS64.h; sourceTree = ""; }; 94B638511B8F8E53004FE1E4 /* Language.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Language.h; path = include/lldb/Target/Language.h; sourceTree = ""; }; 94B638521B8F8E6C004FE1E4 /* Language.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Language.cpp; path = source/Target/Language.cpp; sourceTree = ""; }; 94B6385B1B8FB174004FE1E4 /* CPlusPlusLanguage.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CPlusPlusLanguage.cpp; path = Language/CPlusPlus/CPlusPlusLanguage.cpp; sourceTree = ""; }; 94B6385C1B8FB174004FE1E4 /* CPlusPlusLanguage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CPlusPlusLanguage.h; path = Language/CPlusPlus/CPlusPlusLanguage.h; sourceTree = ""; }; 94B6385E1B8FB7A2004FE1E4 /* ObjCLanguage.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ObjCLanguage.cpp; path = Language/ObjC/ObjCLanguage.cpp; sourceTree = ""; }; 94B6385F1B8FB7A2004FE1E4 /* ObjCLanguage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ObjCLanguage.h; path = Language/ObjC/ObjCLanguage.h; sourceTree = ""; }; 94B638611B8FB7E9004FE1E4 /* ObjCPlusPlusLanguage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ObjCPlusPlusLanguage.h; path = Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h; sourceTree = ""; }; 94B638621B8FB7F1004FE1E4 /* ObjCPlusPlusLanguage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ObjCPlusPlusLanguage.cpp; path = Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp; sourceTree = ""; }; 94B6E76013D8833C005F417F /* ValueObjectSyntheticFilter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ValueObjectSyntheticFilter.h; path = include/lldb/Core/ValueObjectSyntheticFilter.h; sourceTree = ""; }; 94B6E76113D88362005F417F /* ValueObjectSyntheticFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectSyntheticFilter.cpp; path = source/Core/ValueObjectSyntheticFilter.cpp; sourceTree = ""; }; 94B9E50E1BBEFDFE000A48DC /* NSDictionary.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSDictionary.h; path = Language/ObjC/NSDictionary.h; sourceTree = ""; }; 94B9E50F1BBF0069000A48DC /* NSSet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSSet.h; path = Language/ObjC/NSSet.h; sourceTree = ""; }; 94B9E5101BBF20B7000A48DC /* NSString.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSString.h; path = Language/ObjC/NSString.h; sourceTree = ""; }; 94B9E5111BBF20F4000A48DC /* NSString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NSString.cpp; path = Language/ObjC/NSString.cpp; sourceTree = ""; }; 94BA8B6C176F8C9B005A91B5 /* Range.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Range.cpp; path = source/Utility/Range.cpp; sourceTree = ""; }; 94BA8B6E176F8CA0005A91B5 /* Range.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Range.h; path = include/lldb/Utility/Range.h; sourceTree = ""; }; 94BA8B6F176F97CE005A91B5 /* CommandHistory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandHistory.cpp; path = source/Interpreter/CommandHistory.cpp; sourceTree = ""; }; 94BA8B71176F97D4005A91B5 /* CommandHistory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CommandHistory.h; path = include/lldb/Interpreter/CommandHistory.h; sourceTree = ""; }; 94CB255816B069770059775D /* DataVisualization.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DataVisualization.cpp; path = source/DataFormatters/DataVisualization.cpp; sourceTree = ""; }; 94CB255916B069770059775D /* FormatClasses.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FormatClasses.cpp; path = source/DataFormatters/FormatClasses.cpp; sourceTree = ""; }; 94CB255A16B069770059775D /* FormatManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FormatManager.cpp; path = source/DataFormatters/FormatManager.cpp; sourceTree = ""; }; 94CB256016B069800059775D /* DataVisualization.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DataVisualization.h; path = include/lldb/DataFormatters/DataVisualization.h; sourceTree = ""; }; 94CB256116B069800059775D /* FormatClasses.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FormatClasses.h; path = include/lldb/DataFormatters/FormatClasses.h; sourceTree = ""; }; 94CB256216B069800059775D /* FormatManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FormatManager.h; path = include/lldb/DataFormatters/FormatManager.h; sourceTree = ""; }; 94CB256416B096F10059775D /* TypeCategory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeCategory.cpp; path = source/DataFormatters/TypeCategory.cpp; sourceTree = ""; }; 94CB256516B096F10059775D /* TypeCategoryMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeCategoryMap.cpp; path = source/DataFormatters/TypeCategoryMap.cpp; sourceTree = ""; }; 94CB256816B096F90059775D /* TypeCategory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TypeCategory.h; path = include/lldb/DataFormatters/TypeCategory.h; sourceTree = ""; }; 94CB256916B096FA0059775D /* TypeCategoryMap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TypeCategoryMap.h; path = include/lldb/DataFormatters/TypeCategoryMap.h; sourceTree = ""; }; 94CB256A16B0A4030059775D /* TypeFormat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TypeFormat.h; path = include/lldb/DataFormatters/TypeFormat.h; sourceTree = ""; }; 94CB256B16B0A4030059775D /* TypeSummary.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TypeSummary.h; path = include/lldb/DataFormatters/TypeSummary.h; sourceTree = ""; }; 94CB256C16B0A4040059775D /* TypeSynthetic.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TypeSynthetic.h; path = include/lldb/DataFormatters/TypeSynthetic.h; sourceTree = ""; }; 94CB256D16B0A4260059775D /* TypeFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeFormat.cpp; path = source/DataFormatters/TypeFormat.cpp; sourceTree = ""; }; 94CB256E16B0A4260059775D /* TypeSummary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeSummary.cpp; path = source/DataFormatters/TypeSummary.cpp; sourceTree = ""; }; 94CB256F16B0A4270059775D /* TypeSynthetic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeSynthetic.cpp; path = source/DataFormatters/TypeSynthetic.cpp; sourceTree = ""; }; 94CB257316B1D3870059775D /* FormatCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FormatCache.cpp; path = source/DataFormatters/FormatCache.cpp; sourceTree = ""; }; 94CB257516B1D3910059775D /* FormatCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FormatCache.h; path = include/lldb/DataFormatters/FormatCache.h; sourceTree = ""; }; 94CD131819BA33A100DB7BED /* TypeValidator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TypeValidator.h; path = include/lldb/DataFormatters/TypeValidator.h; sourceTree = ""; }; 94CD131919BA33B400DB7BED /* TypeValidator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeValidator.cpp; path = source/DataFormatters/TypeValidator.cpp; sourceTree = ""; }; 94CD7D0719A3FB8600908B7C /* AppleObjCClassDescriptorV2.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleObjCClassDescriptorV2.h; sourceTree = ""; }; 94CD7D0819A3FBA300908B7C /* AppleObjCClassDescriptorV2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppleObjCClassDescriptorV2.cpp; sourceTree = ""; }; 94CD7D0A19A3FBC300908B7C /* AppleObjCTypeEncodingParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppleObjCTypeEncodingParser.h; sourceTree = ""; }; 94CD7D0B19A3FBCE00908B7C /* AppleObjCTypeEncodingParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = AppleObjCTypeEncodingParser.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 94D0858A1B9675A0000D24BD /* FormattersHelpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FormattersHelpers.h; path = include/lldb/DataFormatters/FormattersHelpers.h; sourceTree = ""; }; 94D0858B1B9675B8000D24BD /* FormattersHelpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FormattersHelpers.cpp; path = source/DataFormatters/FormattersHelpers.cpp; sourceTree = ""; }; 94E367CC140C4EC4001C7A5A /* modify-python-lldb.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = "modify-python-lldb.py"; sourceTree = ""; }; 94E367CE140C4EEA001C7A5A /* python-typemaps.swig */ = {isa = PBXFileReference; lastKnownFileType = text; path = "python-typemaps.swig"; sourceTree = ""; }; 94ED54A119C8A822007BE2EA /* ThreadSafeDenseMap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ThreadSafeDenseMap.h; path = include/lldb/Core/ThreadSafeDenseMap.h; sourceTree = ""; }; 94EE33F218643C6900CD703B /* FormattersContainer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FormattersContainer.h; path = include/lldb/DataFormatters/FormattersContainer.h; sourceTree = ""; }; 94F48F231A01C679005C0EC6 /* StringPrinter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StringPrinter.h; path = include/lldb/DataFormatters/StringPrinter.h; sourceTree = ""; }; 94F48F241A01C687005C0EC6 /* StringPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringPrinter.cpp; path = source/DataFormatters/StringPrinter.cpp; sourceTree = ""; }; 94FA3DDD1405D4E500833217 /* ValueObjectConstResultChild.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ValueObjectConstResultChild.h; path = include/lldb/Core/ValueObjectConstResultChild.h; sourceTree = ""; }; 94FA3DDF1405D50300833217 /* ValueObjectConstResultChild.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectConstResultChild.cpp; path = source/Core/ValueObjectConstResultChild.cpp; sourceTree = ""; }; 94FE476613FC1DA8001F8475 /* finish-swig-Python-LLDB.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "finish-swig-Python-LLDB.sh"; sourceTree = ""; }; 961FABB81235DE1600F93A47 /* FuncUnwinders.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FuncUnwinders.cpp; path = source/Symbol/FuncUnwinders.cpp; sourceTree = ""; }; 961FABB91235DE1600F93A47 /* UnwindPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindPlan.cpp; path = source/Symbol/UnwindPlan.cpp; sourceTree = ""; }; 961FABBA1235DE1600F93A47 /* UnwindTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindTable.cpp; path = source/Symbol/UnwindTable.cpp; sourceTree = ""; }; 964463EB1A330C0500154ED8 /* CompactUnwindInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompactUnwindInfo.cpp; path = source/Symbol/CompactUnwindInfo.cpp; sourceTree = ""; }; 964463ED1A330C1B00154ED8 /* CompactUnwindInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompactUnwindInfo.h; path = include/lldb/Symbol/CompactUnwindInfo.h; sourceTree = ""; }; 966C6B7818E6A56A0093F5EC /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = ""; }; 9694FA6F1B32AA64005EBB16 /* ABISysV_mips.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ABISysV_mips.cpp; path = "SysV-mips/ABISysV_mips.cpp"; sourceTree = ""; }; 9694FA701B32AA64005EBB16 /* ABISysV_mips.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ABISysV_mips.h; path = "SysV-mips/ABISysV_mips.h"; sourceTree = ""; }; 9A0FDE951E8EF5010086B2F5 /* RegisterContext_mips.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContext_mips.h; path = Utility/RegisterContext_mips.h; sourceTree = ""; }; 9A0FDE961E8EF5010086B2F5 /* RegisterContext_s390x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContext_s390x.h; path = Utility/RegisterContext_s390x.h; sourceTree = ""; }; 9A0FDE971E8EF5010086B2F5 /* RegisterContextLinux_mips.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextLinux_mips.cpp; path = Utility/RegisterContextLinux_mips.cpp; sourceTree = ""; }; 9A0FDE981E8EF5010086B2F5 /* RegisterContextLinux_mips.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextLinux_mips.h; path = Utility/RegisterContextLinux_mips.h; sourceTree = ""; }; 9A0FDE991E8EF5010086B2F5 /* RegisterInfos_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterInfos_arm.h; path = Utility/RegisterInfos_arm.h; sourceTree = ""; }; 9A0FDE9A1E8EF5010086B2F5 /* RegisterInfos_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterInfos_arm64.h; path = Utility/RegisterInfos_arm64.h; sourceTree = ""; }; 9A0FDE9B1E8EF5010086B2F5 /* RegisterInfos_mips.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterInfos_mips.h; path = Utility/RegisterInfos_mips.h; sourceTree = ""; }; + 9A1542F41F0EE44000DEA1D8 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; + 9A1542F51F0EE44000DEA1D8 /* MockTildeExpressionResolver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MockTildeExpressionResolver.cpp; sourceTree = ""; }; + 9A1542F61F0EE44000DEA1D8 /* MockTildeExpressionResolver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockTildeExpressionResolver.h; sourceTree = ""; }; + 9A1542F71F0EE44000DEA1D8 /* TestUtilities.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TestUtilities.cpp; sourceTree = ""; }; + 9A1542F81F0EE44000DEA1D8 /* TestUtilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestUtilities.h; sourceTree = ""; }; 9A19A6A51163BB7E00E0D453 /* SBValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBValue.h; path = include/lldb/API/SBValue.h; sourceTree = ""; }; 9A19A6AD1163BB9800E0D453 /* SBValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBValue.cpp; path = source/API/SBValue.cpp; sourceTree = ""; }; 9A1E59521EB2B0B9002206A5 /* SBTrace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBTrace.cpp; path = source/API/SBTrace.cpp; sourceTree = ""; }; 9A1E59531EB2B0B9002206A5 /* SBTraceOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBTraceOptions.cpp; path = source/API/SBTraceOptions.cpp; sourceTree = ""; }; 9A1E59581EB2B10D002206A5 /* SBTrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBTrace.h; path = include/lldb/API/SBTrace.h; sourceTree = ""; }; 9A1E59591EB2B10D002206A5 /* SBTraceOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBTraceOptions.h; path = include/lldb/API/SBTraceOptions.h; sourceTree = ""; }; 9A22A15D135E30370024DDC3 /* EmulateInstructionARM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EmulateInstructionARM.cpp; sourceTree = ""; }; 9A22A15E135E30370024DDC3 /* EmulateInstructionARM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EmulateInstructionARM.h; sourceTree = ""; }; 9A22A15F135E30370024DDC3 /* EmulationStateARM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EmulationStateARM.cpp; sourceTree = ""; }; 9A22A160135E30370024DDC3 /* EmulationStateARM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EmulationStateARM.h; sourceTree = ""; }; 9A357582116CFDEE00E8ED2F /* SBValueList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBValueList.h; path = include/lldb/API/SBValueList.h; sourceTree = ""; }; 9A35758D116CFE0F00E8ED2F /* SBValueList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBValueList.cpp; path = source/API/SBValueList.cpp; sourceTree = ""; }; 9A35765E116E76A700E8ED2F /* StringList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringList.h; path = include/lldb/Utility/StringList.h; sourceTree = ""; }; 9A35765F116E76B900E8ED2F /* StringList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringList.cpp; path = source/Utility/StringList.cpp; sourceTree = ""; }; 9A357670116E7B5200E8ED2F /* SBStringList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBStringList.h; path = include/lldb/API/SBStringList.h; sourceTree = ""; }; 9A357672116E7B6400E8ED2F /* SBStringList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBStringList.cpp; path = source/API/SBStringList.cpp; sourceTree = ""; }; 9A3576A7116E9AB700E8ED2F /* SBHostOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBHostOS.h; path = include/lldb/API/SBHostOS.h; sourceTree = ""; }; 9A3576A9116E9AC700E8ED2F /* SBHostOS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBHostOS.cpp; path = source/API/SBHostOS.cpp; sourceTree = ""; }; 9A42976111861A9F00FE05CD /* CommandObjectBreakpointCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectBreakpointCommand.h; path = source/Commands/CommandObjectBreakpointCommand.h; sourceTree = ""; }; 9A42976211861AA600FE05CD /* CommandObjectBreakpointCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectBreakpointCommand.cpp; path = source/Commands/CommandObjectBreakpointCommand.cpp; sourceTree = ""; }; 9A4633DA11F65D8600955CE1 /* UserSettingsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UserSettingsController.h; path = include/lldb/Core/UserSettingsController.h; sourceTree = ""; }; 9A4633DC11F65D9A00955CE1 /* UserSettingsController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UserSettingsController.cpp; path = source/Core/UserSettingsController.cpp; sourceTree = ""; }; 9A48A3A7124AAA5A00922451 /* python-extensions.swig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "python-extensions.swig"; sourceTree = ""; }; 9A4F350F1368A51A00823F52 /* StreamAsynchronousIO.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StreamAsynchronousIO.cpp; path = source/Core/StreamAsynchronousIO.cpp; sourceTree = ""; }; 9A4F35111368A54100823F52 /* StreamAsynchronousIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StreamAsynchronousIO.h; path = include/lldb/Core/StreamAsynchronousIO.h; sourceTree = ""; }; 9A633FE7112DCE3C001A7E43 /* SBFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBFrame.cpp; path = source/API/SBFrame.cpp; sourceTree = ""; }; 9A633FE8112DCE3C001A7E43 /* SBFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBFrame.h; path = include/lldb/API/SBFrame.h; sourceTree = ""; }; 9A77AD501E64E24E0025CE04 /* RegisterInfoPOSIX_arm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterInfoPOSIX_arm.cpp; path = Utility/RegisterInfoPOSIX_arm.cpp; sourceTree = ""; }; 9A77AD511E64E24E0025CE04 /* RegisterInfoPOSIX_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterInfoPOSIX_arm.h; path = Utility/RegisterInfoPOSIX_arm.h; sourceTree = ""; }; 9A82010B10FFB49800182560 /* ScriptInterpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ScriptInterpreter.cpp; path = source/Interpreter/ScriptInterpreter.cpp; sourceTree = ""; }; 9A9830F21125FC5800A56CB0 /* SBBroadcaster.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBBroadcaster.cpp; path = source/API/SBBroadcaster.cpp; sourceTree = ""; }; 9A9830F31125FC5800A56CB0 /* SBBroadcaster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBBroadcaster.h; path = include/lldb/API/SBBroadcaster.h; sourceTree = ""; }; 9A9830F61125FC5800A56CB0 /* SBCommandInterpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBCommandInterpreter.cpp; path = source/API/SBCommandInterpreter.cpp; sourceTree = ""; }; 9A9830F71125FC5800A56CB0 /* SBCommandInterpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBCommandInterpreter.h; path = include/lldb/API/SBCommandInterpreter.h; sourceTree = ""; }; 9A9830F81125FC5800A56CB0 /* SBCommandReturnObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBCommandReturnObject.cpp; path = source/API/SBCommandReturnObject.cpp; sourceTree = ""; }; 9A9830F91125FC5800A56CB0 /* SBCommandReturnObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBCommandReturnObject.h; path = include/lldb/API/SBCommandReturnObject.h; sourceTree = ""; }; 9A9830FA1125FC5800A56CB0 /* SBDebugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBDebugger.cpp; path = source/API/SBDebugger.cpp; sourceTree = ""; }; 9A9830FB1125FC5800A56CB0 /* SBDebugger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBDebugger.h; path = include/lldb/API/SBDebugger.h; sourceTree = ""; }; 9A9830FC1125FC5800A56CB0 /* SBDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBDefines.h; path = include/lldb/API/SBDefines.h; sourceTree = ""; }; 9A9830FD1125FC5800A56CB0 /* SBEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBEvent.cpp; path = source/API/SBEvent.cpp; sourceTree = ""; }; 9A9830FE1125FC5800A56CB0 /* SBEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBEvent.h; path = include/lldb/API/SBEvent.h; sourceTree = ""; }; 9A9831011125FC5800A56CB0 /* SBListener.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBListener.cpp; path = source/API/SBListener.cpp; sourceTree = ""; }; 9A9831021125FC5800A56CB0 /* SBListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBListener.h; path = include/lldb/API/SBListener.h; sourceTree = ""; }; 9A9831031125FC5800A56CB0 /* SBProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBProcess.cpp; path = source/API/SBProcess.cpp; sourceTree = ""; }; 9A9831041125FC5800A56CB0 /* SBProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBProcess.h; path = include/lldb/API/SBProcess.h; sourceTree = ""; }; 9A9831051125FC5800A56CB0 /* SBSourceManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBSourceManager.cpp; path = source/API/SBSourceManager.cpp; sourceTree = ""; }; 9A9831061125FC5800A56CB0 /* SBSourceManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBSourceManager.h; path = include/lldb/API/SBSourceManager.h; sourceTree = ""; }; 9A9831071125FC5800A56CB0 /* SBTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = SBTarget.cpp; path = source/API/SBTarget.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 9A9831081125FC5800A56CB0 /* SBTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBTarget.h; path = include/lldb/API/SBTarget.h; sourceTree = ""; }; 9A9831091125FC5800A56CB0 /* SBThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBThread.cpp; path = source/API/SBThread.cpp; sourceTree = ""; }; 9A98310A1125FC5800A56CB0 /* SBThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBThread.h; path = include/lldb/API/SBThread.h; sourceTree = ""; }; 9AC7033D11752C4C0086C050 /* AddressResolverFileLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AddressResolverFileLine.h; path = include/lldb/Core/AddressResolverFileLine.h; sourceTree = ""; }; 9AC7033E11752C540086C050 /* AddressResolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AddressResolver.h; path = include/lldb/Core/AddressResolver.h; sourceTree = ""; }; 9AC7033F11752C590086C050 /* AddressResolverName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AddressResolverName.h; path = include/lldb/Core/AddressResolverName.h; sourceTree = ""; }; 9AC7034011752C6B0086C050 /* AddressResolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AddressResolver.cpp; path = source/Core/AddressResolver.cpp; sourceTree = ""; }; 9AC7034211752C720086C050 /* AddressResolverFileLine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AddressResolverFileLine.cpp; path = source/Core/AddressResolverFileLine.cpp; sourceTree = ""; }; 9AC7034411752C790086C050 /* AddressResolverName.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AddressResolverName.cpp; path = source/Core/AddressResolverName.cpp; sourceTree = ""; }; 9AC7038D117674EB0086C050 /* SBInstruction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBInstruction.h; path = include/lldb/API/SBInstruction.h; sourceTree = ""; }; 9AC7038F117675270086C050 /* SBInstructionList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBInstructionList.h; path = include/lldb/API/SBInstructionList.h; sourceTree = ""; }; 9AC703AE117675410086C050 /* SBInstruction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBInstruction.cpp; path = source/API/SBInstruction.cpp; sourceTree = ""; }; 9AC703B0117675490086C050 /* SBInstructionList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBInstructionList.cpp; path = source/API/SBInstructionList.cpp; sourceTree = ""; }; 9AD9449B1E8DB267004796ED /* RegisterContextNetBSD_x86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextNetBSD_x86_64.cpp; path = Utility/RegisterContextNetBSD_x86_64.cpp; sourceTree = ""; }; 9AD9449C1E8DB267004796ED /* RegisterContextNetBSD_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextNetBSD_x86_64.h; path = Utility/RegisterContextNetBSD_x86_64.h; sourceTree = ""; }; 9AF16A9C11402D5B007A7B3F /* SBBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBBreakpoint.cpp; path = source/API/SBBreakpoint.cpp; sourceTree = ""; }; 9AF16A9E11402D69007A7B3F /* SBBreakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBBreakpoint.h; path = include/lldb/API/SBBreakpoint.h; sourceTree = ""; }; 9AF16CC611408686007A7B3F /* SBBreakpointLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBBreakpointLocation.h; path = include/lldb/API/SBBreakpointLocation.h; sourceTree = ""; }; 9AF16CC7114086A1007A7B3F /* SBBreakpointLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBBreakpointLocation.cpp; path = source/API/SBBreakpointLocation.cpp; sourceTree = ""; }; A36FF33B17D8E94600244D40 /* OptionParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OptionParser.cpp; sourceTree = ""; }; A36FF33D17D8E98800244D40 /* OptionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionParser.h; path = include/lldb/Host/OptionParser.h; sourceTree = ""; }; AE44FB261BB07DC60033EB62 /* GoAST.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GoAST.h; path = ExpressionParser/Go/GoAST.h; sourceTree = ""; }; AE44FB271BB07DC60033EB62 /* GoLexer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GoLexer.h; path = ExpressionParser/Go/GoLexer.h; sourceTree = ""; }; AE44FB281BB07DC60033EB62 /* GoParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GoParser.h; path = ExpressionParser/Go/GoParser.h; sourceTree = ""; }; AE44FB291BB07DC60033EB62 /* GoUserExpression.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GoUserExpression.h; path = ExpressionParser/Go/GoUserExpression.h; sourceTree = ""; }; AE44FB2A1BB07DD80033EB62 /* GoLexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoLexer.cpp; path = ExpressionParser/Go/GoLexer.cpp; sourceTree = ""; }; AE44FB2B1BB07DD80033EB62 /* GoParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoParser.cpp; path = ExpressionParser/Go/GoParser.cpp; sourceTree = ""; }; AE44FB2C1BB07DD80033EB62 /* GoUserExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoUserExpression.cpp; path = ExpressionParser/Go/GoUserExpression.cpp; sourceTree = ""; }; AE44FB3C1BB4858A0033EB62 /* GoLanguageRuntime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GoLanguageRuntime.h; path = Go/GoLanguageRuntime.h; sourceTree = ""; }; AE44FB3D1BB485960033EB62 /* GoLanguageRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoLanguageRuntime.cpp; path = Go/GoLanguageRuntime.cpp; sourceTree = ""; }; AE44FB451BB4BB090033EB62 /* GoLanguage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoLanguage.cpp; path = Language/Go/GoLanguage.cpp; sourceTree = ""; }; AE44FB461BB4BB090033EB62 /* GoLanguage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GoLanguage.h; path = Language/Go/GoLanguage.h; sourceTree = ""; }; AE44FB4A1BB4BB540033EB62 /* GoFormatterFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoFormatterFunctions.cpp; path = Language/Go/GoFormatterFunctions.cpp; sourceTree = ""; }; AE44FB4B1BB4BB540033EB62 /* GoFormatterFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GoFormatterFunctions.h; path = Language/Go/GoFormatterFunctions.h; sourceTree = ""; }; AE6897261B94F6DE0018845D /* DWARFASTParserGo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFASTParserGo.cpp; sourceTree = ""; }; AE6897271B94F6DE0018845D /* DWARFASTParserGo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFASTParserGo.h; sourceTree = ""; }; AE8F624719EF3E1E00326B21 /* OperatingSystemGo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OperatingSystemGo.cpp; path = Go/OperatingSystemGo.cpp; sourceTree = ""; }; AE8F624819EF3E1E00326B21 /* OperatingSystemGo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OperatingSystemGo.h; path = Go/OperatingSystemGo.h; sourceTree = ""; }; AEB0E4581BD6E9F800B24093 /* LLVMUserExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLVMUserExpression.cpp; path = source/Expression/LLVMUserExpression.cpp; sourceTree = ""; }; AEB0E45A1BD6EA1400B24093 /* LLVMUserExpression.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LLVMUserExpression.h; path = include/lldb/Expression/LLVMUserExpression.h; sourceTree = ""; }; AEC6FF9F1BE970A2007882C1 /* GoParserTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GoParserTest.cpp; sourceTree = ""; }; AEEA33F61AC74FE700AB639D /* TypeSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypeSystem.h; path = include/lldb/Symbol/TypeSystem.h; sourceTree = ""; }; AEEA34041AC88A7400AB639D /* TypeSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeSystem.cpp; path = source/Symbol/TypeSystem.cpp; sourceTree = ""; }; AEEA340F1ACA08A000AB639D /* GoASTContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GoASTContext.h; path = include/lldb/Symbol/GoASTContext.h; sourceTree = ""; }; AEFFBA7C1AC4835D0087B932 /* GoASTContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoASTContext.cpp; path = source/Symbol/GoASTContext.cpp; sourceTree = ""; }; AF061F85182C97ED00B6A19C /* RegisterContextHistory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextHistory.cpp; path = Utility/RegisterContextHistory.cpp; sourceTree = ""; }; AF061F86182C97ED00B6A19C /* RegisterContextHistory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextHistory.h; path = Utility/RegisterContextHistory.h; sourceTree = ""; }; AF061F89182C980000B6A19C /* HistoryThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HistoryThread.h; path = Utility/HistoryThread.h; sourceTree = ""; }; AF061F8A182C980000B6A19C /* HistoryUnwind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HistoryUnwind.h; path = Utility/HistoryUnwind.h; sourceTree = ""; }; AF0C112718580CD800C4C45B /* QueueItem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = QueueItem.cpp; path = source/Target/QueueItem.cpp; sourceTree = ""; }; AF0E22EE18A09FB20009B7D1 /* AppleGetItemInfoHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppleGetItemInfoHandler.cpp; sourceTree = ""; }; AF0E22EF18A09FB20009B7D1 /* AppleGetItemInfoHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppleGetItemInfoHandler.h; sourceTree = ""; }; AF0EBBE6185940FB0059E52F /* SBQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBQueue.cpp; path = source/API/SBQueue.cpp; sourceTree = ""; }; AF0EBBE7185940FB0059E52F /* SBQueueItem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBQueueItem.cpp; path = source/API/SBQueueItem.cpp; sourceTree = ""; }; AF0EBBEA185941360059E52F /* SBQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBQueue.h; path = include/lldb/API/SBQueue.h; sourceTree = ""; }; AF0EBBEB185941360059E52F /* SBQueueItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBQueueItem.h; path = include/lldb/API/SBQueueItem.h; sourceTree = ""; }; AF0EBBEE1859419F0059E52F /* SBQueue.i */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBQueue.i; sourceTree = ""; }; AF0EBBEF1859419F0059E52F /* SBQueueItem.i */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBQueueItem.i; sourceTree = ""; }; AF0F6E4E1739A76D009180FE /* RegisterContextKDP_arm64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextKDP_arm64.cpp; sourceTree = ""; }; AF0F6E4F1739A76D009180FE /* RegisterContextKDP_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextKDP_arm64.h; sourceTree = ""; }; AF1729D4182C907200E0AB97 /* HistoryThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HistoryThread.cpp; path = Utility/HistoryThread.cpp; sourceTree = ""; }; AF1729D5182C907200E0AB97 /* HistoryUnwind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HistoryUnwind.cpp; path = Utility/HistoryUnwind.cpp; sourceTree = ""; }; AF1F7B05189C904B0087DB9C /* AppleGetPendingItemsHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppleGetPendingItemsHandler.cpp; sourceTree = ""; }; AF1F7B06189C904B0087DB9C /* AppleGetPendingItemsHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppleGetPendingItemsHandler.h; sourceTree = ""; }; AF20F7641AF18F8500751A6E /* ABISysV_arm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ABISysV_arm.cpp; path = "SysV-arm/ABISysV_arm.cpp"; sourceTree = ""; }; AF20F7651AF18F8500751A6E /* ABISysV_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ABISysV_arm.h; path = "SysV-arm/ABISysV_arm.h"; sourceTree = ""; }; AF20F7681AF18F9000751A6E /* ABISysV_arm64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ABISysV_arm64.cpp; path = "SysV-arm64/ABISysV_arm64.cpp"; sourceTree = ""; }; AF20F7691AF18F9000751A6E /* ABISysV_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ABISysV_arm64.h; path = "SysV-arm64/ABISysV_arm64.h"; sourceTree = ""; }; AF20F76C1AF18FC700751A6E /* SBLanguageRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBLanguageRuntime.cpp; path = source/API/SBLanguageRuntime.cpp; sourceTree = ""; }; AF23B4D919009C66003E2A58 /* FreeBSDSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FreeBSDSignals.cpp; path = Utility/FreeBSDSignals.cpp; sourceTree = ""; }; AF23B4DA19009C66003E2A58 /* FreeBSDSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FreeBSDSignals.h; path = Utility/FreeBSDSignals.h; sourceTree = ""; }; AF248A4C1DA71C77000B814D /* TestArm64InstEmulation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TestArm64InstEmulation.cpp; path = UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp; sourceTree = ""; }; AF254E2F170CCC33007AE5C9 /* PlatformDarwinKernel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformDarwinKernel.cpp; sourceTree = ""; }; AF254E30170CCC33007AE5C9 /* PlatformDarwinKernel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformDarwinKernel.h; sourceTree = ""; }; AF25AB24188F685C0030DEC3 /* AppleGetQueuesHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppleGetQueuesHandler.cpp; sourceTree = ""; }; AF25AB25188F685C0030DEC3 /* AppleGetQueuesHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppleGetQueuesHandler.h; sourceTree = ""; }; AF2670381852D01E00B6CC36 /* Queue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Queue.cpp; path = source/Target/Queue.cpp; sourceTree = ""; }; AF2670391852D01E00B6CC36 /* QueueList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = QueueList.cpp; path = source/Target/QueueList.cpp; sourceTree = ""; }; AF27AD531D3603EA00CF2833 /* DynamicLoaderDarwin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLoaderDarwin.cpp; sourceTree = ""; }; AF27AD541D3603EA00CF2833 /* DynamicLoaderDarwin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderDarwin.h; sourceTree = ""; }; AF2907BD1D3F082400E10654 /* DynamicLoaderMacOS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLoaderMacOS.cpp; sourceTree = ""; }; AF2907BE1D3F082400E10654 /* DynamicLoaderMacOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderMacOS.h; sourceTree = ""; }; AF2BCA6918C7EFDE005B4526 /* JITLoaderGDB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITLoaderGDB.cpp; sourceTree = ""; }; AF2BCA6A18C7EFDE005B4526 /* JITLoaderGDB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITLoaderGDB.h; sourceTree = ""; }; AF33B4BC1C1FA441001B28D9 /* NetBSDSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetBSDSignals.cpp; path = Utility/NetBSDSignals.cpp; sourceTree = ""; }; AF33B4BD1C1FA441001B28D9 /* NetBSDSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetBSDSignals.h; path = Utility/NetBSDSignals.h; sourceTree = ""; }; AF37E10917C861F20061E18E /* ProcessRunLock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessRunLock.cpp; sourceTree = ""; }; AF3A4AD01EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformRemoteDarwinDevice.cpp; sourceTree = ""; }; AF3A4AD11EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformRemoteDarwinDevice.h; sourceTree = ""; }; AF3F54AE1B3BA59C00186E73 /* CrashReason.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CrashReason.cpp; sourceTree = ""; }; AF3F54AF1B3BA59C00186E73 /* CrashReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CrashReason.h; sourceTree = ""; }; AF3F54B21B3BA5D500186E73 /* POSIXStopInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = POSIXStopInfo.cpp; sourceTree = ""; }; AF3F54B31B3BA5D500186E73 /* POSIXStopInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = POSIXStopInfo.h; sourceTree = ""; }; AF3F54B81B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_arm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextPOSIXProcessMonitor_arm.cpp; sourceTree = ""; }; AF3F54B91B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextPOSIXProcessMonitor_arm.h; sourceTree = ""; }; AF3F54BA1B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_arm64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextPOSIXProcessMonitor_arm64.cpp; sourceTree = ""; }; AF3F54BB1B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextPOSIXProcessMonitor_arm64.h; sourceTree = ""; }; AF3F54BC1B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_mips64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextPOSIXProcessMonitor_mips64.cpp; sourceTree = ""; }; AF3F54BD1B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_mips64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextPOSIXProcessMonitor_mips64.h; sourceTree = ""; }; AF3F54BE1B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_powerpc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextPOSIXProcessMonitor_powerpc.cpp; sourceTree = ""; }; AF3F54BF1B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_powerpc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextPOSIXProcessMonitor_powerpc.h; sourceTree = ""; }; AF3F54C01B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_x86.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextPOSIXProcessMonitor_x86.cpp; sourceTree = ""; }; AF3F54C11B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_x86.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextPOSIXProcessMonitor_x86.h; sourceTree = ""; }; AF415AE51D949E4400FCE0D4 /* x86AssemblyInspectionEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = x86AssemblyInspectionEngine.cpp; sourceTree = ""; }; AF415AE61D949E4400FCE0D4 /* x86AssemblyInspectionEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x86AssemblyInspectionEngine.h; sourceTree = ""; }; AF45E1FC1BF57C8D000563EB /* PythonTestSuite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PythonTestSuite.cpp; sourceTree = ""; }; AF45E1FD1BF57C8D000563EB /* PythonTestSuite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PythonTestSuite.h; sourceTree = ""; }; AF45FDE318A1F3AC0007051C /* AppleGetThreadItemInfoHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppleGetThreadItemInfoHandler.cpp; sourceTree = ""; }; AF45FDE418A1F3AC0007051C /* AppleGetThreadItemInfoHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppleGetThreadItemInfoHandler.h; sourceTree = ""; }; AF6335E01C87B21E00F7D554 /* SymbolFilePDB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SymbolFilePDB.cpp; path = PDB/SymbolFilePDB.cpp; sourceTree = ""; }; AF6335E11C87B21E00F7D554 /* SymbolFilePDB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SymbolFilePDB.h; path = PDB/SymbolFilePDB.h; sourceTree = ""; }; AF68D2541255416E002FF25B /* RegisterContextLLDB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextLLDB.cpp; path = Utility/RegisterContextLLDB.cpp; sourceTree = ""; }; AF68D2551255416E002FF25B /* RegisterContextLLDB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextLLDB.h; path = Utility/RegisterContextLLDB.h; sourceTree = ""; }; AF68D32F1255A110002FF25B /* UnwindLLDB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindLLDB.cpp; path = Utility/UnwindLLDB.cpp; sourceTree = ""; }; AF68D3301255A110002FF25B /* UnwindLLDB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UnwindLLDB.h; path = Utility/UnwindLLDB.h; sourceTree = ""; }; AF77E08D1A033C700096C0EA /* ABISysV_ppc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ABISysV_ppc.cpp; path = "SysV-ppc/ABISysV_ppc.cpp"; sourceTree = ""; }; AF77E08E1A033C700096C0EA /* ABISysV_ppc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ABISysV_ppc.h; path = "SysV-ppc/ABISysV_ppc.h"; sourceTree = ""; }; AF77E0911A033C7F0096C0EA /* ABISysV_ppc64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ABISysV_ppc64.cpp; path = "SysV-ppc64/ABISysV_ppc64.cpp"; sourceTree = ""; }; AF77E0921A033C7F0096C0EA /* ABISysV_ppc64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ABISysV_ppc64.h; path = "SysV-ppc64/ABISysV_ppc64.h"; sourceTree = ""; }; AF77E0991A033D360096C0EA /* RegisterContext_powerpc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContext_powerpc.h; path = Utility/RegisterContext_powerpc.h; sourceTree = ""; }; AF77E09A1A033D360096C0EA /* RegisterContextFreeBSD_powerpc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextFreeBSD_powerpc.cpp; path = Utility/RegisterContextFreeBSD_powerpc.cpp; sourceTree = ""; }; AF77E09B1A033D360096C0EA /* RegisterContextFreeBSD_powerpc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextFreeBSD_powerpc.h; path = Utility/RegisterContextFreeBSD_powerpc.h; sourceTree = ""; }; AF77E09C1A033D360096C0EA /* RegisterContextMacOSXFrameBackchain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextMacOSXFrameBackchain.cpp; path = Utility/RegisterContextMacOSXFrameBackchain.cpp; sourceTree = ""; }; AF77E09D1A033D360096C0EA /* RegisterContextPOSIX_powerpc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextPOSIX_powerpc.cpp; path = Utility/RegisterContextPOSIX_powerpc.cpp; sourceTree = ""; }; AF77E09E1A033D360096C0EA /* RegisterContextPOSIX_powerpc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextPOSIX_powerpc.h; path = Utility/RegisterContextPOSIX_powerpc.h; sourceTree = ""; }; AF77E09F1A033D360096C0EA /* RegisterInfos_powerpc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterInfos_powerpc.h; path = Utility/RegisterInfos_powerpc.h; sourceTree = ""; }; AF77E0A71A033D740096C0EA /* RegisterContextPOSIXCore_powerpc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextPOSIXCore_powerpc.cpp; sourceTree = ""; }; AF77E0A81A033D740096C0EA /* RegisterContextPOSIXCore_powerpc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextPOSIXCore_powerpc.h; sourceTree = ""; }; AF81DEF91828A23F0042CF19 /* SystemRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SystemRuntime.cpp; path = source/Target/SystemRuntime.cpp; sourceTree = ""; }; AF8AD62A1BEC28A400150209 /* PlatformAppleTVSimulator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformAppleTVSimulator.cpp; sourceTree = ""; }; AF8AD62B1BEC28A400150209 /* PlatformAppleTVSimulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformAppleTVSimulator.h; sourceTree = ""; }; AF8AD62C1BEC28A400150209 /* PlatformAppleWatchSimulator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformAppleWatchSimulator.cpp; sourceTree = ""; }; AF8AD62D1BEC28A400150209 /* PlatformAppleWatchSimulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformAppleWatchSimulator.h; sourceTree = ""; }; AF8AD6331BEC28C400150209 /* PlatformRemoteAppleTV.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformRemoteAppleTV.cpp; sourceTree = ""; }; AF8AD6341BEC28C400150209 /* PlatformRemoteAppleTV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformRemoteAppleTV.h; sourceTree = ""; }; AF8AD6351BEC28C400150209 /* PlatformRemoteAppleWatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformRemoteAppleWatch.cpp; sourceTree = ""; }; AF8AD6361BEC28C400150209 /* PlatformRemoteAppleWatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformRemoteAppleWatch.h; sourceTree = ""; }; AF90106315AB7C5700FF120D /* lldb.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = lldb.1; path = docs/lldb.1; sourceTree = ""; }; AF9107EC168570D200DBCD3C /* RegisterContextDarwin_arm64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextDarwin_arm64.cpp; path = Utility/RegisterContextDarwin_arm64.cpp; sourceTree = ""; }; AF9107ED168570D200DBCD3C /* RegisterContextDarwin_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextDarwin_arm64.h; path = Utility/RegisterContextDarwin_arm64.h; sourceTree = ""; }; AF94005711C03F6500085DB9 /* SymbolVendor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SymbolVendor.cpp; path = source/Symbol/SymbolVendor.cpp; sourceTree = ""; }; AF94726E1B575E430063D65C /* ValueObjectConstResultCast.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectConstResultCast.cpp; path = source/Core/ValueObjectConstResultCast.cpp; sourceTree = ""; }; AF9472701B575E5F0063D65C /* ValueObjectConstResultCast.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ValueObjectConstResultCast.h; path = include/lldb/Core/ValueObjectConstResultCast.h; sourceTree = ""; }; AF9B8F31182DB52900DA866F /* SystemRuntimeMacOSX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SystemRuntimeMacOSX.cpp; sourceTree = ""; }; AF9B8F32182DB52900DA866F /* SystemRuntimeMacOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SystemRuntimeMacOSX.h; sourceTree = ""; }; AFAFD8091E57E1B90017A14F /* ModuleCacheTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ModuleCacheTest.cpp; path = Target/ModuleCacheTest.cpp; sourceTree = ""; }; AFB3D27E1AC262AB003B4B30 /* MICmdCmdGdbShow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MICmdCmdGdbShow.cpp; path = "tools/lldb-mi/MICmdCmdGdbShow.cpp"; sourceTree = SOURCE_ROOT; }; AFB3D27F1AC262AB003B4B30 /* MICmdCmdGdbShow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MICmdCmdGdbShow.h; path = "tools/lldb-mi/MICmdCmdGdbShow.h"; sourceTree = SOURCE_ROOT; }; AFC234061AF85CE000CDE8B6 /* CommandObjectLanguage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectLanguage.cpp; path = source/Commands/CommandObjectLanguage.cpp; sourceTree = ""; }; AFC234071AF85CE000CDE8B6 /* CommandObjectLanguage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectLanguage.h; path = source/Commands/CommandObjectLanguage.h; sourceTree = ""; }; AFC2DCE61E6E2ED000283714 /* FastDemangle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FastDemangle.cpp; path = source/Utility/FastDemangle.cpp; sourceTree = ""; }; AFC2DCE81E6E2F2C00283714 /* Baton.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Baton.cpp; path = source/Utility/Baton.cpp; sourceTree = ""; }; AFC2DCEA1E6E2F7D00283714 /* UserID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UserID.cpp; path = source/Utility/UserID.cpp; sourceTree = ""; }; AFC2DCEC1E6E2F8C00283714 /* UserID.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = UserID.h; path = include/lldb/Utility/UserID.h; sourceTree = ""; }; AFC2DCED1E6E2F9800283714 /* FastDemangle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FastDemangle.h; path = include/lldb/Utility/FastDemangle.h; sourceTree = ""; }; AFC2DCEE1E6E2FA300283714 /* Baton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Baton.h; path = include/lldb/Utility/Baton.h; sourceTree = ""; }; AFC2DCEF1E6E2FD200283714 /* VMRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VMRange.cpp; path = source/Utility/VMRange.cpp; sourceTree = ""; }; AFC2DCF11E6E2FDA00283714 /* VMRange.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = VMRange.h; path = include/lldb/Utility/VMRange.h; sourceTree = ""; }; AFC2DCF21E6E30CF00283714 /* History.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = History.cpp; path = source/Utility/History.cpp; sourceTree = ""; }; AFC2DCF41E6E30D800283714 /* History.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = History.h; path = include/lldb/Utility/History.h; sourceTree = ""; }; AFC2DCF51E6E316A00283714 /* StreamCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StreamCallback.cpp; path = source/Utility/StreamCallback.cpp; sourceTree = ""; }; AFC2DCF71E6E316F00283714 /* StreamCallback.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StreamCallback.h; path = include/lldb/Utility/StreamCallback.h; sourceTree = ""; }; AFC2DCF81E6E318000283714 /* StreamGDBRemote.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StreamGDBRemote.cpp; path = source/Utility/StreamGDBRemote.cpp; sourceTree = ""; }; AFC2DCFA1E6E318600283714 /* StreamGDBRemote.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StreamGDBRemote.h; path = include/lldb/Utility/StreamGDBRemote.h; sourceTree = ""; }; AFCB2BBB1BF577F40018B553 /* PythonExceptionState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PythonExceptionState.cpp; path = ScriptInterpreter/Python/PythonExceptionState.cpp; sourceTree = ""; }; AFCB2BBC1BF577F40018B553 /* PythonExceptionState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PythonExceptionState.h; path = ScriptInterpreter/Python/PythonExceptionState.h; sourceTree = ""; }; AFD65C7F1D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextMinidump_x86_64.cpp; sourceTree = ""; }; AFD65C801D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextMinidump_x86_64.h; sourceTree = ""; }; AFDFDFD019E34D3400EAE509 /* ConnectionFileDescriptorPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConnectionFileDescriptorPosix.cpp; sourceTree = ""; }; AFEC3361194A8ABA00FF05C6 /* StructuredData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StructuredData.cpp; path = source/Utility/StructuredData.cpp; sourceTree = ""; }; AFEC5FD51D94F9380076A480 /* Testx86AssemblyInspectionEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Testx86AssemblyInspectionEngine.cpp; path = UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp; sourceTree = ""; }; AFF87C86150FF669000E1742 /* com.apple.debugserver.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.debugserver.plist; path = tools/debugserver/source/com.apple.debugserver.plist; sourceTree = ""; }; AFF87C8A150FF677000E1742 /* com.apple.debugserver.applist.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.debugserver.applist.plist; path = tools/debugserver/source/com.apple.debugserver.applist.plist; sourceTree = ""; }; AFF87C8C150FF680000E1742 /* com.apple.debugserver.applist.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.debugserver.applist.plist; path = tools/debugserver/source/com.apple.debugserver.applist.plist; sourceTree = ""; }; AFF87C8E150FF688000E1742 /* com.apple.debugserver.applist.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.debugserver.applist.plist; path = tools/debugserver/source/com.apple.debugserver.applist.plist; sourceTree = ""; }; AFF8FF0B1E779D4B003830EF /* TildeExpressionResolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TildeExpressionResolver.cpp; path = source/Utility/TildeExpressionResolver.cpp; sourceTree = ""; }; AFF8FF0D1E779D51003830EF /* TildeExpressionResolver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TildeExpressionResolver.h; path = include/lldb/Utility/TildeExpressionResolver.h; sourceTree = ""; }; B207C4921429607D00F36E4E /* CommandObjectWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectWatchpoint.cpp; path = source/Commands/CommandObjectWatchpoint.cpp; sourceTree = ""; }; B207C4941429609C00F36E4E /* CommandObjectWatchpoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CommandObjectWatchpoint.h; path = source/Commands/CommandObjectWatchpoint.h; sourceTree = ""; }; B23DD24F12EDFAC1000C3894 /* ARMUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ARMUtils.h; path = Utility/ARMUtils.h; sourceTree = ""; }; B2462246141AD37D00F3D409 /* OptionGroupWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupWatchpoint.cpp; path = source/Interpreter/OptionGroupWatchpoint.cpp; sourceTree = ""; }; B2462248141AD39B00F3D409 /* OptionGroupWatchpoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupWatchpoint.h; path = include/lldb/Interpreter/OptionGroupWatchpoint.h; sourceTree = ""; }; B27318411416AC12006039C8 /* WatchpointList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WatchpointList.cpp; path = source/Breakpoint/WatchpointList.cpp; sourceTree = ""; }; B27318431416AC43006039C8 /* WatchpointList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WatchpointList.h; path = include/lldb/Breakpoint/WatchpointList.h; sourceTree = ""; }; B28058A0139988B0002D96D0 /* InferiorCallPOSIX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InferiorCallPOSIX.cpp; path = Utility/InferiorCallPOSIX.cpp; sourceTree = ""; }; B28058A2139988C6002D96D0 /* InferiorCallPOSIX.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = InferiorCallPOSIX.h; path = Utility/InferiorCallPOSIX.h; sourceTree = ""; }; B287E63E12EFAE2C00C9BEFE /* ARMDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ARMDefines.h; path = Utility/ARMDefines.h; sourceTree = ""; }; B296983412C2FB2B002D92C3 /* CommandObjectVersion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectVersion.cpp; path = source/Commands/CommandObjectVersion.cpp; sourceTree = ""; }; B296983512C2FB2B002D92C3 /* CommandObjectVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectVersion.h; path = source/Commands/CommandObjectVersion.h; sourceTree = ""; }; B299580A14F2FA1400050A04 /* DisassemblerLLVMC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DisassemblerLLVMC.cpp; sourceTree = ""; }; B299580C14F2FA1F00050A04 /* DisassemblerLLVMC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DisassemblerLLVMC.h; sourceTree = ""; }; B2A58721143119810092BFBA /* SBWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBWatchpoint.h; path = include/lldb/API/SBWatchpoint.h; sourceTree = ""; }; B2A58723143119D50092BFBA /* SBWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBWatchpoint.cpp; path = source/API/SBWatchpoint.cpp; sourceTree = ""; }; B2A5872514313B480092BFBA /* SBWatchpoint.i */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; path = SBWatchpoint.i; sourceTree = ""; }; B2B7CCEA15D1BD6600EEFB57 /* CommandObjectWatchpointCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectWatchpointCommand.cpp; path = source/Commands/CommandObjectWatchpointCommand.cpp; sourceTree = ""; }; B2B7CCEC15D1BD9600EEFB57 /* CommandObjectWatchpointCommand.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CommandObjectWatchpointCommand.h; path = source/Commands/CommandObjectWatchpointCommand.h; sourceTree = ""; }; B2B7CCED15D1BFB700EEFB57 /* WatchpointOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WatchpointOptions.h; path = include/lldb/Breakpoint/WatchpointOptions.h; sourceTree = ""; }; B2B7CCEF15D1C20F00EEFB57 /* WatchpointOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WatchpointOptions.cpp; path = source/Breakpoint/WatchpointOptions.cpp; sourceTree = ""; }; B2D3033612EFA5C500F84EB3 /* InstructionUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InstructionUtils.h; path = Utility/InstructionUtils.h; sourceTree = ""; }; D67521351EA17C3900439694 /* MainLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MainLoop.cpp; sourceTree = ""; }; E73A15A41B548EC500786197 /* GDBRemoteSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GDBRemoteSignals.cpp; path = Utility/GDBRemoteSignals.cpp; sourceTree = ""; }; E73A15A51B548EC500786197 /* GDBRemoteSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GDBRemoteSignals.h; path = Utility/GDBRemoteSignals.h; sourceTree = ""; }; E769331D1A94D18100C73337 /* lldb-server.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "lldb-server.cpp"; path = "tools/lldb-server/lldb-server.cpp"; sourceTree = ""; }; E7723D421AC4A7FB002BA082 /* RegisterContextPOSIXCore_arm64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextPOSIXCore_arm64.cpp; sourceTree = ""; }; E7723D431AC4A7FB002BA082 /* RegisterContextPOSIXCore_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextPOSIXCore_arm64.h; sourceTree = ""; }; E7723D4A1AC4A944002BA082 /* RegisterContextPOSIX_arm64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextPOSIX_arm64.cpp; path = Utility/RegisterContextPOSIX_arm64.cpp; sourceTree = ""; }; E7723D4B1AC4A944002BA082 /* RegisterContextPOSIX_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextPOSIX_arm64.h; path = Utility/RegisterContextPOSIX_arm64.h; sourceTree = ""; }; E778E99F1B062D1700247609 /* EmulateInstructionMIPS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EmulateInstructionMIPS.cpp; sourceTree = ""; }; E778E9A01B062D1700247609 /* EmulateInstructionMIPS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EmulateInstructionMIPS.h; sourceTree = ""; }; EB8375E61B553DE800BA907D /* ThreadPlanCallFunctionUsingABI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanCallFunctionUsingABI.cpp; path = source/Target/ThreadPlanCallFunctionUsingABI.cpp; sourceTree = ""; }; EB8375E81B553DFE00BA907D /* ThreadPlanCallFunctionUsingABI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ThreadPlanCallFunctionUsingABI.h; path = include/lldb/Target/ThreadPlanCallFunctionUsingABI.h; sourceTree = ""; }; EDB919B414F6F10D008FF64B /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = /System/Library/Frameworks/Security.framework; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 239504D11BDD451400963CEA /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 23CB15481D66DA9300EDDDE1 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 23CB15491D66DA9300EDDDE1 /* libxml2.2.dylib in Frameworks */, 23CB154A1D66DA9300EDDDE1 /* libpanel.dylib in Frameworks */, 23CB154B1D66DA9300EDDDE1 /* libedit.dylib in Frameworks */, 23CB154C1D66DA9300EDDDE1 /* libz.dylib in Frameworks */, 23CB154D1D66DA9300EDDDE1 /* libncurses.dylib in Frameworks */, 23CB154E1D66DA9300EDDDE1 /* liblldb-core.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 26579F66126A25920007C5CB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 26680205115FD0ED008E1FE4 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 260157C81885F53100F875CF /* libpanel.dylib in Frameworks */, 2670F8121862B44A006B332C /* libncurses.dylib in Frameworks */, 26CEB5EF18761CB2008F575A /* libedit.dylib in Frameworks */, 26D55235159A7DB100708D8D /* libxml2.dylib in Frameworks */, 268901161335BBC300698AC0 /* liblldb-core.a in Frameworks */, 966C6B7A18E6A56A0093F5EC /* libz.dylib in Frameworks */, 2668022F115FD19D008E1FE4 /* CoreFoundation.framework in Frameworks */, 26680233115FD1A7008E1FE4 /* libobjc.dylib in Frameworks */, 4CF3D80C15AF4DC800845BF3 /* Security.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 2689FFC713353D7A00698AC0 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 2690CD141A6DC0D000E717C8 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 239481861C59EBDD00DF7168 /* libncurses.dylib in Frameworks */, 2669424D1A6DC32B0063BE93 /* LLDB.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 26DC6A0E1337FE6900FF7998 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 260157C61885F51C00F875CF /* libpanel.dylib in Frameworks */, 966C6B7C18E6A56A0093F5EC /* libz.dylib in Frameworks */, 26780C611867C33D00234593 /* libncurses.dylib in Frameworks */, 26CFDCA818616473000E63E5 /* libedit.dylib in Frameworks */, 2606EDDF184E68A10034641B /* liblldb-core.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 26F5C26810F3D9A4009D5894 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 26F5C32D10F3DFDD009D5894 /* libtermcap.dylib in Frameworks */, 2668035C11601108008E1FE4 /* LLDB.framework in Frameworks */, 966C6B7918E6A56A0093F5EC /* libz.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 942829BD1A89835300521B30 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 2656BBC31AE0739C00441749 /* libedit.dylib in Frameworks */, 2656BBC61AE073B500441749 /* libz.dylib in Frameworks */, 2656BBC51AE073AD00441749 /* libpanel.dylib in Frameworks */, 2656BBC41AE073A800441749 /* libncurses.dylib in Frameworks */, 942829CC1A89839300521B30 /* liblldb-core.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 08FB7794FE84155DC02AAC07 /* lldb */ = { isa = PBXGroup; children = ( 239481851C59EBDD00DF7168 /* libncurses.dylib */, 2326CF4E1BDD687800A5CEAC /* libpanel.dylib */, 2326CF4C1BDD684B00A5CEAC /* libedit.dylib */, 2326CF4A1BDD681800A5CEAC /* libz.dylib */, 2326CF471BDD67C100A5CEAC /* libncurses.dylib */, 2326CF451BDD647400A5CEAC /* Foundation.framework */, 2326CF3F1BDD613E00A5CEAC /* Python.framework */, 26F5C32810F3DF7D009D5894 /* Libraries */, 264E8576159BE51A00E9D7A2 /* Resources */, 08FB7795FE84155DC02AAC07 /* Source */, 26F5C22410F3D950009D5894 /* Tools */, 2690CD181A6DC0D000E717C8 /* lldb-mi */, 1AB674ADFE9D54B511CA2CBB /* Products */, 2321F9331BDD326500BA9A93 /* unittests */, 236102941CF389BE00B8E0B9 /* cmake */, 23CB14E21D66CA2200EDDDE1 /* Frameworks */, ); name = lldb; sourceTree = ""; }; 08FB7795FE84155DC02AAC07 /* Source */ = { isa = PBXGroup; children = ( 266960581199F4230075C61A /* Scripts */, 26BC7E7410F1B85900F91463 /* lldb.cpp */, 26BC7C2A10F1B3BC00F91463 /* lldb-private.h */, 26217932133BCB850083B112 /* lldb-private-enumerations.h */, 26BC7C2810F1B3BC00F91463 /* lldb-private-interfaces.h */, 26217930133BC8640083B112 /* lldb-private-types.h */, 262D3190111B4341004E6F88 /* API */, 26BC7CEB10F1B70800F91463 /* Breakpoint */, 26BC7D0D10F1B71D00F91463 /* Commands */, 26BC7C1010F1B34800F91463 /* Core */, 94CB255616B0683B0059775D /* DataFormatters */, 26BC7DBE10F1B78200F91463 /* Expression */, 26BC7DD010F1B7C100F91463 /* Host */, 3F8169261ABB73C1001DA9DF /* Initialization */, 26BC7DDF10F1B7E200F91463 /* Interpreter */, 260C897110F57C5600BB2B04 /* Plugins */, 26BC7C4B10F1B6C100F91463 /* Symbol */, 26BC7DEF10F1B80200F91463 /* Target */, 2682F168115ED9C800CCFF99 /* Utility */, ); name = Source; sourceTree = ""; usesTabs = 0; }; 1AB674ADFE9D54B511CA2CBB /* Products */ = { isa = PBXGroup; children = ( 26F5C26A10F3D9A4009D5894 /* lldb */, 26680207115FD0ED008E1FE4 /* LLDB.framework */, 26579F68126A25920007C5CB /* darwin-debug */, 26DC6A101337FE6900FF7998 /* lldb-server */, 2690CD171A6DC0D000E717C8 /* lldb-mi */, 942829C01A89835300521B30 /* lldb-argdumper */, 239504D41BDD451400963CEA /* lldb-gtest */, 23CB15561D66DA9300EDDDE1 /* lldb-gtest */, ); name = Products; sourceTree = ""; usesTabs = 0; }; 23042D0F1976C9D800621B2C /* Kalimba */ = { isa = PBXGroup; children = ( 23042D111976CA0A00621B2C /* PlatformKalimba.h */, 23042D101976CA0A00621B2C /* PlatformKalimba.cpp */, ); path = Kalimba; sourceTree = ""; }; 2321F9331BDD326500BA9A93 /* unittests */ = { isa = PBXGroup; children = ( 23E2E52C1D903806006F38BB /* Breakpoint */, 239504C61BDD3FF300963CEA /* CMakeLists.txt */, 239504C21BDD3FD600963CEA /* gtest_common.h */, 23CB14E51D66CBEB00EDDDE1 /* Core */, 2326CF501BDD68CA00A5CEAC /* Editline */, AEC6FF9D1BE97035007882C1 /* Expression */, 2321F9371BDD32ED00BA9A93 /* Host */, 2321F93C1BDD339A00BA9A93 /* Interpreter */, 23CB14F51D66CCB700EDDDE1 /* Language */, 2370A3781D66C549000E7BE6 /* Process */, 2321F93F1BDD33D800BA9A93 /* ScriptInterpreter */, 23CB15091D66CF2B00EDDDE1 /* Symbol */, 23CB150A1D66CF3200EDDDE1 /* SymbolFile */, AFAFD8081E57E19E0017A14F /* Target */, AFEC5FD31D94F9130076A480 /* UnwindAssembly */, 2321F9421BDD343A00BA9A93 /* Utility */, ); path = unittests; sourceTree = ""; }; 2321F9371BDD32ED00BA9A93 /* Host */ = { isa = PBXGroup; children = ( 2321F9381BDD332400BA9A93 /* CMakeLists.txt */, 23CB14FD1D66CD2400EDDDE1 /* FileSpecTest.cpp */, 2321F9391BDD332400BA9A93 /* SocketAddressTest.cpp */, 2321F93A1BDD332400BA9A93 /* SocketTest.cpp */, 2321F93B1BDD332400BA9A93 /* SymbolsTest.cpp */, ); path = Host; sourceTree = ""; }; 2321F93C1BDD339A00BA9A93 /* Interpreter */ = { isa = PBXGroup; children = ( 2321F93D1BDD33CE00BA9A93 /* CMakeLists.txt */, 2321F93E1BDD33CE00BA9A93 /* TestArgs.cpp */, ); path = Interpreter; sourceTree = ""; }; 2321F93F1BDD33D800BA9A93 /* ScriptInterpreter */ = { isa = PBXGroup; children = ( 2321F9401BDD340D00BA9A93 /* CMakeLists.txt */, 2321F94B1BDD35D500BA9A93 /* Python */, ); path = ScriptInterpreter; sourceTree = ""; }; 2321F9421BDD343A00BA9A93 /* Utility */ = { isa = PBXGroup; children = ( + 9A1542F31F0EE44000DEA1D8 /* Helpers */, 2321F9431BDD346100BA9A93 /* CMakeLists.txt */, 23CB15041D66CD9200EDDDE1 /* Inputs */, 2321F9441BDD346100BA9A93 /* StringExtractorTest.cpp */, 2321F9451BDD346100BA9A93 /* TaskPoolTest.cpp */, 2321F9461BDD346100BA9A93 /* UriParserTest.cpp */, ); path = Utility; sourceTree = ""; }; 2321F94B1BDD35D500BA9A93 /* Python */ = { isa = PBXGroup; children = ( 2321F94C1BDD360F00BA9A93 /* CMakeLists.txt */, 2321F94D1BDD360F00BA9A93 /* PythonDataObjectsTests.cpp */, 3FA093141BF65D3A0037DD08 /* PythonExceptionStateTests.cpp */, AF45E1FC1BF57C8D000563EB /* PythonTestSuite.cpp */, AF45E1FD1BF57C8D000563EB /* PythonTestSuite.h */, ); path = Python; sourceTree = ""; }; 2326CF501BDD68CA00A5CEAC /* Editline */ = { isa = PBXGroup; children = ( 23CB14F11D66CC9000EDDDE1 /* CMakeLists.txt */, 2326CF511BDD693B00A5CEAC /* EditlineTest.cpp */, ); path = Editline; sourceTree = ""; }; 233B009C19610D130090E598 /* linux */ = { isa = PBXGroup; children = ( 3FDFE56319AF9B77009756A7 /* Config.h */, 233B009D19610D6B0090E598 /* Host.cpp */, 237C577A19AF9D9F00213D59 /* HostInfoLinux.h */, 3FDFE53619A2933E009756A7 /* HostInfoLinux.cpp */, 3FDFE56419AF9B77009756A7 /* HostInfoLinux.h */, 3FDFE56219AF9B60009756A7 /* HostThreadLinux.cpp */, 3FDFE56519AF9B77009756A7 /* HostThreadLinux.h */, ); name = linux; path = source/Host/linux; sourceTree = ""; }; 236102941CF389BE00B8E0B9 /* cmake */ = { isa = PBXGroup; children = ( 236102961CF389F800B8E0B9 /* modules */, 236102971CF38A0900B8E0B9 /* platforms */, ); path = cmake; sourceTree = ""; }; 236102961CF389F800B8E0B9 /* modules */ = { isa = PBXGroup; children = ( 236102981CF38A2B00B8E0B9 /* AddLLDB.cmake */, 236102991CF38A2B00B8E0B9 /* LLDBConfig.cmake */, 2361029A1CF38A2B00B8E0B9 /* LLDBStandalone.cmake */, ); path = modules; sourceTree = ""; }; 236102971CF38A0900B8E0B9 /* platforms */ = { isa = PBXGroup; children = ( 2361029E1CF38A3500B8E0B9 /* Android.cmake */, ); path = platforms; sourceTree = ""; }; 2370A3781D66C549000E7BE6 /* Process */ = { isa = PBXGroup; children = ( 2370A37A1D66C57B000E7BE6 /* CMakeLists.txt */, 2370A3791D66C569000E7BE6 /* gdb-remote */, 23E2E5181D9036CF006F38BB /* minidump */, ); path = Process; sourceTree = ""; }; 2370A3791D66C569000E7BE6 /* gdb-remote */ = { isa = PBXGroup; children = ( 2370A37C1D66C587000E7BE6 /* CMakeLists.txt */, 2370A37D1D66C587000E7BE6 /* GDBRemoteClientBaseTest.cpp */, 2370A37E1D66C587000E7BE6 /* GDBRemoteCommunicationClientTest.cpp */, 2370A37F1D66C587000E7BE6 /* GDBRemoteTestUtils.cpp */, 2370A3801D66C587000E7BE6 /* GDBRemoteTestUtils.h */, ); path = "gdb-remote"; sourceTree = ""; }; 238F2BA41D2C858F001FF92A /* StructuredData */ = { isa = PBXGroup; children = ( 238F2BA51D2C85B2001FF92A /* DarwinLog */, ); path = StructuredData; sourceTree = ""; }; 238F2BA51D2C85B2001FF92A /* DarwinLog */ = { isa = PBXGroup; children = ( 238F2BA71D2C85FA001FF92A /* StructuredDataDarwinLog.h */, 238F2BA61D2C85FA001FF92A /* StructuredDataDarwinLog.cpp */, ); path = DarwinLog; sourceTree = ""; }; 23AB0526199FF5D3003B8084 /* FreeBSD */ = { isa = PBXGroup; children = ( AF3F54B21B3BA5D500186E73 /* POSIXStopInfo.cpp */, AF3F54B31B3BA5D500186E73 /* POSIXStopInfo.h */, 26474CC818D0CB5B0073DEBA /* RegisterContextPOSIX.h */, AF3F54B81B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_arm.cpp */, AF3F54B91B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_arm.h */, AF3F54BA1B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_arm64.cpp */, AF3F54BB1B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_arm64.h */, AF3F54BC1B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_mips64.cpp */, AF3F54BD1B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_mips64.h */, AF3F54BE1B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_powerpc.cpp */, AF3F54BF1B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_powerpc.h */, AF3F54C01B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_x86.cpp */, AF3F54C11B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_x86.h */, 23AB052E199FF639003B8084 /* FreeBSDThread.h */, 23AB052D199FF639003B8084 /* FreeBSDThread.cpp */, 23AB0530199FF639003B8084 /* ProcessFreeBSD.h */, 23AB052F199FF639003B8084 /* ProcessFreeBSD.cpp */, 23AB0532199FF639003B8084 /* ProcessMonitor.h */, 23AB0531199FF639003B8084 /* ProcessMonitor.cpp */, ); path = FreeBSD; sourceTree = ""; }; 23CB14E21D66CA2200EDDDE1 /* Frameworks */ = { isa = PBXGroup; children = ( 23CB14E31D66CA2200EDDDE1 /* libxml2.2.dylib */, ); name = Frameworks; sourceTree = ""; }; 23CB14E51D66CBEB00EDDDE1 /* Core */ = { isa = PBXGroup; children = ( 23E2E5161D903689006F38BB /* ArchSpecTest.cpp */, 23CB14E71D66CC0E00EDDDE1 /* CMakeLists.txt */, 23CB14E61D66CC0E00EDDDE1 /* BroadcasterTest.cpp */, 23CB14E81D66CC0E00EDDDE1 /* DataExtractorTest.cpp */, 23CB14E91D66CC0E00EDDDE1 /* ScalarTest.cpp */, ); path = Core; sourceTree = ""; }; 23CB14F51D66CCB700EDDDE1 /* Language */ = { isa = PBXGroup; children = ( 23CB14F61D66CCD600EDDDE1 /* CMakeLists.txt */, 23CB14F81D66CCDA00EDDDE1 /* CPlusPlus */, ); path = Language; sourceTree = ""; }; 23CB14F81D66CCDA00EDDDE1 /* CPlusPlus */ = { isa = PBXGroup; children = ( 23CB14F91D66CCF100EDDDE1 /* CMakeLists.txt */, 23CB14FA1D66CCF100EDDDE1 /* CPlusPlusLanguageTest.cpp */, ); path = CPlusPlus; sourceTree = ""; }; 23CB15041D66CD9200EDDDE1 /* Inputs */ = { isa = PBXGroup; children = ( 23CB15051D66CDB400EDDDE1 /* TestModule.c */, 23CB15061D66CDB400EDDDE1 /* TestModule.so */, ); path = Inputs; sourceTree = ""; }; 23CB15091D66CF2B00EDDDE1 /* Symbol */ = { isa = PBXGroup; children = ( 23CB150B1D66CF5600EDDDE1 /* CMakeLists.txt */, 23CB150C1D66CF5600EDDDE1 /* TestClangASTContext.cpp */, ); path = Symbol; sourceTree = ""; }; 23CB150A1D66CF3200EDDDE1 /* SymbolFile */ = { isa = PBXGroup; children = ( 23CB15101D66CF6900EDDDE1 /* CMakeLists.txt */, 23CB15121D66CF6E00EDDDE1 /* PDB */, ); path = SymbolFile; sourceTree = ""; }; 23CB15121D66CF6E00EDDDE1 /* PDB */ = { isa = PBXGroup; children = ( 23CB15131D66CF8700EDDDE1 /* CMakeLists.txt */, 23CB15181D66CF9500EDDDE1 /* Inputs */, 23CB15141D66CF8700EDDDE1 /* SymbolFilePDBTests.cpp */, ); path = PDB; sourceTree = ""; }; 23CB15181D66CF9500EDDDE1 /* Inputs */ = { isa = PBXGroup; children = ( 23CB15191D66CFAC00EDDDE1 /* test-dwarf.cpp */, 23CB151A1D66CFAC00EDDDE1 /* test-dwarf.exe */, 23CB151B1D66CFAC00EDDDE1 /* test-pdb-alt.cpp */, 23CB151C1D66CFAC00EDDDE1 /* test-pdb-nested.h */, 23CB151D1D66CFAC00EDDDE1 /* test-pdb-types.cpp */, 23CB151E1D66CFAC00EDDDE1 /* test-pdb-types.exe */, 23CB151F1D66CFAC00EDDDE1 /* test-pdb-types.pdb */, 23CB15201D66CFAC00EDDDE1 /* test-pdb.cpp */, 23CB15211D66CFAC00EDDDE1 /* test-pdb.exe */, 23CB15221D66CFAC00EDDDE1 /* test-pdb.h */, 23CB15231D66CFAC00EDDDE1 /* test-pdb.pdb */, ); path = Inputs; sourceTree = ""; }; 23E2E5181D9036CF006F38BB /* minidump */ = { isa = PBXGroup; children = ( 23E2E5191D9036F2006F38BB /* CMakeLists.txt */, 23E2E51A1D9036F2006F38BB /* MinidumpParserTest.cpp */, 23E2E51D1D9036F6006F38BB /* Inputs */, ); path = minidump; sourceTree = ""; }; 23E2E51D1D9036F6006F38BB /* Inputs */ = { isa = PBXGroup; children = ( 23E2E51E1D903726006F38BB /* fizzbuzz_no_heap.dmp */, 23E2E51F1D903726006F38BB /* linux-x86_64.cpp */, 23E2E5201D903726006F38BB /* linux-x86_64.dmp */, ); path = Inputs; sourceTree = ""; }; 23E2E52C1D903806006F38BB /* Breakpoint */ = { isa = PBXGroup; children = ( 23E2E52D1D90382B006F38BB /* BreakpointIDTest.cpp */, 23E2E52E1D90382B006F38BB /* CMakeLists.txt */, ); path = Breakpoint; sourceTree = ""; }; 23E2E5351D9048E7006F38BB /* minidump */ = { isa = PBXGroup; children = ( AFD65C7F1D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.cpp */, AFD65C801D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.h */, 23E2E5361D9048FB006F38BB /* CMakeLists.txt */, 23E2E5371D9048FB006F38BB /* MinidumpParser.cpp */, 23E2E5381D9048FB006F38BB /* MinidumpParser.h */, 23E2E5391D9048FB006F38BB /* MinidumpTypes.cpp */, 23E2E53A1D9048FB006F38BB /* MinidumpTypes.h */, 947CF76F1DC7B1E300EF980B /* ProcessMinidump.h */, 947CF7701DC7B1EE00EF980B /* ProcessMinidump.cpp */, 947CF7721DC7B20300EF980B /* RegisterContextMinidump_x86_32.h */, 947CF7731DC7B20300EF980B /* ThreadMinidump.h */, 947CF7741DC7B20D00EF980B /* RegisterContextMinidump_x86_32.cpp */, 947CF7751DC7B20D00EF980B /* ThreadMinidump.cpp */, ); path = minidump; sourceTree = ""; }; 260C897110F57C5600BB2B04 /* Plugins */ = { isa = PBXGroup; children = ( 8CF02ADD19DCBEC200B14BE0 /* InstrumentationRuntime */, 8C2D6A58197A1FB9006989C9 /* MemoryHistory */, 26DB3E051379E7AD0080DC73 /* ABI */, 260C897210F57C5600BB2B04 /* Disassembler */, 260C897810F57C5600BB2B04 /* DynamicLoader */, 4984BA0B1B975E9F008658D4 /* ExpressionParser */, 26D9FDCA12F785120003F2EE /* Instruction */, AF2BCA6518C7EFDE005B4526 /* JITLoader */, 94B638541B8FABEA004FE1E4 /* Language */, 4CCA643A13B40B82003BDF98 /* LanguageRuntime */, 260C897E10F57C5600BB2B04 /* ObjectContainer */, 260C898210F57C5600BB2B04 /* ObjectFile */, 266DFE9013FD64D200D0C574 /* OperatingSystem */, 26C5577E132575B6008FD8FE /* Platform */, 260C898A10F57C5600BB2B04 /* Process */, 3FBA69DA1B6066D20008F44A /* ScriptInterpreter */, 238F2BA41D2C858F001FF92A /* StructuredData */, AF11CB34182CA85A00D9B618 /* SystemRuntime */, 260C89B110F57C5600BB2B04 /* SymbolFile */, 260C89E010F57C5600BB2B04 /* SymbolVendor */, 26AC3F441365F40E0065C7EF /* UnwindAssembly */, ); name = Plugins; path = source/Plugins; sourceTree = ""; }; 260C897210F57C5600BB2B04 /* Disassembler */ = { isa = PBXGroup; children = ( 260C897310F57C5600BB2B04 /* llvm */, ); path = Disassembler; sourceTree = ""; }; 260C897310F57C5600BB2B04 /* llvm */ = { isa = PBXGroup; children = ( B299580A14F2FA1400050A04 /* DisassemblerLLVMC.cpp */, B299580C14F2FA1F00050A04 /* DisassemblerLLVMC.h */, ); path = llvm; sourceTree = ""; }; 260C897810F57C5600BB2B04 /* DynamicLoader */ = { isa = PBXGroup; children = ( 26274FA414030F79006BA130 /* Darwin-Kernel */, 2666ADBF1B3CB675001FAFD3 /* Hexagon-DYLD */, 260C897910F57C5600BB2B04 /* MacOSX-DYLD */, 26FFC19214FC072100087D58 /* POSIX-DYLD */, 26F006521B4DD86700B872E5 /* Windows-DYLD */, 268A683C1321B505000E3FB8 /* Static */, ); path = DynamicLoader; sourceTree = ""; }; 260C897910F57C5600BB2B04 /* MacOSX-DYLD */ = { isa = PBXGroup; children = ( AF27AD531D3603EA00CF2833 /* DynamicLoaderDarwin.cpp */, AF27AD541D3603EA00CF2833 /* DynamicLoaderDarwin.h */, AF2907BD1D3F082400E10654 /* DynamicLoaderMacOS.cpp */, AF2907BE1D3F082400E10654 /* DynamicLoaderMacOS.h */, 260C897A10F57C5600BB2B04 /* DynamicLoaderMacOSXDYLD.cpp */, 260C897B10F57C5600BB2B04 /* DynamicLoaderMacOSXDYLD.h */, ); path = "MacOSX-DYLD"; sourceTree = ""; }; 260C897E10F57C5600BB2B04 /* ObjectContainer */ = { isa = PBXGroup; children = ( 26A3B4AB1181454800381BC2 /* BSD-Archive */, 260C897F10F57C5600BB2B04 /* Universal-Mach-O */, ); path = ObjectContainer; sourceTree = ""; }; 260C897F10F57C5600BB2B04 /* Universal-Mach-O */ = { isa = PBXGroup; children = ( 260C898010F57C5600BB2B04 /* ObjectContainerUniversalMachO.cpp */, 260C898110F57C5600BB2B04 /* ObjectContainerUniversalMachO.h */, ); path = "Universal-Mach-O"; sourceTree = ""; }; 260C898210F57C5600BB2B04 /* ObjectFile */ = { isa = PBXGroup; children = ( 260C898310F57C5600BB2B04 /* ELF */, 26EFC4C718CFAF0D00865D87 /* JIT */, 260C898710F57C5600BB2B04 /* Mach-O */, 26E152221419CACA007967D0 /* PECOFF */, ); path = ObjectFile; sourceTree = ""; }; 260C898310F57C5600BB2B04 /* ELF */ = { isa = PBXGroup; children = ( 26D27C9E11ED3A4E0024D721 /* ELFHeader.h */, 26D27C9D11ED3A4E0024D721 /* ELFHeader.cpp */, 260C898610F57C5600BB2B04 /* ObjectFileELF.h */, 260C898510F57C5600BB2B04 /* ObjectFileELF.cpp */, ); path = ELF; sourceTree = ""; }; 260C898710F57C5600BB2B04 /* Mach-O */ = { isa = PBXGroup; children = ( 260C898810F57C5600BB2B04 /* ObjectFileMachO.cpp */, 260C898910F57C5600BB2B04 /* ObjectFileMachO.h */, ); path = "Mach-O"; sourceTree = ""; }; 260C898A10F57C5600BB2B04 /* Process */ = { isa = PBXGroup; children = ( 23E2E5351D9048E7006F38BB /* minidump */, 26BC179F18C7F4CB00D2196D /* elf-core */, 23AB0526199FF5D3003B8084 /* FreeBSD */, 4CEE62F71145F1C70064CF93 /* GDB Remote */, 2642FBA713D003B400ED6808 /* MacOSX-Kernel */, 26A527BC14E24F5F00F3A14A /* mach-core */, 26BC17B318C7F4FA00D2196D /* POSIX */, 26B4666E11A2080F00CF6220 /* Utility */, ); path = Process; sourceTree = ""; }; 260C89B110F57C5600BB2B04 /* SymbolFile */ = { isa = PBXGroup; children = ( AF6335DF1C87B20A00F7D554 /* PDB */, 260C89B210F57C5600BB2B04 /* DWARF */, 260C89DD10F57C5600BB2B04 /* Symtab */, ); path = SymbolFile; sourceTree = ""; }; 260C89B210F57C5600BB2B04 /* DWARF */ = { isa = PBXGroup; children = ( 6D95DC031B9DC06F000E318A /* DIERef.h */, 6D95DC041B9DC06F000E318A /* SymbolFileDWARFDwo.h */, 6D95DBFD1B9DC057000E318A /* DIERef.cpp */, 6D95DBFE1B9DC057000E318A /* HashedNameToDIE.cpp */, 6D95DBFF1B9DC057000E318A /* SymbolFileDWARFDwo.cpp */, 260C89B310F57C5600BB2B04 /* DWARFAbbreviationDeclaration.cpp */, 260C89B410F57C5600BB2B04 /* DWARFAbbreviationDeclaration.h */, 269DDD451B8FD01A00D0DBD8 /* DWARFASTParser.h */, 269DDD491B8FD1C300D0DBD8 /* DWARFASTParserClang.h */, 269DDD481B8FD1C300D0DBD8 /* DWARFASTParserClang.cpp */, AE6897271B94F6DE0018845D /* DWARFASTParserGo.h */, AE6897261B94F6DE0018845D /* DWARFASTParserGo.cpp */, 6D0F61441C80AACF00A4ECEE /* DWARFASTParserJava.cpp */, 6D0F61451C80AACF00A4ECEE /* DWARFASTParserJava.h */, 4CC7C6511D5299140076FF94 /* DWARFASTParserOCaml.h */, 4CC7C6521D5299140076FF94 /* DWARFASTParserOCaml.cpp */, 260C89B610F57C5600BB2B04 /* DWARFAttribute.h */, 266E829C1B8E542C008FCA06 /* DWARFAttribute.cpp */, 260C89B710F57C5600BB2B04 /* DWARFCompileUnit.cpp */, 260C89B810F57C5600BB2B04 /* DWARFCompileUnit.h */, 26AB92101819D74600E63F3E /* DWARFDataExtractor.cpp */, 26AB92111819D74600E63F3E /* DWARFDataExtractor.h */, 260C89B910F57C5600BB2B04 /* DWARFDebugAbbrev.cpp */, 260C89BA10F57C5600BB2B04 /* DWARFDebugAbbrev.h */, 260C89BB10F57C5600BB2B04 /* DWARFDebugAranges.cpp */, 260C89BC10F57C5600BB2B04 /* DWARFDebugAranges.h */, 260C89BD10F57C5600BB2B04 /* DWARFDebugArangeSet.cpp */, 260C89BE10F57C5600BB2B04 /* DWARFDebugArangeSet.h */, 260C89BF10F57C5600BB2B04 /* DWARFDebugInfo.cpp */, 260C89C010F57C5600BB2B04 /* DWARFDebugInfo.h */, 260C89C110F57C5600BB2B04 /* DWARFDebugInfoEntry.cpp */, 260C89C210F57C5600BB2B04 /* DWARFDebugInfoEntry.h */, 260C89C310F57C5600BB2B04 /* DWARFDebugLine.cpp */, 260C89C410F57C5600BB2B04 /* DWARFDebugLine.h */, 260C89C510F57C5600BB2B04 /* DWARFDebugMacinfo.cpp */, 260C89C610F57C5600BB2B04 /* DWARFDebugMacinfo.h */, 260C89C710F57C5600BB2B04 /* DWARFDebugMacinfoEntry.cpp */, 260C89C810F57C5600BB2B04 /* DWARFDebugMacinfoEntry.h */, 23E77CD61C20F29F007192AD /* DWARFDebugMacro.cpp */, 23E77CD71C20F29F007192AD /* DWARFDebugMacro.h */, 260C89C910F57C5600BB2B04 /* DWARFDebugPubnames.cpp */, 260C89CA10F57C5600BB2B04 /* DWARFDebugPubnames.h */, 260C89CB10F57C5600BB2B04 /* DWARFDebugPubnamesSet.cpp */, 260C89CC10F57C5600BB2B04 /* DWARFDebugPubnamesSet.h */, 260C89CD10F57C5600BB2B04 /* DWARFDebugRanges.cpp */, 260C89CE10F57C5600BB2B04 /* DWARFDebugRanges.h */, 26B1EFAC154638AF00E2DAC7 /* DWARFDeclContext.cpp */, 26B1EFAD154638AF00E2DAC7 /* DWARFDeclContext.h */, 260C89CF10F57C5600BB2B04 /* DWARFDefines.cpp */, 260C89D010F57C5600BB2B04 /* DWARFDefines.h */, 266E82951B8CE346008FCA06 /* DWARFDIE.h */, 266E82961B8CE3AC008FCA06 /* DWARFDIE.cpp */, 260C89D110F57C5600BB2B04 /* DWARFDIECollection.cpp */, 260C89D210F57C5600BB2B04 /* DWARFDIECollection.h */, 260C89D310F57C5600BB2B04 /* DWARFFormValue.cpp */, 260C89D410F57C5600BB2B04 /* DWARFFormValue.h */, 26A0DA4D140F721D006DA411 /* HashedNameToDIE.h */, 26109B3B1155D70100CC3529 /* LogChannelDWARF.cpp */, 26109B3C1155D70100CC3529 /* LogChannelDWARF.h */, 2618D9EA12406FE600F2B8FE /* NameToDIE.cpp */, 2618D957124056C700F2B8FE /* NameToDIE.h */, 260C89D910F57C5600BB2B04 /* SymbolFileDWARF.cpp */, 260C89DA10F57C5600BB2B04 /* SymbolFileDWARF.h */, 260C89DB10F57C5600BB2B04 /* SymbolFileDWARFDebugMap.cpp */, 260C89DC10F57C5600BB2B04 /* SymbolFileDWARFDebugMap.h */, 26B8B42212EEC52A00A831B2 /* UniqueDWARFASTType.h */, 26B8B42312EEC52A00A831B2 /* UniqueDWARFASTType.cpp */, ); path = DWARF; sourceTree = ""; }; 260C89DD10F57C5600BB2B04 /* Symtab */ = { isa = PBXGroup; children = ( 260C89DE10F57C5600BB2B04 /* SymbolFileSymtab.cpp */, 260C89DF10F57C5600BB2B04 /* SymbolFileSymtab.h */, ); path = Symtab; sourceTree = ""; }; 260C89E010F57C5600BB2B04 /* SymbolVendor */ = { isa = PBXGroup; children = ( 2635878D17822E56004C30BA /* ELF */, 260C89E110F57C5600BB2B04 /* MacOSX */, ); path = SymbolVendor; sourceTree = ""; }; 260C89E110F57C5600BB2B04 /* MacOSX */ = { isa = PBXGroup; children = ( 260C89E210F57C5600BB2B04 /* SymbolVendorMacOSX.cpp */, 260C89E310F57C5600BB2B04 /* SymbolVendorMacOSX.h */, ); path = MacOSX; sourceTree = ""; }; 2611FEEE142D83060017FEA3 /* interface */ = { isa = PBXGroup; children = ( 2611FEEF142D83060017FEA3 /* SBAddress.i */, 254FBBA61A91672800BD6378 /* SBAttachInfo.i */, 2611FEF0142D83060017FEA3 /* SBBlock.i */, 2611FEF1142D83060017FEA3 /* SBBreakpoint.i */, 2611FEF2142D83060017FEA3 /* SBBreakpointLocation.i */, 2611FEF3142D83060017FEA3 /* SBBroadcaster.i */, 2611FEF4142D83060017FEA3 /* SBCommandInterpreter.i */, 2611FEF5142D83060017FEA3 /* SBCommandReturnObject.i */, 2611FEF6142D83060017FEA3 /* SBCommunication.i */, 2611FEF7142D83060017FEA3 /* SBCompileUnit.i */, 2611FEF8142D83060017FEA3 /* SBData.i */, 2611FEF9142D83060017FEA3 /* SBDebugger.i */, 9452573616262CD000325455 /* SBDeclaration.i */, 2611FEFA142D83060017FEA3 /* SBError.i */, 2611FEFB142D83060017FEA3 /* SBEvent.i */, 940B02F719DC970900AD0F52 /* SBExecutionContext.i */, 2611FEFC142D83060017FEA3 /* SBFileSpec.i */, 2611FEFD142D83060017FEA3 /* SBFileSpecList.i */, 2611FEFE142D83060017FEA3 /* SBFrame.i */, 4CE4F676162CE1E100F75CB3 /* SBExpressionOptions.i */, 2611FEFF142D83060017FEA3 /* SBFunction.i */, 2611FF00142D83060017FEA3 /* SBHostOS.i */, 2611FF02142D83060017FEA3 /* SBInstruction.i */, 2611FF03142D83060017FEA3 /* SBInstructionList.i */, 23DCBE971D63E14B0084C36B /* SBLanguageRuntime.i */, 254FBB921A81AA5200BD6378 /* SBLaunchInfo.i */, 2611FF04142D83060017FEA3 /* SBLineEntry.i */, 2611FF05142D83060017FEA3 /* SBListener.i */, 264297591D1DF2AA003F2BF4 /* SBMemoryRegionInfo.i */, 2642975A1D1DF2AA003F2BF4 /* SBMemoryRegionInfoList.i */, 2611FF06142D83060017FEA3 /* SBModule.i */, 263C493B178B61CC0070F12D /* SBModuleSpec.i */, 262F12B8183546C900AEB384 /* SBPlatform.i */, 2611FF07142D83060017FEA3 /* SBProcess.i */, AF0EBBEE1859419F0059E52F /* SBQueue.i */, AF0EBBEF1859419F0059E52F /* SBQueueItem.i */, 2611FF08142D83060017FEA3 /* SBSection.i */, 2611FF09142D83060017FEA3 /* SBSourceManager.i */, 2611FF0A142D83060017FEA3 /* SBStream.i */, 2611FF0B142D83060017FEA3 /* SBStringList.i */, 23DCBE981D63E14B0084C36B /* SBStructuredData.i */, 2611FF0C142D83060017FEA3 /* SBSymbol.i */, 2611FF0D142D83060017FEA3 /* SBSymbolContext.i */, 2611FF0E142D83060017FEA3 /* SBSymbolContextList.i */, 2611FF0F142D83060017FEA3 /* SBTarget.i */, 2611FF10142D83060017FEA3 /* SBThread.i */, 4C56543819D22FD9002E9C44 /* SBThreadPlan.i */, 8CCB018419BA54930009FD44 /* SBThreadCollection.i */, 2611FF11142D83060017FEA3 /* SBType.i */, 9475C18A14E5EA1C001BFC6D /* SBTypeCategory.i */, 23DCBE991D63E14B0084C36B /* SBTypeEnumMember.i */, 9461569214E3567F003A195C /* SBTypeFilter.i */, 9461569314E3567F003A195C /* SBTypeFormat.i */, 9475C18B14E5F818001BFC6D /* SBTypeNameSpecifier.i */, 9461569414E3567F003A195C /* SBTypeSummary.i */, 9461569514E3567F003A195C /* SBTypeSynthetic.i */, 23DCBE9A1D63E14B0084C36B /* SBUnixSignals.i */, 2611FF12142D83060017FEA3 /* SBValue.i */, 2611FF13142D83060017FEA3 /* SBValueList.i */, 94235B9D1A8D601A00EB2EED /* SBVariablesOptions.i */, B2A5872514313B480092BFBA /* SBWatchpoint.i */, ); name = interface; path = scripts/interface; sourceTree = SOURCE_ROOT; }; 26274FA414030F79006BA130 /* Darwin-Kernel */ = { isa = PBXGroup; children = ( 26274FA514030F79006BA130 /* DynamicLoaderDarwinKernel.cpp */, 26274FA614030F79006BA130 /* DynamicLoaderDarwinKernel.h */, ); path = "Darwin-Kernel"; sourceTree = ""; }; 262D3190111B4341004E6F88 /* API */ = { isa = PBXGroup; children = ( 2611FEEE142D83060017FEA3 /* interface */, 26BC7C2510F1B3BC00F91463 /* lldb-defines.h */, 26BC7C2610F1B3BC00F91463 /* lldb-enumerations.h */, 26DE1E6A11616C2E00A093E2 /* lldb-forward.h */, 26651A14133BEC76005B64B7 /* lldb-public.h */, 26BC7C2910F1B3BC00F91463 /* lldb-types.h */, 94145430175D7FDE00284436 /* lldb-versioning.h */, 26B42C4C1187ABA50079C8C8 /* LLDB.h */, 9A9830FC1125FC5800A56CB0 /* SBDefines.h */, 26DE204211618ACA00A093E2 /* SBAddress.h */, 26DE204411618ADA00A093E2 /* SBAddress.cpp */, 254FBBA21A9166F100BD6378 /* SBAttachInfo.h */, 254FBBA41A91670E00BD6378 /* SBAttachInfo.cpp */, 26DE205611618FC500A093E2 /* SBBlock.h */, 26DE20601161902600A093E2 /* SBBlock.cpp */, 9AF16A9E11402D69007A7B3F /* SBBreakpoint.h */, 9AF16A9C11402D5B007A7B3F /* SBBreakpoint.cpp */, 9AF16CC611408686007A7B3F /* SBBreakpointLocation.h */, 9AF16CC7114086A1007A7B3F /* SBBreakpointLocation.cpp */, 9A9830F31125FC5800A56CB0 /* SBBroadcaster.h */, 9A9830F21125FC5800A56CB0 /* SBBroadcaster.cpp */, 9A9830F71125FC5800A56CB0 /* SBCommandInterpreter.h */, 9A9830F61125FC5800A56CB0 /* SBCommandInterpreter.cpp */, 9A9830F91125FC5800A56CB0 /* SBCommandReturnObject.h */, 9A9830F81125FC5800A56CB0 /* SBCommandReturnObject.cpp */, 260223E7115F06D500A601A2 /* SBCommunication.h */, 260223E8115F06E500A601A2 /* SBCommunication.cpp */, 26DE205411618FB800A093E2 /* SBCompileUnit.h */, 26DE205E1161901B00A093E2 /* SBCompileUnit.cpp */, 9443B120140C18A90013457C /* SBData.h */, 9443B121140C18C10013457C /* SBData.cpp */, 9A9830FB1125FC5800A56CB0 /* SBDebugger.h */, 9A9830FA1125FC5800A56CB0 /* SBDebugger.cpp */, 9452573816262CEF00325455 /* SBDeclaration.h */, 9452573916262D0200325455 /* SBDeclaration.cpp */, 2682F286115EF3BD00CCFF99 /* SBError.h */, 2682F284115EF3A700CCFF99 /* SBError.cpp */, 9A9830FE1125FC5800A56CB0 /* SBEvent.h */, 9A9830FD1125FC5800A56CB0 /* SBEvent.cpp */, 940B02F419DC96CB00AD0F52 /* SBExecutionContext.h */, 940B02F519DC96E700AD0F52 /* SBExecutionContext.cpp */, 4CE4F672162C971A00F75CB3 /* SBExpressionOptions.h */, 4CE4F674162C973F00F75CB3 /* SBExpressionOptions.cpp */, 26022531115F27FA00A601A2 /* SBFileSpec.h */, 26022532115F281400A601A2 /* SBFileSpec.cpp */, 4CF52AF41428291E0051E832 /* SBFileSpecList.h */, 4CF52AF7142829390051E832 /* SBFileSpecList.cpp */, 9A633FE8112DCE3C001A7E43 /* SBFrame.h */, 9A633FE7112DCE3C001A7E43 /* SBFrame.cpp */, 26DE205211618FAC00A093E2 /* SBFunction.h */, 26DE205C1161901400A093E2 /* SBFunction.cpp */, 9A3576A7116E9AB700E8ED2F /* SBHostOS.h */, 9A3576A9116E9AC700E8ED2F /* SBHostOS.cpp */, 9AC7038D117674EB0086C050 /* SBInstruction.h */, 9AC703AE117675410086C050 /* SBInstruction.cpp */, 9AC7038F117675270086C050 /* SBInstructionList.h */, 9AC703B0117675490086C050 /* SBInstructionList.cpp */, 3392EBB71AFF402200858B9F /* SBLanguageRuntime.h */, AF20F76C1AF18FC700751A6E /* SBLanguageRuntime.cpp */, 254FBB961A81B03100BD6378 /* SBLaunchInfo.h */, 254FBB941A81AA7F00BD6378 /* SBLaunchInfo.cpp */, 26DE205811618FE700A093E2 /* SBLineEntry.h */, 26DE20621161904200A093E2 /* SBLineEntry.cpp */, 9A9831021125FC5800A56CB0 /* SBListener.h */, 9A9831011125FC5800A56CB0 /* SBListener.cpp */, 264297531D1DF209003F2BF4 /* SBMemoryRegionInfo.h */, 23DCEA421D1C4C6900A602B4 /* SBMemoryRegionInfo.cpp */, 264297541D1DF209003F2BF4 /* SBMemoryRegionInfoList.h */, 23DCEA431D1C4C6900A602B4 /* SBMemoryRegionInfoList.cpp */, 26DE204E11618E9800A093E2 /* SBModule.h */, 26DE204C11618E7A00A093E2 /* SBModule.cpp */, 263C4939178B50CF0070F12D /* SBModuleSpec.h */, 263C4937178B50C40070F12D /* SBModuleSpec.cpp */, 262F12B61835469C00AEB384 /* SBPlatform.h */, 262F12B41835468600AEB384 /* SBPlatform.cpp */, AF0EBBEA185941360059E52F /* SBQueue.h */, AF0EBBE6185940FB0059E52F /* SBQueue.cpp */, AF0EBBEB185941360059E52F /* SBQueueItem.h */, AF0EBBE7185940FB0059E52F /* SBQueueItem.cpp */, 9A9831041125FC5800A56CB0 /* SBProcess.h */, 9A9831031125FC5800A56CB0 /* SBProcess.cpp */, 26B8283C142D01E9002DBC64 /* SBSection.h */, 26B8283F142D020F002DBC64 /* SBSection.cpp */, 9A9831061125FC5800A56CB0 /* SBSourceManager.h */, 9A9831051125FC5800A56CB0 /* SBSourceManager.cpp */, 26C72C93124322890068DC16 /* SBStream.h */, 26C72C951243229A0068DC16 /* SBStream.cpp */, 9A357670116E7B5200E8ED2F /* SBStringList.h */, 9A357672116E7B6400E8ED2F /* SBStringList.cpp */, 23DCBE9F1D63E3800084C36B /* SBStructuredData.h */, 23DCBEA01D63E6440084C36B /* SBStructuredData.cpp */, 26DE205A11618FF600A093E2 /* SBSymbol.h */, 26DE20641161904E00A093E2 /* SBSymbol.cpp */, 26DE204011618AB900A093E2 /* SBSymbolContext.h */, 26DE204611618AED00A093E2 /* SBSymbolContext.cpp */, 268F9D52123AA15200B91E9B /* SBSymbolContextList.h */, 268F9D54123AA16600B91E9B /* SBSymbolContextList.cpp */, 9A9831081125FC5800A56CB0 /* SBTarget.h */, 9A9831071125FC5800A56CB0 /* SBTarget.cpp */, 9A98310A1125FC5800A56CB0 /* SBThread.h */, 9A9831091125FC5800A56CB0 /* SBThread.cpp */, 8CCB018119BA4E210009FD44 /* SBThreadCollection.h */, 8CCB017F19BA4DD00009FD44 /* SBThreadCollection.cpp */, 4C56543419D2297A002E9C44 /* SBThreadPlan.h */, 4C56543619D22B32002E9C44 /* SBThreadPlan.cpp */, 9A1E59581EB2B10D002206A5 /* SBTrace.h */, 9A1E59521EB2B0B9002206A5 /* SBTrace.cpp */, 9A1E59591EB2B10D002206A5 /* SBTraceOptions.h */, 9A1E59531EB2B0B9002206A5 /* SBTraceOptions.cpp */, 2617447911685869005ADD65 /* SBType.h */, 261744771168585B005ADD65 /* SBType.cpp */, 9475C18514E5E9C5001BFC6D /* SBTypeCategory.h */, 9475C18714E5E9FA001BFC6D /* SBTypeCategory.cpp */, 23EFE388193D1ABC00E54E54 /* SBTypeEnumMember.h */, 23EFE38A193D1AEC00E54E54 /* SBTypeEnumMember.cpp */, 9461568614E355F2003A195C /* SBTypeFilter.h */, 9461568A14E35621003A195C /* SBTypeFilter.cpp */, 9461568714E355F2003A195C /* SBTypeFormat.h */, 9461568B14E35621003A195C /* SBTypeFormat.cpp */, 9475C18C14E5F826001BFC6D /* SBTypeNameSpecifier.h */, 9475C18D14E5F834001BFC6D /* SBTypeNameSpecifier.cpp */, 9461568814E355F2003A195C /* SBTypeSummary.h */, 9461568C14E35621003A195C /* SBTypeSummary.cpp */, 9461568914E355F2003A195C /* SBTypeSynthetic.h */, 9461568D14E35621003A195C /* SBTypeSynthetic.cpp */, 23059A111958B37B007B8189 /* SBUnixSignals.h */, 23059A0F1958B319007B8189 /* SBUnixSignals.cpp */, 9A19A6A51163BB7E00E0D453 /* SBValue.h */, 9A19A6AD1163BB9800E0D453 /* SBValue.cpp */, 9A357582116CFDEE00E8ED2F /* SBValueList.h */, 9A35758D116CFE0F00E8ED2F /* SBValueList.cpp */, 94235B9A1A8D5FD800EB2EED /* SBVariablesOptions.h */, 94235B9B1A8D5FF300EB2EED /* SBVariablesOptions.cpp */, B2A58721143119810092BFBA /* SBWatchpoint.h */, B2A58723143119D50092BFBA /* SBWatchpoint.cpp */, 3F81692D1ABB7A40001DA9DF /* SystemInitializerFull.h */, 3F81692A1ABB7A16001DA9DF /* SystemInitializerFull.cpp */, ); name = API; sourceTree = ""; }; 2635878D17822E56004C30BA /* ELF */ = { isa = PBXGroup; children = ( 2635879017822E56004C30BA /* SymbolVendorELF.cpp */, 2635879117822E56004C30BA /* SymbolVendorELF.h */, ); path = ELF; sourceTree = ""; }; 263641141B34AEE200145B2F /* SysV-mips64 */ = { isa = PBXGroup; children = ( 263641151B34AEE200145B2F /* ABISysV_mips64.cpp */, 263641161B34AEE200145B2F /* ABISysV_mips64.h */, ); path = "SysV-mips64"; sourceTree = ""; }; 2642FBA713D003B400ED6808 /* MacOSX-Kernel */ = { isa = PBXGroup; children = ( AF0F6E4E1739A76D009180FE /* RegisterContextKDP_arm64.cpp */, AF0F6E4F1739A76D009180FE /* RegisterContextKDP_arm64.h */, 2642FBA813D003B400ED6808 /* CommunicationKDP.cpp */, 2642FBA913D003B400ED6808 /* CommunicationKDP.h */, 2642FBAA13D003B400ED6808 /* ProcessKDP.cpp */, 2642FBAB13D003B400ED6808 /* ProcessKDP.h */, 2642FBAC13D003B400ED6808 /* ProcessKDPLog.cpp */, 2642FBAD13D003B400ED6808 /* ProcessKDPLog.h */, 265205A213D3E3F700132FE2 /* RegisterContextKDP_arm.cpp */, 265205A313D3E3F700132FE2 /* RegisterContextKDP_arm.h */, 265205A413D3E3F700132FE2 /* RegisterContextKDP_i386.cpp */, 265205A513D3E3F700132FE2 /* RegisterContextKDP_i386.h */, 265205A613D3E3F700132FE2 /* RegisterContextKDP_x86_64.cpp */, 265205A713D3E3F700132FE2 /* RegisterContextKDP_x86_64.h */, 2628A4D313D4977900F5487A /* ThreadKDP.cpp */, 2628A4D413D4977900F5487A /* ThreadKDP.h */, ); path = "MacOSX-Kernel"; sourceTree = ""; }; 264A12F91372522000875C42 /* ARM64 */ = { isa = PBXGroup; children = ( 264A12FA1372522000875C42 /* EmulateInstructionARM64.cpp */, 264A12FB1372522000875C42 /* EmulateInstructionARM64.h */, ); name = ARM64; path = source/Plugins/Instruction/ARM64; sourceTree = SOURCE_ROOT; }; 264A97BC133918A30017F0BE /* GDB Server */ = { isa = PBXGroup; children = ( 264A97BD133918BC0017F0BE /* PlatformRemoteGDBServer.cpp */, 264A97BE133918BC0017F0BE /* PlatformRemoteGDBServer.h */, ); name = "GDB Server"; sourceTree = ""; }; 264E8576159BE51A00E9D7A2 /* Resources */ = { isa = PBXGroup; children = ( AF90106315AB7C5700FF120D /* lldb.1 */, 268648C116531BF800F04704 /* com.apple.debugserver.posix.plist */, 268648C216531BF800F04704 /* com.apple.debugserver.applist.internal.plist */, 268648C316531BF800F04704 /* com.apple.debugserver.internal.plist */, AFF87C8E150FF688000E1742 /* com.apple.debugserver.applist.plist */, AFF87C8C150FF680000E1742 /* com.apple.debugserver.applist.plist */, AFF87C8A150FF677000E1742 /* com.apple.debugserver.applist.plist */, AFF87C86150FF669000E1742 /* com.apple.debugserver.plist */, ); name = Resources; sourceTree = ""; }; 26579F55126A255E0007C5CB /* darwin-debug */ = { isa = PBXGroup; children = ( 26368A3B126B697600E8659F /* darwin-debug.cpp */, ); name = "darwin-debug"; sourceTree = ""; }; 265E9BE0115C2B8500D0DCCB /* debugserver */ = { isa = PBXGroup; children = ( 265E9BE1115C2BAA00D0DCCB /* debugserver.xcodeproj */, ); name = debugserver; sourceTree = ""; }; 265E9BE2115C2BAA00D0DCCB /* Products */ = { isa = PBXGroup; children = ( 26CE05A0115C31E50022F371 /* debugserver */, 239504C51BDD3FD700963CEA /* debugserver-nonui */, ); name = Products; sourceTree = ""; }; 2665CD0915080846002C8FAE /* install-headers */ = { isa = PBXGroup; children = ( 2665CD0D15080846002C8FAE /* Makefile */, ); name = "install-headers"; path = "tools/install-headers"; sourceTree = ""; }; 2666ADBF1B3CB675001FAFD3 /* Hexagon-DYLD */ = { isa = PBXGroup; children = ( 2666ADC11B3CB675001FAFD3 /* DynamicLoaderHexagonDYLD.cpp */, 2666ADC21B3CB675001FAFD3 /* DynamicLoaderHexagonDYLD.h */, 2666ADC31B3CB675001FAFD3 /* HexagonDYLDRendezvous.cpp */, 2666ADC41B3CB675001FAFD3 /* HexagonDYLDRendezvous.h */, ); path = "Hexagon-DYLD"; sourceTree = ""; }; 266960581199F4230075C61A /* Scripts */ = { isa = PBXGroup; children = ( 266960591199F4230075C61A /* build-llvm.pl */, 2669605A1199F4230075C61A /* build-swig-wrapper-classes.sh */, 2669605B1199F4230075C61A /* checkpoint-llvm.pl */, 2669605C1199F4230075C61A /* finish-swig-wrapper-classes.sh */, 2669605D1199F4230075C61A /* install-lldb.sh */, 2669605E1199F4230075C61A /* lldb.swig */, 2669605F1199F4230075C61A /* Python */, 266960631199F4230075C61A /* sed-sources */, ); name = Scripts; path = scripts; sourceTree = ""; }; 2669605F1199F4230075C61A /* Python */ = { isa = PBXGroup; children = ( 266960601199F4230075C61A /* build-swig-Python.sh */, 266960611199F4230075C61A /* edit-swig-python-wrapper-file.py */, 94FE476613FC1DA8001F8475 /* finish-swig-Python-LLDB.sh */, 94E367CC140C4EC4001C7A5A /* modify-python-lldb.py */, 9A48A3A7124AAA5A00922451 /* python-extensions.swig */, 944DC3481774C99000D7D884 /* python-swigsafecast.swig */, 94E367CE140C4EEA001C7A5A /* python-typemaps.swig */, 94005E0313F438DF001EF42D /* python-wrapper.swig */, ); path = Python; sourceTree = ""; }; 266DFE9013FD64D200D0C574 /* OperatingSystem */ = { isa = PBXGroup; children = ( AE8F624519EF3DFC00326B21 /* Go */, 2698699715E6CBD0002415FF /* Python */, ); path = OperatingSystem; sourceTree = ""; }; 267F68461CC02DED0086832B /* SysV-s390x */ = { isa = PBXGroup; children = ( 267F68471CC02DED0086832B /* ABISysV_s390x.cpp */, 267F68481CC02DED0086832B /* ABISysV_s390x.h */, ); path = "SysV-s390x"; sourceTree = ""; }; 2682F168115ED9C800CCFF99 /* Utility */ = { isa = PBXGroup; children = ( 26BC7D5710F1B77400F91463 /* Connection.h */, 26BC7E6F10F1B85900F91463 /* Connection.cpp */, 26FA4315130103F400E71120 /* FileSpec.h */, 26FA43171301048600E71120 /* FileSpec.cpp */, 26CF992414428766001E4138 /* AnsiTerminal.h */, 26F996A7119B79C300412154 /* ARM_DWARF_Registers.h */, 264A12FF137252C700875C42 /* ARM64_DWARF_Registers.h */, AFC2DCE81E6E2F2C00283714 /* Baton.cpp */, AFC2DCEE1E6E2FA300283714 /* Baton.h */, 264723A511FA076E00DE380C /* CleanUp.h */, 26764C951E48F46F008D3573 /* ConstString.h */, 26764C961E48F482008D3573 /* ConstString.cpp */, 49CA96F01E6AAC8E00C03FEE /* DataBuffer.h */, 49CA96F11E6AAC8E00C03FEE /* DataBufferHeap.h */, 49CA96E61E6AAC6600C03FEE /* DataBufferHeap.cpp */, 49CA96F21E6AAC8E00C03FEE /* DataBufferLLVM.h */, 49CA96E71E6AAC6600C03FEE /* DataBufferLLVM.cpp */, 49CA96F31E6AAC8E00C03FEE /* DataEncoder.h */, 49CA96E81E6AAC6600C03FEE /* DataEncoder.cpp */, 49CA96F41E6AAC8E00C03FEE /* DataExtractor.h */, 49CA96E91E6AAC6600C03FEE /* DataExtractor.cpp */, 9481FE6B1B5F2D9200DED357 /* Either.h */, 26BC7DD310F1B7D500F91463 /* Endian.h */, AFC2DCE61E6E2ED000283714 /* FastDemangle.cpp */, AFC2DCED1E6E2F9800283714 /* FastDemangle.h */, AFC2DCF21E6E30CF00283714 /* History.cpp */, AFC2DCF41E6E30D800283714 /* History.h */, 236124A61986B50E004EFC37 /* IOObject.h */, 236124A21986B4E2004EFC37 /* IOObject.cpp */, 4C73152119B7D71700F865A4 /* Iterable.h */, 942829541A89614000521B30 /* JSON.h */, 942829551A89614C00521B30 /* JSON.cpp */, 943BDEFC1AA7B2DE00789CE8 /* LLDBAssert.h */, 943BDEFD1AA7B2F800789CE8 /* LLDBAssert.cpp */, 3F81691C1ABA242B001DA9DF /* NameMatches.h */, 3F8169181ABA2419001DA9DF /* NameMatches.cpp */, 26764C9C1E48F516008D3573 /* RegularExpression.h */, 26764C9F1E48F528008D3573 /* RegularExpression.cpp */, 4CAB257C18EC9DB800BAD33E /* SafeMachO.h */, 26A375841D59487700D6CBDB /* SelectHelper.h */, 26A3757F1D59462700D6CBDB /* SelectHelper.cpp */, 261B5A5211C3F2AD00AABD0A /* SharingPtr.cpp */, 4C2FAE2E135E3A70001EDE44 /* SharedCluster.h */, 261B5A5311C3F2AD00AABD0A /* SharingPtr.h */, 492DB7E61EC662B100B9E9AF /* Status.h */, 492DB7E81EC662D100B9E9AF /* Status.cpp */, 26764C9B1E48F50C008D3573 /* Stream.h */, 26764C9D1E48F51E008D3573 /* Stream.cpp */, AFC2DCF51E6E316A00283714 /* StreamCallback.cpp */, AFC2DCF71E6E316F00283714 /* StreamCallback.h */, AFC2DCF81E6E318000283714 /* StreamGDBRemote.cpp */, AFC2DCFA1E6E318600283714 /* StreamGDBRemote.h */, 26764CA31E48F550008D3573 /* StreamString.h */, 26764CA11E48F547008D3573 /* StreamString.cpp */, 26764CA41E48F566008D3573 /* StreamTee.h */, 26A375831D59486000D6CBDB /* StringExtractor.h */, 2660D9F611922A1300958FBD /* StringExtractor.cpp */, 2676A094119C93C8008A98EF /* StringExtractorGDBRemote.h */, 2676A093119C93C8008A98EF /* StringExtractorGDBRemote.cpp */, 94380B8019940B0300BFE4A8 /* StringLexer.h */, 94380B8119940B0A00BFE4A8 /* StringLexer.cpp */, 9A35765E116E76A700E8ED2F /* StringList.h */, 9A35765F116E76B900E8ED2F /* StringList.cpp */, 26F2F8FD1B156678007857DE /* StructuredData.h */, AFEC3361194A8ABA00FF05C6 /* StructuredData.cpp */, 94BA8B6E176F8CA0005A91B5 /* Range.h */, 94BA8B6C176F8C9B005A91B5 /* Range.cpp */, 6DEC6F3A1BD66D950091ABA6 /* TaskPool.h */, 6DEC6F381BD66D750091ABA6 /* TaskPool.cpp */, AFF8FF0B1E779D4B003830EF /* TildeExpressionResolver.cpp */, AFF8FF0D1E779D51003830EF /* TildeExpressionResolver.h */, 26BC7D7E10F1B77400F91463 /* Timer.h */, 26BC7E9610F1B85900F91463 /* Timer.cpp */, 2654A6911E552F3C00DA1013 /* UriParser.h */, 33064C991A5C7A330033D415 /* UriParser.cpp */, AFC2DCEA1E6E2F7D00283714 /* UserID.cpp */, AFC2DCEC1E6E2F8C00283714 /* UserID.h */, 49CA96F51E6AAC8E00C03FEE /* UUID.h */, 49CA96EA1E6AAC6600C03FEE /* UUID.cpp */, AFC2DCEF1E6E2FD200283714 /* VMRange.cpp */, AFC2DCF11E6E2FDA00283714 /* VMRange.h */, 2654A6921E552F4600DA1013 /* VASPrintf.h */, 2654A68F1E552ED500DA1013 /* VASprintf.cpp */, ); name = Utility; sourceTree = ""; }; 268A683C1321B505000E3FB8 /* Static */ = { isa = PBXGroup; children = ( 268A683E1321B53B000E3FB8 /* DynamicLoaderStatic.h */, 268A683D1321B53B000E3FB8 /* DynamicLoaderStatic.cpp */, ); path = Static; sourceTree = ""; }; 2690CD181A6DC0D000E717C8 /* lldb-mi */ = { isa = PBXGroup; children = ( 2669415B1A6DC2AB0063BE93 /* CMakeLists.txt */, 2669415E1A6DC2AB0063BE93 /* lldb-Info.plist */, 2669415F1A6DC2AB0063BE93 /* Makefile */, 266941601A6DC2AB0063BE93 /* MICmdArgContext.cpp */, 266941611A6DC2AB0063BE93 /* MICmdArgContext.h */, 266941621A6DC2AB0063BE93 /* MICmdArgSet.cpp */, 266941631A6DC2AB0063BE93 /* MICmdArgSet.h */, 266941641A6DC2AB0063BE93 /* MICmdArgValBase.cpp */, 266941651A6DC2AB0063BE93 /* MICmdArgValBase.h */, 266941661A6DC2AB0063BE93 /* MICmdArgValConsume.cpp */, 266941671A6DC2AB0063BE93 /* MICmdArgValConsume.h */, 266941681A6DC2AB0063BE93 /* MICmdArgValFile.cpp */, 266941691A6DC2AB0063BE93 /* MICmdArgValFile.h */, 2669416A1A6DC2AC0063BE93 /* MICmdArgValListBase.cpp */, 2669416B1A6DC2AC0063BE93 /* MICmdArgValListBase.h */, 2669416C1A6DC2AC0063BE93 /* MICmdArgValListOfN.cpp */, 2669416D1A6DC2AC0063BE93 /* MICmdArgValListOfN.h */, 2669416E1A6DC2AC0063BE93 /* MICmdArgValNumber.cpp */, 2669416F1A6DC2AC0063BE93 /* MICmdArgValNumber.h */, 266941701A6DC2AC0063BE93 /* MICmdArgValOptionLong.cpp */, 266941711A6DC2AC0063BE93 /* MICmdArgValOptionLong.h */, 266941721A6DC2AC0063BE93 /* MICmdArgValOptionShort.cpp */, 266941731A6DC2AC0063BE93 /* MICmdArgValOptionShort.h */, 267DFB441B06752A00000FB7 /* MICmdArgValPrintValues.cpp */, 267DFB451B06752A00000FB7 /* MICmdArgValPrintValues.h */, 266941741A6DC2AC0063BE93 /* MICmdArgValString.cpp */, 266941751A6DC2AC0063BE93 /* MICmdArgValString.h */, 266941761A6DC2AC0063BE93 /* MICmdArgValThreadGrp.cpp */, 266941771A6DC2AC0063BE93 /* MICmdArgValThreadGrp.h */, 266941781A6DC2AC0063BE93 /* MICmdBase.cpp */, 266941791A6DC2AC0063BE93 /* MICmdBase.h */, 2669417A1A6DC2AC0063BE93 /* MICmdCmd.cpp */, 2669417B1A6DC2AC0063BE93 /* MICmdCmd.h */, 2669417C1A6DC2AC0063BE93 /* MICmdCmdBreak.cpp */, 2669417D1A6DC2AC0063BE93 /* MICmdCmdBreak.h */, 2669417E1A6DC2AC0063BE93 /* MICmdCmdData.cpp */, 2669417F1A6DC2AC0063BE93 /* MICmdCmdData.h */, 266941801A6DC2AC0063BE93 /* MICmdCmdEnviro.cpp */, 266941811A6DC2AC0063BE93 /* MICmdCmdEnviro.h */, 266941821A6DC2AC0063BE93 /* MICmdCmdExec.cpp */, 266941831A6DC2AC0063BE93 /* MICmdCmdExec.h */, 266941841A6DC2AC0063BE93 /* MICmdCmdFile.cpp */, 266941851A6DC2AC0063BE93 /* MICmdCmdFile.h */, 266941861A6DC2AC0063BE93 /* MICmdCmdGdbInfo.cpp */, 266941871A6DC2AC0063BE93 /* MICmdCmdGdbInfo.h */, 266941881A6DC2AC0063BE93 /* MICmdCmdGdbSet.cpp */, 266941891A6DC2AC0063BE93 /* MICmdCmdGdbSet.h */, AFB3D27E1AC262AB003B4B30 /* MICmdCmdGdbShow.cpp */, AFB3D27F1AC262AB003B4B30 /* MICmdCmdGdbShow.h */, 2669418A1A6DC2AC0063BE93 /* MICmdCmdGdbThread.cpp */, 2669418B1A6DC2AC0063BE93 /* MICmdCmdGdbThread.h */, 2669418C1A6DC2AC0063BE93 /* MICmdCmdMiscellanous.cpp */, 2669418D1A6DC2AC0063BE93 /* MICmdCmdMiscellanous.h */, 2669418E1A6DC2AC0063BE93 /* MICmdCmdStack.cpp */, 2669418F1A6DC2AC0063BE93 /* MICmdCmdStack.h */, 266941901A6DC2AC0063BE93 /* MICmdCmdSupportInfo.cpp */, 266941911A6DC2AC0063BE93 /* MICmdCmdSupportInfo.h */, 266941921A6DC2AC0063BE93 /* MICmdCmdSupportList.cpp */, 266941931A6DC2AC0063BE93 /* MICmdCmdSupportList.h */, 26D52C1D1A980FE300E5D2FB /* MICmdCmdSymbol.cpp */, 26D52C1E1A980FE300E5D2FB /* MICmdCmdSymbol.h */, 266941941A6DC2AC0063BE93 /* MICmdCmdTarget.cpp */, 266941951A6DC2AC0063BE93 /* MICmdCmdTarget.h */, 266941961A6DC2AC0063BE93 /* MICmdCmdThread.cpp */, 266941971A6DC2AC0063BE93 /* MICmdCmdThread.h */, 266941981A6DC2AC0063BE93 /* MICmdCmdTrace.cpp */, 266941991A6DC2AC0063BE93 /* MICmdCmdTrace.h */, 2669419A1A6DC2AC0063BE93 /* MICmdCmdVar.cpp */, 2669419B1A6DC2AC0063BE93 /* MICmdCmdVar.h */, 2669419C1A6DC2AC0063BE93 /* MICmdCommands.cpp */, 2669419D1A6DC2AC0063BE93 /* MICmdCommands.h */, 2669419E1A6DC2AC0063BE93 /* MICmdData.cpp */, 2669419F1A6DC2AC0063BE93 /* MICmdData.h */, 266941A01A6DC2AC0063BE93 /* MICmdFactory.cpp */, 266941A11A6DC2AC0063BE93 /* MICmdFactory.h */, 266941A21A6DC2AC0063BE93 /* MICmdInterpreter.cpp */, 266941A31A6DC2AC0063BE93 /* MICmdInterpreter.h */, 266941A41A6DC2AC0063BE93 /* MICmdInvoker.cpp */, 266941A51A6DC2AC0063BE93 /* MICmdInvoker.h */, 266941A61A6DC2AC0063BE93 /* MICmdMgr.cpp */, 266941A71A6DC2AC0063BE93 /* MICmdMgr.h */, 266941A81A6DC2AC0063BE93 /* MICmdMgrSetCmdDeleteCallback.cpp */, 266941A91A6DC2AC0063BE93 /* MICmdMgrSetCmdDeleteCallback.h */, 266941AA1A6DC2AC0063BE93 /* MICmnBase.cpp */, 266941AB1A6DC2AC0063BE93 /* MICmnBase.h */, 266941AC1A6DC2AC0063BE93 /* MICmnConfig.h */, 266941AD1A6DC2AC0063BE93 /* MICmnLLDBBroadcaster.cpp */, 266941AE1A6DC2AC0063BE93 /* MICmnLLDBBroadcaster.h */, 266941AF1A6DC2AC0063BE93 /* MICmnLLDBDebugger.cpp */, 266941B01A6DC2AC0063BE93 /* MICmnLLDBDebugger.h */, 266941B11A6DC2AC0063BE93 /* MICmnLLDBDebuggerHandleEvents.cpp */, 266941B21A6DC2AC0063BE93 /* MICmnLLDBDebuggerHandleEvents.h */, 266941B31A6DC2AC0063BE93 /* MICmnLLDBDebugSessionInfo.cpp */, 266941B41A6DC2AC0063BE93 /* MICmnLLDBDebugSessionInfo.h */, 266941B51A6DC2AC0063BE93 /* MICmnLLDBDebugSessionInfoVarObj.cpp */, 266941B61A6DC2AC0063BE93 /* MICmnLLDBDebugSessionInfoVarObj.h */, 266941B71A6DC2AC0063BE93 /* MICmnLLDBProxySBValue.cpp */, 266941B81A6DC2AC0063BE93 /* MICmnLLDBProxySBValue.h */, 266941B91A6DC2AC0063BE93 /* MICmnLLDBUtilSBValue.cpp */, 266941BA1A6DC2AC0063BE93 /* MICmnLLDBUtilSBValue.h */, 266941BB1A6DC2AC0063BE93 /* MICmnLog.cpp */, 266941BC1A6DC2AC0063BE93 /* MICmnLog.h */, 266941BD1A6DC2AC0063BE93 /* MICmnLogMediumFile.cpp */, 266941BE1A6DC2AC0063BE93 /* MICmnLogMediumFile.h */, 266941BF1A6DC2AC0063BE93 /* MICmnMIOutOfBandRecord.cpp */, 266941C01A6DC2AC0063BE93 /* MICmnMIOutOfBandRecord.h */, 266941C11A6DC2AC0063BE93 /* MICmnMIResultRecord.cpp */, 266941C21A6DC2AC0063BE93 /* MICmnMIResultRecord.h */, 266941C31A6DC2AC0063BE93 /* MICmnMIValue.cpp */, 266941C41A6DC2AC0063BE93 /* MICmnMIValue.h */, 266941C51A6DC2AC0063BE93 /* MICmnMIValueConst.cpp */, 266941C61A6DC2AC0063BE93 /* MICmnMIValueConst.h */, 266941C71A6DC2AC0063BE93 /* MICmnMIValueList.cpp */, 266941C81A6DC2AC0063BE93 /* MICmnMIValueList.h */, 266941C91A6DC2AC0063BE93 /* MICmnMIValueResult.cpp */, 266941CA1A6DC2AC0063BE93 /* MICmnMIValueResult.h */, 266941CB1A6DC2AC0063BE93 /* MICmnMIValueTuple.cpp */, 266941CC1A6DC2AC0063BE93 /* MICmnMIValueTuple.h */, 266941CD1A6DC2AC0063BE93 /* MICmnResources.cpp */, 266941CE1A6DC2AC0063BE93 /* MICmnResources.h */, 266941CF1A6DC2AC0063BE93 /* MICmnStreamStderr.cpp */, 266941D01A6DC2AC0063BE93 /* MICmnStreamStderr.h */, 266941D11A6DC2AC0063BE93 /* MICmnStreamStdin.cpp */, 266941D21A6DC2AC0063BE93 /* MICmnStreamStdin.h */, 266941D71A6DC2AC0063BE93 /* MICmnStreamStdout.cpp */, 266941D81A6DC2AC0063BE93 /* MICmnStreamStdout.h */, 266941D91A6DC2AC0063BE93 /* MICmnThreadMgrStd.cpp */, 266941DA1A6DC2AC0063BE93 /* MICmnThreadMgrStd.h */, 266941DB1A6DC2AC0063BE93 /* MIDataTypes.h */, 266941DC1A6DC2AC0063BE93 /* MIDriver.cpp */, 266941DD1A6DC2AC0063BE93 /* MIDriver.h */, 266941DE1A6DC2AC0063BE93 /* MIDriverBase.cpp */, 266941DF1A6DC2AC0063BE93 /* MIDriverBase.h */, 266941E01A6DC2AC0063BE93 /* MIDriverMain.cpp */, 266941E11A6DC2AC0063BE93 /* MIDriverMgr.cpp */, 266941E21A6DC2AC0063BE93 /* MIDriverMgr.h */, 266941E31A6DC2AC0063BE93 /* MIReadMe.txt */, 266941E41A6DC2AC0063BE93 /* MIUtilDateTimeStd.cpp */, 266941E51A6DC2AC0063BE93 /* MIUtilDateTimeStd.h */, 266941E61A6DC2AC0063BE93 /* MIUtilDebug.cpp */, 266941E71A6DC2AC0063BE93 /* MIUtilDebug.h */, 266941E81A6DC2AC0063BE93 /* MIUtilFileStd.cpp */, 266941E91A6DC2AC0063BE93 /* MIUtilFileStd.h */, 266941EA1A6DC2AC0063BE93 /* MIUtilMapIdToVariant.cpp */, 266941EB1A6DC2AC0063BE93 /* MIUtilMapIdToVariant.h */, 266941EC1A6DC2AC0063BE93 /* MIUtilSingletonBase.h */, 266941ED1A6DC2AC0063BE93 /* MIUtilSingletonHelper.h */, 266941EE1A6DC2AC0063BE93 /* MIUtilString.cpp */, 266941EF1A6DC2AC0063BE93 /* MIUtilString.h */, 266941F81A6DC2AC0063BE93 /* MIUtilThreadBaseStd.cpp */, 266941F91A6DC2AC0063BE93 /* MIUtilThreadBaseStd.h */, 266941FA1A6DC2AC0063BE93 /* MIUtilVariant.cpp */, 266941FB1A6DC2AC0063BE93 /* MIUtilVariant.h */, 266941FD1A6DC2AC0063BE93 /* Platform.h */, ); path = "lldb-mi"; sourceTree = ""; }; 2692BA12136610C100F9E14D /* InstEmulation */ = { isa = PBXGroup; children = ( 2692BA13136610C100F9E14D /* UnwindAssemblyInstEmulation.cpp */, 2692BA14136610C100F9E14D /* UnwindAssemblyInstEmulation.h */, ); path = InstEmulation; sourceTree = ""; }; 2692BA17136611CD00F9E14D /* x86 */ = { isa = PBXGroup; children = ( AF415AE51D949E4400FCE0D4 /* x86AssemblyInspectionEngine.cpp */, AF415AE61D949E4400FCE0D4 /* x86AssemblyInspectionEngine.h */, 263E949D13661AE400E7D1CE /* UnwindAssembly-x86.cpp */, 263E949E13661AE400E7D1CE /* UnwindAssembly-x86.h */, ); path = x86; sourceTree = ""; }; 2694E99814FC0BB30076DE67 /* FreeBSD */ = { isa = PBXGroup; children = ( 2694E99A14FC0BB30076DE67 /* PlatformFreeBSD.cpp */, 2694E99B14FC0BB30076DE67 /* PlatformFreeBSD.h */, ); path = FreeBSD; sourceTree = ""; }; 2694E99F14FC0BBD0076DE67 /* Linux */ = { isa = PBXGroup; children = ( 2694E9A114FC0BBD0076DE67 /* PlatformLinux.cpp */, 2694E9A214FC0BBD0076DE67 /* PlatformLinux.h */, ); path = Linux; sourceTree = ""; }; 2698699715E6CBD0002415FF /* Python */ = { isa = PBXGroup; children = ( 2698699815E6CBD0002415FF /* OperatingSystemPython.cpp */, 2698699915E6CBD0002415FF /* OperatingSystemPython.h */, ); path = Python; sourceTree = ""; }; 26A3B4AB1181454800381BC2 /* BSD-Archive */ = { isa = PBXGroup; children = ( 26A3B4AC1181454800381BC2 /* ObjectContainerBSDArchive.cpp */, 26A3B4AD1181454800381BC2 /* ObjectContainerBSDArchive.h */, ); path = "BSD-Archive"; sourceTree = ""; }; 26A527BC14E24F5F00F3A14A /* mach-core */ = { isa = PBXGroup; children = ( 26A527BD14E24F5F00F3A14A /* ProcessMachCore.cpp */, 26A527BE14E24F5F00F3A14A /* ProcessMachCore.h */, 26A527BF14E24F5F00F3A14A /* ThreadMachCore.cpp */, 26A527C014E24F5F00F3A14A /* ThreadMachCore.h */, ); path = "mach-core"; sourceTree = ""; }; 26AC3F441365F40E0065C7EF /* UnwindAssembly */ = { isa = PBXGroup; children = ( 2692BA12136610C100F9E14D /* InstEmulation */, 2692BA17136611CD00F9E14D /* x86 */, ); path = UnwindAssembly; sourceTree = ""; }; 26B4666E11A2080F00CF6220 /* Utility */ = { isa = PBXGroup; children = ( 9A0FDE951E8EF5010086B2F5 /* RegisterContext_mips.h */, 9A0FDE961E8EF5010086B2F5 /* RegisterContext_s390x.h */, 9A0FDE971E8EF5010086B2F5 /* RegisterContextLinux_mips.cpp */, 9A0FDE981E8EF5010086B2F5 /* RegisterContextLinux_mips.h */, 9A0FDE991E8EF5010086B2F5 /* RegisterInfos_arm.h */, 9A0FDE9A1E8EF5010086B2F5 /* RegisterInfos_arm64.h */, 9A0FDE9B1E8EF5010086B2F5 /* RegisterInfos_mips.h */, 9AD9449B1E8DB267004796ED /* RegisterContextNetBSD_x86_64.cpp */, 9AD9449C1E8DB267004796ED /* RegisterContextNetBSD_x86_64.h */, 23F403471926C8D50046DC9B /* NativeRegisterContextRegisterInfo.h */, 23F403481926CC250046DC9B /* NativeRegisterContextRegisterInfo.cpp */, B287E63E12EFAE2C00C9BEFE /* ARMDefines.h */, B23DD24F12EDFAC1000C3894 /* ARMUtils.h */, 26954EBC1401EE8B00294D09 /* DynamicRegisterInfo.cpp */, 26954EBD1401EE8B00294D09 /* DynamicRegisterInfo.h */, AF23B4D919009C66003E2A58 /* FreeBSDSignals.cpp */, AF23B4DA19009C66003E2A58 /* FreeBSDSignals.h */, E73A15A41B548EC500786197 /* GDBRemoteSignals.cpp */, E73A15A51B548EC500786197 /* GDBRemoteSignals.h */, AF1729D4182C907200E0AB97 /* HistoryThread.cpp */, AF061F89182C980000B6A19C /* HistoryThread.h */, AF1729D5182C907200E0AB97 /* HistoryUnwind.cpp */, AF061F8A182C980000B6A19C /* HistoryUnwind.h */, B28058A0139988B0002D96D0 /* InferiorCallPOSIX.cpp */, B28058A2139988C6002D96D0 /* InferiorCallPOSIX.h */, B2D3033612EFA5C500F84EB3 /* InstructionUtils.h */, 23059A0519532B96007B8189 /* LinuxSignals.cpp */, 23059A0619532B96007B8189 /* LinuxSignals.h */, 23173F8B192BA93F005C708F /* lldb-x86-register-enums.h */, 26B75B421AD6E29A001F7A57 /* MipsLinuxSignals.cpp */, 26B75B431AD6E29A001F7A57 /* MipsLinuxSignals.h */, AF33B4BC1C1FA441001B28D9 /* NetBSDSignals.cpp */, AF33B4BD1C1FA441001B28D9 /* NetBSDSignals.h */, AF77E0991A033D360096C0EA /* RegisterContext_powerpc.h */, 26474C9F18D0CAEC0073DEBA /* RegisterContext_x86.h */, 26957D9213D381C900670048 /* RegisterContextDarwin_arm.cpp */, 26957D9313D381C900670048 /* RegisterContextDarwin_arm.h */, AF9107EC168570D200DBCD3C /* RegisterContextDarwin_arm64.cpp */, AF9107ED168570D200DBCD3C /* RegisterContextDarwin_arm64.h */, 26957D9413D381C900670048 /* RegisterContextDarwin_i386.cpp */, 26957D9513D381C900670048 /* RegisterContextDarwin_i386.h */, 26957D9613D381C900670048 /* RegisterContextDarwin_x86_64.cpp */, 26957D9713D381C900670048 /* RegisterContextDarwin_x86_64.h */, 944372DA171F6B4300E57C32 /* RegisterContextDummy.cpp */, 944372DB171F6B4300E57C32 /* RegisterContextDummy.h */, 26474CA218D0CB070073DEBA /* RegisterContextFreeBSD_i386.cpp */, 26474CA318D0CB070073DEBA /* RegisterContextFreeBSD_i386.h */, 26474CA418D0CB070073DEBA /* RegisterContextFreeBSD_mips64.cpp */, 26474CA518D0CB070073DEBA /* RegisterContextFreeBSD_mips64.h */, AF77E09A1A033D360096C0EA /* RegisterContextFreeBSD_powerpc.cpp */, AF77E09B1A033D360096C0EA /* RegisterContextFreeBSD_powerpc.h */, 26474CA618D0CB070073DEBA /* RegisterContextFreeBSD_x86_64.cpp */, 26474CA718D0CB070073DEBA /* RegisterContextFreeBSD_x86_64.h */, AF061F85182C97ED00B6A19C /* RegisterContextHistory.cpp */, AF061F86182C97ED00B6A19C /* RegisterContextHistory.h */, 26474CAE18D0CB180073DEBA /* RegisterContextLinux_i386.cpp */, 26474CAF18D0CB180073DEBA /* RegisterContextLinux_i386.h */, 256CBDB81ADD107200BC6CDC /* RegisterContextLinux_mips64.cpp */, 256CBDB91ADD107200BC6CDC /* RegisterContextLinux_mips64.h */, 267F68511CC02E920086832B /* RegisterContextLinux_s390x.cpp */, 267F68521CC02E920086832B /* RegisterContextLinux_s390x.h */, 26474CB018D0CB180073DEBA /* RegisterContextLinux_x86_64.cpp */, 26474CB118D0CB180073DEBA /* RegisterContextLinux_x86_64.h */, AF68D2541255416E002FF25B /* RegisterContextLLDB.cpp */, AF68D2551255416E002FF25B /* RegisterContextLLDB.h */, 26474CB618D0CB2D0073DEBA /* RegisterContextMach_arm.cpp */, 26474CB718D0CB2D0073DEBA /* RegisterContextMach_arm.h */, 26474CB818D0CB2D0073DEBA /* RegisterContextMach_i386.cpp */, 26474CB918D0CB2D0073DEBA /* RegisterContextMach_i386.h */, 26474CBA18D0CB2D0073DEBA /* RegisterContextMach_x86_64.cpp */, 26474CBB18D0CB2D0073DEBA /* RegisterContextMach_x86_64.h */, AF77E09C1A033D360096C0EA /* RegisterContextMacOSXFrameBackchain.cpp */, 26E3EEF811A994E800FBADB6 /* RegisterContextMacOSXFrameBackchain.h */, 262D24E413FB8710002D1960 /* RegisterContextMemory.cpp */, 262D24E513FB8710002D1960 /* RegisterContextMemory.h */, 4CE4EFAB1E899A1200A80C06 /* RegisterContextOpenBSD_i386.cpp */, 4CE4EFAC1E899A1200A80C06 /* RegisterContextOpenBSD_i386.h */, 4CE4EFAD1E899A1200A80C06 /* RegisterContextOpenBSD_x86_64.cpp */, 4CE4EFAE1E899A1200A80C06 /* RegisterContextOpenBSD_x86_64.h */, 256CBDBE1ADD11C000BC6CDC /* RegisterContextPOSIX_arm.cpp */, 256CBDBF1ADD11C000BC6CDC /* RegisterContextPOSIX_arm.h */, E7723D4A1AC4A944002BA082 /* RegisterContextPOSIX_arm64.cpp */, E7723D4B1AC4A944002BA082 /* RegisterContextPOSIX_arm64.h */, 26474CC418D0CB5B0073DEBA /* RegisterContextPOSIX_mips64.cpp */, 26474CC518D0CB5B0073DEBA /* RegisterContextPOSIX_mips64.h */, AF77E09D1A033D360096C0EA /* RegisterContextPOSIX_powerpc.cpp */, AF77E09E1A033D360096C0EA /* RegisterContextPOSIX_powerpc.h */, 267F68551CC02EAE0086832B /* RegisterContextPOSIX_s390x.cpp */, 267F68561CC02EAE0086832B /* RegisterContextPOSIX_s390x.h */, 26474CC618D0CB5B0073DEBA /* RegisterContextPOSIX_x86.cpp */, 26474CC718D0CB5B0073DEBA /* RegisterContextPOSIX_x86.h */, 26CA979F172B1FD5005DC71B /* RegisterContextThreadMemory.cpp */, 26CA97A0172B1FD5005DC71B /* RegisterContextThreadMemory.h */, 23EDE3371926AAD500F6A132 /* RegisterInfoInterface.h */, 9A77AD501E64E24E0025CE04 /* RegisterInfoPOSIX_arm.cpp */, 9A77AD511E64E24E0025CE04 /* RegisterInfoPOSIX_arm.h */, 237A8BAB1DEC9BBC00CEBAFF /* RegisterInfoPOSIX_arm64.cpp */, 237A8BAC1DEC9BBC00CEBAFF /* RegisterInfoPOSIX_arm64.h */, 26474CD018D0CB700073DEBA /* RegisterInfos_i386.h */, 26474CD118D0CB710073DEBA /* RegisterInfos_mips64.h */, AF77E09F1A033D360096C0EA /* RegisterInfos_powerpc.h */, 267F68591CC02EBE0086832B /* RegisterInfos_s390x.h */, 26474CD218D0CB710073DEBA /* RegisterInfos_x86_64.h */, 2615DBC81208B5FC0021781D /* StopInfoMachException.cpp */, 2615DBC91208B5FC0021781D /* StopInfoMachException.h */, 26F4A21A13FBA31A0064B613 /* ThreadMemory.cpp */, 26F4A21B13FBA31A0064B613 /* ThreadMemory.h */, AF68D32F1255A110002FF25B /* UnwindLLDB.cpp */, AF68D3301255A110002FF25B /* UnwindLLDB.h */, 26E3EEE311A9901300FBADB6 /* UnwindMacOSXFrameBackchain.cpp */, 26E3EEE411A9901300FBADB6 /* UnwindMacOSXFrameBackchain.h */, 26E3EEF711A994E800FBADB6 /* RegisterContextMacOSXFrameBackchain.cpp */, 26474CC218D0CB5B0073DEBA /* RegisterContextMemory.cpp */, 26474CC318D0CB5B0073DEBA /* RegisterContextMemory.h */, ); name = Utility; sourceTree = ""; }; 26BC179F18C7F4CB00D2196D /* elf-core */ = { isa = PBXGroup; children = ( 256CBDB21ADD0EFD00BC6CDC /* RegisterContextPOSIXCore_arm.cpp */, 256CBDB31ADD0EFD00BC6CDC /* RegisterContextPOSIXCore_arm.h */, E7723D421AC4A7FB002BA082 /* RegisterContextPOSIXCore_arm64.cpp */, E7723D431AC4A7FB002BA082 /* RegisterContextPOSIXCore_arm64.h */, 26BC17A218C7F4CB00D2196D /* ProcessElfCore.cpp */, 26BC17A318C7F4CB00D2196D /* ProcessElfCore.h */, 26BC17A418C7F4CB00D2196D /* RegisterContextPOSIXCore_mips64.cpp */, 26BC17A518C7F4CB00D2196D /* RegisterContextPOSIXCore_mips64.h */, AF77E0A71A033D740096C0EA /* RegisterContextPOSIXCore_powerpc.cpp */, AF77E0A81A033D740096C0EA /* RegisterContextPOSIXCore_powerpc.h */, 267F684D1CC02E270086832B /* RegisterContextPOSIXCore_s390x.cpp */, 267F684E1CC02E270086832B /* RegisterContextPOSIXCore_s390x.h */, 26BC17A618C7F4CB00D2196D /* RegisterContextPOSIXCore_x86_64.cpp */, 26BC17A718C7F4CB00D2196D /* RegisterContextPOSIXCore_x86_64.h */, 26BC17A818C7F4CB00D2196D /* ThreadElfCore.cpp */, 26BC17A918C7F4CB00D2196D /* ThreadElfCore.h */, ); path = "elf-core"; sourceTree = ""; }; 26BC17B318C7F4FA00D2196D /* POSIX */ = { isa = PBXGroup; children = ( AF3F54AE1B3BA59C00186E73 /* CrashReason.cpp */, AF3F54AF1B3BA59C00186E73 /* CrashReason.h */, 26BC17BA18C7F4FA00D2196D /* ProcessMessage.cpp */, 26BC17BB18C7F4FA00D2196D /* ProcessMessage.h */, 26BC17BE18C7F4FA00D2196D /* ProcessPOSIXLog.cpp */, 26BC17BF18C7F4FA00D2196D /* ProcessPOSIXLog.h */, ); path = POSIX; sourceTree = ""; }; 26BC7C1010F1B34800F91463 /* Core */ = { isa = PBXGroup; children = ( 26BC7D5010F1B77400F91463 /* Address.h */, 26BC7E6910F1B85900F91463 /* Address.cpp */, 26BC7D5110F1B77400F91463 /* AddressRange.h */, 26BC7E6A10F1B85900F91463 /* AddressRange.cpp */, 9AC7033E11752C540086C050 /* AddressResolver.h */, 9AC7034011752C6B0086C050 /* AddressResolver.cpp */, 9AC7033D11752C4C0086C050 /* AddressResolverFileLine.h */, 9AC7034211752C720086C050 /* AddressResolverFileLine.cpp */, 9AC7033F11752C590086C050 /* AddressResolverName.h */, 9AC7034411752C790086C050 /* AddressResolverName.cpp */, 26BC7D5210F1B77400F91463 /* ArchSpec.h */, 26BC7E6B10F1B85900F91463 /* ArchSpec.cpp */, 26BC7D5410F1B77400F91463 /* Broadcaster.h */, 26BC7E6D10F1B85900F91463 /* Broadcaster.cpp */, 26BC7D5510F1B77400F91463 /* ClangForward.h */, 26BC7D5610F1B77400F91463 /* Communication.h */, 26BC7E6E10F1B85900F91463 /* Communication.cpp */, 263664941140A4C10075843B /* Debugger.h */, 263664921140A4930075843B /* Debugger.cpp */, 26BC7D5E10F1B77400F91463 /* Disassembler.h */, 26BC7E7610F1B85900F91463 /* Disassembler.cpp */, 4C4EB7821E6A4DE7002035C0 /* DumpDataExtractor.h */, 4C4EB77F1E6A4DB8002035C0 /* DumpDataExtractor.cpp */, 26BC7D5F10F1B77400F91463 /* dwarf.h */, 26D9FDC612F784E60003F2EE /* EmulateInstruction.h */, 26D9FDC812F784FD0003F2EE /* EmulateInstruction.cpp */, 26BC7D6110F1B77400F91463 /* Event.h */, 26BC7E7910F1B85900F91463 /* Event.cpp */, 26BD407D135D2AC400237D80 /* FileLineResolver.h */, 26BD407E135D2ADF00237D80 /* FileLineResolver.cpp */, 26BC7D6310F1B77400F91463 /* FileSpecList.h */, 26BC7E7B10F1B85900F91463 /* FileSpecList.cpp */, 263FDE5D1A799F2D00E68013 /* FormatEntity.h */, 263FDE5F1A79A01500E68013 /* FormatEntity.cpp */, 260A63161861008E00FECF8E /* IOHandler.h */, 260A63181861009E00FECF8E /* IOHandler.cpp */, 26BC7D6510F1B77400F91463 /* IOStreamMacros.h */, 26BC7D6710F1B77400F91463 /* Listener.h */, 26BC7E7E10F1B85900F91463 /* Listener.cpp */, 26BC7D6810F1B77400F91463 /* Log.h */, 26BC7E7F10F1B85900F91463 /* Log.cpp */, 3F8160A71AB9F809001DA9DF /* Logging.h */, 3F8160A51AB9F7DD001DA9DF /* Logging.cpp */, 26BC7D6910F1B77400F91463 /* Mangled.h */, 26BC7E8010F1B85900F91463 /* Mangled.cpp */, 2682100C143A59AE004BCF2D /* MappedHash.h */, 26BC7D6A10F1B77400F91463 /* Module.h */, 26BC7E8110F1B85900F91463 /* Module.cpp */, 26BC7D6B10F1B77400F91463 /* ModuleChild.h */, 26BC7E8210F1B85900F91463 /* ModuleChild.cpp */, 26BC7D6C10F1B77400F91463 /* ModuleList.h */, 26BC7E8310F1B85900F91463 /* ModuleList.cpp */, 260D9B2615EC369500960137 /* ModuleSpec.h */, 26651A15133BF9CC005B64B7 /* Opcode.h */, 26651A17133BF9DF005B64B7 /* Opcode.cpp */, 266DFE9813FD658300D0C574 /* OperatingSystem.h */, 266DFE9613FD656E00D0C574 /* OperatingSystem.cpp */, 26BC7D7010F1B77400F91463 /* PluginInterface.h */, 26BC7D7110F1B77400F91463 /* PluginManager.h */, 26BC7E8A10F1B85900F91463 /* PluginManager.cpp */, 2626B6AD143E1BEA00EF935C /* RangeMap.h */, 26C6886D137880B900407EDF /* RegisterValue.h */, 26C6886E137880C400407EDF /* RegisterValue.cpp */, 26BC7D7410F1B77400F91463 /* Scalar.h */, 26BC7E8D10F1B85900F91463 /* Scalar.cpp */, 26BC7CF910F1B71400F91463 /* SearchFilter.h */, 26BC7E1510F1B83100F91463 /* SearchFilter.cpp */, 26BC7D7510F1B77400F91463 /* Section.h */, 26BC7E8E10F1B85900F91463 /* Section.cpp */, 26BC7D7610F1B77400F91463 /* SourceManager.h */, 26BC7E8F10F1B85900F91463 /* SourceManager.cpp */, 26BC7D7710F1B77400F91463 /* State.h */, 26BC7E9010F1B85900F91463 /* State.cpp */, 26BC7D7810F1B77400F91463 /* STLUtils.h */, 9A4F35111368A54100823F52 /* StreamAsynchronousIO.h */, 9A4F350F1368A51A00823F52 /* StreamAsynchronousIO.cpp */, 2623096E13D0EFFB006381D9 /* StreamBuffer.h */, 26BC7D7A10F1B77400F91463 /* StreamFile.h */, 26BC7E9210F1B85900F91463 /* StreamFile.cpp */, 26B167A41123BF5500DC7B4F /* ThreadSafeValue.h */, 263FEDA5112CC1DA00E4C208 /* ThreadSafeSTLMap.h */, 940B01FE1D2D82220058795E /* ThreadSafeSTLVector.h */, 94ED54A119C8A822007BE2EA /* ThreadSafeDenseMap.h */, 9449B8031B30E0690019342B /* ThreadSafeDenseSet.h */, 268A813F115B19D000F645B0 /* UniqueCStringMap.h */, 9A4633DA11F65D8600955CE1 /* UserSettingsController.h */, 9A4633DC11F65D9A00955CE1 /* UserSettingsController.cpp */, 26BC7D8110F1B77400F91463 /* Value.h */, 26BC7E9910F1B85900F91463 /* Value.cpp */, 26BC7D8210F1B77400F91463 /* ValueObject.h */, 26BC7E9A10F1B85900F91463 /* ValueObject.cpp */, 94094C68163B6CCC0083A547 /* ValueObjectCast.h */, 94094C69163B6CD90083A547 /* ValueObjectCast.cpp */, 26BC7D8310F1B77400F91463 /* ValueObjectChild.h */, 26BC7E9B10F1B85900F91463 /* ValueObjectChild.cpp */, 26424E3E125986D30016D82C /* ValueObjectConstResult.h */, 26424E3C125986CB0016D82C /* ValueObjectConstResult.cpp */, AF9472701B575E5F0063D65C /* ValueObjectConstResultCast.h */, AF94726E1B575E430063D65C /* ValueObjectConstResultCast.cpp */, 94FA3DDD1405D4E500833217 /* ValueObjectConstResultChild.h */, 94FA3DDF1405D50300833217 /* ValueObjectConstResultChild.cpp */, 949ADF001406F62E004833E1 /* ValueObjectConstResultImpl.h */, 949ADF021406F648004833E1 /* ValueObjectConstResultImpl.cpp */, 4CD0BD0C134BFAB600CB44D4 /* ValueObjectDynamicValue.h */, 4CD0BD0E134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp */, 26BC7D8410F1B77400F91463 /* ValueObjectList.h */, 26BC7E9C10F1B85900F91463 /* ValueObjectList.cpp */, 4CABA9DC134A8BA700539BDD /* ValueObjectMemory.h */, 4CABA9DF134A8BCD00539BDD /* ValueObjectMemory.cpp */, 2643343A1110F63C00CDB6C6 /* ValueObjectRegister.h */, 264334381110F63100CDB6C6 /* ValueObjectRegister.cpp */, 94B6E76013D8833C005F417F /* ValueObjectSyntheticFilter.h */, 94B6E76113D88362005F417F /* ValueObjectSyntheticFilter.cpp */, 26BC7D8510F1B77400F91463 /* ValueObjectVariable.h */, 26BC7E9D10F1B85900F91463 /* ValueObjectVariable.cpp */, ); name = Core; sourceTree = ""; }; 26BC7C4B10F1B6C100F91463 /* Symbol */ = { isa = PBXGroup; children = ( 3032B1B91CAAA400004BE1AB /* ClangUtil.h */, 3032B1B61CAAA3D1004BE1AB /* ClangUtil.cpp */, 6D0F61411C80AAAA00A4ECEE /* JavaASTContext.cpp */, 6D0F613C1C80AA8900A4ECEE /* DebugMacros.h */, 6D0F613D1C80AA8900A4ECEE /* JavaASTContext.h */, 6D9AB3DE1BB2B76B003F2289 /* TypeMap.h */, 6D9AB3DC1BB2B74E003F2289 /* TypeMap.cpp */, 6D99A3621BBC2F3200979793 /* ArmUnwindInfo.cpp */, 6D99A3611BBC2F1600979793 /* ArmUnwindInfo.h */, 26BC7C5510F1B6E900F91463 /* Block.h */, 26BC7F1310F1B8EC00F91463 /* Block.cpp */, 26BC7C5610F1B6E900F91463 /* ClangASTContext.h */, 26BC7F1410F1B8EC00F91463 /* ClangASTContext.cpp */, 49D8FB3713B5594900411094 /* ClangASTImporter.h */, 49D8FB3513B558DE00411094 /* ClangASTImporter.cpp */, 265192C41BA8E8F8002F08F6 /* CompilerDecl.h */, 265192C51BA8E905002F08F6 /* CompilerDecl.cpp */, 2657AFB51B8690EC00958979 /* CompilerDeclContext.h */, 2657AFB61B86910100958979 /* CompilerDeclContext.cpp */, 49E45FA911F660DC008F7B28 /* CompilerType.h */, 49E45FAD11F660FE008F7B28 /* CompilerType.cpp */, 495B38431489714C002708C5 /* ClangExternalASTSourceCommon.h */, 4966DCC3148978A10028481B /* ClangExternalASTSourceCommon.cpp */, 26E6902E129C6BD500DDECD9 /* ClangExternalASTSourceCallbacks.h */, 26E69030129C6BEF00DDECD9 /* ClangExternalASTSourceCallbacks.cpp */, 964463ED1A330C1B00154ED8 /* CompactUnwindInfo.h */, 964463EB1A330C0500154ED8 /* CompactUnwindInfo.cpp */, 26BC7C5710F1B6E900F91463 /* CompileUnit.h */, 26BC7F1510F1B8EC00F91463 /* CompileUnit.cpp */, 23E77CDB1C20F2F2007192AD /* DebugMacros.cpp */, 26BC7C5810F1B6E900F91463 /* Declaration.h */, 26BC7F1610F1B8EC00F91463 /* Declaration.cpp */, 49B01A2D15F67B1700666829 /* DeclVendor.h */, 26BC7C5910F1B6E900F91463 /* DWARFCallFrameInfo.h */, 26BC7F1710F1B8EC00F91463 /* DWARFCallFrameInfo.cpp */, 26BC7C5A10F1B6E900F91463 /* Function.h */, 26BC7F1810F1B8EC00F91463 /* Function.cpp */, 269FF07D12494F7D00225026 /* FuncUnwinders.h */, 961FABB81235DE1600F93A47 /* FuncUnwinders.cpp */, AEEA340F1ACA08A000AB639D /* GoASTContext.h */, AEFFBA7C1AC4835D0087B932 /* GoASTContext.cpp */, 26BC7C5B10F1B6E900F91463 /* LineEntry.h */, 26BC7F1910F1B8EC00F91463 /* LineEntry.cpp */, 26BC7C5C10F1B6E900F91463 /* LineTable.h */, 26BC7F1A10F1B8EC00F91463 /* LineTable.cpp */, 26BC7C5D10F1B6E900F91463 /* ObjectContainer.h */, 26BC7C5E10F1B6E900F91463 /* ObjectFile.h */, 26BC7F4C10F1BC1A00F91463 /* ObjectFile.cpp */, 4CC7C6551D52996C0076FF94 /* OCamlASTContext.cpp */, 26BC7C5F10F1B6E900F91463 /* Symbol.h */, 26BC7F1B10F1B8EC00F91463 /* Symbol.cpp */, 26BC7C6010F1B6E900F91463 /* SymbolContext.h */, 26BC7F1C10F1B8EC00F91463 /* SymbolContext.cpp */, 26BC7C6110F1B6E900F91463 /* SymbolContextScope.h */, 26BC7C6210F1B6E900F91463 /* SymbolFile.h */, 26BC7F1D10F1B8EC00F91463 /* SymbolFile.cpp */, 26BC7C6310F1B6E900F91463 /* SymbolVendor.h */, AF94005711C03F6500085DB9 /* SymbolVendor.cpp */, 26BC7C6410F1B6E900F91463 /* Symtab.h */, 26BC7F1F10F1B8EC00F91463 /* Symtab.cpp */, 49BB309511F79450001A4197 /* TaggedASTType.h */, 26BC7C6510F1B6E900F91463 /* Type.h */, 26BC7F2010F1B8EC00F91463 /* Type.cpp */, 26BC7C6610F1B6E900F91463 /* TypeList.h */, 26BC7F2110F1B8EC00F91463 /* TypeList.cpp */, AEEA33F61AC74FE700AB639D /* TypeSystem.h */, AEEA34041AC88A7400AB639D /* TypeSystem.cpp */, 269FF07F12494F8E00225026 /* UnwindPlan.h */, 961FABB91235DE1600F93A47 /* UnwindPlan.cpp */, 269FF08112494FC200225026 /* UnwindTable.h */, 961FABBA1235DE1600F93A47 /* UnwindTable.cpp */, 26BC7C6710F1B6E900F91463 /* Variable.h */, 26BC7F2210F1B8EC00F91463 /* Variable.cpp */, 26BC7C6810F1B6E900F91463 /* VariableList.h */, 26BC7F2310F1B8EC00F91463 /* VariableList.cpp */, 494260D7145790D5003C1C78 /* VerifyDecl.h */, 494260D914579144003C1C78 /* VerifyDecl.cpp */, ); name = Symbol; sourceTree = ""; }; 26BC7CEB10F1B70800F91463 /* Breakpoint */ = { isa = PBXGroup; children = ( 26BC7CEE10F1B71400F91463 /* Breakpoint.h */, 26BC7E0A10F1B83100F91463 /* Breakpoint.cpp */, 26BC7CEF10F1B71400F91463 /* BreakpointID.h */, 26BC7E0B10F1B83100F91463 /* BreakpointID.cpp */, 26BC7CF010F1B71400F91463 /* BreakpointIDList.h */, 26BC7E0C10F1B83100F91463 /* BreakpointIDList.cpp */, 26BC7CF110F1B71400F91463 /* BreakpointList.h */, 26BC7E0D10F1B83100F91463 /* BreakpointList.cpp */, 26BC7CF210F1B71400F91463 /* BreakpointLocation.h */, 26BC7E0E10F1B83100F91463 /* BreakpointLocation.cpp */, 26BC7CF310F1B71400F91463 /* BreakpointLocationCollection.h */, 26BC7E0F10F1B83100F91463 /* BreakpointLocationCollection.cpp */, 26BC7CF410F1B71400F91463 /* BreakpointLocationList.h */, 26BC7E1010F1B83100F91463 /* BreakpointLocationList.cpp */, 26BC7CF510F1B71400F91463 /* BreakpointOptions.h */, 26BC7E1110F1B83100F91463 /* BreakpointOptions.cpp */, 26BC7CF610F1B71400F91463 /* BreakpointResolver.h */, 26BC7E1210F1B83100F91463 /* BreakpointResolver.cpp */, 26D0DD5010FE554D00271C65 /* BreakpointResolverAddress.h */, 26D0DD5310FE555900271C65 /* BreakpointResolverAddress.cpp */, 26D0DD5110FE554D00271C65 /* BreakpointResolverFileLine.h */, 26D0DD5410FE555900271C65 /* BreakpointResolverFileLine.cpp */, 4CAA56121422D96A001FFA01 /* BreakpointResolverFileRegex.h */, 4CAA56141422D986001FFA01 /* BreakpointResolverFileRegex.cpp */, 26D0DD5210FE554D00271C65 /* BreakpointResolverName.h */, 26D0DD5510FE555900271C65 /* BreakpointResolverName.cpp */, 26BC7CF710F1B71400F91463 /* BreakpointSite.h */, 26BC7E1310F1B83100F91463 /* BreakpointSite.cpp */, 26BC7CF810F1B71400F91463 /* BreakpointSiteList.h */, 26BC7E1410F1B83100F91463 /* BreakpointSiteList.cpp */, 26BC7CFA10F1B71400F91463 /* Stoppoint.h */, 26BC7E1610F1B83100F91463 /* Stoppoint.cpp */, 26BC7CED10F1B71400F91463 /* StoppointCallbackContext.h */, 26BC7E0910F1B83100F91463 /* StoppointCallbackContext.cpp */, 26BC7CFB10F1B71400F91463 /* StoppointLocation.h */, 26BC7E1710F1B83100F91463 /* StoppointLocation.cpp */, 26BC7CFC10F1B71400F91463 /* Watchpoint.h */, 26BC7E1810F1B83100F91463 /* Watchpoint.cpp */, B27318431416AC43006039C8 /* WatchpointList.h */, B27318411416AC12006039C8 /* WatchpointList.cpp */, B2B7CCED15D1BFB700EEFB57 /* WatchpointOptions.h */, B2B7CCEF15D1C20F00EEFB57 /* WatchpointOptions.cpp */, ); name = Breakpoint; sourceTree = ""; }; 26BC7D0D10F1B71D00F91463 /* Commands */ = { isa = PBXGroup; children = ( 4CA9637A11B6E99A00780E28 /* CommandObjectApropos.h */, 4CA9637911B6E99A00780E28 /* CommandObjectApropos.cpp */, 499F381E11A5B3F300F5CE02 /* CommandObjectArgs.h */, 499F381F11A5B3F300F5CE02 /* CommandObjectArgs.cpp */, 26BC7D1410F1B76300F91463 /* CommandObjectBreakpoint.h */, 26BC7E2D10F1B84700F91463 /* CommandObjectBreakpoint.cpp */, 9A42976111861A9F00FE05CD /* CommandObjectBreakpointCommand.h */, 9A42976211861AA600FE05CD /* CommandObjectBreakpointCommand.cpp */, 6D86CE9F1B440F6B00A7FBFA /* CommandObjectBugreport.h */, 6D86CE9E1B440F6B00A7FBFA /* CommandObjectBugreport.cpp */, 4C5DBBC711E3FEC60035160F /* CommandObjectCommands.h */, 4C5DBBC611E3FEC60035160F /* CommandObjectCommands.cpp */, 26BC7D1710F1B76300F91463 /* CommandObjectDisassemble.h */, 26BC7E3010F1B84700F91463 /* CommandObjectDisassemble.cpp */, 26BC7D1810F1B76300F91463 /* CommandObjectExpression.h */, 26BC7E3110F1B84700F91463 /* CommandObjectExpression.cpp */, 2672D8471189055500FF4019 /* CommandObjectFrame.h */, 2672D8461189055500FF4019 /* CommandObjectFrame.cpp */, 26CEB5F118762056008F575A /* CommandObjectGUI.h */, 26CEB5F018762056008F575A /* CommandObjectGUI.cpp */, 26BC7D1A10F1B76300F91463 /* CommandObjectHelp.h */, 26BC7E3310F1B84700F91463 /* CommandObjectHelp.cpp */, AFC234061AF85CE000CDE8B6 /* CommandObjectLanguage.cpp */, AFC234071AF85CE000CDE8B6 /* CommandObjectLanguage.h */, 264AD83911095BBD00E0B039 /* CommandObjectLog.h */, 264AD83711095BA600E0B039 /* CommandObjectLog.cpp */, 26BC7D1D10F1B76300F91463 /* CommandObjectMemory.h */, 26BC7E3610F1B84700F91463 /* CommandObjectMemory.cpp */, 26879CE51333F5750012C1F8 /* CommandObjectPlatform.h */, 26879CE71333F58B0012C1F8 /* CommandObjectPlatform.cpp */, 947A1D631616476A0017C8D1 /* CommandObjectPlugin.h */, 947A1D621616476A0017C8D1 /* CommandObjectPlugin.cpp */, 26BC7D1F10F1B76300F91463 /* CommandObjectProcess.h */, 26BC7E3810F1B84700F91463 /* CommandObjectProcess.cpp */, 26BC7D2010F1B76300F91463 /* CommandObjectQuit.h */, 26BC7E3910F1B84700F91463 /* CommandObjectQuit.cpp */, 26BC7D2210F1B76300F91463 /* CommandObjectRegister.h */, 26BC7E3B10F1B84700F91463 /* CommandObjectRegister.cpp */, 26BC7D2410F1B76300F91463 /* CommandObjectScript.h */, 26BC7E3D10F1B84700F91463 /* CommandObjectScript.cpp */, 26BC7D2710F1B76300F91463 /* CommandObjectSettings.h */, 26BC7E4010F1B84700F91463 /* CommandObjectSettings.cpp */, 26BC7D2910F1B76300F91463 /* CommandObjectSource.h */, 26BC7E4210F1B84700F91463 /* CommandObjectSource.cpp */, 26BC7D2C10F1B76300F91463 /* CommandObjectSyntax.h */, 26BC7E4510F1B84700F91463 /* CommandObjectSyntax.cpp */, 269416AE119A024800FF2715 /* CommandObjectTarget.h */, 269416AD119A024800FF2715 /* CommandObjectTarget.cpp */, 26BC7D2D10F1B76300F91463 /* CommandObjectThread.h */, 26BC7E4610F1B84700F91463 /* CommandObjectThread.cpp */, 9463D4CE13B179A500C230D4 /* CommandObjectType.h */, 9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */, B296983512C2FB2B002D92C3 /* CommandObjectVersion.h */, B296983412C2FB2B002D92C3 /* CommandObjectVersion.cpp */, B207C4941429609C00F36E4E /* CommandObjectWatchpoint.h */, B207C4921429607D00F36E4E /* CommandObjectWatchpoint.cpp */, B2B7CCEC15D1BD9600EEFB57 /* CommandObjectWatchpointCommand.h */, B2B7CCEA15D1BD6600EEFB57 /* CommandObjectWatchpointCommand.cpp */, ); name = Commands; sourceTree = ""; }; 26BC7DBE10F1B78200F91463 /* Expression */ = { isa = PBXGroup; children = ( 49E4F66C1C9CAD2D008487EA /* DiagnosticManager.h */, 49E4F6681C9CAD12008487EA /* DiagnosticManager.cpp */, 4C00832C1B9A58A700D5CF24 /* Expression.h */, 4C88BC291BA3722B00AA0964 /* Expression.cpp */, 4C29E77D1BA2403F00DFF855 /* ExpressionTypeSystemHelper.h */, 4C00832D1B9A58A700D5CF24 /* FunctionCaller.h */, 4C0083321B9A5DE200D5CF24 /* FunctionCaller.cpp */, 4C00832E1B9A58A700D5CF24 /* UserExpression.h */, 4C0083331B9A5DE200D5CF24 /* UserExpression.cpp */, AEB0E45A1BD6EA1400B24093 /* LLVMUserExpression.h */, AEB0E4581BD6E9F800B24093 /* LLVMUserExpression.cpp */, 4C00833D1B9F9B8400D5CF24 /* UtilityFunction.h */, 4C00833F1B9F9BA900D5CF24 /* UtilityFunction.cpp */, 49A1CAC11430E21D00306AC9 /* ExpressionSourceCode.h */, 49A1CAC31430E8BD00306AC9 /* ExpressionSourceCode.cpp */, 4984BA171B979C08008658D4 /* ExpressionVariable.h */, 4984BA151B979973008658D4 /* ExpressionVariable.cpp */, 4C2479BE1BA39843009C9A7B /* ExpressionParser.h */, 26BC7DC310F1B79500F91463 /* DWARFExpression.h */, 26BC7ED810F1B86700F91463 /* DWARFExpression.cpp */, 49CF9833122C718B007A0B96 /* IRDynamicChecks.h */, 49CF9829122C70BD007A0B96 /* IRDynamicChecks.cpp */, 49C66B1C17011A43004D1922 /* IRMemoryMap.h */, 49DCF6FD170E6B4A0092F75E /* IRMemoryMap.cpp */, 4C98D3E1118FB98F00E575D0 /* IRExecutionUnit.h */, 4C98D3DB118FB96F00E575D0 /* IRExecutionUnit.cpp */, 496B015A1406DEB100F830D5 /* IRInterpreter.h */, 496B01581406DE8900F830D5 /* IRInterpreter.cpp */, 49DCF6FF170E6FD90092F75E /* Materializer.h */, 49DCF700170E70120092F75E /* Materializer.cpp */, 4939EA8B1BD56B3700084382 /* REPL.h */, 4939EA8C1BD56B6D00084382 /* REPL.cpp */, ); name = Expression; sourceTree = ""; }; 26BC7DD010F1B7C100F91463 /* Host */ = { isa = PBXGroup; children = ( 6D55B29B1A8CCFF000A70529 /* android */, 33E5E8451A6736D30024ED68 /* StringConvert.h */, 69A01E1A1236C5D400C660B5 /* common */, 3FDFE53919A29399009756A7 /* freebsd */, 233B009C19610D130090E598 /* linux */, 26BC7EE510F1B88100F91463 /* MacOSX */, 3FDFDDC4199D37BE009756A7 /* posix */, 3FDFE53E19A2940E009756A7 /* windows */, 266F5CBB12FC846200DFCE33 /* Config.h */, 3FDFED1E19BA6D55009756A7 /* Debug.h */, 26CFDCA01861638D000E63E5 /* Editline.h */, 260C6EA013011578005E16B0 /* File.h */, 3FDFDDC0199D34E2009756A7 /* FileCache.h */, 3FDFDDBE199D345E009756A7 /* FileCache.cpp */, 3FDFDDC1199D34E2009756A7 /* FileSystem.h */, 26BC7DD410F1B7D500F91463 /* Host.h */, 3FDFED1F19BA6D55009756A7 /* HostGetOpt.h */, 3FDFE53719A2936B009756A7 /* HostInfo.h */, 3FDFE53819A2936B009756A7 /* HostInfoBase.h */, 3FDFED2019BA6D55009756A7 /* HostNativeThread.h */, 3FDFED2119BA6D55009756A7 /* HostNativeThreadBase.h */, 3FDFE57419AFABFD009756A7 /* HostProcess.h */, 3FDFE57519AFABFD009756A7 /* HostThread.h */, 267A47F31B14116E0021A5BC /* NativeBreakpoint.h */, 232CB60B191E00CC00EF39FC /* NativeBreakpoint.cpp */, 267A47F41B1411750021A5BC /* NativeBreakpointList.h */, 232CB60D191E00CC00EF39FC /* NativeBreakpointList.cpp */, 267A47F51B14117F0021A5BC /* NativeProcessProtocol.h */, 232CB60F191E00CC00EF39FC /* NativeProcessProtocol.cpp */, 267A47F61B14118F0021A5BC /* NativeRegisterContext.h */, 267A47FA1B1411C40021A5BC /* NativeRegisterContext.cpp */, 267A47F81B1411A40021A5BC /* NativeThreadProtocol.h */, 232CB611191E00CC00EF39FC /* NativeThreadProtocol.cpp */, 267A47F91B1411AC0021A5BC /* NativeWatchpointList.h */, 267A47FE1B1411D90021A5BC /* NativeWatchpointList.cpp */, A36FF33D17D8E98800244D40 /* OptionParser.h */, 260A39A519647A3A004B4130 /* Pipe.h */, 3F5E8AF31A40D4A500A73232 /* PipeBase.h */, 26BC7DD610F1B7D500F91463 /* Predicate.h */, 3FDFED2219BA6D55009756A7 /* ProcessRunLock.h */, 2654A68E1E552D2400DA1013 /* PseudoTerminal.h */, 2654A68C1E552D1500DA1013 /* PseudoTerminal.cpp */, 236124A71986B50E004EFC37 /* Socket.h */, 26D7E45B13D5E2F9007FD12B /* SocketAddress.h */, 26D7E45C13D5E30A007FD12B /* SocketAddress.cpp */, 267A47F21B14115A0021A5BC /* SoftwareBreakpoint.h */, 232CB613191E00CC00EF39FC /* SoftwareBreakpoint.cpp */, 2689B0A4113EE3CD00A4AEDB /* Symbols.h */, 268DA871130095D000C9483A /* Terminal.h */, 3FDFED2319BA6D55009756A7 /* ThreadLauncher.h */, 267A48031B1416080021A5BC /* XML.h */, 267A48001B1411E40021A5BC /* XML.cpp */, ); name = Host; sourceTree = ""; }; 26BC7DDF10F1B7E200F91463 /* Interpreter */ = { isa = PBXGroup; children = ( 25420ECE1A64911B009ADBCB /* OptionValueChar.h */, 25420ECC1A6490B8009ADBCB /* OptionValueChar.cpp */, 26BC7D5310F1B77400F91463 /* Args.h */, 26BC7E6C10F1B85900F91463 /* Args.cpp */, 26A4EEB511682AAC007A372A /* LLDBWrapPython.cpp */, 9441816B1C8F5EB000E5A8D9 /* CommandAlias.h */, 9441816D1C8F5EC900E5A8D9 /* CommandAlias.cpp */, 4C09CB73116BD98B00C7A725 /* CommandCompletions.h */, 4C09CB74116BD98B00C7A725 /* CommandCompletions.cpp */, 94BA8B71176F97D4005A91B5 /* CommandHistory.h */, 94BA8B6F176F97CE005A91B5 /* CommandHistory.cpp */, 26BC7DE210F1B7F900F91463 /* CommandInterpreter.h */, 26BC7F0810F1B8DD00F91463 /* CommandInterpreter.cpp */, 26BC7DE310F1B7F900F91463 /* CommandObject.h */, 26BC7F0910F1B8DD00F91463 /* CommandObject.cpp */, 26DFBC51113B48D600DD817F /* CommandObjectMultiword.h */, 26DFBC58113B48F300DD817F /* CommandObjectMultiword.cpp */, 26DFBC52113B48D600DD817F /* CommandObjectRegexCommand.h */, 26DFBC59113B48F300DD817F /* CommandObjectRegexCommand.cpp */, 23DDF224196C3EE600BB8417 /* CommandOptionValidators.cpp */, 26BC7DE410F1B7F900F91463 /* CommandReturnObject.h */, 26BC7F0A10F1B8DD00F91463 /* CommandReturnObject.cpp */, 94005E0513F45A1B001EF42D /* embedded_interpreter.py */, 26A7A036135E6E5300FB369E /* OptionValue.h */, 26A7A034135E6E4200FB369E /* OptionValue.cpp */, 260A248D15D06C4F009981B0 /* OptionValues.h */, 2697A39415E404BA003E682C /* OptionValueArch.h */, 2697A39215E404B1003E682C /* OptionValueArch.cpp */, 260CC62115D04377002BF2E0 /* OptionValueArgs.h */, 260CC63B15D0440D002BF2E0 /* OptionValueArgs.cpp */, 260CC62215D04377002BF2E0 /* OptionValueArray.h */, 260CC63C15D0440D002BF2E0 /* OptionValueArray.cpp */, 260CC62315D04377002BF2E0 /* OptionValueBoolean.h */, 260CC63D15D0440D002BF2E0 /* OptionValueBoolean.cpp */, 260CC62515D04377002BF2E0 /* OptionValueDictionary.h */, 260CC63F15D0440D002BF2E0 /* OptionValueDictionary.cpp */, 260CC62615D04377002BF2E0 /* OptionValueEnumeration.h */, 260CC64015D0440D002BF2E0 /* OptionValueEnumeration.cpp */, 260CC62715D04377002BF2E0 /* OptionValueFileSpec.h */, 260CC64115D0440D002BF2E0 /* OptionValueFileSpec.cpp */, 260CC62815D04377002BF2E0 /* OptionValueFileSpecList.h */, 260CC64215D0440D002BF2E0 /* OptionValueFileSpecLIst.cpp */, 260CC62915D04377002BF2E0 /* OptionValueFormat.h */, 260CC64315D0440D002BF2E0 /* OptionValueFormat.cpp */, 264A58EB1A7DBC8C00A6B1B0 /* OptionValueFormatEntity.h */, 264A58ED1A7DBCAD00A6B1B0 /* OptionValueFormatEntity.cpp */, 946216BF1A97C055006E19CC /* OptionValueLanguage.h */, 946216C11A97C080006E19CC /* OptionValueLanguage.cpp */, 26DAED5F15D327A200E15819 /* OptionValuePathMappings.h */, 26DAED6215D327C200E15819 /* OptionValuePathMappings.cpp */, 260CC62415D04377002BF2E0 /* OptionValueProperties.h */, 260CC63E15D0440D002BF2E0 /* OptionValueProperties.cpp */, 26491E3A15E1DB8600CBFFC2 /* OptionValueRegex.h */, 26491E3D15E1DB9F00CBFFC2 /* OptionValueRegex.cpp */, 260CC62A15D04377002BF2E0 /* OptionValueSInt64.h */, 260CC64415D0440D002BF2E0 /* OptionValueSInt64.cpp */, 260CC62B15D04377002BF2E0 /* OptionValueString.h */, 260CC64515D0440D002BF2E0 /* OptionValueString.cpp */, 260CC62C15D04377002BF2E0 /* OptionValueUInt64.h */, 260CC64615D0440D002BF2E0 /* OptionValueUInt64.cpp */, 260CC62D15D04377002BF2E0 /* OptionValueUUID.h */, 260CC64715D0440D002BF2E0 /* OptionValueUUID.cpp */, 26BC7D6D10F1B77400F91463 /* Options.h */, 26BC7E8610F1B85900F91463 /* Options.cpp */, 26D5E160135BAEB0006EA0A7 /* OptionGroupArchitecture.h */, 26D5E15E135BAEA2006EA0A7 /* OptionGroupArchitecture.cpp */, 2686536D1370ACC600D186A3 /* OptionGroupBoolean.h */, 2686536B1370ACB200D186A3 /* OptionGroupBoolean.cpp */, 260E07C9136FABAC00CF21D3 /* OptionGroupFile.h */, 260E07C7136FAB9200CF21D3 /* OptionGroupFile.cpp */, 26BCFC4F1368ADF7006DC050 /* OptionGroupFormat.h */, 26BCFC511368AE38006DC050 /* OptionGroupFormat.cpp */, 26BCFC541368B4B8006DC050 /* OptionGroupOutputFile.h */, 26BCFC531368B3E4006DC050 /* OptionGroupOutputFile.cpp */, 26D5E161135BB040006EA0A7 /* OptionGroupPlatform.h */, 26D5E162135BB054006EA0A7 /* OptionGroupPlatform.cpp */, 262ED0041631FA2800879631 /* OptionGroupString.h */, 262ED0071631FA3A00879631 /* OptionGroupString.cpp */, 2686536E1370AE5A00D186A3 /* OptionGroupUInt64.h */, 2686536F1370AE7200D186A3 /* OptionGroupUInt64.cpp */, 260E07C3136FA68900CF21D3 /* OptionGroupUUID.h */, 260E07C5136FA69E00CF21D3 /* OptionGroupUUID.cpp */, 267C0128136880C7006E963E /* OptionGroupValueObjectDisplay.h */, 267C012A136880DF006E963E /* OptionGroupValueObjectDisplay.cpp */, 26ED3D6F13C5638A0017D45E /* OptionGroupVariable.h */, 26ED3D6C13C563810017D45E /* OptionGroupVariable.cpp */, B2462248141AD39B00F3D409 /* OptionGroupWatchpoint.h */, B2462246141AD37D00F3D409 /* OptionGroupWatchpoint.cpp */, 26ACEC2715E077AE00E94760 /* Property.h */, 2640E19E15DC78FD00F23B50 /* Property.cpp */, 26BC7DE510F1B7F900F91463 /* ScriptInterpreter.h */, 9A82010B10FFB49800182560 /* ScriptInterpreter.cpp */, ); name = Interpreter; sourceTree = ""; }; 26BC7DEF10F1B80200F91463 /* Target */ = { isa = PBXGroup; children = ( 230EC4571D63C3A7008DF59F /* CMakeLists.txt */, 8CF02AE019DCBF3B00B14BE0 /* InstrumentationRuntime.h */, 8CF02ADF19DCBF3B00B14BE0 /* InstrumentationRuntime.cpp */, 8CF02AEE19DD15CF00B14BE0 /* InstrumentationRuntimeStopInfo.h */, 8CF02AED19DD15CF00B14BE0 /* InstrumentationRuntimeStopInfo.cpp */, 3FDFD6C3199C396E009756A7 /* FileAction.h */, 3FDFDDBC199C3A06009756A7 /* FileAction.cpp */, 23EDE3311926843600F6A132 /* NativeRegisterContext.h */, 23EDE3301926839700F6A132 /* NativeRegisterContext.cpp */, 497E7B331188ED300065CCA1 /* ABI.h */, 497E7B9D1188F6690065CCA1 /* ABI.cpp */, 4CB443BB1249920C00C13DC2 /* CPPLanguageRuntime.h */, 4CB443BC1249920C00C13DC2 /* CPPLanguageRuntime.cpp */, 26BC7DF110F1B81A00F91463 /* DynamicLoader.h */, 26BC7E7710F1B85900F91463 /* DynamicLoader.cpp */, 26BC7DF210F1B81A00F91463 /* ExecutionContext.h */, 26BC7F3510F1B90C00F91463 /* ExecutionContext.cpp */, 26DAFD9711529BC7005A394E /* ExecutionContextScope.h */, 26BC179B18C7F2CB00D2196D /* JITLoader.h */, 26BC179718C7F2B300D2196D /* JITLoader.cpp */, 26BC179C18C7F2CB00D2196D /* JITLoaderList.h */, 26BC179818C7F2B300D2196D /* JITLoaderList.cpp */, 94B638511B8F8E53004FE1E4 /* Language.h */, 94B638521B8F8E6C004FE1E4 /* Language.cpp */, 4CB4430912491DDA00C13DC2 /* LanguageRuntime.h */, 4CB4430A12491DDA00C13DC2 /* LanguageRuntime.cpp */, 2690B36F1381D5B600ECFBAE /* Memory.h */, 2690B3701381D5C300ECFBAE /* Memory.cpp */, 8C2D6A54197A1EBE006989C9 /* MemoryHistory.h */, 8C2D6A52197A1EAF006989C9 /* MemoryHistory.cpp */, 2360092C193FB21500189DB1 /* MemoryRegionInfo.h */, 2654A6811E54D5A200DA1013 /* ModuleCache.h */, 2654A67F1E54D59400DA1013 /* ModuleCache.cpp */, 4CB443F612499B6E00C13DC2 /* ObjCLanguageRuntime.h */, 4CB443F212499B5000C13DC2 /* ObjCLanguageRuntime.cpp */, 495BBACF119A0DE700418BEA /* PathMappingList.h */, 495BBACB119A0DBE00418BEA /* PathMappingList.cpp */, 264A43BB1320B3B4005B4096 /* Platform.h */, 264A43BD1320BCEB005B4096 /* Platform.cpp */, 233B007A1960A0440090E598 /* ProcessInfo.h */, 233B007B1960C9E60090E598 /* ProcessInfo.cpp */, 233B007E1960CB280090E598 /* ProcessLaunchInfo.cpp */, 233B007919609DB40090E598 /* ProcessLaunchInfo.h */, 26BC7DF310F1B81A00F91463 /* Process.h */, 26BC7F3610F1B90C00F91463 /* Process.cpp */, 260A63111860FDB600FECF8E /* Queue.h */, AF2670381852D01E00B6CC36 /* Queue.cpp */, 260A63121860FDBD00FECF8E /* QueueItem.h */, AF0C112718580CD800C4C45B /* QueueItem.cpp */, 260A63131860FDC700FECF8E /* QueueList.h */, AF2670391852D01E00B6CC36 /* QueueList.cpp */, 26AB54111832DC3400EADFF3 /* RegisterCheckpoint.h */, 26BC7DF410F1B81A00F91463 /* RegisterContext.h */, 26BC7F3710F1B90C00F91463 /* RegisterContext.cpp */, 2654A6841E54D5EE00DA1013 /* RegisterNumber.h */, 2654A6821E54D5E200DA1013 /* RegisterNumber.cpp */, 262173A018395D3800C52091 /* SectionLoadHistory.h */, 262173A218395D4600C52091 /* SectionLoadHistory.cpp */, 2618D78F1240115500F2B8FE /* SectionLoadList.h */, 2618D7911240116900F2B8FE /* SectionLoadList.cpp */, 26BC7DF510F1B81A00F91463 /* StackFrame.h */, 26BC7F3810F1B90C00F91463 /* StackFrame.cpp */, 26BC7DF610F1B81A00F91463 /* StackFrameList.h */, 26BC7F3910F1B90C00F91463 /* StackFrameList.cpp */, 26BC7DF710F1B81A00F91463 /* StackID.h */, 26BC7F3A10F1B90C00F91463 /* StackID.cpp */, 2615DB841208A9C90021781D /* StopInfo.h */, 2615DB861208A9E40021781D /* StopInfo.cpp */, 238F2B9F1D2C835A001FF92A /* StructuredDataPlugin.h */, 238F2B9D1D2C82D0001FF92A /* StructuredDataPlugin.cpp */, 238F2BA01D2C835A001FF92A /* SystemRuntime.h */, AF81DEF91828A23F0042CF19 /* SystemRuntime.cpp */, 26BC7DF810F1B81A00F91463 /* Target.h */, 26BC7F3B10F1B90C00F91463 /* Target.cpp */, 26BC7DF910F1B81A00F91463 /* TargetList.h */, 26BC7F3C10F1B90C00F91463 /* TargetList.cpp */, 26BC7DFA10F1B81A00F91463 /* Thread.h */, 26BC7F3D10F1B90C00F91463 /* Thread.cpp */, 8CCB017C19BA289B0009FD44 /* ThreadCollection.h */, 8CCB017A19BA283D0009FD44 /* ThreadCollection.cpp */, 26BC7DFB10F1B81A00F91463 /* ThreadList.h */, 26BC7F3E10F1B90C00F91463 /* ThreadList.cpp */, 26BC7DFC10F1B81A00F91463 /* ThreadPlan.h */, 26BC7F3F10F1B90C00F91463 /* ThreadPlan.cpp */, 260C847F10F50F0A00BB2B04 /* ThreadPlanBase.h */, 260C847110F50EFC00BB2B04 /* ThreadPlanBase.cpp */, 49EC3E9C118F90D400B1265E /* ThreadPlanCallFunction.h */, 49EC3E98118F90AC00B1265E /* ThreadPlanCallFunction.cpp */, EB8375E81B553DFE00BA907D /* ThreadPlanCallFunctionUsingABI.h */, EB8375E61B553DE800BA907D /* ThreadPlanCallFunctionUsingABI.cpp */, 230EC4581D63C3A7008DF59F /* ThreadPlanCallOnFunctionExit.cpp */, 4C7CF7E31295E10E00B4FBB5 /* ThreadPlanCallUserExpression.h */, 4C7CF7E51295E12B00B4FBB5 /* ThreadPlanCallUserExpression.cpp */, 4C56543219D1EFB5002E9C44 /* ThreadPlanPython.h */, 4C56543019D1EFAA002E9C44 /* ThreadPlanPython.cpp */, 4C43DEF9110641F300E55CBF /* ThreadPlanShouldStopHere.h */, 4C43DEFA110641F300E55CBF /* ThreadPlanShouldStopHere.cpp */, 260C848010F50F0A00BB2B04 /* ThreadPlanStepInstruction.h */, 260C847210F50EFC00BB2B04 /* ThreadPlanStepInstruction.cpp */, 260C848110F50F0A00BB2B04 /* ThreadPlanStepOut.h */, 260C847310F50EFC00BB2B04 /* ThreadPlanStepOut.cpp */, 260C848210F50F0A00BB2B04 /* ThreadPlanStepOverBreakpoint.h */, 260C847410F50EFC00BB2B04 /* ThreadPlanStepOverBreakpoint.cpp */, 260C848410F50F0A00BB2B04 /* ThreadPlanStepRange.h */, 260C847610F50EFC00BB2B04 /* ThreadPlanStepRange.cpp */, 4C43DF8511069BFD00E55CBF /* ThreadPlanStepInRange.h */, 4C43DF8911069C3200E55CBF /* ThreadPlanStepInRange.cpp */, 4C43DF8611069BFD00E55CBF /* ThreadPlanStepOverRange.h */, 4C43DF8A11069C3200E55CBF /* ThreadPlanStepOverRange.cpp */, 4CAFCE001101216B00CA63DB /* ThreadPlanRunToAddress.h */, 4CAFCE031101218900CA63DB /* ThreadPlanRunToAddress.cpp */, 260C848310F50F0A00BB2B04 /* ThreadPlanStepThrough.h */, 260C847510F50EFC00BB2B04 /* ThreadPlanStepThrough.cpp */, 4CEDAED311754F5E00E875A6 /* ThreadPlanStepUntil.h */, 2660D9FE11922A7F00958FBD /* ThreadPlanStepUntil.cpp */, 4CC2A14C128C7409001531C4 /* ThreadPlanTracer.h */, 4CC2A148128C73ED001531C4 /* ThreadPlanTracer.cpp */, 4C08CDEB11C81F1E001610A8 /* ThreadSpec.h */, 4C08CDE711C81EF8001610A8 /* ThreadSpec.cpp */, 4C00986F11500B4300F316B0 /* UnixSignals.h */, 4C00987011500B4300F316B0 /* UnixSignals.cpp */, 26E3EEBD11A9870400FBADB6 /* Unwind.h */, 264D8D4E13661BCC003A368F /* UnwindAssembly.h */, 264D8D4F13661BD7003A368F /* UnwindAssembly.cpp */, ); name = Target; sourceTree = ""; }; 26BC7EE510F1B88100F91463 /* MacOSX */ = { isa = PBXGroup; children = ( 26BC7EED10F1B8AD00F91463 /* CFCBundle.cpp */, 26BC7EEE10F1B8AD00F91463 /* CFCBundle.h */, 26BC7EEF10F1B8AD00F91463 /* CFCData.cpp */, 26BC7EF010F1B8AD00F91463 /* CFCData.h */, 26BC7EF110F1B8AD00F91463 /* CFCMutableArray.cpp */, 26BC7EF210F1B8AD00F91463 /* CFCMutableArray.h */, 26BC7EF310F1B8AD00F91463 /* CFCMutableDictionary.cpp */, 26BC7EF410F1B8AD00F91463 /* CFCMutableDictionary.h */, 26BC7EF510F1B8AD00F91463 /* CFCMutableSet.cpp */, 26BC7EF610F1B8AD00F91463 /* CFCMutableSet.h */, 26BC7EF710F1B8AD00F91463 /* CFCReleaser.h */, 26BC7EF810F1B8AD00F91463 /* CFCString.cpp */, 26BC7EF910F1B8AD00F91463 /* CFCString.h */, 26BC7EE810F1B88F00F91463 /* Host.mm */, 3FDFE52B19A2917A009756A7 /* HostInfoMacOSX.mm */, 3FDFE52D19A291AF009756A7 /* HostInfoMacOSX.h */, 3FDFED0519B7C898009756A7 /* HostThreadMacOSX.mm */, 3FDFE56719AF9BB2009756A7 /* HostThreadMacOSX.h */, 2689B0B5113EE47E00A4AEDB /* Symbols.cpp */, ); name = MacOSX; sourceTree = ""; }; 26BF51E91B3C754400016294 /* SysV-hexagon */ = { isa = PBXGroup; children = ( 26BF51EA1B3C754400016294 /* ABISysV_hexagon.cpp */, 26BF51EB1B3C754400016294 /* ABISysV_hexagon.h */, ); path = "SysV-hexagon"; sourceTree = ""; }; 26BF51EE1B3C754400016294 /* SysV-i386 */ = { isa = PBXGroup; children = ( 26BF51EF1B3C754400016294 /* ABISysV_i386.cpp */, 26BF51F01B3C754400016294 /* ABISysV_i386.h */, ); path = "SysV-i386"; sourceTree = ""; }; 26C5577E132575B6008FD8FE /* Platform */ = { isa = PBXGroup; children = ( 6D55BAE61A8CD08C00A70529 /* Android */, 2694E99814FC0BB30076DE67 /* FreeBSD */, 264A97BC133918A30017F0BE /* GDB Server */, 23042D0F1976C9D800621B2C /* Kalimba */, 2694E99F14FC0BBD0076DE67 /* Linux */, 26C5577F132575C8008FD8FE /* MacOSX */, 26EFB6151BFE8D3E00544801 /* NetBSD */, 4CE4EFA51E89998800A80C06 /* OpenBSD */, 9457596415349416005A9070 /* POSIX */, 490A36BA180F0E6F00BA31F8 /* Windows */, ); path = Platform; sourceTree = ""; }; 26C5577F132575C8008FD8FE /* MacOSX */ = { isa = PBXGroup; children = ( 9455630A1BEAD0570073F75F /* PlatformAppleSimulator.cpp */, 9455630B1BEAD0570073F75F /* PlatformAppleSimulator.h */, AF8AD62A1BEC28A400150209 /* PlatformAppleTVSimulator.cpp */, AF8AD62B1BEC28A400150209 /* PlatformAppleTVSimulator.h */, AF8AD62C1BEC28A400150209 /* PlatformAppleWatchSimulator.cpp */, AF8AD62D1BEC28A400150209 /* PlatformAppleWatchSimulator.h */, AF254E2F170CCC33007AE5C9 /* PlatformDarwinKernel.cpp */, AF254E30170CCC33007AE5C9 /* PlatformDarwinKernel.h */, 2697A54B133A6305004E4240 /* PlatformDarwin.cpp */, 2697A54C133A6305004E4240 /* PlatformDarwin.h */, 26B7564C14F89356008D9CB3 /* PlatformiOSSimulator.cpp */, 26B7564D14F89356008D9CB3 /* PlatformiOSSimulator.h */, 9455630C1BEAD0570073F75F /* PlatformiOSSimulatorCoreSimulatorSupport.h */, 9455630D1BEAD0570073F75F /* PlatformiOSSimulatorCoreSimulatorSupport.mm */, 26C5577B132575AD008FD8FE /* PlatformMacOSX.cpp */, 26C5577C132575AD008FD8FE /* PlatformMacOSX.h */, AF3A4AD01EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.cpp */, AF3A4AD11EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.h */, AF8AD6331BEC28C400150209 /* PlatformRemoteAppleTV.cpp */, AF8AD6341BEC28C400150209 /* PlatformRemoteAppleTV.h */, AF8AD6351BEC28C400150209 /* PlatformRemoteAppleWatch.cpp */, AF8AD6361BEC28C400150209 /* PlatformRemoteAppleWatch.h */, 2675F6FE1332BE690067997B /* PlatformRemoteiOS.cpp */, 2675F6FF1332BE690067997B /* PlatformRemoteiOS.h */, ); path = MacOSX; sourceTree = ""; }; 26D9FDCA12F785120003F2EE /* Instruction */ = { isa = PBXGroup; children = ( E778E99D1B062D1700247609 /* MIPS */, 26D9FDCB12F785270003F2EE /* ARM */, 264A12F91372522000875C42 /* ARM64 */, 94A5B3941AB9FE5F00A5EE7F /* MIPS64 */, ); path = Instruction; sourceTree = ""; }; 26D9FDCB12F785270003F2EE /* ARM */ = { isa = PBXGroup; children = ( 9A22A15D135E30370024DDC3 /* EmulateInstructionARM.cpp */, 9A22A15E135E30370024DDC3 /* EmulateInstructionARM.h */, 9A22A15F135E30370024DDC3 /* EmulationStateARM.cpp */, 9A22A160135E30370024DDC3 /* EmulationStateARM.h */, ); path = ARM; sourceTree = ""; }; 26DB3E051379E7AD0080DC73 /* ABI */ = { isa = PBXGroup; children = ( 26DB3E061379E7AD0080DC73 /* MacOSX-arm */, 26DB3E0A1379E7AD0080DC73 /* MacOSX-arm64 */, 26DB3E0E1379E7AD0080DC73 /* MacOSX-i386 */, AF20F7621AF18F5E00751A6E /* SysV-arm */, AF20F7631AF18F6800751A6E /* SysV-arm64 */, 26BF51E91B3C754400016294 /* SysV-hexagon */, 26BF51EE1B3C754400016294 /* SysV-i386 */, 9694FA6E1B32AA35005EBB16 /* SysV-mips */, 263641141B34AEE200145B2F /* SysV-mips64 */, AF77E08B1A033C3E0096C0EA /* SysV-ppc */, AF77E08C1A033C4B0096C0EA /* SysV-ppc64 */, 267F68461CC02DED0086832B /* SysV-s390x */, 26DB3E121379E7AD0080DC73 /* SysV-x86_64 */, ); path = ABI; sourceTree = ""; }; 26DB3E061379E7AD0080DC73 /* MacOSX-arm */ = { isa = PBXGroup; children = ( 26DB3E071379E7AD0080DC73 /* ABIMacOSX_arm.cpp */, 26DB3E081379E7AD0080DC73 /* ABIMacOSX_arm.h */, ); path = "MacOSX-arm"; sourceTree = ""; }; 26DB3E0A1379E7AD0080DC73 /* MacOSX-arm64 */ = { isa = PBXGroup; children = ( 26DB3E0B1379E7AD0080DC73 /* ABIMacOSX_arm64.cpp */, 26DB3E0C1379E7AD0080DC73 /* ABIMacOSX_arm64.h */, ); path = "MacOSX-arm64"; sourceTree = ""; }; 26DB3E0E1379E7AD0080DC73 /* MacOSX-i386 */ = { isa = PBXGroup; children = ( 26DB3E0F1379E7AD0080DC73 /* ABIMacOSX_i386.cpp */, 26DB3E101379E7AD0080DC73 /* ABIMacOSX_i386.h */, ); path = "MacOSX-i386"; sourceTree = ""; }; 26DB3E121379E7AD0080DC73 /* SysV-x86_64 */ = { isa = PBXGroup; children = ( 26DB3E131379E7AD0080DC73 /* ABISysV_x86_64.cpp */, 26DB3E141379E7AD0080DC73 /* ABISysV_x86_64.h */, ); path = "SysV-x86_64"; sourceTree = ""; }; 26E152221419CACA007967D0 /* PECOFF */ = { isa = PBXGroup; children = ( 26E152231419CACA007967D0 /* ObjectFilePECOFF.cpp */, 26E152241419CACA007967D0 /* ObjectFilePECOFF.h */, 26C7C4811BFFEA7E009BD01F /* WindowsMiniDump.cpp */, 26C7C4821BFFEA7E009BD01F /* WindowsMiniDump.h */, ); path = PECOFF; sourceTree = ""; }; 26EFB6151BFE8D3E00544801 /* NetBSD */ = { isa = PBXGroup; children = ( 26EFB6181BFE8D3E00544801 /* PlatformNetBSD.cpp */, 26EFB6191BFE8D3E00544801 /* PlatformNetBSD.h */, ); path = NetBSD; sourceTree = ""; }; 26EFC4C718CFAF0D00865D87 /* JIT */ = { isa = PBXGroup; children = ( 26EFC4CA18CFAF0D00865D87 /* ObjectFileJIT.cpp */, 26EFC4CB18CFAF0D00865D87 /* ObjectFileJIT.h */, ); path = JIT; sourceTree = ""; }; 26F006521B4DD86700B872E5 /* Windows-DYLD */ = { isa = PBXGroup; children = ( 26F006541B4DD86700B872E5 /* DynamicLoaderWindowsDYLD.cpp */, 26F006551B4DD86700B872E5 /* DynamicLoaderWindowsDYLD.h */, ); path = "Windows-DYLD"; sourceTree = ""; }; 26F5C22410F3D950009D5894 /* Tools */ = { isa = PBXGroup; children = ( E769331B1A94D10E00C73337 /* lldb-server */, 942829BA1A89830900521B30 /* argdumper */, 26579F55126A255E0007C5CB /* darwin-debug */, 265E9BE0115C2B8500D0DCCB /* debugserver */, 26F5C22510F3D956009D5894 /* Driver */, 2665CD0915080846002C8FAE /* install-headers */, ); name = Tools; sourceTree = ""; usesTabs = 0; }; 26F5C22510F3D956009D5894 /* Driver */ = { isa = PBXGroup; children = ( 26F5C27210F3D9E4009D5894 /* lldb-Info.plist */, 26F5C27410F3D9E4009D5894 /* Driver.h */, 26F5C27310F3D9E4009D5894 /* Driver.cpp */, ); name = Driver; sourceTree = ""; }; 26F5C32810F3DF7D009D5894 /* Libraries */ = { isa = PBXGroup; children = ( 26F5C39010F3FA26009D5894 /* CoreFoundation.framework */, 265ABF6210F42EE900531910 /* DebugSymbols.framework */, 260C876910F538E700BB2B04 /* Foundation.framework */, 26709E311964A34000B94724 /* LaunchServices.framework */, 26F5C32A10F3DFDD009D5894 /* libedit.dylib */, 2689FFCA13353D7A00698AC0 /* liblldb-core.a */, 2670F8111862B44A006B332C /* libncurses.dylib */, 26F5C37410F3F61B009D5894 /* libobjc.dylib */, 260157C41885F4FF00F875CF /* libpanel.dylib */, 26F5C32410F3DF23009D5894 /* libpython.dylib */, 26F5C32B10F3DFDD009D5894 /* libtermcap.dylib */, 26D55234159A7DB100708D8D /* libxml2.dylib */, 966C6B7818E6A56A0093F5EC /* libz.dylib */, EDB919B414F6F10D008FF64B /* Security.framework */, ); name = Libraries; sourceTree = ""; usesTabs = 0; }; 26FFC19214FC072100087D58 /* POSIX-DYLD */ = { isa = PBXGroup; children = ( 26FFC19314FC072100087D58 /* AuxVector.cpp */, 26FFC19414FC072100087D58 /* AuxVector.h */, 26FFC19514FC072100087D58 /* DYLDRendezvous.cpp */, 26FFC19614FC072100087D58 /* DYLDRendezvous.h */, 26FFC19714FC072100087D58 /* DynamicLoaderPOSIXDYLD.cpp */, 26FFC19814FC072100087D58 /* DynamicLoaderPOSIXDYLD.h */, ); path = "POSIX-DYLD"; sourceTree = ""; }; 3F8169261ABB73C1001DA9DF /* Initialization */ = { isa = PBXGroup; children = ( 3F8169341ABB7A80001DA9DF /* SystemInitializer.h */, 3F81692E1ABB7A6D001DA9DF /* SystemInitializer.cpp */, 3F8169351ABB7A80001DA9DF /* SystemInitializerCommon.h */, 3F81692F1ABB7A6D001DA9DF /* SystemInitializerCommon.cpp */, 3F8169361ABB7A80001DA9DF /* SystemLifetimeManager.h */, 3F8169301ABB7A6D001DA9DF /* SystemLifetimeManager.cpp */, ); name = Initialization; sourceTree = ""; }; 3FBA69DA1B6066D20008F44A /* ScriptInterpreter */ = { isa = PBXGroup; children = ( 3FBA69DC1B6066E90008F44A /* None */, 3FBA69DB1B6066E40008F44A /* Python */, ); name = ScriptInterpreter; sourceTree = ""; }; 3FBA69DB1B6066E40008F44A /* Python */ = { isa = PBXGroup; children = ( 3FBA69E21B60672A0008F44A /* lldb-python.h */, 3FBA69E31B60672A0008F44A /* PythonDataObjects.cpp */, 3FBA69E41B60672A0008F44A /* PythonDataObjects.h */, AFCB2BBB1BF577F40018B553 /* PythonExceptionState.cpp */, AFCB2BBC1BF577F40018B553 /* PythonExceptionState.h */, 3FBA69E51B60672A0008F44A /* ScriptInterpreterPython.cpp */, 3FBA69E61B60672A0008F44A /* ScriptInterpreterPython.h */, ); name = Python; sourceTree = ""; }; 3FBA69DC1B6066E90008F44A /* None */ = { isa = PBXGroup; children = ( 3FBA69DD1B6067020008F44A /* ScriptInterpreterNone.cpp */, 3FBA69DE1B6067020008F44A /* ScriptInterpreterNone.h */, ); name = None; sourceTree = ""; }; 3FDFDDC4199D37BE009756A7 /* posix */ = { isa = PBXGroup; children = ( 2579065E1BD0488D00178368 /* DomainSocket.cpp */, 255EFF751AFABA950069F277 /* LockFilePosix.cpp */, AFDFDFD019E34D3400EAE509 /* ConnectionFileDescriptorPosix.cpp */, 3FDFDDC5199D37ED009756A7 /* FileSystem.cpp */, 3FDFE53019A292F0009756A7 /* HostInfoPosix.cpp */, 3FDFE53219A29304009756A7 /* HostInfoPosix.h */, 3FDFE56A19AF9C44009756A7 /* HostProcessPosix.cpp */, 3FDFE56E19AF9C5A009756A7 /* HostProcessPosix.h */, 3FDFE56B19AF9C44009756A7 /* HostThreadPosix.cpp */, 3FDFE56F19AF9C5A009756A7 /* HostThreadPosix.h */, 2377C2F719E613C100737875 /* PipePosix.cpp */, ); name = posix; path = source/Host/posix; sourceTree = ""; }; 3FDFE53919A29399009756A7 /* freebsd */ = { isa = PBXGroup; children = ( 3FDFE53C19A293CA009756A7 /* Config.h */, 3FDFE55E19AF9B14009756A7 /* Host.cpp */, 3FDFE53B19A293B3009756A7 /* HostInfoFreeBSD.cpp */, 3FDFE53D19A293CA009756A7 /* HostInfoFreeBSD.h */, 3FDFE55F19AF9B14009756A7 /* HostThreadFreeBSD.cpp */, 3FDFE56019AF9B39009756A7 /* HostThreadFreeBSD.h */, ); name = freebsd; sourceTree = ""; }; 3FDFE53E19A2940E009756A7 /* windows */ = { isa = PBXGroup; children = ( 255EFF711AFABA4D0069F277 /* LockFileWindows.cpp */, 255EFF6F1AFABA320069F277 /* LockFileWindows.h */, 255EFF701AFABA320069F277 /* PipeWindows.h */, 3FDFE54719A2946B009756A7 /* AutoHandle.h */, 3FDFE54819A2946B009756A7 /* editlinewin.h */, 3FDFE54019A29448009756A7 /* EditLineWin.cpp */, 3FDFE54119A29448009756A7 /* FileSystem.cpp */, 3FDFE54219A29448009756A7 /* Host.cpp */, 3FDFE54319A29448009756A7 /* HostInfoWindows.cpp */, 3FDFE54919A2946B009756A7 /* HostInfoWindows.h */, 3FDFE57019AF9CA0009756A7 /* HostProcessWindows.cpp */, 3FDFE57219AF9CD3009756A7 /* HostProcessWindows.h */, 3FDFE57119AF9CA0009756A7 /* HostThreadWindows.cpp */, 3FDFE57319AF9CD3009756A7 /* HostThreadWindows.h */, 3FDFE54519A29448009756A7 /* ProcessRunLock.cpp */, 3FDFE54A19A2946B009756A7 /* win32.h */, 3FDFE54619A29448009756A7 /* Windows.cpp */, 3FDFE54B19A2946B009756A7 /* windows.h */, ); name = windows; sourceTree = ""; }; 490A36BA180F0E6F00BA31F8 /* Windows */ = { isa = PBXGroup; children = ( 490A36BD180F0E6F00BA31F8 /* PlatformWindows.cpp */, 490A36BE180F0E6F00BA31F8 /* PlatformWindows.h */, ); path = Windows; sourceTree = ""; }; 49724D961AD6ECFA0033C538 /* RenderScript */ = { isa = PBXGroup; children = ( 23D065811D4A7BDA0008EDE6 /* CMakeLists.txt */, 948554591DCBAE3B00345FF5 /* RenderScriptScriptGroup.cpp */, 948554581DCBAE3200345FF5 /* RenderScriptScriptGroup.h */, 23D065831D4A7BDA0008EDE6 /* RenderScriptExpressionOpts.h */, 23D065821D4A7BDA0008EDE6 /* RenderScriptExpressionOpts.cpp */, 23D065851D4A7BDA0008EDE6 /* RenderScriptRuntime.h */, 23D065841D4A7BDA0008EDE6 /* RenderScriptRuntime.cpp */, 23D065871D4A7BDA0008EDE6 /* RenderScriptx86ABIFixups.h */, 23D065861D4A7BDA0008EDE6 /* RenderScriptx86ABIFixups.cpp */, ); name = RenderScript; path = RenderScript/RenderScriptRuntime; sourceTree = ""; }; 4984BA0B1B975E9F008658D4 /* ExpressionParser */ = { isa = PBXGroup; children = ( 4984BA0C1B97620B008658D4 /* Clang */, AE44FB371BB35A2E0033EB62 /* Go */, ); name = ExpressionParser; sourceTree = ""; }; 4984BA0C1B97620B008658D4 /* Clang */ = { isa = PBXGroup; children = ( 4C3DA2301CA0BFB800CEB1D4 /* ClangDiagnostic.h */, 4C98D3E0118FB98F00E575D0 /* ClangFunctionCaller.h */, 4C98D3DA118FB96F00E575D0 /* ClangFunctionCaller.cpp */, 26BC7DC010F1B79500F91463 /* ClangExpressionHelper.h */, 49445E341225AB6A00C11A81 /* ClangUserExpression.h */, 26BC7ED510F1B86700F91463 /* ClangUserExpression.cpp */, 497C86C1122823F300B54702 /* ClangUtilityFunction.h */, 497C86BD122823D800B54702 /* ClangUtilityFunction.cpp */, 49D7072611B5AD03001AD875 /* ClangASTSource.h */, 49D7072811B5AD11001AD875 /* ClangASTSource.cpp */, 49F1A74911B338AE003ED505 /* ClangExpressionDeclMap.h */, 49F1A74511B3388F003ED505 /* ClangExpressionDeclMap.cpp */, 49445C2912245E5500C11A81 /* ClangExpressionParser.h */, 49445C2512245E3600C11A81 /* ClangExpressionParser.cpp */, 4959511B1A1BC48100F6F8FC /* ClangModulesDeclVendor.h */, 4959511E1A1BC4BC00F6F8FC /* ClangModulesDeclVendor.cpp */, 49D4FE821210B5FB00CDB854 /* ClangPersistentVariables.h */, 49D4FE871210B61C00CDB854 /* ClangPersistentVariables.cpp */, 4906FD4412F2257600A2A77C /* ASTDumper.h */, 4906FD4012F2255300A2A77C /* ASTDumper.cpp */, 49A8A3A311D568BF00AD3B68 /* ASTResultSynthesizer.h */, 49A8A39F11D568A300AD3B68 /* ASTResultSynthesizer.cpp */, 4911934B1226383D00578B7F /* ASTStructExtractor.h */, 491193501226386000578B7F /* ASTStructExtractor.cpp */, 49307AB111DEA4F20081F992 /* IRForTarget.h */, 49307AAD11DEA4D90081F992 /* IRForTarget.cpp */, 4984BA0F1B978C3E008658D4 /* ClangExpressionVariable.h */, 4984BA0E1B978C3E008658D4 /* ClangExpressionVariable.cpp */, ); name = Clang; sourceTree = ""; }; 4CC7C64B1D5298AB0076FF94 /* OCaml */ = { isa = PBXGroup; children = ( 4CC7C64C1D5298E20076FF94 /* OCamlLanguage.h */, 4CC7C64D1D5298E20076FF94 /* OCamlLanguage.cpp */, ); name = OCaml; sourceTree = ""; }; 4CCA643A13B40B82003BDF98 /* LanguageRuntime */ = { isa = PBXGroup; children = ( 6D0F61491C80AAF200A4ECEE /* Java */, AE44FB3B1BB485730033EB62 /* Go */, 49724D961AD6ECFA0033C538 /* RenderScript */, 4CCA643B13B40B82003BDF98 /* CPlusPlus */, 4CCA644013B40B82003BDF98 /* ObjC */, ); path = LanguageRuntime; sourceTree = ""; }; 4CCA643B13B40B82003BDF98 /* CPlusPlus */ = { isa = PBXGroup; children = ( 4CCA643C13B40B82003BDF98 /* ItaniumABI */, ); path = CPlusPlus; sourceTree = ""; }; 4CCA643C13B40B82003BDF98 /* ItaniumABI */ = { isa = PBXGroup; children = ( 4CCA643D13B40B82003BDF98 /* ItaniumABILanguageRuntime.cpp */, 4CCA643E13B40B82003BDF98 /* ItaniumABILanguageRuntime.h */, ); path = ItaniumABI; sourceTree = ""; }; 4CCA644013B40B82003BDF98 /* ObjC */ = { isa = PBXGroup; children = ( 4CCA644113B40B82003BDF98 /* AppleObjCRuntime */, ); path = ObjC; sourceTree = ""; }; 4CCA644113B40B82003BDF98 /* AppleObjCRuntime */ = { isa = PBXGroup; children = ( 94CD7D0719A3FB8600908B7C /* AppleObjCClassDescriptorV2.h */, 94CD7D0819A3FBA300908B7C /* AppleObjCClassDescriptorV2.cpp */, 4CCA644213B40B82003BDF98 /* AppleObjCRuntime.cpp */, 4CCA644313B40B82003BDF98 /* AppleObjCRuntime.h */, 4CCA644413B40B82003BDF98 /* AppleObjCRuntimeV1.cpp */, 4CCA644513B40B82003BDF98 /* AppleObjCRuntimeV1.h */, 4CCA644613B40B82003BDF98 /* AppleObjCRuntimeV2.cpp */, 4CCA644713B40B82003BDF98 /* AppleObjCRuntimeV2.h */, 4CCA644813B40B82003BDF98 /* AppleObjCTrampolineHandler.cpp */, 4CCA644913B40B82003BDF98 /* AppleObjCTrampolineHandler.h */, 94CD7D0A19A3FBC300908B7C /* AppleObjCTypeEncodingParser.h */, 94CD7D0B19A3FBCE00908B7C /* AppleObjCTypeEncodingParser.cpp */, 49DA65041485C942005FF180 /* AppleObjCDeclVendor.h */, 49DA65021485C92A005FF180 /* AppleObjCDeclVendor.cpp */, 4CCA644A13B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.cpp */, 4CCA644B13B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.h */, ); path = AppleObjCRuntime; sourceTree = ""; }; 4CE4EFA51E89998800A80C06 /* OpenBSD */ = { isa = PBXGroup; children = ( 4CE4EFA61E8999B000A80C06 /* PlatformOpenBSD.cpp */, 4CE4EFA71E8999B000A80C06 /* PlatformOpenBSD.h */, ); path = OpenBSD; sourceTree = ""; }; 4CEE62F71145F1C70064CF93 /* GDB Remote */ = { isa = PBXGroup; children = ( 2374D7431D4BAA1D005C9575 /* CMakeLists.txt */, 2374D74F1D4BB299005C9575 /* GDBRemoteClientBase.h */, 2374D74E1D4BB299005C9575 /* GDBRemoteClientBase.cpp */, 6D55B2931A8A808400A70529 /* GDBRemoteCommunicationServerCommon.h */, 6D55B2941A8A808400A70529 /* GDBRemoteCommunicationServerLLGS.h */, 6D55B2951A8A808400A70529 /* GDBRemoteCommunicationServerPlatform.h */, 6D55B28D1A8A806200A70529 /* GDBRemoteCommunicationServerCommon.cpp */, 6D55B28E1A8A806200A70529 /* GDBRemoteCommunicationServerLLGS.cpp */, 6D55B28F1A8A806200A70529 /* GDBRemoteCommunicationServerPlatform.cpp */, 2618EE5B1315B29C001D6D71 /* GDBRemoteCommunication.cpp */, 2618EE5C1315B29C001D6D71 /* GDBRemoteCommunication.h */, 26744EED1338317700EF765A /* GDBRemoteCommunicationClient.cpp */, 26744EEE1338317700EF765A /* GDBRemoteCommunicationClient.h */, 26744EEF1338317700EF765A /* GDBRemoteCommunicationServer.cpp */, 26744EF01338317700EF765A /* GDBRemoteCommunicationServer.h */, 2618EE5D1315B29C001D6D71 /* GDBRemoteRegisterContext.cpp */, 2618EE5E1315B29C001D6D71 /* GDBRemoteRegisterContext.h */, 2618EE5F1315B29C001D6D71 /* ProcessGDBRemote.cpp */, 2618EE601315B29C001D6D71 /* ProcessGDBRemote.h */, 2618EE611315B29C001D6D71 /* ProcessGDBRemoteLog.cpp */, 2618EE621315B29C001D6D71 /* ProcessGDBRemoteLog.h */, 2618EE631315B29C001D6D71 /* ThreadGDBRemote.cpp */, 2618EE641315B29C001D6D71 /* ThreadGDBRemote.h */, ); name = "GDB Remote"; path = "gdb-remote"; sourceTree = ""; }; 54067BEA1DF2033700749AA5 /* UBSan */ = { isa = PBXGroup; children = ( 54067BEC1DF2034B00749AA5 /* UBSanRuntime.cpp */, 54067BED1DF2034B00749AA5 /* UBSanRuntime.h */, ); path = UBSan; sourceTree = ""; }; 69A01E1A1236C5D400C660B5 /* common */ = { isa = PBXGroup; children = ( D67521351EA17C3900439694 /* MainLoop.cpp */, 2579065A1BD0488100178368 /* TCPSocket.cpp */, 2579065B1BD0488100178368 /* UDPSocket.cpp */, 255EFF731AFABA720069F277 /* LockFileBase.cpp */, 250D6AE11A9679270049CC70 /* FileSystem.cpp */, 33E5E8411A672A240024ED68 /* StringConvert.cpp */, 25420ED11A649D88009ADBCB /* PipeBase.cpp */, 26CFDCA2186163A4000E63E5 /* Editline.cpp */, 260C6EA213011581005E16B0 /* File.cpp */, 69A01E1C1236C5D400C660B5 /* Host.cpp */, 3FDFE53419A29327009756A7 /* HostInfoBase.cpp */, 3FDFED2419BA6D96009756A7 /* HostNativeThreadBase.cpp */, 3FDFED2C19C257A0009756A7 /* HostProcess.cpp */, 3FDFED2519BA6D96009756A7 /* HostThread.cpp */, A36FF33B17D8E94600244D40 /* OptionParser.cpp */, AF37E10917C861F20061E18E /* ProcessRunLock.cpp */, 236124A31986B4E2004EFC37 /* Socket.cpp */, 69A01E1F1236C5D400C660B5 /* Symbols.cpp */, 268DA873130095ED00C9483A /* Terminal.cpp */, 3FDFED2619BA6D96009756A7 /* ThreadLauncher.cpp */, ); name = common; path = source/Host/common; sourceTree = ""; }; 6D0F61491C80AAF200A4ECEE /* Java */ = { isa = PBXGroup; children = ( 6D0F614A1C80AB0400A4ECEE /* JavaLanguageRuntime.cpp */, 6D0F614B1C80AB0400A4ECEE /* JavaLanguageRuntime.h */, ); name = Java; sourceTree = ""; }; 6D0F61501C80AB1400A4ECEE /* Java */ = { isa = PBXGroup; children = ( 6D0F61511C80AB3000A4ECEE /* JavaFormatterFunctions.cpp */, 6D0F61521C80AB3000A4ECEE /* JavaFormatterFunctions.h */, 6D0F61531C80AB3000A4ECEE /* JavaLanguage.cpp */, 6D0F61541C80AB3000A4ECEE /* JavaLanguage.h */, ); name = Java; sourceTree = ""; }; 6D55B29B1A8CCFF000A70529 /* android */ = { isa = PBXGroup; children = ( 6D55BAE21A8CD06000A70529 /* Android.h */, 6D55BAE31A8CD06000A70529 /* Config.h */, 6D55BAE41A8CD06000A70529 /* HostInfoAndroid.h */, 6D55BAE01A8CD03D00A70529 /* HostInfoAndroid.cpp */, ); name = android; sourceTree = ""; }; 6D55BAE61A8CD08C00A70529 /* Android */ = { isa = PBXGroup; children = ( 25EF23751AC09AD800908DF0 /* AdbClient.cpp */, 25EF23761AC09AD800908DF0 /* AdbClient.h */, 6D55BAE91A8CD08C00A70529 /* PlatformAndroid.cpp */, 6D55BAEA1A8CD08C00A70529 /* PlatformAndroid.h */, 6D55BAEB1A8CD08C00A70529 /* PlatformAndroidRemoteGDBServer.cpp */, 6D55BAEC1A8CD08C00A70529 /* PlatformAndroidRemoteGDBServer.h */, ); path = Android; sourceTree = ""; }; 8C26C4221C3EA4050031DF7C /* TSan */ = { isa = PBXGroup; children = ( 8C26C4241C3EA4340031DF7C /* TSanRuntime.cpp */, 8C26C4251C3EA4340031DF7C /* TSanRuntime.h */, ); name = TSan; sourceTree = ""; }; 8C2D6A58197A1FB9006989C9 /* MemoryHistory */ = { isa = PBXGroup; children = ( 8C2D6A59197A1FCD006989C9 /* asan */, ); path = MemoryHistory; sourceTree = ""; }; 8C2D6A59197A1FCD006989C9 /* asan */ = { isa = PBXGroup; children = ( 8C2D6A5A197A1FDC006989C9 /* MemoryHistoryASan.cpp */, 8C2D6A5B197A1FDC006989C9 /* MemoryHistoryASan.h */, ); path = asan; sourceTree = ""; }; 8C3BD9911EF45D9B0016C343 /* MainThreadChecker */ = { isa = PBXGroup; children = ( 8C3BD9931EF45D9B0016C343 /* MainThreadCheckerRuntime.h */, 8C3BD9951EF45D9B0016C343 /* MainThreadCheckerRuntime.cpp */, ); path = MainThreadChecker; sourceTree = ""; }; 8CF02ADD19DCBEC200B14BE0 /* InstrumentationRuntime */ = { isa = PBXGroup; children = ( 54067BEA1DF2033700749AA5 /* UBSan */, 8C26C4221C3EA4050031DF7C /* TSan */, 8CF02ADE19DCBEE600B14BE0 /* ASan */, 8C3BD9911EF45D9B0016C343 /* MainThreadChecker */, ); path = InstrumentationRuntime; sourceTree = ""; }; 8CF02ADE19DCBEE600B14BE0 /* ASan */ = { isa = PBXGroup; children = ( 8CF02AE519DCBF8400B14BE0 /* ASanRuntime.cpp */, 8CF02AE619DCBF8400B14BE0 /* ASanRuntime.h */, ); path = ASan; sourceTree = ""; }; 942829BA1A89830900521B30 /* argdumper */ = { isa = PBXGroup; children = ( 940B04D81A8984FF0045D5F7 /* argdumper.cpp */, ); name = argdumper; sourceTree = ""; }; 945261B01B9A11BE00BF138D /* Formatters */ = { isa = PBXGroup; children = ( 4CDB8D671DBA91A6006C5B13 /* LibStdcppUniquePointer.cpp */, 4CDB8D681DBA91A6006C5B13 /* LibStdcppTuple.cpp */, 49DEF1201CD7BD90006A7C7D /* BlockPointer.h */, 49DEF11F1CD7BD90006A7C7D /* BlockPointer.cpp */, 945261B41B9A11E800BF138D /* CxxStringTypes.h */, 945261B31B9A11E800BF138D /* CxxStringTypes.cpp */, 945261B61B9A11E800BF138D /* LibCxx.h */, 945261B51B9A11E800BF138D /* LibCxx.cpp */, 9428BC2A1C6E64DC002A24D7 /* LibCxxAtomic.h */, 9428BC291C6E64DC002A24D7 /* LibCxxAtomic.cpp */, 945261B71B9A11E800BF138D /* LibCxxInitializerList.cpp */, 945261B81B9A11E800BF138D /* LibCxxList.cpp */, 945261B91B9A11E800BF138D /* LibCxxMap.cpp */, 945261BA1B9A11E800BF138D /* LibCxxUnorderedMap.cpp */, 945261BB1B9A11E800BF138D /* LibCxxVector.cpp */, 945261BD1B9A11E800BF138D /* LibStdcpp.h */, 945261BC1B9A11E800BF138D /* LibStdcpp.cpp */, ); name = Formatters; sourceTree = ""; }; 9457596415349416005A9070 /* POSIX */ = { isa = PBXGroup; children = ( 945759651534941F005A9070 /* PlatformPOSIX.cpp */, 945759661534941F005A9070 /* PlatformPOSIX.h */, ); name = POSIX; sourceTree = ""; }; 949EED9D1BA74AB6008C63CF /* Formatters */ = { isa = PBXGroup; children = ( 949EEDAD1BA76719008C63CF /* CF.h */, 949EEDAC1BA76719008C63CF /* CF.cpp */, 949EEDA21BA76571008C63CF /* Cocoa.h */, 949EEDA11BA76571008C63CF /* Cocoa.cpp */, 949EED9F1BA74B64008C63CF /* CoreMedia.h */, 949EED9E1BA74B64008C63CF /* CoreMedia.cpp */, 949EEDA41BA765B5008C63CF /* NSArray.cpp */, 94B9E50E1BBEFDFE000A48DC /* NSDictionary.h */, 949EEDA51BA765B5008C63CF /* NSDictionary.cpp */, 940495781BEC497E00926025 /* NSError.cpp */, 940495791BEC497E00926025 /* NSException.cpp */, 949EEDA61BA765B5008C63CF /* NSIndexPath.cpp */, 94B9E50F1BBF0069000A48DC /* NSSet.h */, 949EEDA71BA765B5008C63CF /* NSSet.cpp */, 94B9E5101BBF20B7000A48DC /* NSString.h */, 94B9E5111BBF20F4000A48DC /* NSString.cpp */, ); name = Formatters; sourceTree = ""; }; 94A5B3941AB9FE5F00A5EE7F /* MIPS64 */ = { isa = PBXGroup; children = ( 94A5B3951AB9FE8300A5EE7F /* EmulateInstructionMIPS64.cpp */, 94A5B3961AB9FE8300A5EE7F /* EmulateInstructionMIPS64.h */, ); name = MIPS64; sourceTree = ""; }; 94B638541B8FABEA004FE1E4 /* Language */ = { isa = PBXGroup; children = ( 6D0F61501C80AB1400A4ECEE /* Java */, 94B6385A1B8FB109004FE1E4 /* CPlusPlus */, AE44FB431BB4BAC20033EB62 /* Go */, 94B638551B8FAC87004FE1E4 /* ObjC */, 94B638601B8FB7BE004FE1E4 /* ObjCPlusPlus */, 4CC7C64B1D5298AB0076FF94 /* OCaml */, ); name = Language; sourceTree = ""; }; 94B638551B8FAC87004FE1E4 /* ObjC */ = { isa = PBXGroup; children = ( 949EED9D1BA74AB6008C63CF /* Formatters */, 94B6385F1B8FB7A2004FE1E4 /* ObjCLanguage.h */, 94B6385E1B8FB7A2004FE1E4 /* ObjCLanguage.cpp */, ); name = ObjC; sourceTree = ""; }; 94B6385A1B8FB109004FE1E4 /* CPlusPlus */ = { isa = PBXGroup; children = ( 945261B01B9A11BE00BF138D /* Formatters */, 94B6385C1B8FB174004FE1E4 /* CPlusPlusLanguage.h */, 94B6385B1B8FB174004FE1E4 /* CPlusPlusLanguage.cpp */, 49F811F01E931B1500F4E163 /* CPlusPlusNameParser.h */, 49F811EF1E931B1500F4E163 /* CPlusPlusNameParser.cpp */, ); name = CPlusPlus; sourceTree = ""; }; 94B638601B8FB7BE004FE1E4 /* ObjCPlusPlus */ = { isa = PBXGroup; children = ( 94B638611B8FB7E9004FE1E4 /* ObjCPlusPlusLanguage.h */, 94B638621B8FB7F1004FE1E4 /* ObjCPlusPlusLanguage.cpp */, ); name = ObjCPlusPlus; sourceTree = ""; }; 94CB255616B0683B0059775D /* DataFormatters */ = { isa = PBXGroup; children = ( 945261C91B9A14E000BF138D /* CXXFunctionPointer.h */, 945261C71B9A14D300BF138D /* CXXFunctionPointer.cpp */, 94CB256016B069800059775D /* DataVisualization.h */, 94CB255816B069770059775D /* DataVisualization.cpp */, 9447DE411BD5962900E67212 /* DumpValueObjectOptions.h */, 9447DE421BD5963300E67212 /* DumpValueObjectOptions.cpp */, 94CB257516B1D3910059775D /* FormatCache.h */, 94CB257316B1D3870059775D /* FormatCache.cpp */, 94CB256116B069800059775D /* FormatClasses.h */, 94CB255916B069770059775D /* FormatClasses.cpp */, 94CB256216B069800059775D /* FormatManager.h */, 94CB255A16B069770059775D /* FormatManager.cpp */, 94EE33F218643C6900CD703B /* FormattersContainer.h */, 94D0858A1B9675A0000D24BD /* FormattersHelpers.h */, 94D0858B1B9675B8000D24BD /* FormattersHelpers.cpp */, 942612F51B94FFE900EF842E /* LanguageCategory.h */, 942612F61B95000000EF842E /* LanguageCategory.cpp */, 94F48F231A01C679005C0EC6 /* StringPrinter.h */, 94F48F241A01C687005C0EC6 /* StringPrinter.cpp */, 94CB256816B096F90059775D /* TypeCategory.h */, 94CB256416B096F10059775D /* TypeCategory.cpp */, 94CB256916B096FA0059775D /* TypeCategoryMap.h */, 94CB256516B096F10059775D /* TypeCategoryMap.cpp */, 94CB256A16B0A4030059775D /* TypeFormat.h */, 94CB256D16B0A4260059775D /* TypeFormat.cpp */, 94CB256B16B0A4030059775D /* TypeSummary.h */, 94CB256E16B0A4260059775D /* TypeSummary.cpp */, 94CB256C16B0A4040059775D /* TypeSynthetic.h */, 94CB256F16B0A4270059775D /* TypeSynthetic.cpp */, 94CD131819BA33A100DB7BED /* TypeValidator.h */, 94CD131919BA33B400DB7BED /* TypeValidator.cpp */, 945215DD17F639E600521C0B /* ValueObjectPrinter.h */, 945215DE17F639EE00521C0B /* ValueObjectPrinter.cpp */, 943B90FC1B991586007BA499 /* VectorIterator.h */, 9418EBCB1AA9108B0058B02E /* VectorType.h */, 9418EBCC1AA910910058B02E /* VectorType.cpp */, ); name = DataFormatters; sourceTree = ""; }; 9694FA6E1B32AA35005EBB16 /* SysV-mips */ = { isa = PBXGroup; children = ( 9694FA6F1B32AA64005EBB16 /* ABISysV_mips.cpp */, 9694FA701B32AA64005EBB16 /* ABISysV_mips.h */, ); name = "SysV-mips"; sourceTree = ""; }; + 9A1542F31F0EE44000DEA1D8 /* Helpers */ = { + isa = PBXGroup; + children = ( + 9A1542F41F0EE44000DEA1D8 /* CMakeLists.txt */, + 9A1542F51F0EE44000DEA1D8 /* MockTildeExpressionResolver.cpp */, + 9A1542F61F0EE44000DEA1D8 /* MockTildeExpressionResolver.h */, + 9A1542F71F0EE44000DEA1D8 /* TestUtilities.cpp */, + 9A1542F81F0EE44000DEA1D8 /* TestUtilities.h */, + ); + path = Helpers; + sourceTree = ""; + }; AE44FB371BB35A2E0033EB62 /* Go */ = { isa = PBXGroup; children = ( AE44FB261BB07DC60033EB62 /* GoAST.h */, AE44FB271BB07DC60033EB62 /* GoLexer.h */, AE44FB2A1BB07DD80033EB62 /* GoLexer.cpp */, AE44FB281BB07DC60033EB62 /* GoParser.h */, AE44FB2B1BB07DD80033EB62 /* GoParser.cpp */, AE44FB291BB07DC60033EB62 /* GoUserExpression.h */, AE44FB2C1BB07DD80033EB62 /* GoUserExpression.cpp */, ); name = Go; sourceTree = ""; }; AE44FB3B1BB485730033EB62 /* Go */ = { isa = PBXGroup; children = ( AE44FB3C1BB4858A0033EB62 /* GoLanguageRuntime.h */, AE44FB3D1BB485960033EB62 /* GoLanguageRuntime.cpp */, ); name = Go; sourceTree = ""; }; AE44FB431BB4BAC20033EB62 /* Go */ = { isa = PBXGroup; children = ( AE44FB491BB4BB1B0033EB62 /* Formatters */, AE44FB461BB4BB090033EB62 /* GoLanguage.h */, AE44FB451BB4BB090033EB62 /* GoLanguage.cpp */, ); name = Go; sourceTree = ""; }; AE44FB491BB4BB1B0033EB62 /* Formatters */ = { isa = PBXGroup; children = ( AE44FB4B1BB4BB540033EB62 /* GoFormatterFunctions.h */, AE44FB4A1BB4BB540033EB62 /* GoFormatterFunctions.cpp */, ); name = Formatters; sourceTree = ""; }; AE8F624519EF3DFC00326B21 /* Go */ = { isa = PBXGroup; children = ( AE8F624719EF3E1E00326B21 /* OperatingSystemGo.cpp */, AE8F624819EF3E1E00326B21 /* OperatingSystemGo.h */, ); name = Go; sourceTree = ""; }; AEC6FF9D1BE97035007882C1 /* Expression */ = { isa = PBXGroup; children = ( 23CB14F31D66CC9B00EDDDE1 /* CMakeLists.txt */, AEC6FF9F1BE970A2007882C1 /* GoParserTest.cpp */, ); path = Expression; sourceTree = ""; }; AF11CB34182CA85A00D9B618 /* SystemRuntime */ = { isa = PBXGroup; children = ( AF11CB35182CA85A00D9B618 /* MacOSX */, ); path = SystemRuntime; sourceTree = ""; }; AF11CB35182CA85A00D9B618 /* MacOSX */ = { isa = PBXGroup; children = ( AF0E22EE18A09FB20009B7D1 /* AppleGetItemInfoHandler.cpp */, AF0E22EF18A09FB20009B7D1 /* AppleGetItemInfoHandler.h */, AF1F7B05189C904B0087DB9C /* AppleGetPendingItemsHandler.cpp */, AF1F7B06189C904B0087DB9C /* AppleGetPendingItemsHandler.h */, AF25AB24188F685C0030DEC3 /* AppleGetQueuesHandler.cpp */, AF25AB25188F685C0030DEC3 /* AppleGetQueuesHandler.h */, AF45FDE318A1F3AC0007051C /* AppleGetThreadItemInfoHandler.cpp */, AF45FDE418A1F3AC0007051C /* AppleGetThreadItemInfoHandler.h */, AF9B8F31182DB52900DA866F /* SystemRuntimeMacOSX.cpp */, AF9B8F32182DB52900DA866F /* SystemRuntimeMacOSX.h */, ); path = MacOSX; sourceTree = ""; }; AF20F7621AF18F5E00751A6E /* SysV-arm */ = { isa = PBXGroup; children = ( AF20F7641AF18F8500751A6E /* ABISysV_arm.cpp */, AF20F7651AF18F8500751A6E /* ABISysV_arm.h */, ); name = "SysV-arm"; sourceTree = ""; }; AF20F7631AF18F6800751A6E /* SysV-arm64 */ = { isa = PBXGroup; children = ( AF20F7681AF18F9000751A6E /* ABISysV_arm64.cpp */, AF20F7691AF18F9000751A6E /* ABISysV_arm64.h */, ); name = "SysV-arm64"; sourceTree = ""; }; AF248A4B1DA71C67000B814D /* InstEmulation */ = { isa = PBXGroup; children = ( AF248A4C1DA71C77000B814D /* TestArm64InstEmulation.cpp */, ); name = InstEmulation; sourceTree = ""; }; AF2BCA6518C7EFDE005B4526 /* JITLoader */ = { isa = PBXGroup; children = ( AF2BCA6718C7EFDE005B4526 /* GDB */, ); path = JITLoader; sourceTree = ""; }; AF2BCA6718C7EFDE005B4526 /* GDB */ = { isa = PBXGroup; children = ( AF2BCA6A18C7EFDE005B4526 /* JITLoaderGDB.h */, AF2BCA6918C7EFDE005B4526 /* JITLoaderGDB.cpp */, ); path = GDB; sourceTree = ""; }; AF6335DF1C87B20A00F7D554 /* PDB */ = { isa = PBXGroup; children = ( 4C562CC21CC07DDD00C52EAC /* PDBASTParser.cpp */, 4C562CC31CC07DDD00C52EAC /* PDBASTParser.h */, AF6335E01C87B21E00F7D554 /* SymbolFilePDB.cpp */, AF6335E11C87B21E00F7D554 /* SymbolFilePDB.h */, ); name = PDB; sourceTree = ""; }; AF77E08B1A033C3E0096C0EA /* SysV-ppc */ = { isa = PBXGroup; children = ( AF77E08D1A033C700096C0EA /* ABISysV_ppc.cpp */, AF77E08E1A033C700096C0EA /* ABISysV_ppc.h */, ); name = "SysV-ppc"; sourceTree = ""; }; AF77E08C1A033C4B0096C0EA /* SysV-ppc64 */ = { isa = PBXGroup; children = ( AF77E0911A033C7F0096C0EA /* ABISysV_ppc64.cpp */, AF77E0921A033C7F0096C0EA /* ABISysV_ppc64.h */, ); name = "SysV-ppc64"; sourceTree = ""; }; AFAFD8081E57E19E0017A14F /* Target */ = { isa = PBXGroup; children = ( AFAFD8091E57E1B90017A14F /* ModuleCacheTest.cpp */, ); name = Target; sourceTree = ""; }; AFEC5FD31D94F9130076A480 /* UnwindAssembly */ = { isa = PBXGroup; children = ( AF248A4B1DA71C67000B814D /* InstEmulation */, AFEC5FD41D94F9270076A480 /* x86 */, ); name = UnwindAssembly; sourceTree = ""; }; AFEC5FD41D94F9270076A480 /* x86 */ = { isa = PBXGroup; children = ( AFEC5FD51D94F9380076A480 /* Testx86AssemblyInspectionEngine.cpp */, ); name = x86; sourceTree = ""; }; E769331B1A94D10E00C73337 /* lldb-server */ = { isa = PBXGroup; children = ( 257906621BD5AFD000178368 /* Acceptor.cpp */, 257906631BD5AFD000178368 /* Acceptor.h */, 6D762BEC1B1605CD006C929D /* LLDBServerUtilities.cpp */, 6D762BED1B1605CD006C929D /* LLDBServerUtilities.h */, E769331D1A94D18100C73337 /* lldb-server.cpp */, 26DC6A1C1337FECA00FF7998 /* lldb-platform.cpp */, 26D6F3F4183E7F9300194858 /* lldb-gdbserver.cpp */, ); name = "lldb-server"; sourceTree = ""; }; E778E99D1B062D1700247609 /* MIPS */ = { isa = PBXGroup; children = ( E778E99F1B062D1700247609 /* EmulateInstructionMIPS.cpp */, E778E9A01B062D1700247609 /* EmulateInstructionMIPS.h */, ); path = MIPS; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 26680202115FD0ED008E1FE4 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 2668020E115FD12C008E1FE4 /* lldb-defines.h in Headers */, 2668020F115FD12C008E1FE4 /* lldb-enumerations.h in Headers */, 26DE1E6C11616C2E00A093E2 /* lldb-forward.h in Headers */, 26680214115FD12C008E1FE4 /* lldb-types.h in Headers */, 94145431175E63B500284436 /* lldb-versioning.h in Headers */, 26B42C4D1187ABA50079C8C8 /* LLDB.h in Headers */, 26DE204311618ACA00A093E2 /* SBAddress.h in Headers */, 26151DC31B41E4A200FF7F1C /* SharingPtr.h in Headers */, 26DE205711618FC500A093E2 /* SBBlock.h in Headers */, 332CCB181AFF41620034D4C4 /* SBLanguageRuntime.h in Headers */, 26680219115FD13D008E1FE4 /* SBBreakpoint.h in Headers */, 2668021A115FD13D008E1FE4 /* SBBreakpointLocation.h in Headers */, 2668021B115FD13D008E1FE4 /* SBBroadcaster.h in Headers */, 2668021D115FD13D008E1FE4 /* SBCommandInterpreter.h in Headers */, 2668021E115FD13D008E1FE4 /* SBCommandReturnObject.h in Headers */, 2668021F115FD13D008E1FE4 /* SBCommunication.h in Headers */, 26DE205511618FB800A093E2 /* SBCompileUnit.h in Headers */, 9443B123140C26AB0013457C /* SBData.h in Headers */, 26680220115FD13D008E1FE4 /* SBDebugger.h in Headers */, 490A966B1628C3BF00F0002E /* SBDeclaration.h in Headers */, 254FBBA31A9166F100BD6378 /* SBAttachInfo.h in Headers */, 26680221115FD13D008E1FE4 /* SBDefines.h in Headers */, 8CCB018219BA4E270009FD44 /* SBThreadCollection.h in Headers */, 9A36D24D1EB3BE7F00AAD9EA /* SBTrace.h in Headers */, AF0EBBEC185941360059E52F /* SBQueue.h in Headers */, 26680222115FD13D008E1FE4 /* SBError.h in Headers */, 26680223115FD13D008E1FE4 /* SBEvent.h in Headers */, AFDCDBCB19DD0F42005EA55E /* SBExecutionContext.h in Headers */, 26680224115FD13D008E1FE4 /* SBFileSpec.h in Headers */, 4CF52AF51428291E0051E832 /* SBFileSpecList.h in Headers */, 26680225115FD13D008E1FE4 /* SBFrame.h in Headers */, 26DE205311618FAC00A093E2 /* SBFunction.h in Headers */, 9A3576A8116E9AB700E8ED2F /* SBHostOS.h in Headers */, 264297571D1DF247003F2BF4 /* SBMemoryRegionInfoList.h in Headers */, 9AC7038E117674FB0086C050 /* SBInstruction.h in Headers */, 9AC70390117675270086C050 /* SBInstructionList.h in Headers */, 264297581D1DF250003F2BF4 /* SBMemoryRegionInfo.h in Headers */, 26DE205911618FE700A093E2 /* SBLineEntry.h in Headers */, 254FBB971A81B03100BD6378 /* SBLaunchInfo.h in Headers */, AF0EBBED185941360059E52F /* SBQueueItem.h in Headers */, 26680227115FD13D008E1FE4 /* SBListener.h in Headers */, 26DE204F11618E9800A093E2 /* SBModule.h in Headers */, 2668022A115FD13D008E1FE4 /* SBProcess.h in Headers */, 26B8283D142D01E9002DBC64 /* SBSection.h in Headers */, 2668022B115FD13D008E1FE4 /* SBSourceManager.h in Headers */, 26C72C94124322890068DC16 /* SBStream.h in Headers */, 9A357671116E7B5200E8ED2F /* SBStringList.h in Headers */, 26DE205B11618FF600A093E2 /* SBSymbol.h in Headers */, 262F12B71835469C00AEB384 /* SBPlatform.h in Headers */, 23DCBEA31D63E71F0084C36B /* SBStructuredData.h in Headers */, 26DE204111618AB900A093E2 /* SBSymbolContext.h in Headers */, 268F9D53123AA15200B91E9B /* SBSymbolContextList.h in Headers */, 2668022C115FD13D008E1FE4 /* SBTarget.h in Headers */, 2668022E115FD13D008E1FE4 /* SBThread.h in Headers */, 4C56543519D2297A002E9C44 /* SBThreadPlan.h in Headers */, 263C493A178B50CF0070F12D /* SBModuleSpec.h in Headers */, 2617447A11685869005ADD65 /* SBType.h in Headers */, 9475C18914E5EA08001BFC6D /* SBTypeCategory.h in Headers */, 941BCC7F14E48C4000BB969C /* SBTypeFilter.h in Headers */, 941BCC8014E48C4000BB969C /* SBTypeFormat.h in Headers */, 9475C18F14E5F858001BFC6D /* SBTypeNameSpecifier.h in Headers */, 941BCC8114E48C4000BB969C /* SBTypeSummary.h in Headers */, 9A36D24E1EB3BE7F00AAD9EA /* SBTraceOptions.h in Headers */, 23059A121958B3B2007B8189 /* SBUnixSignals.h in Headers */, 941BCC8214E48C4000BB969C /* SBTypeSynthetic.h in Headers */, 9A19A6AF1163BBB200E0D453 /* SBValue.h in Headers */, 9A357583116CFDEE00E8ED2F /* SBValueList.h in Headers */, B2A58722143119810092BFBA /* SBWatchpoint.h in Headers */, 26D265BC136B4269002EEE45 /* lldb-public.h in Headers */, 4CE4F673162C971A00F75CB3 /* SBExpressionOptions.h in Headers */, 94235B9F1A8D66D600EB2EED /* SBVariablesOptions.h in Headers */, 23EFE389193D1ABC00E54E54 /* SBTypeEnumMember.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; 2689FFC813353D7A00698AC0 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( AF8AD6381BEC28C400150209 /* PlatformRemoteAppleTV.h in Headers */, 26EFB61C1BFE8D3E00544801 /* PlatformNetBSD.h in Headers */, AF3A4AD31EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.h in Headers */, AF33B4BF1C1FA441001B28D9 /* NetBSDSignals.h in Headers */, AF6335E31C87B21E00F7D554 /* SymbolFilePDB.h in Headers */, 267F685A1CC02EBE0086832B /* RegisterInfos_s390x.h in Headers */, 267F68541CC02E920086832B /* RegisterContextLinux_s390x.h in Headers */, 267F68501CC02E270086832B /* RegisterContextPOSIXCore_s390x.h in Headers */, 4984BA181B979C08008658D4 /* ExpressionVariable.h in Headers */, 26C7C4841BFFEA7E009BD01F /* WindowsMiniDump.h in Headers */, 30B38A001CAAA6D7009524E3 /* ClangUtil.h in Headers */, AFD65C821D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.h in Headers */, 238F2BA11D2C835A001FF92A /* StructuredDataPlugin.h in Headers */, AF415AE81D949E4400FCE0D4 /* x86AssemblyInspectionEngine.h in Headers */, AF8AD62F1BEC28A400150209 /* PlatformAppleTVSimulator.h in Headers */, 238F2BA91D2C85FA001FF92A /* StructuredDataDarwinLog.h in Headers */, AF8AD63A1BEC28C400150209 /* PlatformRemoteAppleWatch.h in Headers */, 257906651BD5AFD000178368 /* Acceptor.h in Headers */, 238F2BA21D2C835A001FF92A /* SystemRuntime.h in Headers */, 260A63171861008E00FECF8E /* IOHandler.h in Headers */, 267F68581CC02EAE0086832B /* RegisterContextPOSIX_s390x.h in Headers */, 6D0F614F1C80AB0C00A4ECEE /* JavaLanguageRuntime.h in Headers */, AF27AD561D3603EA00CF2833 /* DynamicLoaderDarwin.h in Headers */, AFCB2BBE1BF577F40018B553 /* PythonExceptionState.h in Headers */, 267F684B1CC02DED0086832B /* ABISysV_s390x.h in Headers */, AF8AD6311BEC28A400150209 /* PlatformAppleWatchSimulator.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXLegacyTarget section */ 2387551E1C24974600CCE8C3 /* lldb-python-test-suite */ = { isa = PBXLegacyTarget; buildArgumentsString = "-u $(SRCROOT)/test/dotest.py --apple-sdk $(PLATFORM_NAME) --executable=$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/lldb -C $(LLDB_PYTHON_TESTSUITE_CC) --arch $(LLDB_PYTHON_TESTSUITE_ARCH) --session-file-format fm --results-formatter lldbsuite.test_event.formatter.xunit.XunitFormatter --results-file $(BUILD_DIR)/test-results-$(LLDB_PYTHON_TESTSUITE_ARCH).xml --rerun-all-issues --env TERM=vt100 -O--xpass=ignore"; buildConfigurationList = 238755241C24974600CCE8C3 /* Build configuration list for PBXLegacyTarget "lldb-python-test-suite" */; buildPhases = ( ); buildToolPath = /usr/bin/python; buildWorkingDirectory = "$(BUILD_DIR)"; dependencies = ( ); name = "lldb-python-test-suite"; passBuildSettingsInEnvironment = 1; productName = "LLDB Python Test Suite"; }; 2687EAC51508110B00DD8C2E /* install-headers */ = { isa = PBXLegacyTarget; buildArgumentsString = "$(ACTION)"; buildConfigurationList = 2687EAC61508110B00DD8C2E /* Build configuration list for PBXLegacyTarget "install-headers" */; buildPhases = ( ); buildToolPath = /usr/bin/make; buildWorkingDirectory = "$(SRCROOT)/tools/install-headers"; dependencies = ( ); name = "install-headers"; passBuildSettingsInEnvironment = 1; productName = "install-headers"; }; /* End PBXLegacyTarget section */ /* Begin PBXNativeTarget section */ 239504D31BDD451400963CEA /* lldb-gtest */ = { isa = PBXNativeTarget; buildConfigurationList = 239504DD1BDD451400963CEA /* Build configuration list for PBXNativeTarget "lldb-gtest" */; buildPhases = ( 239504D01BDD451400963CEA /* Sources */, 239504D11BDD451400963CEA /* Frameworks */, 239504D21BDD451400963CEA /* CopyFiles */, 23B9815E1CB2E2F90059938A /* Run gtests */, ); buildRules = ( ); dependencies = ( 23E2E5481D904D72006F38BB /* PBXTargetDependency */, ); name = "lldb-gtest"; productName = "lldb-gtest"; productReference = 239504D41BDD451400963CEA /* lldb-gtest */; productType = "com.apple.product-type.tool"; }; 23CB152F1D66DA9300EDDDE1 /* lldb-gtest-build */ = { isa = PBXNativeTarget; buildConfigurationList = 23CB15511D66DA9300EDDDE1 /* Build configuration list for PBXNativeTarget "lldb-gtest-build" */; buildPhases = ( 23CB15321D66DA9300EDDDE1 /* Sources */, 23CB15481D66DA9300EDDDE1 /* Frameworks */, 23E2E5461D904B8A006F38BB /* Copy Inputs content to run dir */, 23CB154F1D66DA9300EDDDE1 /* Copy Files */, ); buildRules = ( ); dependencies = ( 23CB15301D66DA9300EDDDE1 /* PBXTargetDependency */, ); name = "lldb-gtest-build"; productName = "lldb-gtest"; productReference = 23CB15561D66DA9300EDDDE1 /* lldb-gtest */; productType = "com.apple.product-type.tool"; }; 26579F67126A25920007C5CB /* darwin-debug */ = { isa = PBXNativeTarget; buildConfigurationList = 26579F6D126A25BF0007C5CB /* Build configuration list for PBXNativeTarget "darwin-debug" */; buildPhases = ( 26579F65126A25920007C5CB /* Sources */, 26579F66126A25920007C5CB /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = "darwin-debug"; productName = "lldb-launcher"; productReference = 26579F68126A25920007C5CB /* darwin-debug */; productType = "com.apple.product-type.tool"; }; 26680206115FD0ED008E1FE4 /* LLDB */ = { isa = PBXNativeTarget; buildConfigurationList = 2668020B115FD0EE008E1FE4 /* Build configuration list for PBXNativeTarget "LLDB" */; buildPhases = ( 26DC6A5813380D4300FF7998 /* Prepare Swig Bindings */, 26680202115FD0ED008E1FE4 /* Headers */, 26680203115FD0ED008E1FE4 /* Resources */, 26680204115FD0ED008E1FE4 /* Sources */, 26680205115FD0ED008E1FE4 /* Frameworks */, 261B5A7511C3FA6F00AABD0A /* Fixup Framework Headers */, 9A19ACE2116563A700E0D453 /* Finish swig wrapper classes (lldb) */, 4959511A1A1ACE9500F6F8FC /* Install Clang compiler headers */, 940B04E31A89875C0045D5F7 /* CopyFiles */, ); buildRules = ( ); dependencies = ( 942829CE1A89842900521B30 /* PBXTargetDependency */, 94E829C9152D33B4006F96A3 /* PBXTargetDependency */, 2689011513353E9B00698AC0 /* PBXTargetDependency */, 262CFC7211A450CB00946C6C /* PBXTargetDependency */, 26368AF6126B95FA00E8659F /* PBXTargetDependency */, ); name = LLDB; productName = LLDB; productReference = 26680207115FD0ED008E1FE4 /* LLDB.framework */; productType = "com.apple.product-type.framework"; }; 2689FFC913353D7A00698AC0 /* lldb-core */ = { isa = PBXNativeTarget; buildConfigurationList = 2689FFD813353D7A00698AC0 /* Build configuration list for PBXNativeTarget "lldb-core" */; buildPhases = ( 261EECA21337D399001D193C /* Build llvm and clang */, 2689FFC613353D7A00698AC0 /* Sources */, 2689FFC713353D7A00698AC0 /* Frameworks */, 2689FFC813353D7A00698AC0 /* Headers */, ); buildRules = ( ); dependencies = ( ); name = "lldb-core"; productName = "lldb-core"; productReference = 2689FFCA13353D7A00698AC0 /* liblldb-core.a */; productType = "com.apple.product-type.library.dynamic"; }; 2690CD161A6DC0D000E717C8 /* lldb-mi */ = { isa = PBXNativeTarget; buildConfigurationList = 2690CD1F1A6DC0D000E717C8 /* Build configuration list for PBXNativeTarget "lldb-mi" */; buildPhases = ( 2690CD131A6DC0D000E717C8 /* Sources */, 2690CD141A6DC0D000E717C8 /* Frameworks */, ); buildRules = ( ); dependencies = ( 26DF74601A6DCDB300B85563 /* PBXTargetDependency */, ); name = "lldb-mi"; productName = "lldb-mi"; productReference = 2690CD171A6DC0D000E717C8 /* lldb-mi */; productType = "com.apple.product-type.tool"; }; 26DC6A0F1337FE6900FF7998 /* lldb-server */ = { isa = PBXNativeTarget; buildConfigurationList = 26DC6A1A1337FE8B00FF7998 /* Build configuration list for PBXNativeTarget "lldb-server" */; buildPhases = ( 26DC6A0D1337FE6900FF7998 /* Sources */, 26DC6A0E1337FE6900FF7998 /* Frameworks */, 4C3326CA18B2A2B800EB5DD7 /* ShellScript */, ); buildRules = ( ); dependencies = ( 26DC6A161337FE7300FF7998 /* PBXTargetDependency */, ); name = "lldb-server"; productName = "lldb-server"; productReference = 26DC6A101337FE6900FF7998 /* lldb-server */; productType = "com.apple.product-type.tool"; }; 26F5C26910F3D9A4009D5894 /* lldb-tool */ = { isa = PBXNativeTarget; buildConfigurationList = 26F5C26E10F3D9C5009D5894 /* Build configuration list for PBXNativeTarget "lldb-tool" */; buildPhases = ( 26F5C26710F3D9A4009D5894 /* Sources */, 26F5C26810F3D9A4009D5894 /* Frameworks */, ); buildRules = ( ); dependencies = ( 266803621160110D008E1FE4 /* PBXTargetDependency */, ); name = "lldb-tool"; productName = lldb; productReference = 26F5C26A10F3D9A4009D5894 /* lldb */; productType = "com.apple.product-type.tool"; }; 942829BF1A89835300521B30 /* lldb-argdumper */ = { isa = PBXNativeTarget; buildConfigurationList = 942829C41A89835400521B30 /* Build configuration list for PBXNativeTarget "lldb-argdumper" */; buildPhases = ( 942829BC1A89835300521B30 /* Sources */, 942829BD1A89835300521B30 /* Frameworks */, 942829BE1A89835300521B30 /* CopyFiles */, 940B04E21A89871F0045D5F7 /* ShellScript */, ); buildRules = ( ); dependencies = ( 942829CA1A89836A00521B30 /* PBXTargetDependency */, ); name = "lldb-argdumper"; productName = argdumper; productReference = 942829C01A89835300521B30 /* lldb-argdumper */; productType = "com.apple.product-type.tool"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; LastUpgradeCheck = 0720; TargetAttributes = { 2387551E1C24974600CCE8C3 = { CreatedOnToolsVersion = 7.2; }; 239504D31BDD451400963CEA = { CreatedOnToolsVersion = 7.1; }; 2690CD161A6DC0D000E717C8 = { CreatedOnToolsVersion = 6.3; }; 942829BF1A89835300521B30 = { CreatedOnToolsVersion = 7.0; }; }; }; buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "lldb" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( en, ); mainGroup = 08FB7794FE84155DC02AAC07 /* lldb */; projectDirPath = ""; projectReferences = ( { ProductGroup = 265E9BE2115C2BAA00D0DCCB /* Products */; ProjectRef = 265E9BE1115C2BAA00D0DCCB /* debugserver.xcodeproj */; }, ); projectRoot = ""; targets = ( 26CEF3B114FD592B007286B2 /* desktop */, 26CEF3A914FD58BF007286B2 /* desktop_no_xpc */, 26CEF3BC14FD596A007286B2 /* ios */, 26F5C26910F3D9A4009D5894 /* lldb-tool */, 26680206115FD0ED008E1FE4 /* LLDB */, 239504D31BDD451400963CEA /* lldb-gtest */, 23CB152F1D66DA9300EDDDE1 /* lldb-gtest-build */, 2387551E1C24974600CCE8C3 /* lldb-python-test-suite */, 26579F67126A25920007C5CB /* darwin-debug */, 2689FFC913353D7A00698AC0 /* lldb-core */, 26DC6A0F1337FE6900FF7998 /* lldb-server */, 2687EAC51508110B00DD8C2E /* install-headers */, 2690CD161A6DC0D000E717C8 /* lldb-mi */, 942829BF1A89835300521B30 /* lldb-argdumper */, ); }; /* End PBXProject section */ /* Begin PBXReferenceProxy section */ 239504C51BDD3FD700963CEA /* debugserver-nonui */ = { isa = PBXReferenceProxy; fileType = "compiled.mach-o.executable"; path = "debugserver-nonui"; remoteRef = 239504C41BDD3FD700963CEA /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 26CE05A0115C31E50022F371 /* debugserver */ = { isa = PBXReferenceProxy; fileType = "compiled.mach-o.executable"; path = debugserver; remoteRef = 26CE059F115C31E50022F371 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ 26680203115FD0ED008E1FE4 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 94E829CA152D33C1006F96A3 /* lldb-server in Resources */, 262CFC7711A4510000946C6C /* debugserver in Resources */, 26368AF7126B960500E8659F /* darwin-debug in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 23B9815E1CB2E2F90059938A /* Run gtests */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Run gtests"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = "/bin/sh -x"; shellScript = "# Run the just-built gtest executable\n\n# Uncomment this to see the steps in action\n# set -x\n\n# We need to hide the lldb.py that goes into BUILT_PRODUCTS\n# because it will conflict with finding the lldb module later,\n# which causes the python exception tests to fail.\nif [ -f \"${BUILT_PRODUCTS_DIR}/lldb.py\" ]; then\n mv -f \"${BUILT_PRODUCTS_DIR}/lldb.py\" \"${BUILT_PRODUCTS_DIR}/park.lldb.py\"\nfi\n\n# Tell lldb-gtest where to find the lldb package\nexport PYTHONPATH=${BUILT_PRODUCTS_DIR}/LLDB.framework/Resources/Python\n\n# Set the terminal to VT100 so that the editline internals don't\n# fail.\nexport TERM=vt100\n\n# We must redirect stdin to /dev/null: without this, xcodebuild\n# will wait forever for input when we run the TestExceptionStateChecking\n# test.\n${BUILT_PRODUCTS_DIR}/lldb-gtest --gtest_output=xml:${BUILD_DIR}/gtest-results.xml < /dev/null\nRETCODE=$?\n\nif [ -f \"${BUILT_PRODUCTS_DIR}/park.lldb.py\" ]; then\nmv -f \"${BUILT_PRODUCTS_DIR}/park.lldb.py\" \"${BUILT_PRODUCTS_DIR}/lldb.py\"\nfi\n\nexit ${RETCODE}"; }; 23E2E5461D904B8A006F38BB /* Copy Inputs content to run dir */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Copy Inputs content to run dir"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = "/bin/bash +x scripts/Xcode/prepare-gtest-run-dir.sh"; shellScript = ""; }; 261B5A7511C3FA6F00AABD0A /* Fixup Framework Headers */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Fixup Framework Headers"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "cd \"${TARGET_BUILD_DIR}/${PUBLIC_HEADERS_FOLDER_PATH}\"\nfor file in *.h\ndo\n\t/usr/bin/sed -i '' 's/\\(#include\\)[ ]*\"lldb\\/\\(API\\/\\)\\{0,1\\}\\(.*\\)\"/\\1 /1' \"$file\"\n\t/usr/bin/sed -i '' 's| 0, VALID_BREAKPOINT) - - # Launch the process, and do not stop at the entry point. - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - - self.assertTrue(process, PROCESS_IS_VALID) - - # Frame #0 should be at our breakpoint. - threads = lldbutil.get_threads_stopped_at_breakpoint( - process, breakpoint) - - self.assertTrue(len(threads) == 1) - self.thread = threads[0] + (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + 'Stop here in main.', self.main_source_spec) # Make sure the SIGCHLD behavior is pass/no-stop/no-notify: return_obj = lldb.SBCommandReturnObject() self.dbg.GetCommandInterpreter().HandleCommand( "process handle SIGCHLD -s 0 -p 1 -n 0", return_obj) self.assertTrue(return_obj.Succeeded(), "Set SIGCHLD to pass, no-stop") # The sigchld_no variable should be 0 at this point. self.sigchld_no = target.FindFirstGlobalVariable("sigchld_no") self.assertTrue( self.sigchld_no.IsValid(), "Got a value for sigchld_no") self.start_sigchld_no = self.sigchld_no.GetValueAsSigned(-1) self.assertTrue( self.start_sigchld_no != -1, "Got an actual value for sigchld_no") options = lldb.SBExpressionOptions() # processing 30 signals takes a while, increase the expression timeout # a bit options.SetTimeoutInMicroSeconds(3000000) # 3s options.SetUnwindOnError(True) frame = self.thread.GetFrameAtIndex(0) # Store away the PC to check that the functions unwind to the right # place after calls self.orig_frame_pc = frame.GetPC() num_sigchld = 30 value = frame.EvaluateExpression( "call_me (%d)" % (num_sigchld), options) self.assertTrue(value.IsValid()) self.assertTrue(value.GetError().Success()) self.assertTrue(value.GetValueAsSigned(-1) == num_sigchld) self.check_after_call(num_sigchld) # Okay, now try with a breakpoint in the called code in the case where # we are ignoring breakpoint hits. handler_bkpt = target.BreakpointCreateBySourceRegex( "Got sigchld %d.", self.main_source_spec) self.assertTrue(handler_bkpt.GetNumLocations() > 0) options.SetIgnoreBreakpoints(True) options.SetUnwindOnError(True) value = frame.EvaluateExpression( "call_me (%d)" % (num_sigchld), options) self.assertTrue(value.IsValid() and value.GetError().Success()) self.assertTrue(value.GetValueAsSigned(-1) == num_sigchld) self.check_after_call(num_sigchld) # Now set the signal to print but not stop and make sure that calling # still works: self.dbg.GetCommandInterpreter().HandleCommand( "process handle SIGCHLD -s 0 -p 1 -n 1", return_obj) self.assertTrue( return_obj.Succeeded(), "Set SIGCHLD to pass, no-stop, notify") value = frame.EvaluateExpression( "call_me (%d)" % (num_sigchld), options) self.assertTrue(value.IsValid() and value.GetError().Success()) self.assertTrue(value.GetValueAsSigned(-1) == num_sigchld) self.check_after_call(num_sigchld) # Now set this unwind on error to false, and make sure that we still # complete the call: options.SetUnwindOnError(False) value = frame.EvaluateExpression( "call_me (%d)" % (num_sigchld), options) self.assertTrue(value.IsValid() and value.GetError().Success()) self.assertTrue(value.GetValueAsSigned(-1) == num_sigchld) self.check_after_call(num_sigchld) # Okay, now set UnwindOnError to true, and then make the signal behavior to stop # and see that now we do stop at the signal point: self.dbg.GetCommandInterpreter().HandleCommand( "process handle SIGCHLD -s 1 -p 1 -n 1", return_obj) self.assertTrue( return_obj.Succeeded(), "Set SIGCHLD to pass, stop, notify") value = frame.EvaluateExpression( "call_me (%d)" % (num_sigchld), options) self.assertTrue( value.IsValid() and value.GetError().Success() == False) # Set signal handling back to no-stop, and continue and we should end # up back in out starting frame: self.dbg.GetCommandInterpreter().HandleCommand( "process handle SIGCHLD -s 0 -p 1 -n 1", return_obj) self.assertTrue( return_obj.Succeeded(), "Set SIGCHLD to pass, no-stop, notify") error = process.Continue() self.assertTrue( error.Success(), "Continuing after stopping for signal succeeds.") frame = self.thread.GetFrameAtIndex(0) self.assertTrue( frame.GetPC() == self.orig_frame_pc, "Continuing returned to the place we started.") Index: vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/call-throws/TestCallThatThrows.py =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/call-throws/TestCallThatThrows.py (revision 320966) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/call-throws/TestCallThatThrows.py (revision 320967) @@ -1,124 +1,104 @@ """ Test calling a function that throws an ObjC exception, make sure that it doesn't propagate the exception. """ from __future__ import print_function import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil class ExprCommandWithThrowTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) def setUp(self): # Call super's setUp(). TestBase.setUp(self) self.main_source = "call-throws.m" self.main_source_spec = lldb.SBFileSpec(self.main_source) @skipUnlessDarwin def test(self): """Test calling a function that throws and ObjC exception.""" self.build() self.call_function() def check_after_call(self): # Check that we are back where we were before: frame = self.thread.GetFrameAtIndex(0) self.assertTrue( self.orig_frame_pc == frame.GetPC(), "Restored the zeroth frame correctly") def call_function(self): """Test calling function that throws.""" - exe_name = "a.out" - exe = os.path.join(os.getcwd(), exe_name) - - target = self.dbg.CreateTarget(exe) - self.assertTrue(target, VALID_TARGET) - - breakpoint = target.BreakpointCreateBySourceRegex( - 'I am about to throw.', self.main_source_spec) - self.assertTrue(breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT) - - # Launch the process, and do not stop at the entry point. - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - - self.assertTrue(process, PROCESS_IS_VALID) - - # Frame #0 should be at our breakpoint. - threads = lldbutil.get_threads_stopped_at_breakpoint( - process, breakpoint) - - self.assertTrue(len(threads) == 1) - self.thread = threads[0] + (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + 'I am about to throw.', self.main_source_spec) options = lldb.SBExpressionOptions() options.SetUnwindOnError(True) frame = self.thread.GetFrameAtIndex(0) # Store away the PC to check that the functions unwind to the right # place after calls self.orig_frame_pc = frame.GetPC() value = frame.EvaluateExpression("[my_class callMeIThrow]", options) self.assertTrue(value.IsValid()) self.assertTrue(value.GetError().Success() == False) self.check_after_call() # Okay, now try with a breakpoint in the called code in the case where # we are ignoring breakpoint hits. handler_bkpt = target.BreakpointCreateBySourceRegex( "I felt like it", self.main_source_spec) self.assertTrue(handler_bkpt.GetNumLocations() > 0) options.SetIgnoreBreakpoints(True) options.SetUnwindOnError(True) value = frame.EvaluateExpression("[my_class callMeIThrow]", options) self.assertTrue( value.IsValid() and value.GetError().Success() == False) self.check_after_call() # Now set the ObjC language breakpoint and make sure that doesn't # interfere with the call: exception_bkpt = target.BreakpointCreateForException( lldb.eLanguageTypeObjC, False, True) self.assertTrue(exception_bkpt.GetNumLocations() > 0) options.SetIgnoreBreakpoints(True) options.SetUnwindOnError(True) value = frame.EvaluateExpression("[my_class callMeIThrow]", options) self.assertTrue( value.IsValid() and value.GetError().Success() == False) self.check_after_call() # Now turn off exception trapping, and call a function that catches the exceptions, # and make sure the function actually completes, and we get the right # value: options.SetTrapExceptions(False) value = frame.EvaluateExpression("[my_class iCatchMyself]", options) self.assertTrue(value.IsValid()) self.assertTrue(value.GetError().Success()) self.assertTrue(value.GetValueAsUnsigned() == 57) self.check_after_call() options.SetTrapExceptions(True) # Now set this unwind on error to false, and make sure that we stop # where the exception was thrown options.SetUnwindOnError(False) value = frame.EvaluateExpression("[my_class callMeIThrow]", options) self.assertTrue( value.IsValid() and value.GetError().Success() == False) self.check_after_call() Index: vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py (revision 320966) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py (revision 320967) @@ -1,81 +1,66 @@ from __future__ import print_function import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil class ExprCharTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) def setUp(self): # Call super's setUp(). TestBase.setUp(self) self.main_source = "main.cpp" self.main_source_spec = lldb.SBFileSpec(self.main_source) - self.exe = os.path.join(os.getcwd(), "a.out") def do_test(self, dictionary=None): """These basic expression commands should work as expected.""" self.build(dictionary=dictionary) - target = self.dbg.CreateTarget(self.exe) - self.assertTrue(target) - - breakpoint = target.BreakpointCreateBySourceRegex( - '// Break here', self.main_source_spec) - self.assertTrue(breakpoint) - - # Launch the process, and do not stop at the entry point. - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - self.assertTrue(process) - - threads = lldbutil.get_threads_stopped_at_breakpoint( - process, breakpoint) - self.assertEqual(len(threads), 1) - - frame = threads[0].GetFrameAtIndex(0) + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + '// Break here', self.main_source_spec) + frame = thread.GetFrameAtIndex(0) value = frame.EvaluateExpression("foo(c)") self.assertTrue(value.IsValid()) self.assertTrue(value.GetError().Success()) self.assertEqual(value.GetValueAsSigned(0), 1) value = frame.EvaluateExpression("foo(sc)") self.assertTrue(value.IsValid()) self.assertTrue(value.GetError().Success()) self.assertEqual(value.GetValueAsSigned(0), 2) value = frame.EvaluateExpression("foo(uc)") self.assertTrue(value.IsValid()) self.assertTrue(value.GetError().Success()) self.assertEqual(value.GetValueAsSigned(0), 3) @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_default_char(self): self.do_test() @expectedFailureAll( archs=[ "arm", "aarch64", "s390x"], bugnumber="llvm.org/pr23069") @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") def test_signed_char(self): self.do_test(dictionary={'CFLAGS_EXTRAS': '-fsigned-char'}) @expectedFailureAll( archs=[ "i[3-6]86", "x86_64"], bugnumber="llvm.org/pr23069, ") @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") @expectedFailureAll(triple='mips*', bugnumber="llvm.org/pr23069") def test_unsigned_char(self): self.do_test(dictionary={'CFLAGS_EXTRAS': '-funsigned-char'}) Index: vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py (revision 320966) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/fixits/TestFixIts.py (revision 320967) @@ -1,92 +1,72 @@ """ Test calling an expression with errors that a FixIt can fix. """ from __future__ import print_function import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil class ExprCommandWithFixits(TestBase): mydir = TestBase.compute_mydir(__file__) def setUp(self): # Call super's setUp(). TestBase.setUp(self) self.main_source = "main.cpp" self.main_source_spec = lldb.SBFileSpec(self.main_source) @skipUnlessDarwin def test_with_target(self): """Test calling expressions with errors that can be fixed by the FixIts.""" self.build() self.try_expressions() def test_with_dummy_target(self): """Test calling expressions in the dummy target with errors that can be fixed by the FixIts.""" ret_val = lldb.SBCommandReturnObject() result = self.dbg.GetCommandInterpreter().HandleCommand("expression ((1 << 16) - 1))", ret_val) self.assertEqual(result, lldb.eReturnStatusSuccessFinishResult, "The expression was successful.") self.assertTrue("Fix-it applied" in ret_val.GetError(), "Found the applied FixIt.") def try_expressions(self): """Test calling expressions with errors that can be fixed by the FixIts.""" - exe_name = "a.out" - exe = os.path.join(os.getcwd(), exe_name) - - target = self.dbg.CreateTarget(exe) - self.assertTrue(target, VALID_TARGET) - - breakpoint = target.BreakpointCreateBySourceRegex( - 'Stop here to evaluate expressions', self.main_source_spec) - self.assertTrue(breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT) - - # Launch the process, and do not stop at the entry point. - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - - self.assertTrue(process, PROCESS_IS_VALID) - - # Frame #0 should be at our breakpoint. - threads = lldbutil.get_threads_stopped_at_breakpoint( - process, breakpoint) - - self.assertTrue(len(threads) == 1) - self.thread = threads[0] + (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + 'Stop here to evaluate expressions', self.main_source_spec) options = lldb.SBExpressionOptions() options.SetAutoApplyFixIts(True) frame = self.thread.GetFrameAtIndex(0) # Try with one error: value = frame.EvaluateExpression("my_pointer.first", options) self.assertTrue(value.IsValid()) self.assertTrue(value.GetError().Success()) self.assertTrue(value.GetValueAsUnsigned() == 10) # Try with two errors: two_error_expression = "my_pointer.second->a" value = frame.EvaluateExpression(two_error_expression, options) self.assertTrue(value.IsValid()) self.assertTrue(value.GetError().Success()) self.assertTrue(value.GetValueAsUnsigned() == 20) # Now turn off the fixits, and the expression should fail: options.SetAutoApplyFixIts(False) value = frame.EvaluateExpression(two_error_expression, options) self.assertTrue(value.IsValid()) self.assertTrue(value.GetError().Fail()) error_string = value.GetError().GetCString() self.assertTrue( error_string.find("fixed expression suggested:") != -1, "Fix was suggested") self.assertTrue( error_string.find("my_pointer->second.a") != -1, "Fix was right") Index: vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/issue_11588/Test11588.py =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/issue_11588/Test11588.py (revision 320966) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/issue_11588/Test11588.py (revision 320967) @@ -1,86 +1,69 @@ """ Test the solution to issue 11581. valobj.AddressOf() returns None when an address is expected in a SyntheticChildrenProvider """ from __future__ import print_function import os import time import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil class Issue11581TestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_11581_commands(self): # This is the function to remove the custom commands in order to have a # clean slate for the next test case. def cleanup(): self.runCmd('type synthetic clear', check=False) # Execute the cleanup function during test case tear down. self.addTearDownHook(cleanup) """valobj.AddressOf() should return correct values.""" self.build() - exe = os.path.join(os.getcwd(), "a.out") - - target = self.dbg.CreateTarget(exe) - self.assertTrue(target, VALID_TARGET) - - breakpoint = target.BreakpointCreateBySourceRegex( - 'Set breakpoint here.', lldb.SBFileSpec("main.cpp", False)) - - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - self.assertTrue(process, "Created a process.") - self.assertTrue( - process.GetState() == lldb.eStateStopped, - "Stopped it too.") - - thread_list = lldbutil.get_threads_stopped_at_breakpoint( - process, breakpoint) - self.assertTrue(len(thread_list) == 1) - thread = thread_list[0] - + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + 'Set breakpoint here.', + lldb.SBFileSpec("main.cpp", False)) self.runCmd("command script import --allow-reload s11588.py") self.runCmd( "type synthetic add --python-class s11588.Issue11581SyntheticProvider StgClosure") self.expect("expr --show-types -- *((StgClosure*)(r14-1))", substrs=["(StgClosure) $", "(StgClosure *) &$", "0x", "addr = ", "load_address = "]) # register r14 is an x86_64 extension let's skip this part of the test # if we are on a different architecture if self.getArchitecture() == 'x86_64': target = lldb.debugger.GetSelectedTarget() process = target.GetProcess() frame = process.GetSelectedThread().GetSelectedFrame() pointer = frame.FindVariable("r14") addr = pointer.GetValueAsUnsigned(0) self.assertTrue(addr != 0, "could not read pointer to StgClosure") addr = addr - 1 self.runCmd("register write r14 %d" % addr) self.expect( "register read r14", substrs=[ "0x", hex(addr)[ 2:].rstrip("L")]) # Remove trailing 'L' if it exists self.expect("expr --show-types -- *(StgClosure*)$r14", substrs=["(StgClosure) $", "(StgClosure *) &$", "0x", "addr = ", "load_address = ", hex(addr)[2:].rstrip("L"), str(addr)]) Index: vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py (revision 320966) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py (revision 320967) @@ -1,155 +1,131 @@ from __future__ import print_function import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil class TestMacros(TestBase): mydir = TestBase.compute_mydir(__file__) @expectedFailureAll( compiler="clang", bugnumber="clang does not emit .debug_macro[.dwo] sections.") @expectedFailureAll( debug_info="dwo", bugnumber="GCC produces multiple .debug_macro.dwo sections and the spec is unclear as to what it means") @expectedFailureAll( hostoslist=["windows"], compiler="gcc", triple='.*-android') def test_expr_with_macros(self): self.build() # Get main source file src_file = "main.cpp" hdr_file = "macro1.h" src_file_spec = lldb.SBFileSpec(src_file) self.assertTrue(src_file_spec.IsValid(), "Main source file") - # Get the path of the executable - cwd = os.getcwd() - exe_file = "a.out" - exe_path = os.path.join(cwd, exe_file) - - # Load the executable - target = self.dbg.CreateTarget(exe_path) - self.assertTrue(target.IsValid(), VALID_TARGET) - - # Set breakpoints - bp1 = target.BreakpointCreateBySourceRegex("Break here", src_file_spec) - self.assertTrue( - bp1.IsValid() and bp1.GetNumLocations() >= 1, - VALID_BREAKPOINT) - - # Launch the process - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - self.assertTrue(process.IsValid(), PROCESS_IS_VALID) - - # Get the thread of the process - self.assertTrue( - process.GetState() == lldb.eStateStopped, - PROCESS_STOPPED) - thread = lldbutil.get_stopped_thread( - process, lldb.eStopReasonBreakpoint) + (target, process, thread, bp1) = lldbutil.run_to_source_breakpoint( + self, "Break here", src_file_spec) # Get frame for current thread frame = thread.GetSelectedFrame() result = frame.EvaluateExpression("MACRO_1") self.assertTrue( result.IsValid() and result.GetValue() == "100", "MACRO_1 = 100") result = frame.EvaluateExpression("MACRO_2") self.assertTrue( result.IsValid() and result.GetValue() == "200", "MACRO_2 = 200") result = frame.EvaluateExpression("ONE") self.assertTrue( result.IsValid() and result.GetValue() == "1", "ONE = 1") result = frame.EvaluateExpression("TWO") self.assertTrue( result.IsValid() and result.GetValue() == "2", "TWO = 2") result = frame.EvaluateExpression("THREE") self.assertTrue( result.IsValid() and result.GetValue() == "3", "THREE = 3") result = frame.EvaluateExpression("FOUR") self.assertTrue( result.IsValid() and result.GetValue() == "4", "FOUR = 4") result = frame.EvaluateExpression("HUNDRED") self.assertTrue( result.IsValid() and result.GetValue() == "100", "HUNDRED = 100") result = frame.EvaluateExpression("THOUSAND") self.assertTrue( result.IsValid() and result.GetValue() == "1000", "THOUSAND = 1000") result = frame.EvaluateExpression("MILLION") self.assertTrue(result.IsValid() and result.GetValue() == "1000000", "MILLION = 1000000") result = frame.EvaluateExpression("MAX(ONE, TWO)") self.assertTrue( result.IsValid() and result.GetValue() == "2", "MAX(ONE, TWO) = 2") result = frame.EvaluateExpression("MAX(THREE, TWO)") self.assertTrue( result.IsValid() and result.GetValue() == "3", "MAX(THREE, TWO) = 3") # Get the thread of the process thread.StepOver() # Get frame for current thread frame = thread.GetSelectedFrame() result = frame.EvaluateExpression("MACRO_2") self.assertTrue( result.GetError().Fail(), "Printing MACRO_2 fails in the mail file") result = frame.EvaluateExpression("FOUR") self.assertTrue( result.GetError().Fail(), "Printing FOUR fails in the main file") thread.StepInto() # Get frame for current thread frame = thread.GetSelectedFrame() result = frame.EvaluateExpression("ONE") self.assertTrue( result.IsValid() and result.GetValue() == "1", "ONE = 1") result = frame.EvaluateExpression("MAX(ONE, TWO)") self.assertTrue( result.IsValid() and result.GetValue() == "2", "MAX(ONE, TWO) = 2") # This time, MACRO_1 and MACRO_2 are not visible. result = frame.EvaluateExpression("MACRO_1") self.assertTrue(result.GetError().Fail(), "Printing MACRO_1 fails in the header file") result = frame.EvaluateExpression("MACRO_2") self.assertTrue(result.GetError().Fail(), "Printing MACRO_2 fails in the header file") Index: vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py (revision 320966) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py (revision 320967) @@ -1,80 +1,65 @@ """ Test expression command options. Test cases: o test_expr_options: Test expression command options. """ from __future__ import print_function import os import time import lldb import lldbsuite.test.lldbutil as lldbutil from lldbsuite.test.lldbtest import * class ExprOptionsTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) def setUp(self): # Call super's setUp(). TestBase.setUp(self) self.main_source = "main.cpp" self.main_source_spec = lldb.SBFileSpec(self.main_source) self.line = line_number('main.cpp', '// breakpoint_in_main') self.exe = os.path.join(os.getcwd(), "a.out") def test_expr_options(self): """These expression command options should work as expected.""" self.build() # Set debugger into synchronous mode self.dbg.SetAsync(False) - # Create a target by the debugger. - target = self.dbg.CreateTarget(self.exe) - self.assertTrue(target, VALID_TARGET) + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, '// breakpoint_in_main', self.main_source_spec) - # Set breakpoints inside main. - breakpoint = target.BreakpointCreateBySourceRegex( - '// breakpoint_in_main', self.main_source_spec) - self.assertTrue(breakpoint) - - # Now launch the process, and do not stop at entry point. - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - self.assertTrue(process, PROCESS_IS_VALID) - - threads = lldbutil.get_threads_stopped_at_breakpoint( - process, breakpoint) - self.assertEqual(len(threads), 1) - - frame = threads[0].GetFrameAtIndex(0) + frame = thread.GetFrameAtIndex(0) options = lldb.SBExpressionOptions() # test --language on C++ expression using the SB API's # Make sure we can evaluate a C++11 expression. val = frame.EvaluateExpression('foo != nullptr') self.assertTrue(val.IsValid()) self.assertTrue(val.GetError().Success()) self.DebugSBValue(val) # Make sure it still works if language is set to C++11: options.SetLanguage(lldb.eLanguageTypeC_plus_plus_11) val = frame.EvaluateExpression('foo != nullptr', options) self.assertTrue(val.IsValid()) self.assertTrue(val.GetError().Success()) self.DebugSBValue(val) # Make sure it fails if language is set to C: options.SetLanguage(lldb.eLanguageTypeC) val = frame.EvaluateExpression('foo != nullptr', options) self.assertTrue(val.IsValid()) self.assertFalse(val.GetError().Success()) Index: vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/save_jit_objects/TestSaveJITObjects.py =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/save_jit_objects/TestSaveJITObjects.py (revision 320966) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/save_jit_objects/TestSaveJITObjects.py (revision 320967) @@ -1,58 +1,51 @@ """ Test that LLDB can emit JIT objects when the appropriate setting is enabled """ from __future__ import print_function import os import time import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil def enumerateJITFiles(): return [f for f in os.listdir(os.getcwd()) if f.startswith("jit")] def countJITFiles(): return len(enumerateJITFiles()) def cleanJITFiles(): for j in enumerateJITFiles(): os.remove(j) return class SaveJITObjectsTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) @expectedFailureAll(oslist=["windows"]) def test_save_jit_objects(self): self.build() src_file = "main.c" src_file_spec = lldb.SBFileSpec(src_file) - exe_path = os.path.join(os.getcwd(), "a.out") - target = self.dbg.CreateTarget(exe_path) + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, "break", src_file_spec) - breakpoint = target.BreakpointCreateBySourceRegex( - "break", src_file_spec) - - process = target.LaunchSimple(None, None, - self.get_process_working_directory()) - - thread = process.GetSelectedThread() - frame = thread.GetSelectedFrame() + frame = thread.frames[0] cleanJITFiles() frame.EvaluateExpression("(void*)malloc(0x1)") self.assertTrue(countJITFiles() == 0, "No files emitted with save-jit-objects=false") self.runCmd("settings set target.save-jit-objects true") frame.EvaluateExpression("(void*)malloc(0x1)") jit_files_count = countJITFiles() cleanJITFiles() self.assertTrue(jit_files_count != 0, "At least one file emitted with save-jit-objects=true") process.Kill() Index: vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/timeout/TestCallWithTimeout.py =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/timeout/TestCallWithTimeout.py (revision 320966) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/expression_command/timeout/TestCallWithTimeout.py (revision 320967) @@ -1,102 +1,80 @@ """ Test calling a function that waits a while, and make sure the timeout option to expr works. """ from __future__ import print_function import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil class ExprCommandWithTimeoutsTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) def setUp(self): # Call super's setUp(). TestBase.setUp(self) self.main_source = "wait-a-while.cpp" self.main_source_spec = lldb.SBFileSpec(self.main_source) @expectedFlakeyFreeBSD("llvm.org/pr19605") @expectedFailureAll( oslist=[ - "windows", - "macosx"], + "windows"], bugnumber="llvm.org/pr21765") def test(self): """Test calling std::String member function.""" self.build() - exe_name = "a.out" - exe = os.path.join(os.getcwd(), exe_name) - - target = self.dbg.CreateTarget(exe) - self.assertTrue(target, VALID_TARGET) - - breakpoint = target.BreakpointCreateBySourceRegex( - 'stop here in main.', self.main_source_spec) - self.assertTrue(breakpoint, VALID_BREAKPOINT) - self.runCmd("breakpoint list") - - # Launch the process, and do not stop at the entry point. - process = target.LaunchSimple( - None, None, self.get_process_working_directory()) - - self.assertTrue(process, PROCESS_IS_VALID) - - # Frame #0 should be on self.step_out_of_malloc. - threads = lldbutil.get_threads_stopped_at_breakpoint( - process, breakpoint) - - self.assertTrue(len(threads) == 1) - thread = threads[0] + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, 'stop here in main.', self.main_source_spec) # First set the timeout too short, and make sure we fail. options = lldb.SBExpressionOptions() options.SetTimeoutInMicroSeconds(10) options.SetUnwindOnError(True) frame = thread.GetFrameAtIndex(0) value = frame.EvaluateExpression("wait_a_while(1000000)", options) self.assertTrue(value.IsValid()) self.assertFalse(value.GetError().Success()) # Now do the same thing with the command line command, and make sure it # works too. interp = self.dbg.GetCommandInterpreter() result = lldb.SBCommandReturnObject() return_value = interp.HandleCommand( "expr -t 100 -u true -- wait_a_while(1000000)", result) self.assertTrue(return_value == lldb.eReturnStatusFailed) # Okay, now do it again with long enough time outs: options.SetTimeoutInMicroSeconds(1000000) value = frame.EvaluateExpression("wait_a_while (1000)", options) self.assertTrue(value.IsValid()) self.assertTrue(value.GetError().Success()) # Now do the same thingwith the command line command, and make sure it # works too. interp = self.dbg.GetCommandInterpreter() result = lldb.SBCommandReturnObject() return_value = interp.HandleCommand( "expr -t 1000000 -u true -- wait_a_while(1000)", result) self.assertTrue(return_value == lldb.eReturnStatusSuccessFinishResult) # Finally set the one thread timeout and make sure that doesn't change # things much: options.SetTimeoutInMicroSeconds(1000000) options.SetOneThreadTimeoutInMicroSeconds(500000) value = frame.EvaluateExpression("wait_a_while (1000)", options) self.assertTrue(value.IsValid()) self.assertTrue(value.GetError().Success()) Index: vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/mtc/simple/Makefile =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/mtc/simple/Makefile (nonexistent) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/mtc/simple/Makefile (revision 320967) @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := main.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation -framework AppKit + +include $(LEVEL)/Makefile.rules Property changes on: vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/mtc/simple/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/mtc/simple/TestMTCSimple.py =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/mtc/simple/TestMTCSimple.py (nonexistent) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/mtc/simple/TestMTCSimple.py (revision 320967) @@ -0,0 +1,57 @@ +""" +Tests basic Main Thread Checker support (detecting a main-thread-only violation). +""" + +import os +import time +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbplatformutil import * +import json + + +class MTCSimpleTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + def test(self): + self.mtc_dylib_path = findMainThreadCheckerDylib() + if self.mtc_dylib_path == "": + self.skipTest("This test requires libMainThreadChecker.dylib.") + + self.build() + self.mtc_tests() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def mtc_tests(self): + # Load the test + exe = os.path.join(os.getcwd(), "a.out") + self.expect("file " + exe, patterns=["Current executable set to .*a.out"]) + + self.runCmd("env DYLD_INSERT_LIBRARIES=%s" % self.mtc_dylib_path) + self.runCmd("run") + + process = self.dbg.GetSelectedTarget().process + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + + self.expect("thread info", substrs=['stop reason = -[NSView superview] must be used from main thread only']) + + self.expect( + "thread info -s", + substrs=["instrumentation_class", "api_name", "class_name", "selector", "description"]) + self.assertEqual(thread.GetStopReason(), lldb.eStopReasonInstrumentation) + output_lines = self.res.GetOutput().split('\n') + json_line = '\n'.join(output_lines[2:]) + data = json.loads(json_line) + self.assertEqual(data["instrumentation_class"], "MainThreadChecker") + self.assertEqual(data["api_name"], "-[NSView superview]") + self.assertEqual(data["class_name"], "NSView") + self.assertEqual(data["selector"], "superview") + self.assertEqual(data["description"], "-[NSView superview] must be used from main thread only") Property changes on: vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/mtc/simple/TestMTCSimple.py ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/mtc/simple/main.m =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/mtc/simple/main.m (nonexistent) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/mtc/simple/main.m (revision 320967) @@ -0,0 +1,15 @@ +#import +#import + +int main() { + NSView *view = [[NSView alloc] init]; + dispatch_group_t g = dispatch_group_create(); + dispatch_group_enter(g); + [NSThread detachNewThreadWithBlock:^{ + @autoreleasepool { + [view superview]; + } + dispatch_group_leave(g); + }]; + dispatch_group_wait(g, DISPATCH_TIME_FOREVER); +} Index: vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py (revision 320966) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/return-value/TestReturnValue.py (revision 320967) @@ -1,262 +1,260 @@ """ Test getting return-values correctly when stepping out """ from __future__ import print_function import os import time import re import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil class ReturnValueTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) def affected_by_pr33042(self): return ("clang" in self.getCompiler() and self.getArchitecture() == "aarch64" and self.getPlatform() == "linux") @expectedFailureAll(oslist=["freebsd"], archs=["i386"]) @expectedFailureAll(oslist=["macosx"], archs=["i386"], bugnumber="") @expectedFailureAll( oslist=["linux"], compiler="clang", compiler_version=[ "<=", "3.6"], archs=["i386"]) - @expectedFailureAll(compiler="clang", compiler_version=["<=", "5.0.300080"], - triple='.*-android', archs=["i386"]) @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") @add_test_categories(['pyapi']) def test_with_python(self): """Test getting return values from stepping out.""" self.build() exe = os.path.join(os.getcwd(), "a.out") error = lldb.SBError() self.target = self.dbg.CreateTarget(exe) self.assertTrue(self.target, VALID_TARGET) inner_sint_bkpt = self.target.BreakpointCreateByName("inner_sint", exe) self.assertTrue(inner_sint_bkpt, VALID_BREAKPOINT) # Now launch the process, and do not stop at entry point. self.process = self.target.LaunchSimple( None, None, self.get_process_working_directory()) self.assertTrue(self.process, PROCESS_IS_VALID) # The stop reason of the thread should be breakpoint. self.assertTrue(self.process.GetState() == lldb.eStateStopped, STOPPED_DUE_TO_BREAKPOINT) # Now finish, and make sure the return value is correct. thread = lldbutil.get_stopped_thread( self.process, lldb.eStopReasonBreakpoint) # inner_sint returns the variable value, so capture that here: in_int = thread.GetFrameAtIndex(0).FindVariable( "value").GetValueAsSigned(error) self.assertTrue(error.Success()) thread.StepOut() self.assertTrue(self.process.GetState() == lldb.eStateStopped) self.assertTrue(thread.GetStopReason() == lldb.eStopReasonPlanComplete) frame = thread.GetFrameAtIndex(0) fun_name = frame.GetFunctionName() self.assertTrue(fun_name == "outer_sint") return_value = thread.GetStopReturnValue() self.assertTrue(return_value.IsValid()) ret_int = return_value.GetValueAsSigned(error) self.assertTrue(error.Success()) self.assertTrue(in_int == ret_int) # Run again and we will stop in inner_sint the second time outer_sint is called. # Then test stepping out two frames at once: self.process.Continue() thread_list = lldbutil.get_threads_stopped_at_breakpoint( self.process, inner_sint_bkpt) self.assertTrue(len(thread_list) == 1) thread = thread_list[0] # We are done with the inner_sint breakpoint: self.target.BreakpointDelete(inner_sint_bkpt.GetID()) frame = thread.GetFrameAtIndex(1) fun_name = frame.GetFunctionName() self.assertTrue(fun_name == "outer_sint") in_int = frame.FindVariable("value").GetValueAsSigned(error) self.assertTrue(error.Success()) thread.StepOutOfFrame(frame) self.assertTrue(self.process.GetState() == lldb.eStateStopped) self.assertTrue(thread.GetStopReason() == lldb.eStopReasonPlanComplete) frame = thread.GetFrameAtIndex(0) fun_name = frame.GetFunctionName() self.assertTrue(fun_name == "main") ret_value = thread.GetStopReturnValue() self.assertTrue(return_value.IsValid()) ret_int = ret_value.GetValueAsSigned(error) self.assertTrue(error.Success()) self.assertTrue(2 * in_int == ret_int) # Now try some simple returns that have different types: inner_float_bkpt = self.target.BreakpointCreateByName( "inner_float", exe) self.assertTrue(inner_float_bkpt, VALID_BREAKPOINT) self.process.Continue() thread_list = lldbutil.get_threads_stopped_at_breakpoint( self.process, inner_float_bkpt) self.assertTrue(len(thread_list) == 1) thread = thread_list[0] self.target.BreakpointDelete(inner_float_bkpt.GetID()) frame = thread.GetFrameAtIndex(0) in_value = frame.FindVariable("value") in_float = float(in_value.GetValue()) thread.StepOut() self.assertTrue(self.process.GetState() == lldb.eStateStopped) self.assertTrue(thread.GetStopReason() == lldb.eStopReasonPlanComplete) frame = thread.GetFrameAtIndex(0) fun_name = frame.GetFunctionName() self.assertTrue(fun_name == "outer_float") #return_value = thread.GetStopReturnValue() #self.assertTrue(return_value.IsValid()) #return_float = float(return_value.GetValue()) #self.assertTrue(in_float == return_float) self.return_and_test_struct_value("return_one_int") self.return_and_test_struct_value("return_two_int") self.return_and_test_struct_value("return_three_int") self.return_and_test_struct_value("return_four_int") if not self.affected_by_pr33042(): self.return_and_test_struct_value("return_five_int") self.return_and_test_struct_value("return_two_double") self.return_and_test_struct_value("return_one_double_two_float") self.return_and_test_struct_value("return_one_int_one_float_one_int") self.return_and_test_struct_value("return_one_pointer") self.return_and_test_struct_value("return_two_pointer") self.return_and_test_struct_value("return_one_float_one_pointer") self.return_and_test_struct_value("return_one_int_one_pointer") self.return_and_test_struct_value("return_three_short_one_float") self.return_and_test_struct_value("return_one_int_one_double") self.return_and_test_struct_value("return_one_int_one_double_one_int") self.return_and_test_struct_value( "return_one_short_one_double_one_short") self.return_and_test_struct_value("return_one_float_one_int_one_float") self.return_and_test_struct_value("return_two_float") # I am leaving out the packed test until we have a way to tell CLANG # about alignment when reading DWARF for packed types. #self.return_and_test_struct_value ("return_one_int_one_double_packed") self.return_and_test_struct_value("return_one_int_one_long") @expectedFailureAll(oslist=["freebsd"], archs=["i386"]) @expectedFailureAll(oslist=["macosx"], archs=["i386"], bugnumber="") @expectedFailureAll( oslist=["linux"], compiler="clang", compiler_version=[ "<=", "3.6"], archs=["i386"]) @expectedFailureAll(compiler=["gcc"], archs=["x86_64", "i386"]) @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") def test_vector_values(self): self.build() exe = os.path.join(os.getcwd(), "a.out") error = lldb.SBError() self.target = self.dbg.CreateTarget(exe) self.assertTrue(self.target, VALID_TARGET) main_bktp = self.target.BreakpointCreateByName("main", exe) self.assertTrue(main_bktp, VALID_BREAKPOINT) self.process = self.target.LaunchSimple( None, None, self.get_process_working_directory()) self.assertEqual(len(lldbutil.get_threads_stopped_at_breakpoint( self.process, main_bktp)), 1) self.return_and_test_struct_value("return_vector_size_float32_8") self.return_and_test_struct_value("return_vector_size_float32_16") self.return_and_test_struct_value("return_vector_size_float32_32") self.return_and_test_struct_value("return_ext_vector_size_float32_2") self.return_and_test_struct_value("return_ext_vector_size_float32_4") self.return_and_test_struct_value("return_ext_vector_size_float32_8") def return_and_test_struct_value(self, func_name): """Pass in the name of the function to return from - takes in value, returns value.""" # Set the breakpoint, run to it, finish out. bkpt = self.target.BreakpointCreateByName(func_name) self.assertTrue(bkpt.GetNumResolvedLocations() > 0) self.process.Continue() thread_list = lldbutil.get_threads_stopped_at_breakpoint( self.process, bkpt) self.assertTrue(len(thread_list) == 1) thread = thread_list[0] self.target.BreakpointDelete(bkpt.GetID()) in_value = thread.GetFrameAtIndex(0).FindVariable("value") self.assertTrue(in_value.IsValid()) num_in_children = in_value.GetNumChildren() # This is a little hokey, but if we don't get all the children now, then # once we've stepped we won't be able to get them? for idx in range(0, num_in_children): in_child = in_value.GetChildAtIndex(idx) in_child_str = in_child.GetValue() thread.StepOut() self.assertTrue(self.process.GetState() == lldb.eStateStopped) self.assertTrue(thread.GetStopReason() == lldb.eStopReasonPlanComplete) # Assuming all these functions step out to main. Could figure out the caller dynamically # if that would add something to the test. frame = thread.GetFrameAtIndex(0) fun_name = frame.GetFunctionName() self.assertTrue(fun_name == "main") frame = thread.GetFrameAtIndex(0) ret_value = thread.GetStopReturnValue() self.assertTrue(ret_value.IsValid()) num_ret_children = ret_value.GetNumChildren() self.assertTrue(num_in_children == num_ret_children) for idx in range(0, num_ret_children): in_child = in_value.GetChildAtIndex(idx) ret_child = ret_value.GetChildAtIndex(idx) in_child_str = in_child.GetValue() ret_child_str = ret_child.GetValue() self.assertEqual(in_child_str, ret_child_str) Index: vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/signal/raise/TestRaise.py =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/signal/raise/TestRaise.py (revision 320966) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/signal/raise/TestRaise.py (revision 320967) @@ -1,274 +1,279 @@ """Test that we handle inferiors that send signals to themselves""" from __future__ import print_function import os import lldb import re from lldbsuite.test.lldbplatformutil import getDarwinOSTriples from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil @skipIfWindows # signals do not exist on Windows class RaiseTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True def test_sigstop(self): self.build() self.signal_test('SIGSTOP', False) # passing of SIGSTOP is not correctly handled, so not testing that # scenario: https://llvm.org/bugs/show_bug.cgi?id=23574 @skipIfDarwin # darwin does not support real time signals @skipIfTargetAndroid() def test_sigsigrtmin(self): self.build() self.signal_test('SIGRTMIN', True) + + def test_sigtrap(self): + self.build() + self.signal_test('SIGTRAP', True) def launch(self, target, signal): # launch the process, do not stop at entry point. process = target.LaunchSimple( [signal], None, self.get_process_working_directory()) self.assertTrue(process, PROCESS_IS_VALID) self.assertEqual(process.GetState(), lldb.eStateStopped) thread = lldbutil.get_stopped_thread( process, lldb.eStopReasonBreakpoint) self.assertTrue( thread.IsValid(), "Thread should be stopped due to a breakpoint") return process def set_handle(self, signal, pass_signal, stop_at_signal, notify_signal): return_obj = lldb.SBCommandReturnObject() self.dbg.GetCommandInterpreter().HandleCommand( "process handle %s -p %s -s %s -n %s" % (signal, pass_signal, stop_at_signal, notify_signal), return_obj) self.assertTrue( return_obj.Succeeded(), "Setting signal handling failed") def signal_test(self, signal, test_passing): """Test that we handle inferior raising signals""" exe = os.path.join(os.getcwd(), "a.out") # Create a target by the debugger. target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) lldbutil.run_break_set_by_symbol(self, "main") # launch process = self.launch(target, signal) signo = process.GetUnixSignals().GetSignalNumberFromName(signal) # retrieve default signal disposition return_obj = lldb.SBCommandReturnObject() self.dbg.GetCommandInterpreter().HandleCommand( "process handle %s " % signal, return_obj) match = re.match( 'NAME *PASS *STOP *NOTIFY.*(false|true) *(false|true) *(false|true)', return_obj.GetOutput(), re.IGNORECASE | re.DOTALL) if not match: self.fail('Unable to retrieve default signal disposition.') default_pass = match.group(1) default_stop = match.group(2) default_notify = match.group(3) # Make sure we stop at the signal self.set_handle(signal, "false", "true", "true") process.Continue() self.assertEqual(process.GetState(), lldb.eStateStopped) thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonSignal) self.assertTrue( thread.IsValid(), "Thread should be stopped due to a signal") self.assertTrue( thread.GetStopReasonDataCount() >= 1, "There was data in the event.") self.assertEqual(thread.GetStopReasonDataAtIndex(0), signo, "The stop signal was %s" % signal) # Continue until we exit. process.Continue() self.assertEqual(process.GetState(), lldb.eStateExited) self.assertEqual(process.GetExitStatus(), 0) # launch again process = self.launch(target, signal) # Make sure we do not stop at the signal. We should still get the # notification. self.set_handle(signal, "false", "false", "true") self.expect( "process continue", substrs=[ "stopped and restarted", signal]) self.assertEqual(process.GetState(), lldb.eStateExited) self.assertEqual(process.GetExitStatus(), 0) # launch again process = self.launch(target, signal) # Make sure we do not stop at the signal, and we do not get the # notification. self.set_handle(signal, "false", "false", "false") self.expect( "process continue", substrs=["stopped and restarted"], matching=False) self.assertEqual(process.GetState(), lldb.eStateExited) self.assertEqual(process.GetExitStatus(), 0) if not test_passing: # reset signal handling to default self.set_handle(signal, default_pass, default_stop, default_notify) return # launch again process = self.launch(target, signal) # Make sure we stop at the signal self.set_handle(signal, "true", "true", "true") process.Continue() self.assertEqual(process.GetState(), lldb.eStateStopped) thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonSignal) self.assertTrue( thread.IsValid(), "Thread should be stopped due to a signal") self.assertTrue( thread.GetStopReasonDataCount() >= 1, "There was data in the event.") self.assertEqual( thread.GetStopReasonDataAtIndex(0), process.GetUnixSignals().GetSignalNumberFromName(signal), "The stop signal was %s" % signal) # Continue until we exit. The process should receive the signal. process.Continue() self.assertEqual(process.GetState(), lldb.eStateExited) self.assertEqual(process.GetExitStatus(), signo) # launch again process = self.launch(target, signal) # Make sure we do not stop at the signal. We should still get the notification. Process # should receive the signal. self.set_handle(signal, "true", "false", "true") self.expect( "process continue", substrs=[ "stopped and restarted", signal]) self.assertEqual(process.GetState(), lldb.eStateExited) self.assertEqual(process.GetExitStatus(), signo) # launch again process = self.launch(target, signal) # Make sure we do not stop at the signal, and we do not get the notification. Process # should receive the signal. self.set_handle(signal, "true", "false", "false") self.expect( "process continue", substrs=["stopped and restarted"], matching=False) self.assertEqual(process.GetState(), lldb.eStateExited) self.assertEqual(process.GetExitStatus(), signo) # reset signal handling to default self.set_handle(signal, default_pass, default_stop, default_notify) @expectedFailureAll( oslist=["linux"] + getDarwinOSTriples(), bugnumber="llvm.org/pr20231") def test_restart_bug(self): """Test that we catch a signal in the edge case where the process receives it while we are about to interrupt it""" self.build() exe = os.path.join(os.getcwd(), "a.out") # Create a target by the debugger. target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) bkpt = target.BreakpointCreateByName("main") self.assertTrue(bkpt.IsValid(), VALID_BREAKPOINT) # launch the inferior and don't wait for it to stop self.dbg.SetAsync(True) error = lldb.SBError() listener = lldb.SBListener("my listener") process = target.Launch(listener, ["SIGSTOP"], # argv None, # envp None, # stdin_path None, # stdout_path None, # stderr_path None, # working directory 0, # launch flags False, # Stop at entry error) # error self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID) event = lldb.SBEvent() # Give the child enough time to reach the breakpoint, # while clearing out all the pending events. # The last WaitForEvent call will time out after 2 seconds. while listener.WaitForEvent(2, event): if self.TraceOn(): print( "Process changing state to:", self.dbg.StateAsCString( process.GetStateFromEvent(event))) # now the process should be stopped self.assertEqual( process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) self.assertEqual(len(lldbutil.get_threads_stopped_at_breakpoint( process, bkpt)), 1, "A thread should be stopped at breakpoint") # Remove all breakpoints. This makes sure we don't have to single-step over them when we # resume the process below target.DeleteAllBreakpoints() # resume the process and immediately try to set another breakpoint. When using the remote # stub, this will trigger a request to stop the process just as it is about to stop # naturally due to a SIGSTOP signal it raises. Make sure we do not lose # this signal. process.Continue() self.assertTrue(target.BreakpointCreateByName( "handler").IsValid(), VALID_BREAKPOINT) # Clear the events again while listener.WaitForEvent(2, event): if self.TraceOn(): print( "Process changing state to:", self.dbg.StateAsCString( process.GetStateFromEvent(event))) # The process should be stopped due to a signal self.assertEqual(process.GetState(), lldb.eStateStopped) thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonSignal) self.assertTrue( thread.IsValid(), "Thread should be stopped due to a signal") self.assertTrue( thread.GetStopReasonDataCount() >= 1, "There was data in the event.") signo = process.GetUnixSignals().GetSignalNumberFromName("SIGSTOP") self.assertEqual(thread.GetStopReasonDataAtIndex(0), signo, "The stop signal was %s" % signal) # We are done process.Kill() Index: vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/signal/raise/main.c =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/signal/raise/main.c (revision 320966) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/signal/raise/main.c (revision 320967) @@ -1,42 +1,49 @@ #include #include #include #include void handler(int signo) { _exit(signo); } int main (int argc, char *argv[]) { + if (signal(SIGTRAP, handler) == SIG_ERR) + { + perror("signal(SIGTRAP)"); + return 1; + } #ifndef __APPLE__ // Real time signals not supported on apple platforms. if (signal(SIGRTMIN, handler) == SIG_ERR) { perror("signal(SIGRTMIN)"); return 1; } #endif if (argc < 2) { puts("Please specify a signal to raise"); return 1; } if (strcmp(argv[1], "SIGSTOP") == 0) raise(SIGSTOP); + else if (strcmp(argv[1], "SIGTRAP") == 0) + raise(SIGTRAP); #ifndef __APPLE__ else if (strcmp(argv[1], "SIGRTMIN") == 0) raise(SIGRTMIN); #endif else { printf("Unknown signal: %s\n", argv[1]); return 1; } return 0; } Index: vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/Makefile =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/Makefile (nonexistent) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/Makefile (revision 320967) @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS := -fsanitize=undefined -g + +include $(LEVEL)/Makefile.rules Property changes on: vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/TestUbsanUserExpression.py =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/TestUbsanUserExpression.py (nonexistent) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/TestUbsanUserExpression.py (revision 320967) @@ -0,0 +1,49 @@ +""" +Test that hitting a UBSan issue while running user expression doesn't break the evaluation. +""" + +import os +import time +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil +import json + + +class UbsanUserExpressionTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessUndefinedBehaviorSanitizer + def test(self): + self.build() + self.ubsan_tests() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + self.line_breakpoint = line_number('main.c', '// breakpoint line') + + def ubsan_tests(self): + # Load the test + exe = os.path.join(os.getcwd(), "a.out") + self.expect( + "file " + exe, + patterns=["Current executable set to .*a.out"]) + + self.runCmd("breakpoint set -f main.c -l %d" % self.line_breakpoint) + + self.runCmd("run") + + process = self.dbg.GetSelectedTarget().process + thread = process.GetSelectedThread() + frame = thread.GetSelectedFrame() + + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + self.expect("p foo()", substrs=["(int) $0 = 42"]) + + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) Property changes on: vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/TestUbsanUserExpression.py ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/main.c =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/main.c (nonexistent) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/main.c (revision 320967) @@ -0,0 +1,9 @@ +int foo() { + int data[4]; + int x = *(int *)(((char *)&data[0]) + 2); + return 42; +} + +int main() { + return 0; // breakpoint line +} Property changes on: vendor/lldb/dist/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/main.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/lldb/dist/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py (revision 320966) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py (revision 320967) @@ -1,144 +1,145 @@ """Test the go DWARF type parsing.""" from __future__ import print_function import os import time import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil class TestGoASTContext(TestBase): mydir = TestBase.compute_mydir(__file__) @add_test_categories(['pyapi']) @skipIfFreeBSD # llvm.org/pr24895 triggers assertion failure @skipIfRemote # Not remote test suit ready @no_debug_info_test @skipUnlessGoInstalled + @expectedFailureAll(bugnumber="llvm.org/pr33643") def test_with_dsym_and_python_api(self): """Test GoASTContext dwarf parsing.""" self.buildGo() self.launchProcess() self.go_builtin_types() self.check_main_vars() def setUp(self): # Call super's setUp(). TestBase.setUp(self) # Find the line numbers to break inside main(). self.main_source = "main.go" self.break_line = line_number( self.main_source, '// Set breakpoint here.') def check_builtin(self, name, size=0, typeclass=lldb.eTypeClassBuiltin): tl = self.target().FindTypes(name) self.assertEqual(1, len(tl)) t = list(tl)[0] self.assertEqual(name, t.name) self.assertEqual(typeclass, t.type) if size > 0: self.assertEqual(size, t.size) def launchProcess(self): exe = os.path.join(os.getcwd(), "a.out") target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) bpt = target.BreakpointCreateByLocation( self.main_source, self.break_line) self.assertTrue(bpt, VALID_BREAKPOINT) # Now launch the process, and do not stop at entry point. process = target.LaunchSimple( None, None, self.get_process_working_directory()) self.assertTrue(process, PROCESS_IS_VALID) # The stop reason of the thread should be breakpoint. thread_list = lldbutil.get_threads_stopped_at_breakpoint(process, bpt) # Make sure we stopped at the first breakpoint. self.assertTrue( len(thread_list) != 0, "No thread stopped at our breakpoint.") self.assertTrue(len(thread_list) == 1, "More than one thread stopped at our breakpoint.") frame = thread_list[0].GetFrameAtIndex(0) self.assertTrue(frame, "Got a valid frame 0 frame.") def go_builtin_types(self): address_size = self.target().GetAddressByteSize() self.check_builtin('bool') self.check_builtin('uint8', 1) self.check_builtin('int8', 1) self.check_builtin('uint16', 2) self.check_builtin('int16', 2) self.check_builtin('uint32', 4) self.check_builtin('int32', 4) self.check_builtin('uint64', 8) self.check_builtin('int64', 8) self.check_builtin('uintptr', address_size) self.check_builtin('int', address_size) self.check_builtin('uint', address_size) self.check_builtin('float32', 4) self.check_builtin('float64', 8) self.check_builtin('complex64', 8, lldb.eTypeClassComplexFloat) self.check_builtin('complex128', 16, lldb.eTypeClassComplexFloat) def var(self, name): var = self.frame().FindVariable(name) self.assertTrue(var.IsValid(), "%s %s" % (VALID_VARIABLE, name)) return var def check_main_vars(self): v = self.var('theBool') self.assertEqual('true', v.value) v = self.var('theInt') self.assertEqual('-7', v.value) v = self.var('theComplex') self.assertEqual('1 + 2i', v.value) v = self.var('thePointer') self.assertTrue(v.TypeIsPointerType()) self.assertEqual('-10', v.Dereference().value) self.assertEqual(1, v.GetNumChildren()) self.assertEqual('-10', v.GetChildAtIndex(0).value) # print() # print(os.getpid()) # time.sleep(60) v = self.var('theStruct') if v.TypeIsPointerType(): v = v.Dereference() self.assertEqual(2, v.GetNumChildren()) self.assertEqual('7', v.GetChildAtIndex(0).value) self.assertEqual('7', v.GetChildMemberWithName('myInt').value) self.assertEqual( v.load_addr, v.GetChildAtIndex(1).GetValueAsUnsigned()) self.assertEqual(v.load_addr, v.GetChildMemberWithName( 'myPointer').GetValueAsUnsigned()) # Test accessing struct fields through pointers. v = v.GetChildMemberWithName('myPointer') self.assertTrue(v.TypeIsPointerType()) self.assertEqual(2, v.GetNumChildren()) self.assertEqual('7', v.GetChildAtIndex(0).value) c = v.GetChildMemberWithName('myPointer') self.assertTrue(c.TypeIsPointerType()) self.assertEqual(2, c.GetNumChildren()) self.assertEqual('7', c.GetChildAtIndex(0).value) v = self.var('theArray') self.assertEqual(5, v.GetNumChildren()) for i in list(range(5)): self.assertEqual(str(i + 1), v.GetChildAtIndex(i).value) Index: vendor/lldb/dist/packages/Python/lldbsuite/test/lldbplatformutil.py =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/lldbplatformutil.py (revision 320966) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/lldbplatformutil.py (revision 320967) @@ -1,166 +1,180 @@ """ This module contains functions used by the test cases to hide the architecture and/or the platform dependent nature of the tests. """ from __future__ import absolute_import # System modules import itertools import re import subprocess import sys +import os # Third-party modules import six from six.moves.urllib import parse as urlparse # LLDB modules from . import configuration import use_lldb_suite import lldb def check_first_register_readable(test_case): arch = test_case.getArchitecture() if arch in ['x86_64', 'i386']: test_case.expect("register read eax", substrs=['eax = 0x']) elif arch in ['arm']: test_case.expect("register read r0", substrs=['r0 = 0x']) elif arch in ['aarch64']: test_case.expect("register read x0", substrs=['x0 = 0x']) elif re.match("mips", arch): test_case.expect("register read zero", substrs=['zero = 0x']) elif arch in ['s390x']: test_case.expect("register read r0", substrs=['r0 = 0x']) else: # TODO: Add check for other architectures test_case.fail( "Unsupported architecture for test case (arch: %s)" % test_case.getArchitecture()) def _run_adb_command(cmd, device_id): device_id_args = [] if device_id: device_id_args = ["-s", device_id] full_cmd = ["adb"] + device_id_args + cmd p = subprocess.Popen( full_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate() return p.returncode, stdout, stderr def target_is_android(): if not hasattr(target_is_android, 'result'): triple = lldb.DBG.GetSelectedPlatform().GetTriple() match = re.match(".*-.*-.*-android", triple) target_is_android.result = match is not None return target_is_android.result def android_device_api(): if not hasattr(android_device_api, 'result'): assert configuration.lldb_platform_url is not None device_id = None parsed_url = urlparse.urlparse(configuration.lldb_platform_url) host_name = parsed_url.netloc.split(":")[0] if host_name != 'localhost': device_id = host_name if device_id.startswith('[') and device_id.endswith(']'): device_id = device_id[1:-1] retcode, stdout, stderr = _run_adb_command( ["shell", "getprop", "ro.build.version.sdk"], device_id) if retcode == 0: android_device_api.result = int(stdout) else: raise LookupError( ">>> Unable to determine the API level of the Android device.\n" ">>> stdout:\n%s\n" ">>> stderr:\n%s\n" % (stdout, stderr)) return android_device_api.result def match_android_device(device_arch, valid_archs=None, valid_api_levels=None): if not target_is_android(): return False if valid_archs is not None and device_arch not in valid_archs: return False if valid_api_levels is not None and android_device_api() not in valid_api_levels: return False return True def finalize_build_dictionary(dictionary): if target_is_android(): if dictionary is None: dictionary = {} dictionary["OS"] = "Android" if android_device_api() >= 16: dictionary["PIE"] = 1 return dictionary def getHostPlatform(): """Returns the host platform running the test suite.""" # Attempts to return a platform name matching a target Triple platform. if sys.platform.startswith('linux'): return 'linux' elif sys.platform.startswith('win32'): return 'windows' elif sys.platform.startswith('darwin'): return 'darwin' elif sys.platform.startswith('freebsd'): return 'freebsd' elif sys.platform.startswith('netbsd'): return 'netbsd' else: return sys.platform def getDarwinOSTriples(): return ['darwin', 'macosx', 'ios'] def getPlatform(): """Returns the target platform which the tests are running on.""" platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2] if platform.startswith('freebsd'): platform = 'freebsd' elif platform.startswith('netbsd'): platform = 'netbsd' return platform def platformIsDarwin(): """Returns true if the OS triple for the selected platform is any valid apple OS""" return getPlatform() in getDarwinOSTriples() + + +def findMainThreadCheckerDylib(): + if not platformIsDarwin(): + return "" + + with os.popen('xcode-select -p') as output: + xcode_developer_path = output.read().strip() + mtc_dylib_path = '%s/usr/lib/libMainThreadChecker.dylib' % xcode_developer_path + if os.path.isfile(mtc_dylib_path): + return mtc_dylib_path + + return "" class _PlatformContext(object): """Value object class which contains platform-specific options.""" def __init__(self, shlib_environment_var, shlib_prefix, shlib_extension): self.shlib_environment_var = shlib_environment_var self.shlib_prefix = shlib_prefix self.shlib_extension = shlib_extension def createPlatformContext(): if platformIsDarwin(): return _PlatformContext('DYLD_LIBRARY_PATH', 'lib', 'dylib') elif getPlatform() in ("freebsd", "linux", "netbsd"): return _PlatformContext('LD_LIBRARY_PATH', 'lib', 'so') else: return None def hasChattyStderr(test_case): """Some targets produce garbage on the standard error output. This utility function determines whether the tests can be strict about the expected stderr contents.""" if match_android_device(test_case.getArchitecture(), ['aarch64'], [22]): return True # The dynamic linker on the device will complain about unknown DT entries return False Index: vendor/lldb/dist/packages/Python/lldbsuite/test/lldbutil.py =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/lldbutil.py (revision 320966) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/lldbutil.py (revision 320967) @@ -1,1247 +1,1288 @@ """ This LLDB module contains miscellaneous utilities. Some of the test suite takes advantage of the utility functions defined here. They can also be useful for general purpose lldb scripting. """ from __future__ import print_function from __future__ import absolute_import # System modules import collections import os import re import sys import time # Third-party modules from six import StringIO as SixStringIO import six # LLDB modules import lldb # =================================================== # Utilities for locating/checking executable programs # =================================================== def is_exe(fpath): """Returns True if fpath is an executable.""" return os.path.isfile(fpath) and os.access(fpath, os.X_OK) def which(program): """Returns the full path to a program; None otherwise.""" fpath, fname = os.path.split(program) if fpath: if is_exe(program): return program else: for path in os.environ["PATH"].split(os.pathsep): exe_file = os.path.join(path, program) if is_exe(exe_file): return exe_file return None # =================================================== # Disassembly for an SBFunction or an SBSymbol object # =================================================== def disassemble(target, function_or_symbol): """Disassemble the function or symbol given a target. It returns the disassembly content in a string object. """ buf = SixStringIO() insts = function_or_symbol.GetInstructions(target) for i in insts: print(i, file=buf) return buf.getvalue() # ========================================================== # Integer (byte size 1, 2, 4, and 8) to bytearray conversion # ========================================================== def int_to_bytearray(val, bytesize): """Utility function to convert an integer into a bytearray. It returns the bytearray in the little endian format. It is easy to get the big endian format, just do ba.reverse() on the returned object. """ import struct if bytesize == 1: return bytearray([val]) # Little endian followed by a format character. template = "<%c" if bytesize == 2: fmt = template % 'h' elif bytesize == 4: fmt = template % 'i' elif bytesize == 4: fmt = template % 'q' else: return None packed = struct.pack(fmt, val) return bytearray(packed) def bytearray_to_int(bytes, bytesize): """Utility function to convert a bytearray into an integer. It interprets the bytearray in the little endian format. For a big endian bytearray, just do ba.reverse() on the object before passing it in. """ import struct if bytesize == 1: return bytes[0] # Little endian followed by a format character. template = "<%c" if bytesize == 2: fmt = template % 'h' elif bytesize == 4: fmt = template % 'i' elif bytesize == 4: fmt = template % 'q' else: return None unpacked = struct.unpack_from(fmt, bytes) return unpacked[0] # ============================================================== # Get the description of an lldb object or None if not available # ============================================================== def get_description(obj, option=None): """Calls lldb_obj.GetDescription() and returns a string, or None. For SBTarget, SBBreakpointLocation, and SBWatchpoint lldb objects, an extra option can be passed in to describe the detailed level of description desired: o lldb.eDescriptionLevelBrief o lldb.eDescriptionLevelFull o lldb.eDescriptionLevelVerbose """ method = getattr(obj, 'GetDescription') if not method: return None tuple = (lldb.SBTarget, lldb.SBBreakpointLocation, lldb.SBWatchpoint) if isinstance(obj, tuple): if option is None: option = lldb.eDescriptionLevelBrief stream = lldb.SBStream() if option is None: success = method(stream) else: success = method(stream, option) if not success: return None return stream.GetData() # ================================================= # Convert some enum value to its string counterpart # ================================================= def state_type_to_str(enum): """Returns the stateType string given an enum.""" if enum == lldb.eStateInvalid: return "invalid" elif enum == lldb.eStateUnloaded: return "unloaded" elif enum == lldb.eStateConnected: return "connected" elif enum == lldb.eStateAttaching: return "attaching" elif enum == lldb.eStateLaunching: return "launching" elif enum == lldb.eStateStopped: return "stopped" elif enum == lldb.eStateRunning: return "running" elif enum == lldb.eStateStepping: return "stepping" elif enum == lldb.eStateCrashed: return "crashed" elif enum == lldb.eStateDetached: return "detached" elif enum == lldb.eStateExited: return "exited" elif enum == lldb.eStateSuspended: return "suspended" else: raise Exception("Unknown StateType enum") def stop_reason_to_str(enum): """Returns the stopReason string given an enum.""" if enum == lldb.eStopReasonInvalid: return "invalid" elif enum == lldb.eStopReasonNone: return "none" elif enum == lldb.eStopReasonTrace: return "trace" elif enum == lldb.eStopReasonBreakpoint: return "breakpoint" elif enum == lldb.eStopReasonWatchpoint: return "watchpoint" elif enum == lldb.eStopReasonExec: return "exec" elif enum == lldb.eStopReasonSignal: return "signal" elif enum == lldb.eStopReasonException: return "exception" elif enum == lldb.eStopReasonPlanComplete: return "plancomplete" elif enum == lldb.eStopReasonThreadExiting: return "threadexiting" else: raise Exception("Unknown StopReason enum") def symbol_type_to_str(enum): """Returns the symbolType string given an enum.""" if enum == lldb.eSymbolTypeInvalid: return "invalid" elif enum == lldb.eSymbolTypeAbsolute: return "absolute" elif enum == lldb.eSymbolTypeCode: return "code" elif enum == lldb.eSymbolTypeData: return "data" elif enum == lldb.eSymbolTypeTrampoline: return "trampoline" elif enum == lldb.eSymbolTypeRuntime: return "runtime" elif enum == lldb.eSymbolTypeException: return "exception" elif enum == lldb.eSymbolTypeSourceFile: return "sourcefile" elif enum == lldb.eSymbolTypeHeaderFile: return "headerfile" elif enum == lldb.eSymbolTypeObjectFile: return "objectfile" elif enum == lldb.eSymbolTypeCommonBlock: return "commonblock" elif enum == lldb.eSymbolTypeBlock: return "block" elif enum == lldb.eSymbolTypeLocal: return "local" elif enum == lldb.eSymbolTypeParam: return "param" elif enum == lldb.eSymbolTypeVariable: return "variable" elif enum == lldb.eSymbolTypeVariableType: return "variabletype" elif enum == lldb.eSymbolTypeLineEntry: return "lineentry" elif enum == lldb.eSymbolTypeLineHeader: return "lineheader" elif enum == lldb.eSymbolTypeScopeBegin: return "scopebegin" elif enum == lldb.eSymbolTypeScopeEnd: return "scopeend" elif enum == lldb.eSymbolTypeAdditional: return "additional" elif enum == lldb.eSymbolTypeCompiler: return "compiler" elif enum == lldb.eSymbolTypeInstrumentation: return "instrumentation" elif enum == lldb.eSymbolTypeUndefined: return "undefined" def value_type_to_str(enum): """Returns the valueType string given an enum.""" if enum == lldb.eValueTypeInvalid: return "invalid" elif enum == lldb.eValueTypeVariableGlobal: return "global_variable" elif enum == lldb.eValueTypeVariableStatic: return "static_variable" elif enum == lldb.eValueTypeVariableArgument: return "argument_variable" elif enum == lldb.eValueTypeVariableLocal: return "local_variable" elif enum == lldb.eValueTypeRegister: return "register" elif enum == lldb.eValueTypeRegisterSet: return "register_set" elif enum == lldb.eValueTypeConstResult: return "constant_result" else: raise Exception("Unknown ValueType enum") # ================================================== # Get stopped threads due to each stop reason. # ================================================== def sort_stopped_threads(process, breakpoint_threads=None, crashed_threads=None, watchpoint_threads=None, signal_threads=None, exiting_threads=None, other_threads=None): """ Fills array *_threads with threads stopped for the corresponding stop reason. """ for lst in [breakpoint_threads, watchpoint_threads, signal_threads, exiting_threads, other_threads]: if lst is not None: lst[:] = [] for thread in process: dispatched = False for (reason, list) in [(lldb.eStopReasonBreakpoint, breakpoint_threads), (lldb.eStopReasonException, crashed_threads), (lldb.eStopReasonWatchpoint, watchpoint_threads), (lldb.eStopReasonSignal, signal_threads), (lldb.eStopReasonThreadExiting, exiting_threads), (None, other_threads)]: if not dispatched and list is not None: if thread.GetStopReason() == reason or reason is None: list.append(thread) dispatched = True # ================================================== # Utility functions for setting breakpoints # ================================================== def run_break_set_by_file_and_line( test, file_name, line_number, extra_options=None, num_expected_locations=1, loc_exact=False, module_name=None): """Set a breakpoint by file and line, returning the breakpoint number. If extra_options is not None, then we append it to the breakpoint set command. If num_expected_locations is -1 we check that we got AT LEAST one location, otherwise we check that num_expected_locations equals the number of locations. If loc_exact is true, we check that there is one location, and that location must be at the input file and line number.""" if file_name is None: command = 'breakpoint set -l %d' % (line_number) else: command = 'breakpoint set -f "%s" -l %d' % (file_name, line_number) if module_name: command += " --shlib '%s'" % (module_name) if extra_options: command += " " + extra_options break_results = run_break_set_command(test, command) if num_expected_locations == 1 and loc_exact: check_breakpoint_result( test, break_results, num_locations=num_expected_locations, file_name=file_name, line_number=line_number, module_name=module_name) else: check_breakpoint_result( test, break_results, num_locations=num_expected_locations) return get_bpno_from_match(break_results) def run_break_set_by_symbol( test, symbol, extra_options=None, num_expected_locations=-1, sym_exact=False, module_name=None): """Set a breakpoint by symbol name. Common options are the same as run_break_set_by_file_and_line. If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match.""" command = 'breakpoint set -n "%s"' % (symbol) if module_name: command += " --shlib '%s'" % (module_name) if extra_options: command += " " + extra_options break_results = run_break_set_command(test, command) if num_expected_locations == 1 and sym_exact: check_breakpoint_result( test, break_results, num_locations=num_expected_locations, symbol_name=symbol, module_name=module_name) else: check_breakpoint_result( test, break_results, num_locations=num_expected_locations) return get_bpno_from_match(break_results) def run_break_set_by_selector( test, selector, extra_options=None, num_expected_locations=-1, module_name=None): """Set a breakpoint by selector. Common options are the same as run_break_set_by_file_and_line.""" command = 'breakpoint set -S "%s"' % (selector) if module_name: command += ' --shlib "%s"' % (module_name) if extra_options: command += " " + extra_options break_results = run_break_set_command(test, command) if num_expected_locations == 1: check_breakpoint_result( test, break_results, num_locations=num_expected_locations, symbol_name=selector, symbol_match_exact=False, module_name=module_name) else: check_breakpoint_result( test, break_results, num_locations=num_expected_locations) return get_bpno_from_match(break_results) def run_break_set_by_regexp( test, regexp, extra_options=None, num_expected_locations=-1): """Set a breakpoint by regular expression match on symbol name. Common options are the same as run_break_set_by_file_and_line.""" command = 'breakpoint set -r "%s"' % (regexp) if extra_options: command += " " + extra_options break_results = run_break_set_command(test, command) check_breakpoint_result( test, break_results, num_locations=num_expected_locations) return get_bpno_from_match(break_results) def run_break_set_by_source_regexp( test, regexp, extra_options=None, num_expected_locations=-1): """Set a breakpoint by source regular expression. Common options are the same as run_break_set_by_file_and_line.""" command = 'breakpoint set -p "%s"' % (regexp) if extra_options: command += " " + extra_options break_results = run_break_set_command(test, command) check_breakpoint_result( test, break_results, num_locations=num_expected_locations) return get_bpno_from_match(break_results) def run_break_set_command(test, command): """Run the command passed in - it must be some break set variant - and analyze the result. Returns a dictionary of information gleaned from the command-line results. Will assert if the breakpoint setting fails altogether. Dictionary will contain: bpno - breakpoint of the newly created breakpoint, -1 on error. num_locations - number of locations set for the breakpoint. If there is only one location, the dictionary MAY contain: file - source file name line_no - source line number symbol - symbol name inline_symbol - inlined symbol name offset - offset from the original symbol module - module address - address at which the breakpoint was set.""" patterns = [ r"^Breakpoint (?P[0-9]+): (?P[0-9]+) locations\.$", r"^Breakpoint (?P[0-9]+): (?Pno) locations \(pending\)\.", r"^Breakpoint (?P[0-9]+): where = (?P.*)`(?P[+\-]{0,1}[^+]+)( \+ (?P[0-9]+)){0,1}( \[inlined\] (?P.*)){0,1} at (?P[^:]+):(?P[0-9]+), address = (?P
0x[0-9a-fA-F]+)$", r"^Breakpoint (?P[0-9]+): where = (?P.*)`(?P.*)( \+ (?P[0-9]+)){0,1}, address = (?P
0x[0-9a-fA-F]+)$"] match_object = test.match(command, patterns) break_results = match_object.groupdict() # We always insert the breakpoint number, setting it to -1 if we couldn't find it # Also, make sure it gets stored as an integer. if not 'bpno' in break_results: break_results['bpno'] = -1 else: break_results['bpno'] = int(break_results['bpno']) # We always insert the number of locations # If ONE location is set for the breakpoint, then the output doesn't mention locations, but it has to be 1... # We also make sure it is an integer. if not 'num_locations' in break_results: num_locations = 1 else: num_locations = break_results['num_locations'] if num_locations == 'no': num_locations = 0 else: num_locations = int(break_results['num_locations']) break_results['num_locations'] = num_locations if 'line_no' in break_results: break_results['line_no'] = int(break_results['line_no']) return break_results def get_bpno_from_match(break_results): return int(break_results['bpno']) def check_breakpoint_result( test, break_results, file_name=None, line_number=-1, symbol_name=None, symbol_match_exact=True, module_name=None, offset=-1, num_locations=-1): out_num_locations = break_results['num_locations'] if num_locations == -1: test.assertTrue(out_num_locations > 0, "Expecting one or more locations, got none.") else: test.assertTrue( num_locations == out_num_locations, "Expecting %d locations, got %d." % (num_locations, out_num_locations)) if file_name: out_file_name = "" if 'file' in break_results: out_file_name = break_results['file'] test.assertTrue( file_name == out_file_name, "Breakpoint file name '%s' doesn't match resultant name '%s'." % (file_name, out_file_name)) if line_number != -1: out_line_number = -1 if 'line_no' in break_results: out_line_number = break_results['line_no'] test.assertTrue( line_number == out_line_number, "Breakpoint line number %s doesn't match resultant line %s." % (line_number, out_line_number)) if symbol_name: out_symbol_name = "" # Look first for the inlined symbol name, otherwise use the symbol # name: if 'inline_symbol' in break_results and break_results['inline_symbol']: out_symbol_name = break_results['inline_symbol'] elif 'symbol' in break_results: out_symbol_name = break_results['symbol'] if symbol_match_exact: test.assertTrue( symbol_name == out_symbol_name, "Symbol name '%s' doesn't match resultant symbol '%s'." % (symbol_name, out_symbol_name)) else: test.assertTrue( out_symbol_name.find(symbol_name) != - 1, "Symbol name '%s' isn't in resultant symbol '%s'." % (symbol_name, out_symbol_name)) if module_name: out_module_name = None if 'module' in break_results: out_module_name = break_results['module'] test.assertTrue( module_name.find(out_module_name) != - 1, "Symbol module name '%s' isn't in expected module name '%s'." % (out_module_name, module_name)) # ================================================== # Utility functions related to Threads and Processes # ================================================== def get_stopped_threads(process, reason): """Returns the thread(s) with the specified stop reason in a list. The list can be empty if no such thread exists. """ threads = [] for t in process: if t.GetStopReason() == reason: threads.append(t) return threads def get_stopped_thread(process, reason): """A convenience function which returns the first thread with the given stop reason or None. Example usages: 1. Get the stopped thread due to a breakpoint condition ... from lldbutil import get_stopped_thread thread = get_stopped_thread(process, lldb.eStopReasonPlanComplete) self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") ... 2. Get the thread stopped due to a breakpoint ... from lldbutil import get_stopped_thread thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint") ... """ threads = get_stopped_threads(process, reason) if len(threads) == 0: return None return threads[0] def get_threads_stopped_at_breakpoint_id(process, bpid): """ For a stopped process returns the thread stopped at the breakpoint passed in bkpt""" stopped_threads = [] threads = [] stopped_threads = get_stopped_threads(process, lldb.eStopReasonBreakpoint) if len(stopped_threads) == 0: return threads for thread in stopped_threads: # Make sure we've hit our breakpoint... break_id = thread.GetStopReasonDataAtIndex(0) if break_id == bpid: threads.append(thread) return threads def get_threads_stopped_at_breakpoint(process, bkpt): return get_threads_stopped_at_breakpoint_id(process, bkpt.GetID()) def get_one_thread_stopped_at_breakpoint_id( process, bpid, require_exactly_one=True): threads = get_threads_stopped_at_breakpoint_id(process, bpid) if len(threads) == 0: return None if require_exactly_one and len(threads) != 1: return None return threads[0] def get_one_thread_stopped_at_breakpoint( process, bkpt, require_exactly_one=True): return get_one_thread_stopped_at_breakpoint_id( process, bkpt.GetID(), require_exactly_one) def is_thread_crashed(test, thread): """In the test suite we dereference a null pointer to simulate a crash. The way this is reported depends on the platform.""" if test.platformIsDarwin(): return thread.GetStopReason( ) == lldb.eStopReasonException and "EXC_BAD_ACCESS" in thread.GetStopDescription(100) elif test.getPlatform() == "linux": return thread.GetStopReason() == lldb.eStopReasonSignal and thread.GetStopReasonDataAtIndex( 0) == thread.GetProcess().GetUnixSignals().GetSignalNumberFromName("SIGSEGV") else: return "invalid address" in thread.GetStopDescription(100) def get_crashed_threads(test, process): threads = [] if process.GetState() != lldb.eStateStopped: return threads for thread in process: if is_thread_crashed(test, thread): threads.append(thread) return threads +def run_to_source_breakpoint(test, bkpt_pattern, source_spec, launch_info = None, exe_name = "a.out", in_cwd = True): + """Start up a target, using exe_name as the executable, and run it to + a breakpoint set by source regex bkpt_pattern. + If you want to pass in launch arguments or environment variables, you can optionally pass in + an SBLaunchInfo. If you do that, remember to set the working directory as well. + If your executable isn't called a.out, you can pass that in. And if your executable isn't + in the CWD, pass in the absolute path to the executable in exe_name, and set in_cwd to False. + If the target isn't valid, the breakpoint isn't found, or hit, the + function will cause a testsuite failure. + If successful it returns a tuple with the target process and thread that hit the breakpoint.""" + + if in_cwd: + exe = os.path.join(os.getcwd(), exe_name) + + # Create the target + target = test.dbg.CreateTarget(exe) + test.assertTrue(target, "Target: %s is not valid."%(exe_name)) + + # Set the breakpoints + breakpoint = target.BreakpointCreateBySourceRegex( + bkpt_pattern, source_spec) + test.assertTrue(breakpoint.GetNumLocations() > 0, + 'No locations found for source breakpoint: "%s"'%(bkpt_pattern)) + + # Launch the process, and do not stop at the entry point. + if not launch_info: + launch_info = lldb.SBLaunchInfo(None) + launch_info.SetWorkingDirectory(test.get_process_working_directory()) + + error = lldb.SBError() + process = target.Launch(launch_info, error) + + test.assertTrue(process, "Could not create a valid process for %s: %s"%(exe_name, error.GetCString())) + + # Frame #0 should be at our breakpoint. + threads = get_threads_stopped_at_breakpoint( + process, breakpoint) + + test.assertTrue(len(threads) == 1, "Expected 1 thread to stop at breakpoint, %d did."%(len(threads))) + thread = threads[0] + return (target, process, thread, breakpoint) def continue_to_breakpoint(process, bkpt): """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None""" process.Continue() if process.GetState() != lldb.eStateStopped: return None else: return get_threads_stopped_at_breakpoint(process, bkpt) def get_caller_symbol(thread): """ Returns the symbol name for the call site of the leaf function. """ depth = thread.GetNumFrames() if depth <= 1: return None caller = thread.GetFrameAtIndex(1).GetSymbol() if caller: return caller.GetName() else: return None def get_function_names(thread): """ Returns a sequence of function names from the stack frames of this thread. """ def GetFuncName(i): return thread.GetFrameAtIndex(i).GetFunctionName() return list(map(GetFuncName, list(range(thread.GetNumFrames())))) def get_symbol_names(thread): """ Returns a sequence of symbols for this thread. """ def GetSymbol(i): return thread.GetFrameAtIndex(i).GetSymbol().GetName() return list(map(GetSymbol, list(range(thread.GetNumFrames())))) def get_pc_addresses(thread): """ Returns a sequence of pc addresses for this thread. """ def GetPCAddress(i): return thread.GetFrameAtIndex(i).GetPCAddress() return list(map(GetPCAddress, list(range(thread.GetNumFrames())))) def get_filenames(thread): """ Returns a sequence of file names from the stack frames of this thread. """ def GetFilename(i): return thread.GetFrameAtIndex( i).GetLineEntry().GetFileSpec().GetFilename() return list(map(GetFilename, list(range(thread.GetNumFrames())))) def get_line_numbers(thread): """ Returns a sequence of line numbers from the stack frames of this thread. """ def GetLineNumber(i): return thread.GetFrameAtIndex(i).GetLineEntry().GetLine() return list(map(GetLineNumber, list(range(thread.GetNumFrames())))) def get_module_names(thread): """ Returns a sequence of module names from the stack frames of this thread. """ def GetModuleName(i): return thread.GetFrameAtIndex( i).GetModule().GetFileSpec().GetFilename() return list(map(GetModuleName, list(range(thread.GetNumFrames())))) def get_stack_frames(thread): """ Returns a sequence of stack frames for this thread. """ def GetStackFrame(i): return thread.GetFrameAtIndex(i) return list(map(GetStackFrame, list(range(thread.GetNumFrames())))) def print_stacktrace(thread, string_buffer=False): """Prints a simple stack trace of this thread.""" output = SixStringIO() if string_buffer else sys.stdout target = thread.GetProcess().GetTarget() depth = thread.GetNumFrames() mods = get_module_names(thread) funcs = get_function_names(thread) symbols = get_symbol_names(thread) files = get_filenames(thread) lines = get_line_numbers(thread) addrs = get_pc_addresses(thread) if thread.GetStopReason() != lldb.eStopReasonInvalid: desc = "stop reason=" + stop_reason_to_str(thread.GetStopReason()) else: desc = "" print( "Stack trace for thread id={0:#x} name={1} queue={2} ".format( thread.GetThreadID(), thread.GetName(), thread.GetQueueName()) + desc, file=output) for i in range(depth): frame = thread.GetFrameAtIndex(i) function = frame.GetFunction() load_addr = addrs[i].GetLoadAddress(target) if not function: file_addr = addrs[i].GetFileAddress() start_addr = frame.GetSymbol().GetStartAddress().GetFileAddress() symbol_offset = file_addr - start_addr print( " frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format( num=i, addr=load_addr, mod=mods[i], symbol=symbols[i], offset=symbol_offset), file=output) else: print( " frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format( num=i, addr=load_addr, mod=mods[i], func='%s [inlined]' % funcs[i] if frame.IsInlined() else funcs[i], file=files[i], line=lines[i], args=get_args_as_string( frame, showFuncName=False) if not frame.IsInlined() else '()'), file=output) if string_buffer: return output.getvalue() def print_stacktraces(process, string_buffer=False): """Prints the stack traces of all the threads.""" output = SixStringIO() if string_buffer else sys.stdout print("Stack traces for " + str(process), file=output) for thread in process: print(print_stacktrace(thread, string_buffer=True), file=output) if string_buffer: return output.getvalue() def expect_state_changes(test, listener, process, states, timeout=5): """Listens for state changed events on the listener and makes sure they match what we expect. Stop-and-restart events (where GetRestartedFromEvent() returns true) are ignored.""" for expected_state in states: def get_next_event(): event = lldb.SBEvent() if not listener.WaitForEventForBroadcasterWithType( timeout, process.GetBroadcaster(), lldb.SBProcess.eBroadcastBitStateChanged, event): test.fail( "Timed out while waiting for a transition to state %s" % lldb.SBDebugger.StateAsCString(expected_state)) return event event = get_next_event() while (lldb.SBProcess.GetStateFromEvent(event) == lldb.eStateStopped and lldb.SBProcess.GetRestartedFromEvent(event)): # Ignore restarted event and the subsequent running event. event = get_next_event() test.assertEqual( lldb.SBProcess.GetStateFromEvent(event), lldb.eStateRunning, "Restarted event followed by a running event") event = get_next_event() test.assertEqual( lldb.SBProcess.GetStateFromEvent(event), expected_state) # =================================== # Utility functions related to Frames # =================================== def get_parent_frame(frame): """ Returns the parent frame of the input frame object; None if not available. """ thread = frame.GetThread() parent_found = False for f in thread: if parent_found: return f if f.GetFrameID() == frame.GetFrameID(): parent_found = True # If we reach here, no parent has been found, return None. return None def get_args_as_string(frame, showFuncName=True): """ Returns the args of the input frame object as a string. """ # arguments => True # locals => False # statics => False # in_scope_only => True vars = frame.GetVariables(True, False, False, True) # type of SBValueList args = [] # list of strings for var in vars: args.append("(%s)%s=%s" % (var.GetTypeName(), var.GetName(), var.GetValue())) if frame.GetFunction(): name = frame.GetFunction().GetName() elif frame.GetSymbol(): name = frame.GetSymbol().GetName() else: name = "" if showFuncName: return "%s(%s)" % (name, ", ".join(args)) else: return "(%s)" % (", ".join(args)) def print_registers(frame, string_buffer=False): """Prints all the register sets of the frame.""" output = SixStringIO() if string_buffer else sys.stdout print("Register sets for " + str(frame), file=output) registerSet = frame.GetRegisters() # Return type of SBValueList. print("Frame registers (size of register set = %d):" % registerSet.GetSize(), file=output) for value in registerSet: #print(value, file=output) print("%s (number of children = %d):" % (value.GetName(), value.GetNumChildren()), file=output) for child in value: print( "Name: %s, Value: %s" % (child.GetName(), child.GetValue()), file=output) if string_buffer: return output.getvalue() def get_registers(frame, kind): """Returns the registers given the frame and the kind of registers desired. Returns None if there's no such kind. """ registerSet = frame.GetRegisters() # Return type of SBValueList. for value in registerSet: if kind.lower() in value.GetName().lower(): return value return None def get_GPRs(frame): """Returns the general purpose registers of the frame as an SBValue. The returned SBValue object is iterable. An example: ... from lldbutil import get_GPRs regs = get_GPRs(frame) for reg in regs: print("%s => %s" % (reg.GetName(), reg.GetValue())) ... """ return get_registers(frame, "general purpose") def get_FPRs(frame): """Returns the floating point registers of the frame as an SBValue. The returned SBValue object is iterable. An example: ... from lldbutil import get_FPRs regs = get_FPRs(frame) for reg in regs: print("%s => %s" % (reg.GetName(), reg.GetValue())) ... """ return get_registers(frame, "floating point") def get_ESRs(frame): """Returns the exception state registers of the frame as an SBValue. The returned SBValue object is iterable. An example: ... from lldbutil import get_ESRs regs = get_ESRs(frame) for reg in regs: print("%s => %s" % (reg.GetName(), reg.GetValue())) ... """ return get_registers(frame, "exception state") # ====================================== # Utility classes/functions for SBValues # ====================================== class BasicFormatter(object): """The basic formatter inspects the value object and prints the value.""" def format(self, value, buffer=None, indent=0): if not buffer: output = SixStringIO() else: output = buffer # If there is a summary, it suffices. val = value.GetSummary() # Otherwise, get the value. if val is None: val = value.GetValue() if val is None and value.GetNumChildren() > 0: val = "%s (location)" % value.GetLocation() print("{indentation}({type}) {name} = {value}".format( indentation=' ' * indent, type=value.GetTypeName(), name=value.GetName(), value=val), file=output) return output.getvalue() class ChildVisitingFormatter(BasicFormatter): """The child visiting formatter prints the value and its immediate children. The constructor takes a keyword arg: indent_child, which defaults to 2. """ def __init__(self, indent_child=2): """Default indentation of 2 SPC's for the children.""" self.cindent = indent_child def format(self, value, buffer=None): if not buffer: output = SixStringIO() else: output = buffer BasicFormatter.format(self, value, buffer=output) for child in value: BasicFormatter.format( self, child, buffer=output, indent=self.cindent) return output.getvalue() class RecursiveDecentFormatter(BasicFormatter): """The recursive decent formatter prints the value and the decendents. The constructor takes two keyword args: indent_level, which defaults to 0, and indent_child, which defaults to 2. The current indentation level is determined by indent_level, while the immediate children has an additional indentation by inden_child. """ def __init__(self, indent_level=0, indent_child=2): self.lindent = indent_level self.cindent = indent_child def format(self, value, buffer=None): if not buffer: output = SixStringIO() else: output = buffer BasicFormatter.format(self, value, buffer=output, indent=self.lindent) new_indent = self.lindent + self.cindent for child in value: if child.GetSummary() is not None: BasicFormatter.format( self, child, buffer=output, indent=new_indent) else: if child.GetNumChildren() > 0: rdf = RecursiveDecentFormatter(indent_level=new_indent) rdf.format(child, buffer=output) else: BasicFormatter.format( self, child, buffer=output, indent=new_indent) return output.getvalue() # =========================================================== # Utility functions for path manipulation on remote platforms # =========================================================== def join_remote_paths(*paths): # TODO: update with actual platform name for remote windows once it exists if lldb.remote_platform.GetName() == 'remote-windows': return os.path.join(*paths).replace(os.path.sep, '\\') return os.path.join(*paths).replace(os.path.sep, '/') def append_to_process_working_directory(*paths): remote = lldb.remote_platform if remote: return join_remote_paths(remote.GetWorkingDirectory(), *paths) return os.path.join(os.getcwd(), *paths) # ================================================== # Utility functions to get the correct signal number # ================================================== import signal def get_signal_number(signal_name): platform = lldb.remote_platform if platform and platform.IsValid(): signals = platform.GetUnixSignals() if signals.IsValid(): signal_number = signals.GetSignalNumberFromName(signal_name) if signal_number > 0: return signal_number # No remote platform; fall back to using local python signals. return getattr(signal, signal_name) class PrintableRegex(object): def __init__(self, text): self.regex = re.compile(text) self.text = text def match(self, str): return self.regex.match(str) def __str__(self): return "%s" % (self.text) def __repr__(self): return "re.compile(%s) -> %s" % (self.text, self.regex) def skip_if_callable(test, mycallable, reason): if six.callable(mycallable): if mycallable(test): test.skipTest(reason) return True return False def skip_if_library_missing(test, target, library): def find_library(target, library): for module in target.modules: filename = module.file.GetFilename() if isinstance(library, str): if library == filename: return False elif hasattr(library, 'match'): if library.match(filename): return False return True def find_library_callable(test): return find_library(target, library) return skip_if_callable( test, find_library_callable, "could not find library matching '%s' in target %s" % (library, target)) def wait_for_file_on_target(testcase, file_path, max_attempts=6): for i in range(max_attempts): err, retcode, msg = testcase.run_platform_command("ls %s" % file_path) if err.Success() and retcode == 0: break if i < max_attempts: # Exponential backoff! import time time.sleep(pow(2, i) * 0.25) else: testcase.fail( "File %s not found even after %d attempts." % (file_path, max_attempts)) err, retcode, data = testcase.run_platform_command("cat %s" % (file_path)) testcase.assertTrue( err.Success() and retcode == 0, "Failed to read file %s: %s, retcode: %d" % (file_path, err.GetCString(), retcode)) return data Index: vendor/lldb/dist/packages/Python/lldbsuite/test/make/Android.rules =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/make/Android.rules (revision 320966) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/make/Android.rules (revision 320967) @@ -1,96 +1,92 @@ NDK_ROOT := $(shell dirname $(CC))/../../../../.. ifeq "$(findstring 64, $(ARCH))" "64" # lowest 64-bit API level API_LEVEL := 21 else ifeq "$(ARCH)" "i386" # clone(2) declaration is present only since this api level API_LEVEL := 17 else # lowest supported 32-bit API level API_LEVEL := 9 endif ifeq "$(ARCH)" "arm" SYSROOT_ARCH := arm STL_ARCH := armeabi-v7a TRIPLE := armv7-none-linux-androideabi ARCH_CFLAGS += -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -marm else ifeq "$(ARCH)" "aarch64" SYSROOT_ARCH := arm64 TRIPLE := aarch64-none-linux-android STL_ARCH := arm64-v8a else ifeq "$(ARCH)" "i386" SYSROOT_ARCH := x86 STL_ARCH := x86 TRIPLE := i686-none-linux-android else ifeq "$(ARCH)" "mips64r6" SYSROOT_ARCH := mips64 STL_ARCH := mips64 TRIPLE := mips64el-none-linux-android else ifeq "$(ARCH)" "mips32" SYSROOT_ARCH := mips STL_ARCH := mips TRIPLE := mipsel-none-linux-android else SYSROOT_ARCH := $(ARCH) STL_ARCH := $(ARCH) TRIPLE := $(ARCH)-none-linux-android endif ifeq "$(findstring 86,$(ARCH))" "86" TOOLCHAIN_DIR := $(STL_ARCH)-4.9 else ifeq "$(ARCH)" "arm" TOOLCHAIN_DIR := arm-linux-androideabi-4.9 else TOOLCHAIN_DIR := $(subst -none,,$(TRIPLE))-4.9 endif ifeq "$(ARCH)" "arm" TOOL_PREFIX := arm-linux-androideabi else TOOL_PREFIX := $(subst -none,,$(TRIPLE)) endif ifeq "$(HOST_OS)" "Linux" HOST_TAG := linux-x86_64 else ifeq "$(HOST_OS)" "Darwin" HOST_TAG := darwin-x86_64 else HOST_TAG := windows-x86_64 endif GCC_TOOLCHAIN = $(NDK_ROOT)/toolchains/$(TOOLCHAIN_DIR)/prebuilt/$(HOST_TAG) OBJCOPY ?= $(GCC_TOOLCHAIN)/bin/$(TOOL_PREFIX)-objcopy ARCHIVER ?= $(GCC_TOOLCHAIN)/bin/$(TOOL_PREFIX)-ar ifeq "$(findstring clang,$(CC))" "clang" ARCH_CFLAGS += -target $(TRIPLE) -gcc-toolchain $(GCC_TOOLCHAIN) ARCH_LDFLAGS += -target $(TRIPLE) -gcc-toolchain $(GCC_TOOLCHAIN) endif ARCH_CFLAGS += --sysroot=$(NDK_ROOT)/platforms/android-$(API_LEVEL)/arch-$(SYSROOT_ARCH) ARCH_LDFLAGS += --sysroot=$(NDK_ROOT)/platforms/android-$(API_LEVEL)/arch-$(SYSROOT_ARCH) -lm ifeq (1,$(USE_LIBCPP)) ARCH_CFLAGS += \ -isystem $(NDK_ROOT)/sources/cxx-stl/llvm-libc++/include \ -isystem $(NDK_ROOT)/sources/android/support/include \ -isystem $(NDK_ROOT)/sources/cxx-stl/llvm-libc++abi/include ARCH_LDFLAGS += \ -L$(NDK_ROOT)/sources/cxx-stl/llvm-libc++/libs/$(STL_ARCH) \ $(NDK_ROOT)/sources/cxx-stl/llvm-libc++/libs/$(STL_ARCH)/libc++.a else ARCH_CFLAGS += \ -isystem $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.9/include \ -isystem $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.9/libs/$(STL_ARCH)/include \ -isystem $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.9/include/backward ARCH_LDFLAGS += $(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.9/libs/$(STL_ARCH)/libgnustl_static.a endif - -ifeq "$(ARCH)" "i386" - ARCH_CFLAGS += -mstackrealign -endif Index: vendor/lldb/dist/packages/Python/lldbsuite/test/sample_test/TestSampleTest.py =================================================================== --- vendor/lldb/dist/packages/Python/lldbsuite/test/sample_test/TestSampleTest.py (revision 320966) +++ vendor/lldb/dist/packages/Python/lldbsuite/test/sample_test/TestSampleTest.py (revision 320967) @@ -1,74 +1,50 @@ """ Describe the purpose of the test class here. """ from __future__ import print_function import os import time import re import lldb import lldbsuite.test.lldbutil as lldbutil from lldbsuite.test.lldbtest import * class RenameThisSampleTestTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) # If your test case doesn't stress debug info, the # set this to true. That way it won't be run once for # each debug info format. NO_DEBUG_INFO_TESTCASE = True def test_sample_rename_this(self): """There can be many tests in a test case - describe this test here.""" self.build() + self.main_source_file = lldb.SBFileSpec("main.c") self.sample_test() def setUp(self): # Call super's setUp(). TestBase.setUp(self) def sample_test(self): """You might use the test implementation in several ways, say so here.""" - exe = os.path.join(os.getcwd(), "a.out") - # Create a target by the debugger. - target = self.dbg.CreateTarget(exe) - self.assertTrue(target, VALID_TARGET) + # This function starts a process, "a.out" by default, sets a source + # breakpoint, runs to it, and returns the thread, process & target. + # It optionally takes an SBLaunchOption argument if you want to pass + # arguments or environment variables. + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + "Set a breakpoint here", self.main_source_file) - # Now create a breakpoint in main.c at the source matching - # "Set a breakpoint here" - breakpoint = target.BreakpointCreateBySourceRegex( - "Set a breakpoint here", lldb.SBFileSpec("main.c")) - self.assertTrue(breakpoint and - breakpoint.GetNumLocations() >= 1, - VALID_BREAKPOINT) - - error = lldb.SBError() - # This is the launch info. If you want to launch with arguments or - # environment variables, add them using SetArguments or - # SetEnvironmentEntries - - launch_info = lldb.SBLaunchInfo(None) - process = target.Launch(launch_info, error) - self.assertTrue(process, PROCESS_IS_VALID) - - # Did we hit our breakpoint? - from lldbsuite.test.lldbutil import get_threads_stopped_at_breakpoint - threads = get_threads_stopped_at_breakpoint(process, breakpoint) - self.assertTrue( - len(threads) == 1, - "There should be a thread stopped at our breakpoint") - - # The hit count for the breakpoint should be 1. - self.assertTrue(breakpoint.GetHitCount() == 1) - - frame = threads[0].GetFrameAtIndex(0) + frame = thread.GetFrameAtIndex(0) test_var = frame.FindVariable("test_var") self.assertTrue(test_var.GetError().Success(), "Failed to fetch test_var") test_value = test_var.GetValueAsUnsigned() self.assertEqual(test_value, 10, "Got the right value for test_var") Index: vendor/lldb/dist/source/Commands/CommandObjectThread.cpp =================================================================== --- vendor/lldb/dist/source/Commands/CommandObjectThread.cpp (revision 320966) +++ vendor/lldb/dist/source/Commands/CommandObjectThread.cpp (revision 320967) @@ -1,2097 +1,2097 @@ //===-- CommandObjectThread.cpp ---------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "CommandObjectThread.h" // C Includes // C++ Includes // Other libraries and framework includes // Project includes #include "lldb/Core/SourceManager.h" #include "lldb/Core/State.h" #include "lldb/Core/ValueObject.h" #include "lldb/Host/Host.h" #include "lldb/Host/OptionParser.h" #include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/Options.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/LineEntry.h" #include "lldb/Symbol/LineTable.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/SystemRuntime.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" #include "lldb/Target/ThreadPlanStepInRange.h" #include "lldb/Target/ThreadPlanStepInstruction.h" #include "lldb/Target/ThreadPlanStepOut.h" #include "lldb/Target/ThreadPlanStepRange.h" #include "lldb/lldb-private.h" using namespace lldb; using namespace lldb_private; //------------------------------------------------------------------------- // CommandObjectIterateOverThreads //------------------------------------------------------------------------- class CommandObjectIterateOverThreads : public CommandObjectParsed { class UniqueStack { public: UniqueStack(std::stack stack_frames, uint32_t thread_index_id) : m_stack_frames(stack_frames) { m_thread_index_ids.push_back(thread_index_id); } void AddThread(uint32_t thread_index_id) const { m_thread_index_ids.push_back(thread_index_id); } const std::vector &GetUniqueThreadIndexIDs() const { return m_thread_index_ids; } lldb::tid_t GetRepresentativeThread() const { return m_thread_index_ids.front(); } friend bool inline operator<(const UniqueStack &lhs, const UniqueStack &rhs) { return lhs.m_stack_frames < rhs.m_stack_frames; } protected: // Mark the thread index as mutable, as we don't care about it from a const // perspective, we only care about m_stack_frames so we keep our std::set // sorted. mutable std::vector m_thread_index_ids; std::stack m_stack_frames; }; public: CommandObjectIterateOverThreads(CommandInterpreter &interpreter, const char *name, const char *help, const char *syntax, uint32_t flags) : CommandObjectParsed(interpreter, name, help, syntax, flags) {} ~CommandObjectIterateOverThreads() override = default; bool DoExecute(Args &command, CommandReturnObject &result) override { result.SetStatus(m_success_return); bool all_threads = false; if (command.GetArgumentCount() == 0) { Thread *thread = m_exe_ctx.GetThreadPtr(); if (!HandleOneThread(thread->GetID(), result)) return false; return result.Succeeded(); } else if (command.GetArgumentCount() == 1) { all_threads = ::strcmp(command.GetArgumentAtIndex(0), "all") == 0; m_unique_stacks = ::strcmp(command.GetArgumentAtIndex(0), "unique") == 0; } // Use tids instead of ThreadSPs to prevent deadlocking problems which // result from JIT-ing // code while iterating over the (locked) ThreadSP list. std::vector tids; if (all_threads || m_unique_stacks) { Process *process = m_exe_ctx.GetProcessPtr(); for (ThreadSP thread_sp : process->Threads()) tids.push_back(thread_sp->GetID()); } else { const size_t num_args = command.GetArgumentCount(); Process *process = m_exe_ctx.GetProcessPtr(); std::lock_guard guard( process->GetThreadList().GetMutex()); for (size_t i = 0; i < num_args; i++) { bool success; uint32_t thread_idx = StringConvert::ToUInt32( command.GetArgumentAtIndex(i), 0, 0, &success); if (!success) { result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n", command.GetArgumentAtIndex(i)); result.SetStatus(eReturnStatusFailed); return false; } ThreadSP thread = process->GetThreadList().FindThreadByIndexID(thread_idx); if (!thread) { result.AppendErrorWithFormat("no thread with index: \"%s\"\n", command.GetArgumentAtIndex(i)); result.SetStatus(eReturnStatusFailed); return false; } tids.push_back(thread->GetID()); } } if (m_unique_stacks) { // Iterate over threads, finding unique stack buckets. std::set unique_stacks; for (const lldb::tid_t &tid : tids) { if (!BucketThread(tid, unique_stacks, result)) { return false; } } // Write the thread id's and unique call stacks to the output stream Stream &strm = result.GetOutputStream(); Process *process = m_exe_ctx.GetProcessPtr(); for (const UniqueStack &stack : unique_stacks) { // List the common thread ID's const std::vector &thread_index_ids = stack.GetUniqueThreadIndexIDs(); - strm.Printf("%lu thread(s) ", thread_index_ids.size()); + strm.Format("{0} thread(s) ", thread_index_ids.size()); for (const uint32_t &thread_index_id : thread_index_ids) { - strm.Printf("#%u ", thread_index_id); + strm.Format("#{0} ", thread_index_id); } strm.EOL(); // List the shared call stack for this set of threads uint32_t representative_thread_id = stack.GetRepresentativeThread(); ThreadSP thread = process->GetThreadList().FindThreadByIndexID( representative_thread_id); if (!HandleOneThread(thread->GetID(), result)) { return false; } } } else { uint32_t idx = 0; for (const lldb::tid_t &tid : tids) { if (idx != 0 && m_add_return) result.AppendMessage(""); if (!HandleOneThread(tid, result)) return false; ++idx; } } return result.Succeeded(); } protected: // Override this to do whatever you need to do for one thread. // // If you return false, the iteration will stop, otherwise it will proceed. // The result is set to m_success_return (defaults to // eReturnStatusSuccessFinishResult) before the iteration, // so you only need to set the return status in HandleOneThread if you want to // indicate an error. // If m_add_return is true, a blank line will be inserted between each of the // listings (except the last one.) virtual bool HandleOneThread(lldb::tid_t, CommandReturnObject &result) = 0; bool BucketThread(lldb::tid_t tid, std::set &unique_stacks, CommandReturnObject &result) { // Grab the corresponding thread for the given thread id. Process *process = m_exe_ctx.GetProcessPtr(); Thread *thread = process->GetThreadList().FindThreadByID(tid).get(); if (thread == nullptr) { - result.AppendErrorWithFormat("Failed to process thread# %llu.\n", tid); + result.AppendErrorWithFormatv("Failed to process thread #{0}.\n", tid); result.SetStatus(eReturnStatusFailed); return false; } // Collect the each frame's address for this call-stack std::stack stack_frames; const uint32_t frame_count = thread->GetStackFrameCount(); for (uint32_t frame_index = 0; frame_index < frame_count; frame_index++) { const lldb::StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_index); const lldb::addr_t pc = frame_sp->GetStackID().GetPC(); stack_frames.push(pc); } uint32_t thread_index_id = thread->GetIndexID(); UniqueStack new_unique_stack(stack_frames, thread_index_id); // Try to match the threads stack to and existing entry. std::set::iterator matching_stack = unique_stacks.find(new_unique_stack); if (matching_stack != unique_stacks.end()) { matching_stack->AddThread(thread_index_id); } else { unique_stacks.insert(new_unique_stack); } return true; } ReturnStatus m_success_return = eReturnStatusSuccessFinishResult; bool m_unique_stacks = false; bool m_add_return = true; }; //------------------------------------------------------------------------- // CommandObjectThreadBacktrace //------------------------------------------------------------------------- static OptionDefinition g_thread_backtrace_options[] = { // clang-format off { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "How many frames to display (-1 for all)" }, { LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace" }, { LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Show the extended backtrace, if available" } // clang-format on }; class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads { public: class CommandOptions : public Options { public: CommandOptions() : Options() { // Keep default values of all options in one place: OptionParsingStarting // () OptionParsingStarting(nullptr); } ~CommandOptions() override = default; Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override { Status error; const int short_option = m_getopt_table[option_idx].val; switch (short_option) { case 'c': { int32_t input_count = 0; if (option_arg.getAsInteger(0, m_count)) { m_count = UINT32_MAX; error.SetErrorStringWithFormat( "invalid integer value for option '%c'", short_option); } else if (input_count < 0) m_count = UINT32_MAX; } break; case 's': if (option_arg.getAsInteger(0, m_start)) error.SetErrorStringWithFormat( "invalid integer value for option '%c'", short_option); break; case 'e': { bool success; m_extended_backtrace = Args::StringToBoolean(option_arg, false, &success); if (!success) error.SetErrorStringWithFormat( "invalid boolean value for option '%c'", short_option); } break; default: error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); break; } return error; } void OptionParsingStarting(ExecutionContext *execution_context) override { m_count = UINT32_MAX; m_start = 0; m_extended_backtrace = false; } llvm::ArrayRef GetDefinitions() override { return llvm::makeArrayRef(g_thread_backtrace_options); } // Instance variables to hold the values for command options. uint32_t m_count; uint32_t m_start; bool m_extended_backtrace; }; CommandObjectThreadBacktrace(CommandInterpreter &interpreter) : CommandObjectIterateOverThreads( interpreter, "thread backtrace", "Show thread call stacks. Defaults to the current thread, thread " "indexes can be specified as arguments.\n" "Use the thread-index \"all\" to see all threads.\n" "Use the thread-index \"unique\" to see threads grouped by unique " "call stacks.", nullptr, eCommandRequiresProcess | eCommandRequiresThread | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), m_options() {} ~CommandObjectThreadBacktrace() override = default; Options *GetOptions() override { return &m_options; } protected: void DoExtendedBacktrace(Thread *thread, CommandReturnObject &result) { SystemRuntime *runtime = thread->GetProcess()->GetSystemRuntime(); if (runtime) { Stream &strm = result.GetOutputStream(); const std::vector &types = runtime->GetExtendedBacktraceTypes(); for (auto type : types) { ThreadSP ext_thread_sp = runtime->GetExtendedBacktraceThread( thread->shared_from_this(), type); if (ext_thread_sp && ext_thread_sp->IsValid()) { const uint32_t num_frames_with_source = 0; const bool stop_format = false; if (ext_thread_sp->GetStatus(strm, m_options.m_start, m_options.m_count, num_frames_with_source, stop_format)) { DoExtendedBacktrace(ext_thread_sp.get(), result); } } } } } bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { ThreadSP thread_sp = m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); if (!thread_sp) { result.AppendErrorWithFormat( "thread disappeared while computing backtraces: 0x%" PRIx64 "\n", tid); result.SetStatus(eReturnStatusFailed); return false; } Thread *thread = thread_sp.get(); Stream &strm = result.GetOutputStream(); // Only dump stack info if we processing unique stacks. const bool only_stacks = m_unique_stacks; // Don't show source context when doing backtraces. const uint32_t num_frames_with_source = 0; const bool stop_format = true; if (!thread->GetStatus(strm, m_options.m_start, m_options.m_count, num_frames_with_source, stop_format, only_stacks)) { result.AppendErrorWithFormat( "error displaying backtrace for thread: \"0x%4.4x\"\n", thread->GetIndexID()); result.SetStatus(eReturnStatusFailed); return false; } if (m_options.m_extended_backtrace) { DoExtendedBacktrace(thread, result); } return true; } CommandOptions m_options; }; enum StepScope { eStepScopeSource, eStepScopeInstruction }; static OptionEnumValueElement g_tri_running_mode[] = { {eOnlyThisThread, "this-thread", "Run only this thread"}, {eAllThreads, "all-threads", "Run all threads"}, {eOnlyDuringStepping, "while-stepping", "Run only this thread while stepping"}, {0, nullptr, nullptr}}; static OptionEnumValueElement g_duo_running_mode[] = { {eOnlyThisThread, "this-thread", "Run only this thread"}, {eAllThreads, "all-threads", "Run all threads"}, {0, nullptr, nullptr}}; static OptionDefinition g_thread_step_scope_options[] = { // clang-format off { LLDB_OPT_SET_1, false, "step-in-avoids-no-debug", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "A boolean value that sets whether stepping into functions will step over functions with no debug information." }, { LLDB_OPT_SET_1, false, "step-out-avoids-no-debug", 'A', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "A boolean value, if true stepping out of functions will continue to step out till it hits a function with debug information." }, { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 1, eArgTypeCount, "How many times to perform the stepping operation - currently only supported for step-inst and next-inst." }, { LLDB_OPT_SET_1, false, "end-linenumber", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 1, eArgTypeLineNum, "The line at which to stop stepping - defaults to the next line and only supported for step-in and step-over. You can also pass the string 'block' to step to the end of the current block. This is particularly useful in conjunction with --step-target to step through a complex calling sequence." }, { LLDB_OPT_SET_1, false, "run-mode", 'm', OptionParser::eRequiredArgument, nullptr, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread." }, { LLDB_OPT_SET_1, false, "step-over-regexp", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "A regular expression that defines function names to not to stop at when stepping in." }, { LLDB_OPT_SET_1, false, "step-in-target", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into." }, { LLDB_OPT_SET_2, false, "python-class", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "The name of the class that will manage this step - only supported for Scripted Step." } // clang-format on }; class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed { public: class CommandOptions : public Options { public: CommandOptions() : Options() { // Keep default values of all options in one place: OptionParsingStarting // () OptionParsingStarting(nullptr); } ~CommandOptions() override = default; Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override { Status error; const int short_option = m_getopt_table[option_idx].val; switch (short_option) { case 'a': { bool success; bool avoid_no_debug = Args::StringToBoolean(option_arg, true, &success); if (!success) error.SetErrorStringWithFormat( "invalid boolean value for option '%c'", short_option); else { m_step_in_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; } } break; case 'A': { bool success; bool avoid_no_debug = Args::StringToBoolean(option_arg, true, &success); if (!success) error.SetErrorStringWithFormat( "invalid boolean value for option '%c'", short_option); else { m_step_out_avoid_no_debug = avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; } } break; case 'c': if (option_arg.getAsInteger(0, m_step_count)) error.SetErrorStringWithFormat("invalid step count '%s'", option_arg.str().c_str()); break; case 'C': m_class_name.clear(); m_class_name.assign(option_arg); break; case 'm': { OptionEnumValueElement *enum_values = GetDefinitions()[option_idx].enum_values; m_run_mode = (lldb::RunMode)Args::StringToOptionEnum( option_arg, enum_values, eOnlyDuringStepping, error); } break; case 'e': if (option_arg == "block") { m_end_line_is_block_end = 1; break; } if (option_arg.getAsInteger(0, m_end_line)) error.SetErrorStringWithFormat("invalid end line number '%s'", option_arg.str().c_str()); break; case 'r': m_avoid_regexp.clear(); m_avoid_regexp.assign(option_arg); break; case 't': m_step_in_target.clear(); m_step_in_target.assign(option_arg); break; default: error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); break; } return error; } void OptionParsingStarting(ExecutionContext *execution_context) override { m_step_in_avoid_no_debug = eLazyBoolCalculate; m_step_out_avoid_no_debug = eLazyBoolCalculate; m_run_mode = eOnlyDuringStepping; // Check if we are in Non-Stop mode TargetSP target_sp = execution_context ? execution_context->GetTargetSP() : TargetSP(); if (target_sp && target_sp->GetNonStopModeEnabled()) m_run_mode = eOnlyThisThread; m_avoid_regexp.clear(); m_step_in_target.clear(); m_class_name.clear(); m_step_count = 1; m_end_line = LLDB_INVALID_LINE_NUMBER; m_end_line_is_block_end = false; } llvm::ArrayRef GetDefinitions() override { return llvm::makeArrayRef(g_thread_step_scope_options); } // Instance variables to hold the values for command options. LazyBool m_step_in_avoid_no_debug; LazyBool m_step_out_avoid_no_debug; RunMode m_run_mode; std::string m_avoid_regexp; std::string m_step_in_target; std::string m_class_name; uint32_t m_step_count; uint32_t m_end_line; bool m_end_line_is_block_end; }; CommandObjectThreadStepWithTypeAndScope(CommandInterpreter &interpreter, const char *name, const char *help, const char *syntax, StepType step_type, StepScope step_scope) : CommandObjectParsed(interpreter, name, help, syntax, eCommandRequiresProcess | eCommandRequiresThread | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), m_step_type(step_type), m_step_scope(step_scope), m_options() { CommandArgumentEntry arg; CommandArgumentData thread_id_arg; // Define the first (and only) variant of this arg. thread_id_arg.arg_type = eArgTypeThreadID; thread_id_arg.arg_repetition = eArgRepeatOptional; // There is only one variant this argument could be; put it into the // argument entry. arg.push_back(thread_id_arg); // Push the data for the first argument into the m_arguments vector. m_arguments.push_back(arg); } ~CommandObjectThreadStepWithTypeAndScope() override = default; Options *GetOptions() override { return &m_options; } protected: bool DoExecute(Args &command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); bool synchronous_execution = m_interpreter.GetSynchronous(); const uint32_t num_threads = process->GetThreadList().GetSize(); Thread *thread = nullptr; if (command.GetArgumentCount() == 0) { thread = GetDefaultThread(); if (thread == nullptr) { result.AppendError("no selected thread in process"); result.SetStatus(eReturnStatusFailed); return false; } } else { const char *thread_idx_cstr = command.GetArgumentAtIndex(0); uint32_t step_thread_idx = StringConvert::ToUInt32(thread_idx_cstr, LLDB_INVALID_INDEX32); if (step_thread_idx == LLDB_INVALID_INDEX32) { result.AppendErrorWithFormat("invalid thread index '%s'.\n", thread_idx_cstr); result.SetStatus(eReturnStatusFailed); return false; } thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get(); if (thread == nullptr) { result.AppendErrorWithFormat( "Thread index %u is out of range (valid values are 0 - %u).\n", step_thread_idx, num_threads); result.SetStatus(eReturnStatusFailed); return false; } } if (m_step_type == eStepTypeScripted) { if (m_options.m_class_name.empty()) { result.AppendErrorWithFormat("empty class name for scripted step."); result.SetStatus(eReturnStatusFailed); return false; } else if (!m_interpreter.GetScriptInterpreter()->CheckObjectExists( m_options.m_class_name.c_str())) { result.AppendErrorWithFormat( "class for scripted step: \"%s\" does not exist.", m_options.m_class_name.c_str()); result.SetStatus(eReturnStatusFailed); return false; } } if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER && m_step_type != eStepTypeInto) { result.AppendErrorWithFormat( "end line option is only valid for step into"); result.SetStatus(eReturnStatusFailed); return false; } const bool abort_other_plans = false; const lldb::RunMode stop_other_threads = m_options.m_run_mode; // This is a bit unfortunate, but not all the commands in this command // object support // only while stepping, so I use the bool for them. bool bool_stop_other_threads; if (m_options.m_run_mode == eAllThreads) bool_stop_other_threads = false; else if (m_options.m_run_mode == eOnlyDuringStepping) bool_stop_other_threads = (m_step_type != eStepTypeOut && m_step_type != eStepTypeScripted); else bool_stop_other_threads = true; ThreadPlanSP new_plan_sp; if (m_step_type == eStepTypeInto) { StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); assert(frame != nullptr); if (frame->HasDebugInformation()) { AddressRange range; SymbolContext sc = frame->GetSymbolContext(eSymbolContextEverything); if (m_options.m_end_line != LLDB_INVALID_LINE_NUMBER) { Status error; if (!sc.GetAddressRangeFromHereToEndLine(m_options.m_end_line, range, error)) { result.AppendErrorWithFormat("invalid end-line option: %s.", error.AsCString()); result.SetStatus(eReturnStatusFailed); return false; } } else if (m_options.m_end_line_is_block_end) { Status error; Block *block = frame->GetSymbolContext(eSymbolContextBlock).block; if (!block) { result.AppendErrorWithFormat("Could not find the current block."); result.SetStatus(eReturnStatusFailed); return false; } AddressRange block_range; Address pc_address = frame->GetFrameCodeAddress(); block->GetRangeContainingAddress(pc_address, block_range); if (!block_range.GetBaseAddress().IsValid()) { result.AppendErrorWithFormat( "Could not find the current block address."); result.SetStatus(eReturnStatusFailed); return false; } lldb::addr_t pc_offset_in_block = pc_address.GetFileAddress() - block_range.GetBaseAddress().GetFileAddress(); lldb::addr_t range_length = block_range.GetByteSize() - pc_offset_in_block; range = AddressRange(pc_address, range_length); } else { range = sc.line_entry.range; } new_plan_sp = thread->QueueThreadPlanForStepInRange( abort_other_plans, range, frame->GetSymbolContext(eSymbolContextEverything), m_options.m_step_in_target.c_str(), stop_other_threads, m_options.m_step_in_avoid_no_debug, m_options.m_step_out_avoid_no_debug); if (new_plan_sp && !m_options.m_avoid_regexp.empty()) { ThreadPlanStepInRange *step_in_range_plan = static_cast(new_plan_sp.get()); step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str()); } } else new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( false, abort_other_plans, bool_stop_other_threads); } else if (m_step_type == eStepTypeOver) { StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); if (frame->HasDebugInformation()) new_plan_sp = thread->QueueThreadPlanForStepOverRange( abort_other_plans, frame->GetSymbolContext(eSymbolContextEverything).line_entry, frame->GetSymbolContext(eSymbolContextEverything), stop_other_threads, m_options.m_step_out_avoid_no_debug); else new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( true, abort_other_plans, bool_stop_other_threads); } else if (m_step_type == eStepTypeTrace) { new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( false, abort_other_plans, bool_stop_other_threads); } else if (m_step_type == eStepTypeTraceOver) { new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( true, abort_other_plans, bool_stop_other_threads); } else if (m_step_type == eStepTypeOut) { new_plan_sp = thread->QueueThreadPlanForStepOut( abort_other_plans, nullptr, false, bool_stop_other_threads, eVoteYes, eVoteNoOpinion, thread->GetSelectedFrameIndex(), m_options.m_step_out_avoid_no_debug); } else if (m_step_type == eStepTypeScripted) { new_plan_sp = thread->QueueThreadPlanForStepScripted( abort_other_plans, m_options.m_class_name.c_str(), bool_stop_other_threads); } else { result.AppendError("step type is not supported"); result.SetStatus(eReturnStatusFailed); return false; } // If we got a new plan, then set it to be a master plan (User level Plans // should be master plans // so that they can be interruptible). Then resume the process. if (new_plan_sp) { new_plan_sp->SetIsMasterPlan(true); new_plan_sp->SetOkayToDiscard(false); if (m_options.m_step_count > 1) { if (!new_plan_sp->SetIterationCount(m_options.m_step_count)) { result.AppendWarning( "step operation does not support iteration count."); } } process->GetThreadList().SetSelectedThreadByID(thread->GetID()); const uint32_t iohandler_id = process->GetIOHandlerID(); StreamString stream; Status error; if (synchronous_execution) error = process->ResumeSynchronous(&stream); else error = process->Resume(); // There is a race condition where this thread will return up the call // stack to the main command handler // and show an (lldb) prompt before HandlePrivateEvent (from // PrivateStateThread) has // a chance to call PushProcessIOHandler(). process->SyncIOHandler(iohandler_id, 2000); if (synchronous_execution) { // If any state changed events had anything to say, add that to the // result if (stream.GetSize() > 0) result.AppendMessage(stream.GetString()); process->GetThreadList().SetSelectedThreadByID(thread->GetID()); result.SetDidChangeProcessState(true); result.SetStatus(eReturnStatusSuccessFinishNoResult); } else { result.SetStatus(eReturnStatusSuccessContinuingNoResult); } } else { result.AppendError("Couldn't find thread plan to implement step type."); result.SetStatus(eReturnStatusFailed); } return result.Succeeded(); } protected: StepType m_step_type; StepScope m_step_scope; CommandOptions m_options; }; //------------------------------------------------------------------------- // CommandObjectThreadContinue //------------------------------------------------------------------------- class CommandObjectThreadContinue : public CommandObjectParsed { public: CommandObjectThreadContinue(CommandInterpreter &interpreter) : CommandObjectParsed( interpreter, "thread continue", "Continue execution of the current target process. One " "or more threads may be specified, by default all " "threads continue.", nullptr, eCommandRequiresThread | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) { CommandArgumentEntry arg; CommandArgumentData thread_idx_arg; // Define the first (and only) variant of this arg. thread_idx_arg.arg_type = eArgTypeThreadIndex; thread_idx_arg.arg_repetition = eArgRepeatPlus; // There is only one variant this argument could be; put it into the // argument entry. arg.push_back(thread_idx_arg); // Push the data for the first argument into the m_arguments vector. m_arguments.push_back(arg); } ~CommandObjectThreadContinue() override = default; bool DoExecute(Args &command, CommandReturnObject &result) override { bool synchronous_execution = m_interpreter.GetSynchronous(); if (!m_interpreter.GetDebugger().GetSelectedTarget()) { result.AppendError("invalid target, create a debug target using the " "'target create' command"); result.SetStatus(eReturnStatusFailed); return false; } Process *process = m_exe_ctx.GetProcessPtr(); if (process == nullptr) { result.AppendError("no process exists. Cannot continue"); result.SetStatus(eReturnStatusFailed); return false; } StateType state = process->GetState(); if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended)) { const size_t argc = command.GetArgumentCount(); if (argc > 0) { // These two lines appear at the beginning of both blocks in // this if..else, but that is because we need to release the // lock before calling process->Resume below. std::lock_guard guard( process->GetThreadList().GetMutex()); const uint32_t num_threads = process->GetThreadList().GetSize(); std::vector resume_threads; for (auto &entry : command.entries()) { uint32_t thread_idx; if (entry.ref.getAsInteger(0, thread_idx)) { result.AppendErrorWithFormat( "invalid thread index argument: \"%s\".\n", entry.c_str()); result.SetStatus(eReturnStatusFailed); return false; } Thread *thread = process->GetThreadList().FindThreadByIndexID(thread_idx).get(); if (thread) { resume_threads.push_back(thread); } else { result.AppendErrorWithFormat("invalid thread index %u.\n", thread_idx); result.SetStatus(eReturnStatusFailed); return false; } } if (resume_threads.empty()) { result.AppendError("no valid thread indexes were specified"); result.SetStatus(eReturnStatusFailed); return false; } else { if (resume_threads.size() == 1) result.AppendMessageWithFormat("Resuming thread: "); else result.AppendMessageWithFormat("Resuming threads: "); for (uint32_t idx = 0; idx < num_threads; ++idx) { Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); std::vector::iterator this_thread_pos = find(resume_threads.begin(), resume_threads.end(), thread); if (this_thread_pos != resume_threads.end()) { resume_threads.erase(this_thread_pos); if (!resume_threads.empty()) result.AppendMessageWithFormat("%u, ", thread->GetIndexID()); else result.AppendMessageWithFormat("%u ", thread->GetIndexID()); const bool override_suspend = true; thread->SetResumeState(eStateRunning, override_suspend); } else { thread->SetResumeState(eStateSuspended); } } result.AppendMessageWithFormat("in process %" PRIu64 "\n", process->GetID()); } } else { // These two lines appear at the beginning of both blocks in // this if..else, but that is because we need to release the // lock before calling process->Resume below. std::lock_guard guard( process->GetThreadList().GetMutex()); const uint32_t num_threads = process->GetThreadList().GetSize(); Thread *current_thread = GetDefaultThread(); if (current_thread == nullptr) { result.AppendError("the process doesn't have a current thread"); result.SetStatus(eReturnStatusFailed); return false; } // Set the actions that the threads should each take when resuming for (uint32_t idx = 0; idx < num_threads; ++idx) { Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); if (thread == current_thread) { result.AppendMessageWithFormat("Resuming thread 0x%4.4" PRIx64 " in process %" PRIu64 "\n", thread->GetID(), process->GetID()); const bool override_suspend = true; thread->SetResumeState(eStateRunning, override_suspend); } else { thread->SetResumeState(eStateSuspended); } } } StreamString stream; Status error; if (synchronous_execution) error = process->ResumeSynchronous(&stream); else error = process->Resume(); // We should not be holding the thread list lock when we do this. if (error.Success()) { result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", process->GetID()); if (synchronous_execution) { // If any state changed events had anything to say, add that to the // result if (stream.GetSize() > 0) result.AppendMessage(stream.GetString()); result.SetDidChangeProcessState(true); result.SetStatus(eReturnStatusSuccessFinishNoResult); } else { result.SetStatus(eReturnStatusSuccessContinuingNoResult); } } else { result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString()); result.SetStatus(eReturnStatusFailed); } } else { result.AppendErrorWithFormat( "Process cannot be continued from its current state (%s).\n", StateAsCString(state)); result.SetStatus(eReturnStatusFailed); } return result.Succeeded(); } }; //------------------------------------------------------------------------- // CommandObjectThreadUntil //------------------------------------------------------------------------- static OptionDefinition g_thread_until_options[] = { // clang-format off { LLDB_OPT_SET_1, false, "frame", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0" }, { LLDB_OPT_SET_1, false, "thread", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation" }, { LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, nullptr, g_duo_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping this one" }, { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Run until we reach the specified address, or leave the function - can be specified multiple times." } // clang-format on }; class CommandObjectThreadUntil : public CommandObjectParsed { public: class CommandOptions : public Options { public: uint32_t m_thread_idx; uint32_t m_frame_idx; CommandOptions() : Options(), m_thread_idx(LLDB_INVALID_THREAD_ID), m_frame_idx(LLDB_INVALID_FRAME_ID) { // Keep default values of all options in one place: OptionParsingStarting // () OptionParsingStarting(nullptr); } ~CommandOptions() override = default; Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override { Status error; const int short_option = m_getopt_table[option_idx].val; switch (short_option) { case 'a': { lldb::addr_t tmp_addr = Args::StringToAddress( execution_context, option_arg, LLDB_INVALID_ADDRESS, &error); if (error.Success()) m_until_addrs.push_back(tmp_addr); } break; case 't': if (option_arg.getAsInteger(0, m_thread_idx)) { m_thread_idx = LLDB_INVALID_INDEX32; error.SetErrorStringWithFormat("invalid thread index '%s'", option_arg.str().c_str()); } break; case 'f': if (option_arg.getAsInteger(0, m_frame_idx)) { m_frame_idx = LLDB_INVALID_FRAME_ID; error.SetErrorStringWithFormat("invalid frame index '%s'", option_arg.str().c_str()); } break; case 'm': { OptionEnumValueElement *enum_values = GetDefinitions()[option_idx].enum_values; lldb::RunMode run_mode = (lldb::RunMode)Args::StringToOptionEnum( option_arg, enum_values, eOnlyDuringStepping, error); if (error.Success()) { if (run_mode == eAllThreads) m_stop_others = false; else m_stop_others = true; } } break; default: error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); break; } return error; } void OptionParsingStarting(ExecutionContext *execution_context) override { m_thread_idx = LLDB_INVALID_THREAD_ID; m_frame_idx = 0; m_stop_others = false; m_until_addrs.clear(); } llvm::ArrayRef GetDefinitions() override { return llvm::makeArrayRef(g_thread_until_options); } uint32_t m_step_thread_idx; bool m_stop_others; std::vector m_until_addrs; // Instance variables to hold the values for command options. }; CommandObjectThreadUntil(CommandInterpreter &interpreter) : CommandObjectParsed( interpreter, "thread until", "Continue until a line number or address is reached by the " "current or specified thread. Stops when returning from " "the current function as a safety measure. " "The target line number(s) are given as arguments, and if more than one" " is provided, stepping will stop when the first one is hit.", nullptr, eCommandRequiresThread | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), m_options() { CommandArgumentEntry arg; CommandArgumentData line_num_arg; // Define the first (and only) variant of this arg. line_num_arg.arg_type = eArgTypeLineNum; line_num_arg.arg_repetition = eArgRepeatPlain; // There is only one variant this argument could be; put it into the // argument entry. arg.push_back(line_num_arg); // Push the data for the first argument into the m_arguments vector. m_arguments.push_back(arg); } ~CommandObjectThreadUntil() override = default; Options *GetOptions() override { return &m_options; } protected: bool DoExecute(Args &command, CommandReturnObject &result) override { bool synchronous_execution = m_interpreter.GetSynchronous(); Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); if (target == nullptr) { result.AppendError("invalid target, create a debug target using the " "'target create' command"); result.SetStatus(eReturnStatusFailed); return false; } Process *process = m_exe_ctx.GetProcessPtr(); if (process == nullptr) { result.AppendError("need a valid process to step"); result.SetStatus(eReturnStatusFailed); } else { Thread *thread = nullptr; std::vector line_numbers; if (command.GetArgumentCount() >= 1) { size_t num_args = command.GetArgumentCount(); for (size_t i = 0; i < num_args; i++) { uint32_t line_number; line_number = StringConvert::ToUInt32(command.GetArgumentAtIndex(i), UINT32_MAX); if (line_number == UINT32_MAX) { result.AppendErrorWithFormat("invalid line number: '%s'.\n", command.GetArgumentAtIndex(i)); result.SetStatus(eReturnStatusFailed); return false; } else line_numbers.push_back(line_number); } } else if (m_options.m_until_addrs.empty()) { result.AppendErrorWithFormat("No line number or address provided:\n%s", GetSyntax().str().c_str()); result.SetStatus(eReturnStatusFailed); return false; } if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID) { thread = GetDefaultThread(); } else { thread = process->GetThreadList() .FindThreadByIndexID(m_options.m_thread_idx) .get(); } if (thread == nullptr) { const uint32_t num_threads = process->GetThreadList().GetSize(); result.AppendErrorWithFormat( "Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, num_threads); result.SetStatus(eReturnStatusFailed); return false; } const bool abort_other_plans = false; StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get(); if (frame == nullptr) { result.AppendErrorWithFormat( "Frame index %u is out of range for thread %u.\n", m_options.m_frame_idx, m_options.m_thread_idx); result.SetStatus(eReturnStatusFailed); return false; } ThreadPlanSP new_plan_sp; if (frame->HasDebugInformation()) { // Finally we got here... Translate the given line number to a bunch of // addresses: SymbolContext sc(frame->GetSymbolContext(eSymbolContextCompUnit)); LineTable *line_table = nullptr; if (sc.comp_unit) line_table = sc.comp_unit->GetLineTable(); if (line_table == nullptr) { result.AppendErrorWithFormat("Failed to resolve the line table for " "frame %u of thread index %u.\n", m_options.m_frame_idx, m_options.m_thread_idx); result.SetStatus(eReturnStatusFailed); return false; } LineEntry function_start; uint32_t index_ptr = 0, end_ptr; std::vector address_list; // Find the beginning & end index of the AddressRange fun_addr_range = sc.function->GetAddressRange(); Address fun_start_addr = fun_addr_range.GetBaseAddress(); line_table->FindLineEntryByAddress(fun_start_addr, function_start, &index_ptr); Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize()); bool all_in_function = true; line_table->FindLineEntryByAddress(fun_end_addr, function_start, &end_ptr); for (uint32_t line_number : line_numbers) { uint32_t start_idx_ptr = index_ptr; while (start_idx_ptr <= end_ptr) { LineEntry line_entry; const bool exact = false; start_idx_ptr = sc.comp_unit->FindLineEntry( start_idx_ptr, line_number, sc.comp_unit, exact, &line_entry); if (start_idx_ptr == UINT32_MAX) break; addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(target); if (address != LLDB_INVALID_ADDRESS) { if (fun_addr_range.ContainsLoadAddress(address, target)) address_list.push_back(address); else all_in_function = false; } start_idx_ptr++; } } for (lldb::addr_t address : m_options.m_until_addrs) { if (fun_addr_range.ContainsLoadAddress(address, target)) address_list.push_back(address); else all_in_function = false; } if (address_list.empty()) { if (all_in_function) result.AppendErrorWithFormat( "No line entries matching until target.\n"); else result.AppendErrorWithFormat( "Until target outside of the current function.\n"); result.SetStatus(eReturnStatusFailed); return false; } new_plan_sp = thread->QueueThreadPlanForStepUntil( abort_other_plans, &address_list.front(), address_list.size(), m_options.m_stop_others, m_options.m_frame_idx); // User level plans should be master plans so they can be interrupted // (e.g. by hitting a breakpoint) // and other plans executed by the user (stepping around the breakpoint) // and then a "continue" // will resume the original plan. new_plan_sp->SetIsMasterPlan(true); new_plan_sp->SetOkayToDiscard(false); } else { result.AppendErrorWithFormat( "Frame index %u of thread %u has no debug information.\n", m_options.m_frame_idx, m_options.m_thread_idx); result.SetStatus(eReturnStatusFailed); return false; } process->GetThreadList().SetSelectedThreadByID(m_options.m_thread_idx); StreamString stream; Status error; if (synchronous_execution) error = process->ResumeSynchronous(&stream); else error = process->Resume(); if (error.Success()) { result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n", process->GetID()); if (synchronous_execution) { // If any state changed events had anything to say, add that to the // result if (stream.GetSize() > 0) result.AppendMessage(stream.GetString()); result.SetDidChangeProcessState(true); result.SetStatus(eReturnStatusSuccessFinishNoResult); } else { result.SetStatus(eReturnStatusSuccessContinuingNoResult); } } else { result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); result.SetStatus(eReturnStatusFailed); } } return result.Succeeded(); } CommandOptions m_options; }; //------------------------------------------------------------------------- // CommandObjectThreadSelect //------------------------------------------------------------------------- class CommandObjectThreadSelect : public CommandObjectParsed { public: CommandObjectThreadSelect(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "thread select", "Change the currently selected thread.", nullptr, eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) { CommandArgumentEntry arg; CommandArgumentData thread_idx_arg; // Define the first (and only) variant of this arg. thread_idx_arg.arg_type = eArgTypeThreadIndex; thread_idx_arg.arg_repetition = eArgRepeatPlain; // There is only one variant this argument could be; put it into the // argument entry. arg.push_back(thread_idx_arg); // Push the data for the first argument into the m_arguments vector. m_arguments.push_back(arg); } ~CommandObjectThreadSelect() override = default; protected: bool DoExecute(Args &command, CommandReturnObject &result) override { Process *process = m_exe_ctx.GetProcessPtr(); if (process == nullptr) { result.AppendError("no process"); result.SetStatus(eReturnStatusFailed); return false; } else if (command.GetArgumentCount() != 1) { result.AppendErrorWithFormat( "'%s' takes exactly one thread index argument:\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); result.SetStatus(eReturnStatusFailed); return false; } uint32_t index_id = StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0); Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get(); if (new_thread == nullptr) { result.AppendErrorWithFormat("invalid thread #%s.\n", command.GetArgumentAtIndex(0)); result.SetStatus(eReturnStatusFailed); return false; } process->GetThreadList().SetSelectedThreadByID(new_thread->GetID(), true); result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); } }; //------------------------------------------------------------------------- // CommandObjectThreadList //------------------------------------------------------------------------- class CommandObjectThreadList : public CommandObjectParsed { public: CommandObjectThreadList(CommandInterpreter &interpreter) : CommandObjectParsed( interpreter, "thread list", "Show a summary of each thread in the current target process.", "thread list", eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {} ~CommandObjectThreadList() override = default; protected: bool DoExecute(Args &command, CommandReturnObject &result) override { Stream &strm = result.GetOutputStream(); result.SetStatus(eReturnStatusSuccessFinishNoResult); Process *process = m_exe_ctx.GetProcessPtr(); const bool only_threads_with_stop_reason = false; const uint32_t start_frame = 0; const uint32_t num_frames = 0; const uint32_t num_frames_with_source = 0; process->GetStatus(strm); process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame, num_frames, num_frames_with_source, false); return result.Succeeded(); } }; //------------------------------------------------------------------------- // CommandObjectThreadInfo //------------------------------------------------------------------------- static OptionDefinition g_thread_info_options[] = { // clang-format off { LLDB_OPT_SET_ALL, false, "json", 'j', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the thread info in JSON format." }, { LLDB_OPT_SET_ALL, false, "stop-info", 's', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the extended stop info in JSON format." } // clang-format on }; class CommandObjectThreadInfo : public CommandObjectIterateOverThreads { public: class CommandOptions : public Options { public: CommandOptions() : Options() { OptionParsingStarting(nullptr); } ~CommandOptions() override = default; void OptionParsingStarting(ExecutionContext *execution_context) override { m_json_thread = false; m_json_stopinfo = false; } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override { const int short_option = m_getopt_table[option_idx].val; Status error; switch (short_option) { case 'j': m_json_thread = true; break; case 's': m_json_stopinfo = true; break; default: return Status("invalid short option character '%c'", short_option); } return error; } llvm::ArrayRef GetDefinitions() override { return llvm::makeArrayRef(g_thread_info_options); } bool m_json_thread; bool m_json_stopinfo; }; CommandObjectThreadInfo(CommandInterpreter &interpreter) : CommandObjectIterateOverThreads( interpreter, "thread info", "Show an extended summary of one or " "more threads. Defaults to the " "current thread.", "thread info", eCommandRequiresProcess | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), m_options() { m_add_return = false; } ~CommandObjectThreadInfo() override = default; Options *GetOptions() override { return &m_options; } bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { ThreadSP thread_sp = m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); if (!thread_sp) { result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n", tid); result.SetStatus(eReturnStatusFailed); return false; } Thread *thread = thread_sp.get(); Stream &strm = result.GetOutputStream(); if (!thread->GetDescription(strm, eDescriptionLevelFull, m_options.m_json_thread, m_options.m_json_stopinfo)) { result.AppendErrorWithFormat("error displaying info for thread: \"%d\"\n", thread->GetIndexID()); result.SetStatus(eReturnStatusFailed); return false; } return true; } CommandOptions m_options; }; //------------------------------------------------------------------------- // CommandObjectThreadReturn //------------------------------------------------------------------------- static OptionDefinition g_thread_return_options[] = { // clang-format off { LLDB_OPT_SET_ALL, false, "from-expression", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Return from the innermost expression evaluation." } // clang-format on }; class CommandObjectThreadReturn : public CommandObjectRaw { public: class CommandOptions : public Options { public: CommandOptions() : Options(), m_from_expression(false) { // Keep default values of all options in one place: OptionParsingStarting // () OptionParsingStarting(nullptr); } ~CommandOptions() override = default; Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override { Status error; const int short_option = m_getopt_table[option_idx].val; switch (short_option) { case 'x': { bool success; bool tmp_value = Args::StringToBoolean(option_arg, false, &success); if (success) m_from_expression = tmp_value; else { error.SetErrorStringWithFormat( "invalid boolean value '%s' for 'x' option", option_arg.str().c_str()); } } break; default: error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); break; } return error; } void OptionParsingStarting(ExecutionContext *execution_context) override { m_from_expression = false; } llvm::ArrayRef GetDefinitions() override { return llvm::makeArrayRef(g_thread_return_options); } bool m_from_expression; // Instance variables to hold the values for command options. }; CommandObjectThreadReturn(CommandInterpreter &interpreter) : CommandObjectRaw(interpreter, "thread return", "Prematurely return from a stack frame, " "short-circuiting execution of newer frames " "and optionally yielding a specified value. Defaults " "to the exiting the current stack " "frame.", "thread return", eCommandRequiresFrame | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), m_options() { CommandArgumentEntry arg; CommandArgumentData expression_arg; // Define the first (and only) variant of this arg. expression_arg.arg_type = eArgTypeExpression; expression_arg.arg_repetition = eArgRepeatOptional; // There is only one variant this argument could be; put it into the // argument entry. arg.push_back(expression_arg); // Push the data for the first argument into the m_arguments vector. m_arguments.push_back(arg); } ~CommandObjectThreadReturn() override = default; Options *GetOptions() override { return &m_options; } protected: bool DoExecute(const char *command, CommandReturnObject &result) override { // I am going to handle this by hand, because I don't want you to have to // say: // "thread return -- -5". if (command[0] == '-' && command[1] == 'x') { if (command && command[2] != '\0') result.AppendWarning("Return values ignored when returning from user " "called expressions"); Thread *thread = m_exe_ctx.GetThreadPtr(); Status error; error = thread->UnwindInnermostExpression(); if (!error.Success()) { result.AppendErrorWithFormat("Unwinding expression failed - %s.", error.AsCString()); result.SetStatus(eReturnStatusFailed); } else { bool success = thread->SetSelectedFrameByIndexNoisily(0, result.GetOutputStream()); if (success) { m_exe_ctx.SetFrameSP(thread->GetSelectedFrame()); result.SetStatus(eReturnStatusSuccessFinishResult); } else { result.AppendErrorWithFormat( "Could not select 0th frame after unwinding expression."); result.SetStatus(eReturnStatusFailed); } } return result.Succeeded(); } ValueObjectSP return_valobj_sp; StackFrameSP frame_sp = m_exe_ctx.GetFrameSP(); uint32_t frame_idx = frame_sp->GetFrameIndex(); if (frame_sp->IsInlined()) { result.AppendError("Don't know how to return from inlined frames."); result.SetStatus(eReturnStatusFailed); return false; } if (command && command[0] != '\0') { Target *target = m_exe_ctx.GetTargetPtr(); EvaluateExpressionOptions options; options.SetUnwindOnError(true); options.SetUseDynamic(eNoDynamicValues); ExpressionResults exe_results = eExpressionSetupError; exe_results = target->EvaluateExpression(command, frame_sp.get(), return_valobj_sp, options); if (exe_results != eExpressionCompleted) { if (return_valobj_sp) result.AppendErrorWithFormat( "Error evaluating result expression: %s", return_valobj_sp->GetError().AsCString()); else result.AppendErrorWithFormat( "Unknown error evaluating result expression."); result.SetStatus(eReturnStatusFailed); return false; } } Status error; ThreadSP thread_sp = m_exe_ctx.GetThreadSP(); const bool broadcast = true; error = thread_sp->ReturnFromFrame(frame_sp, return_valobj_sp, broadcast); if (!error.Success()) { result.AppendErrorWithFormat( "Error returning from frame %d of thread %d: %s.", frame_idx, thread_sp->GetIndexID(), error.AsCString()); result.SetStatus(eReturnStatusFailed); return false; } result.SetStatus(eReturnStatusSuccessFinishResult); return true; } CommandOptions m_options; }; //------------------------------------------------------------------------- // CommandObjectThreadJump //------------------------------------------------------------------------- static OptionDefinition g_thread_jump_options[] = { // clang-format off { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file to jump to." }, { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specifies the line number to jump to." }, { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "Jumps by a relative line offset from the current line." }, { LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Jumps to a specific address." }, { LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "force", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allows the PC to leave the current function." } // clang-format on }; class CommandObjectThreadJump : public CommandObjectParsed { public: class CommandOptions : public Options { public: CommandOptions() : Options() { OptionParsingStarting(nullptr); } ~CommandOptions() override = default; void OptionParsingStarting(ExecutionContext *execution_context) override { m_filenames.Clear(); m_line_num = 0; m_line_offset = 0; m_load_addr = LLDB_INVALID_ADDRESS; m_force = false; } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override { const int short_option = m_getopt_table[option_idx].val; Status error; switch (short_option) { case 'f': m_filenames.AppendIfUnique(FileSpec(option_arg, false)); if (m_filenames.GetSize() > 1) return Status("only one source file expected."); break; case 'l': if (option_arg.getAsInteger(0, m_line_num)) return Status("invalid line number: '%s'.", option_arg.str().c_str()); break; case 'b': if (option_arg.getAsInteger(0, m_line_offset)) return Status("invalid line offset: '%s'.", option_arg.str().c_str()); break; case 'a': m_load_addr = Args::StringToAddress(execution_context, option_arg, LLDB_INVALID_ADDRESS, &error); break; case 'r': m_force = true; break; default: return Status("invalid short option character '%c'", short_option); } return error; } llvm::ArrayRef GetDefinitions() override { return llvm::makeArrayRef(g_thread_jump_options); } FileSpecList m_filenames; uint32_t m_line_num; int32_t m_line_offset; lldb::addr_t m_load_addr; bool m_force; }; CommandObjectThreadJump(CommandInterpreter &interpreter) : CommandObjectParsed( interpreter, "thread jump", "Sets the program counter to a new address.", "thread jump", eCommandRequiresFrame | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), m_options() {} ~CommandObjectThreadJump() override = default; Options *GetOptions() override { return &m_options; } protected: bool DoExecute(Args &args, CommandReturnObject &result) override { RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); StackFrame *frame = m_exe_ctx.GetFramePtr(); Thread *thread = m_exe_ctx.GetThreadPtr(); Target *target = m_exe_ctx.GetTargetPtr(); const SymbolContext &sym_ctx = frame->GetSymbolContext(eSymbolContextLineEntry); if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) { // Use this address directly. Address dest = Address(m_options.m_load_addr); lldb::addr_t callAddr = dest.GetCallableLoadAddress(target); if (callAddr == LLDB_INVALID_ADDRESS) { result.AppendErrorWithFormat("Invalid destination address."); result.SetStatus(eReturnStatusFailed); return false; } if (!reg_ctx->SetPC(callAddr)) { result.AppendErrorWithFormat("Error changing PC value for thread %d.", thread->GetIndexID()); result.SetStatus(eReturnStatusFailed); return false; } } else { // Pick either the absolute line, or work out a relative one. int32_t line = (int32_t)m_options.m_line_num; if (line == 0) line = sym_ctx.line_entry.line + m_options.m_line_offset; // Try the current file, but override if asked. FileSpec file = sym_ctx.line_entry.file; if (m_options.m_filenames.GetSize() == 1) file = m_options.m_filenames.GetFileSpecAtIndex(0); if (!file) { result.AppendErrorWithFormat( "No source file available for the current location."); result.SetStatus(eReturnStatusFailed); return false; } std::string warnings; Status err = thread->JumpToLine(file, line, m_options.m_force, &warnings); if (err.Fail()) { result.SetError(err); return false; } if (!warnings.empty()) result.AppendWarning(warnings.c_str()); } result.SetStatus(eReturnStatusSuccessFinishResult); return true; } CommandOptions m_options; }; //------------------------------------------------------------------------- // Next are the subcommands of CommandObjectMultiwordThreadPlan //------------------------------------------------------------------------- //------------------------------------------------------------------------- // CommandObjectThreadPlanList //------------------------------------------------------------------------- static OptionDefinition g_thread_plan_list_options[] = { // clang-format off { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display more information about the thread plans" }, { LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display internal as well as user thread plans" } // clang-format on }; class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads { public: class CommandOptions : public Options { public: CommandOptions() : Options() { // Keep default values of all options in one place: OptionParsingStarting // () OptionParsingStarting(nullptr); } ~CommandOptions() override = default; Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override { Status error; const int short_option = m_getopt_table[option_idx].val; switch (short_option) { case 'i': m_internal = true; break; case 'v': m_verbose = true; break; default: error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); break; } return error; } void OptionParsingStarting(ExecutionContext *execution_context) override { m_verbose = false; m_internal = false; } llvm::ArrayRef GetDefinitions() override { return llvm::makeArrayRef(g_thread_plan_list_options); } // Instance variables to hold the values for command options. bool m_verbose; bool m_internal; }; CommandObjectThreadPlanList(CommandInterpreter &interpreter) : CommandObjectIterateOverThreads( interpreter, "thread plan list", "Show thread plans for one or more threads. If no threads are " "specified, show the " "current thread. Use the thread-index \"all\" to see all threads.", nullptr, eCommandRequiresProcess | eCommandRequiresThread | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), m_options() {} ~CommandObjectThreadPlanList() override = default; Options *GetOptions() override { return &m_options; } protected: bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override { ThreadSP thread_sp = m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid); if (!thread_sp) { result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n", tid); result.SetStatus(eReturnStatusFailed); return false; } Thread *thread = thread_sp.get(); Stream &strm = result.GetOutputStream(); DescriptionLevel desc_level = eDescriptionLevelFull; if (m_options.m_verbose) desc_level = eDescriptionLevelVerbose; thread->DumpThreadPlans(&strm, desc_level, m_options.m_internal, true); return true; } CommandOptions m_options; }; class CommandObjectThreadPlanDiscard : public CommandObjectParsed { public: CommandObjectThreadPlanDiscard(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "thread plan discard", "Discards thread plans up to and including the " "specified index (see 'thread plan list'.) " "Only user visible plans can be discarded.", nullptr, eCommandRequiresProcess | eCommandRequiresThread | eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) { CommandArgumentEntry arg; CommandArgumentData plan_index_arg; // Define the first (and only) variant of this arg. plan_index_arg.arg_type = eArgTypeUnsignedInteger; plan_index_arg.arg_repetition = eArgRepeatPlain; // There is only one variant this argument could be; put it into the // argument entry. arg.push_back(plan_index_arg); // Push the data for the first argument into the m_arguments vector. m_arguments.push_back(arg); } ~CommandObjectThreadPlanDiscard() override = default; bool DoExecute(Args &args, CommandReturnObject &result) override { Thread *thread = m_exe_ctx.GetThreadPtr(); if (args.GetArgumentCount() != 1) { result.AppendErrorWithFormat("Too many arguments, expected one - the " "thread plan index - but got %zu.", args.GetArgumentCount()); result.SetStatus(eReturnStatusFailed); return false; } bool success; uint32_t thread_plan_idx = StringConvert::ToUInt32(args.GetArgumentAtIndex(0), 0, 0, &success); if (!success) { result.AppendErrorWithFormat( "Invalid thread index: \"%s\" - should be unsigned int.", args.GetArgumentAtIndex(0)); result.SetStatus(eReturnStatusFailed); return false; } if (thread_plan_idx == 0) { result.AppendErrorWithFormat( "You wouldn't really want me to discard the base thread plan."); result.SetStatus(eReturnStatusFailed); return false; } if (thread->DiscardUserThreadPlansUpToIndex(thread_plan_idx)) { result.SetStatus(eReturnStatusSuccessFinishNoResult); return true; } else { result.AppendErrorWithFormat( "Could not find User thread plan with index %s.", args.GetArgumentAtIndex(0)); result.SetStatus(eReturnStatusFailed); return false; } } }; //------------------------------------------------------------------------- // CommandObjectMultiwordThreadPlan //------------------------------------------------------------------------- class CommandObjectMultiwordThreadPlan : public CommandObjectMultiword { public: CommandObjectMultiwordThreadPlan(CommandInterpreter &interpreter) : CommandObjectMultiword( interpreter, "plan", "Commands for managing thread plans that control execution.", "thread plan [ []") { LoadSubCommand("backtrace", CommandObjectSP(new CommandObjectThreadBacktrace( interpreter))); LoadSubCommand("continue", CommandObjectSP(new CommandObjectThreadContinue(interpreter))); LoadSubCommand("list", CommandObjectSP(new CommandObjectThreadList(interpreter))); LoadSubCommand("return", CommandObjectSP(new CommandObjectThreadReturn(interpreter))); LoadSubCommand("jump", CommandObjectSP(new CommandObjectThreadJump(interpreter))); LoadSubCommand("select", CommandObjectSP(new CommandObjectThreadSelect(interpreter))); LoadSubCommand("until", CommandObjectSP(new CommandObjectThreadUntil(interpreter))); LoadSubCommand("info", CommandObjectSP(new CommandObjectThreadInfo(interpreter))); LoadSubCommand("step-in", CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( interpreter, "thread step-in", "Source level single step, stepping into calls. Defaults " "to current thread unless specified.", nullptr, eStepTypeInto, eStepScopeSource))); LoadSubCommand("step-out", CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( interpreter, "thread step-out", "Finish executing the current stack frame and stop after " "returning. Defaults to current thread unless specified.", nullptr, eStepTypeOut, eStepScopeSource))); LoadSubCommand("step-over", CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( interpreter, "thread step-over", "Source level single step, stepping over calls. Defaults " "to current thread unless specified.", nullptr, eStepTypeOver, eStepScopeSource))); LoadSubCommand("step-inst", CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( interpreter, "thread step-inst", "Instruction level single step, stepping into calls. " "Defaults to current thread unless specified.", nullptr, eStepTypeTrace, eStepScopeInstruction))); LoadSubCommand("step-inst-over", CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( interpreter, "thread step-inst-over", "Instruction level single step, stepping over calls. " "Defaults to current thread unless specified.", nullptr, eStepTypeTraceOver, eStepScopeInstruction))); LoadSubCommand( "step-scripted", CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( interpreter, "thread step-scripted", "Step as instructed by the script class passed in the -C option.", nullptr, eStepTypeScripted, eStepScopeSource))); LoadSubCommand("plan", CommandObjectSP(new CommandObjectMultiwordThreadPlan( interpreter))); } CommandObjectMultiwordThread::~CommandObjectMultiwordThread() = default; Index: vendor/lldb/dist/source/Core/DumpDataExtractor.cpp =================================================================== --- vendor/lldb/dist/source/Core/DumpDataExtractor.cpp (revision 320966) +++ vendor/lldb/dist/source/Core/DumpDataExtractor.cpp (revision 320967) @@ -1,824 +1,825 @@ //===-- DumpDataExtractor.cpp -----------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/Core/DumpDataExtractor.h" #include "lldb/lldb-defines.h" // for LLDB_INVALID_ADDRESS #include "lldb/lldb-forward.h" // for TargetSP, DisassemblerSP #include "lldb/Core/Address.h" // for Address #include "lldb/Core/Disassembler.h" #include "lldb/Core/ModuleList.h" // for ModuleList #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Stream.h" #include "clang/AST/ASTContext.h" // for ASTContext #include "clang/AST/CanonicalType.h" // for CanQualType #include "llvm/ADT/APFloat.h" // for APFloat, APFloatBase:... #include "llvm/ADT/APInt.h" // for APInt #include "llvm/ADT/ArrayRef.h" // for ArrayRef #include "llvm/ADT/SmallVector.h" // for SmallVector #include // for numeric_limits, numer... #include // for shared_ptr #include // for string, basic_string #include // for assert #include // for isprint #include // for PRIu64, PRIx64, PRIX64 #include // for ldexpf #include #include using namespace lldb_private; using namespace lldb; #define NON_PRINTABLE_CHAR '.' static float half2float(uint16_t half) { union { float f; uint32_t u; } u; int32_t v = (int16_t)half; if (0 == (v & 0x7c00)) { u.u = v & 0x80007FFFU; return u.f * ldexpf(1, 125); } v <<= 13; u.u = v | 0x70000000U; return u.f * ldexpf(1, -112); } static bool GetAPInt(const DataExtractor &data, lldb::offset_t *offset_ptr, lldb::offset_t byte_size, llvm::APInt &result) { llvm::SmallVector uint64_array; lldb::offset_t bytes_left = byte_size; uint64_t u64; const lldb::ByteOrder byte_order = data.GetByteOrder(); if (byte_order == lldb::eByteOrderLittle) { while (bytes_left > 0) { if (bytes_left >= 8) { u64 = data.GetU64(offset_ptr); bytes_left -= 8; } else { u64 = data.GetMaxU64(offset_ptr, (uint32_t)bytes_left); bytes_left = 0; } uint64_array.push_back(u64); } result = llvm::APInt(byte_size * 8, llvm::ArrayRef(uint64_array)); return true; } else if (byte_order == lldb::eByteOrderBig) { lldb::offset_t be_offset = *offset_ptr + byte_size; lldb::offset_t temp_offset; while (bytes_left > 0) { if (bytes_left >= 8) { be_offset -= 8; temp_offset = be_offset; u64 = data.GetU64(&temp_offset); bytes_left -= 8; } else { be_offset -= bytes_left; temp_offset = be_offset; u64 = data.GetMaxU64(&temp_offset, (uint32_t)bytes_left); bytes_left = 0; } uint64_array.push_back(u64); } *offset_ptr += byte_size; result = llvm::APInt(byte_size * 8, llvm::ArrayRef(uint64_array)); return true; } return false; } static lldb::offset_t DumpAPInt(Stream *s, const DataExtractor &data, lldb::offset_t offset, lldb::offset_t byte_size, bool is_signed, unsigned radix) { llvm::APInt apint; if (GetAPInt(data, &offset, byte_size, apint)) { std::string apint_str(apint.toString(radix, is_signed)); switch (radix) { case 2: s->Write("0b", 2); break; case 8: s->Write("0", 1); break; case 10: break; } s->Write(apint_str.c_str(), apint_str.size()); } return offset; } lldb::offset_t lldb_private::DumpDataExtractor( const DataExtractor &DE, Stream *s, offset_t start_offset, lldb::Format item_format, size_t item_byte_size, size_t item_count, size_t num_per_line, uint64_t base_addr, uint32_t item_bit_size, // If zero, this is not a bitfield value, if // non-zero, the value is a bitfield uint32_t item_bit_offset, // If "item_bit_size" is non-zero, this is the // shift amount to apply to a bitfield ExecutionContextScope *exe_scope) { if (s == nullptr) return start_offset; if (item_format == eFormatPointer) { if (item_byte_size != 4 && item_byte_size != 8) item_byte_size = s->GetAddressByteSize(); } offset_t offset = start_offset; if (item_format == eFormatInstruction) { TargetSP target_sp; if (exe_scope) target_sp = exe_scope->CalculateTarget(); if (target_sp) { DisassemblerSP disassembler_sp(Disassembler::FindPlugin( - target_sp->GetArchitecture(), nullptr, nullptr)); + target_sp->GetArchitecture(), + target_sp->GetDisassemblyFlavor(), nullptr)); if (disassembler_sp) { lldb::addr_t addr = base_addr + start_offset; lldb_private::Address so_addr; bool data_from_file = true; if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) { data_from_file = false; } else { if (target_sp->GetSectionLoadList().IsEmpty() || !target_sp->GetImages().ResolveFileAddress(addr, so_addr)) so_addr.SetRawAddress(addr); } size_t bytes_consumed = disassembler_sp->DecodeInstructions( so_addr, DE, start_offset, item_count, false, data_from_file); if (bytes_consumed) { offset += bytes_consumed; const bool show_address = base_addr != LLDB_INVALID_ADDRESS; const bool show_bytes = true; ExecutionContext exe_ctx; exe_scope->CalculateExecutionContext(exe_ctx); disassembler_sp->GetInstructionList().Dump(s, show_address, show_bytes, &exe_ctx); } } } else s->Printf("invalid target"); return offset; } if ((item_format == eFormatOSType || item_format == eFormatAddressInfo) && item_byte_size > 8) item_format = eFormatHex; lldb::offset_t line_start_offset = start_offset; for (uint32_t count = 0; DE.ValidOffset(offset) && count < item_count; ++count) { if ((count % num_per_line) == 0) { if (count > 0) { if (item_format == eFormatBytesWithASCII && offset > line_start_offset) { s->Printf("%*s", static_cast( (num_per_line - (offset - line_start_offset)) * 3 + 2), ""); DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1, offset - line_start_offset, SIZE_MAX, LLDB_INVALID_ADDRESS, 0, 0); } s->EOL(); } if (base_addr != LLDB_INVALID_ADDRESS) s->Printf("0x%8.8" PRIx64 ": ", (uint64_t)(base_addr + (offset - start_offset) / DE.getTargetByteSize())); line_start_offset = offset; } else if (item_format != eFormatChar && item_format != eFormatCharPrintable && item_format != eFormatCharArray && count > 0) { s->PutChar(' '); } switch (item_format) { case eFormatBoolean: if (item_byte_size <= 8) s->Printf("%s", DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset) ? "true" : "false"); else { s->Printf("error: unsupported byte size (%" PRIu64 ") for boolean format", (uint64_t)item_byte_size); return offset; } break; case eFormatBinary: if (item_byte_size <= 8) { uint64_t uval64 = DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset); // Avoid std::bitset<64>::to_string() since it is missing in // earlier C++ libraries std::string binary_value(64, '0'); std::bitset<64> bits(uval64); for (uint32_t i = 0; i < 64; ++i) if (bits[i]) binary_value[64 - 1 - i] = '1'; if (item_bit_size > 0) s->Printf("0b%s", binary_value.c_str() + 64 - item_bit_size); else if (item_byte_size > 0 && item_byte_size <= 8) s->Printf("0b%s", binary_value.c_str() + 64 - item_byte_size * 8); } else { const bool is_signed = false; const unsigned radix = 2; offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix); } break; case eFormatBytes: case eFormatBytesWithASCII: for (uint32_t i = 0; i < item_byte_size; ++i) { s->Printf("%2.2x", DE.GetU8(&offset)); } // Put an extra space between the groups of bytes if more than one // is being dumped in a group (item_byte_size is more than 1). if (item_byte_size > 1) s->PutChar(' '); break; case eFormatChar: case eFormatCharPrintable: case eFormatCharArray: { // If we are only printing one character surround it with single // quotes if (item_count == 1 && item_format == eFormatChar) s->PutChar('\''); const uint64_t ch = DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset); if (isprint(ch)) s->Printf("%c", (char)ch); else if (item_format != eFormatCharPrintable) { switch (ch) { case '\033': s->Printf("\\e"); break; case '\a': s->Printf("\\a"); break; case '\b': s->Printf("\\b"); break; case '\f': s->Printf("\\f"); break; case '\n': s->Printf("\\n"); break; case '\r': s->Printf("\\r"); break; case '\t': s->Printf("\\t"); break; case '\v': s->Printf("\\v"); break; case '\0': s->Printf("\\0"); break; default: if (item_byte_size == 1) s->Printf("\\x%2.2x", (uint8_t)ch); else s->Printf("%" PRIu64, ch); break; } } else { s->PutChar(NON_PRINTABLE_CHAR); } // If we are only printing one character surround it with single quotes if (item_count == 1 && item_format == eFormatChar) s->PutChar('\''); } break; case eFormatEnum: // Print enum value as a signed integer when we don't get // the enum type case eFormatDecimal: if (item_byte_size <= 8) s->Printf("%" PRId64, DE.GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset)); else { const bool is_signed = true; const unsigned radix = 10; offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix); } break; case eFormatUnsigned: if (item_byte_size <= 8) s->Printf("%" PRIu64, DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset)); else { const bool is_signed = false; const unsigned radix = 10; offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix); } break; case eFormatOctal: if (item_byte_size <= 8) s->Printf("0%" PRIo64, DE.GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset)); else { const bool is_signed = false; const unsigned radix = 8; offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix); } break; case eFormatOSType: { uint64_t uval64 = DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset); s->PutChar('\''); for (uint32_t i = 0; i < item_byte_size; ++i) { uint8_t ch = (uint8_t)(uval64 >> ((item_byte_size - i - 1) * 8)); if (isprint(ch)) s->Printf("%c", ch); else { switch (ch) { case '\033': s->Printf("\\e"); break; case '\a': s->Printf("\\a"); break; case '\b': s->Printf("\\b"); break; case '\f': s->Printf("\\f"); break; case '\n': s->Printf("\\n"); break; case '\r': s->Printf("\\r"); break; case '\t': s->Printf("\\t"); break; case '\v': s->Printf("\\v"); break; case '\0': s->Printf("\\0"); break; default: s->Printf("\\x%2.2x", ch); break; } } } s->PutChar('\''); } break; case eFormatCString: { const char *cstr = DE.GetCStr(&offset); if (!cstr) { s->Printf("NULL"); offset = LLDB_INVALID_OFFSET; } else { s->PutChar('\"'); while (const char c = *cstr) { if (isprint(c)) { s->PutChar(c); } else { switch (c) { case '\033': s->Printf("\\e"); break; case '\a': s->Printf("\\a"); break; case '\b': s->Printf("\\b"); break; case '\f': s->Printf("\\f"); break; case '\n': s->Printf("\\n"); break; case '\r': s->Printf("\\r"); break; case '\t': s->Printf("\\t"); break; case '\v': s->Printf("\\v"); break; default: s->Printf("\\x%2.2x", c); break; } } ++cstr; } s->PutChar('\"'); } } break; case eFormatPointer: s->Address(DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset), sizeof(addr_t)); break; case eFormatComplexInteger: { size_t complex_int_byte_size = item_byte_size / 2; if (complex_int_byte_size > 0 && complex_int_byte_size <= 8) { s->Printf("%" PRIu64, DE.GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0)); s->Printf(" + %" PRIu64 "i", DE.GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0)); } else { s->Printf("error: unsupported byte size (%" PRIu64 ") for complex integer format", (uint64_t)item_byte_size); return offset; } } break; case eFormatComplex: if (sizeof(float) * 2 == item_byte_size) { float f32_1 = DE.GetFloat(&offset); float f32_2 = DE.GetFloat(&offset); s->Printf("%g + %gi", f32_1, f32_2); break; } else if (sizeof(double) * 2 == item_byte_size) { double d64_1 = DE.GetDouble(&offset); double d64_2 = DE.GetDouble(&offset); s->Printf("%lg + %lgi", d64_1, d64_2); break; } else if (sizeof(long double) * 2 == item_byte_size) { long double ld64_1 = DE.GetLongDouble(&offset); long double ld64_2 = DE.GetLongDouble(&offset); s->Printf("%Lg + %Lgi", ld64_1, ld64_2); break; } else { s->Printf("error: unsupported byte size (%" PRIu64 ") for complex float format", (uint64_t)item_byte_size); return offset; } break; default: case eFormatDefault: case eFormatHex: case eFormatHexUppercase: { bool wantsuppercase = (item_format == eFormatHexUppercase); switch (item_byte_size) { case 1: case 2: case 4: case 8: s->Printf(wantsuppercase ? "0x%*.*" PRIX64 : "0x%*.*" PRIx64, (int)(2 * item_byte_size), (int)(2 * item_byte_size), DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset)); break; default: { assert(item_bit_size == 0 && item_bit_offset == 0); const uint8_t *bytes = (const uint8_t *)DE.GetData(&offset, item_byte_size); if (bytes) { s->PutCString("0x"); uint32_t idx; if (DE.GetByteOrder() == eByteOrderBig) { for (idx = 0; idx < item_byte_size; ++idx) s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", bytes[idx]); } else { for (idx = 0; idx < item_byte_size; ++idx) s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", bytes[item_byte_size - 1 - idx]); } } } break; } } break; case eFormatFloat: { TargetSP target_sp; bool used_apfloat = false; if (exe_scope) target_sp = exe_scope->CalculateTarget(); if (target_sp) { ClangASTContext *clang_ast = target_sp->GetScratchClangASTContext(); if (clang_ast) { clang::ASTContext *ast = clang_ast->getASTContext(); if (ast) { llvm::SmallVector sv; // Show full precision when printing float values const unsigned format_precision = 0; const unsigned format_max_padding = 100; size_t item_bit_size = item_byte_size * 8; if (item_bit_size == ast->getTypeSize(ast->FloatTy)) { llvm::APInt apint(item_bit_size, DE.GetMaxU64(&offset, item_byte_size)); llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->FloatTy), apint); apfloat.toString(sv, format_precision, format_max_padding); } else if (item_bit_size == ast->getTypeSize(ast->DoubleTy)) { llvm::APInt apint; if (GetAPInt(DE, &offset, item_byte_size, apint)) { llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->DoubleTy), apint); apfloat.toString(sv, format_precision, format_max_padding); } } else if (item_bit_size == ast->getTypeSize(ast->LongDoubleTy)) { const auto &semantics = ast->getFloatTypeSemantics(ast->LongDoubleTy); const auto byte_size = (llvm::APFloat::getSizeInBits(semantics) + 7) / 8; llvm::APInt apint; if (GetAPInt(DE, &offset, byte_size, apint)) { llvm::APFloat apfloat(semantics, apint); apfloat.toString(sv, format_precision, format_max_padding); } } else if (item_bit_size == ast->getTypeSize(ast->HalfTy)) { llvm::APInt apint(item_bit_size, DE.GetU16(&offset)); llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->HalfTy), apint); apfloat.toString(sv, format_precision, format_max_padding); } if (!sv.empty()) { s->Printf("%*.*s", (int)sv.size(), (int)sv.size(), sv.data()); used_apfloat = true; } } } } if (!used_apfloat) { std::ostringstream ss; if (item_byte_size == sizeof(float) || item_byte_size == 2) { float f; if (item_byte_size == 2) { uint16_t half = DE.GetU16(&offset); f = half2float(half); } else { f = DE.GetFloat(&offset); } ss.precision(std::numeric_limits::digits10); ss << f; } else if (item_byte_size == sizeof(double)) { ss.precision(std::numeric_limits::digits10); ss << DE.GetDouble(&offset); } else if (item_byte_size == sizeof(long double) || item_byte_size == 10) { ss.precision(std::numeric_limits::digits10); ss << DE.GetLongDouble(&offset); } else { s->Printf("error: unsupported byte size (%" PRIu64 ") for float format", (uint64_t)item_byte_size); return offset; } ss.flush(); s->Printf("%s", ss.str().c_str()); } } break; case eFormatUnicode16: s->Printf("U+%4.4x", DE.GetU16(&offset)); break; case eFormatUnicode32: s->Printf("U+0x%8.8x", DE.GetU32(&offset)); break; case eFormatAddressInfo: { addr_t addr = DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset); s->Printf("0x%*.*" PRIx64, (int)(2 * item_byte_size), (int)(2 * item_byte_size), addr); if (exe_scope) { TargetSP target_sp(exe_scope->CalculateTarget()); lldb_private::Address so_addr; if (target_sp) { if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) { s->PutChar(' '); so_addr.Dump(s, exe_scope, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress); } else { so_addr.SetOffset(addr); so_addr.Dump(s, exe_scope, Address::DumpStyleResolvedPointerDescription); } } } } break; case eFormatHexFloat: if (sizeof(float) == item_byte_size) { char float_cstr[256]; llvm::APFloat ap_float(DE.GetFloat(&offset)); ap_float.convertToHexString(float_cstr, 0, false, llvm::APFloat::rmNearestTiesToEven); s->Printf("%s", float_cstr); break; } else if (sizeof(double) == item_byte_size) { char float_cstr[256]; llvm::APFloat ap_float(DE.GetDouble(&offset)); ap_float.convertToHexString(float_cstr, 0, false, llvm::APFloat::rmNearestTiesToEven); s->Printf("%s", float_cstr); break; } else { s->Printf("error: unsupported byte size (%" PRIu64 ") for hex float format", (uint64_t)item_byte_size); return offset; } break; // please keep the single-item formats below in sync with // FormatManager::GetSingleItemFormat // if you fail to do so, users will start getting different outputs // depending on internal // implementation details they should not care about || case eFormatVectorOfChar: // || s->PutChar('{'); // \/ offset = DumpDataExtractor(DE, s, offset, eFormatCharArray, 1, item_byte_size, item_byte_size, LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfSInt8: s->PutChar('{'); offset = DumpDataExtractor(DE, s, offset, eFormatDecimal, 1, item_byte_size, item_byte_size, LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfUInt8: s->PutChar('{'); offset = DumpDataExtractor(DE, s, offset, eFormatHex, 1, item_byte_size, item_byte_size, LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfSInt16: s->PutChar('{'); offset = DumpDataExtractor( DE, s, offset, eFormatDecimal, sizeof(uint16_t), item_byte_size / sizeof(uint16_t), item_byte_size / sizeof(uint16_t), LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfUInt16: s->PutChar('{'); offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint16_t), item_byte_size / sizeof(uint16_t), item_byte_size / sizeof(uint16_t), LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfSInt32: s->PutChar('{'); offset = DumpDataExtractor( DE, s, offset, eFormatDecimal, sizeof(uint32_t), item_byte_size / sizeof(uint32_t), item_byte_size / sizeof(uint32_t), LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfUInt32: s->PutChar('{'); offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint32_t), item_byte_size / sizeof(uint32_t), item_byte_size / sizeof(uint32_t), LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfSInt64: s->PutChar('{'); offset = DumpDataExtractor( DE, s, offset, eFormatDecimal, sizeof(uint64_t), item_byte_size / sizeof(uint64_t), item_byte_size / sizeof(uint64_t), LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfUInt64: s->PutChar('{'); offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint64_t), item_byte_size / sizeof(uint64_t), item_byte_size / sizeof(uint64_t), LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfFloat16: s->PutChar('{'); offset = DumpDataExtractor(DE, s, offset, eFormatFloat, 2, item_byte_size / 2, item_byte_size / 2, LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfFloat32: s->PutChar('{'); offset = DumpDataExtractor(DE, s, offset, eFormatFloat, 4, item_byte_size / 4, item_byte_size / 4, LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfFloat64: s->PutChar('{'); offset = DumpDataExtractor(DE, s, offset, eFormatFloat, 8, item_byte_size / 8, item_byte_size / 8, LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfUInt128: s->PutChar('{'); offset = DumpDataExtractor(DE, s, offset, eFormatHex, 16, item_byte_size / 16, item_byte_size / 16, LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; } } if (item_format == eFormatBytesWithASCII && offset > line_start_offset) { s->Printf("%*s", static_cast( (num_per_line - (offset - line_start_offset)) * 3 + 2), ""); DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1, offset - line_start_offset, SIZE_MAX, LLDB_INVALID_ADDRESS, 0, 0); } return offset; // Return the offset at which we ended up } void lldb_private::DumpHexBytes(Stream *s, const void *src, size_t src_len, uint32_t bytes_per_line, lldb::addr_t base_addr) { DataExtractor data(src, src_len, lldb::eByteOrderLittle, 4); DumpDataExtractor(data, s, 0, // Offset into "src" lldb::eFormatBytes, // Dump as hex bytes 1, // Size of each item is 1 for single bytes src_len, // Number of bytes bytes_per_line, // Num bytes per line base_addr, // Base address 0, 0); // Bitfield info } Index: vendor/lldb/dist/source/Host/common/File.cpp =================================================================== --- vendor/lldb/dist/source/Host/common/File.cpp (revision 320966) +++ vendor/lldb/dist/source/Host/common/File.cpp (revision 320967) @@ -1,861 +1,841 @@ //===-- File.cpp ------------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/Host/File.h" #include #include #include #include #include #ifdef _WIN32 #include "lldb/Host/windows/windows.h" #else #include #include #include #endif #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Errno.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors() #include "lldb/Host/Config.h" +#include "lldb/Host/Host.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" using namespace lldb; using namespace lldb_private; static const char *GetStreamOpenModeFromOptions(uint32_t options) { if (options & File::eOpenOptionAppend) { if (options & File::eOpenOptionRead) { if (options & File::eOpenOptionCanCreateNewOnly) return "a+x"; else return "a+"; } else if (options & File::eOpenOptionWrite) { if (options & File::eOpenOptionCanCreateNewOnly) return "ax"; else return "a"; } } else if (options & File::eOpenOptionRead && options & File::eOpenOptionWrite) { if (options & File::eOpenOptionCanCreate) { if (options & File::eOpenOptionCanCreateNewOnly) return "w+x"; else return "w+"; } else return "r+"; } else if (options & File::eOpenOptionRead) { return "r"; } else if (options & File::eOpenOptionWrite) { return "w"; } return NULL; } int File::kInvalidDescriptor = -1; FILE *File::kInvalidStream = NULL; File::File(const char *path, uint32_t options, uint32_t permissions) : IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor), m_stream(kInvalidStream), m_options(), m_own_stream(false), m_is_interactive(eLazyBoolCalculate), m_is_real_terminal(eLazyBoolCalculate) { Open(path, options, permissions); } File::File(const FileSpec &filespec, uint32_t options, uint32_t permissions) : IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor), m_stream(kInvalidStream), m_options(0), m_own_stream(false), m_is_interactive(eLazyBoolCalculate), m_is_real_terminal(eLazyBoolCalculate) { if (filespec) { Open(filespec.GetPath().c_str(), options, permissions); } } File::~File() { Close(); } int File::GetDescriptor() const { if (DescriptorIsValid()) return m_descriptor; // Don't open the file descriptor if we don't need to, just get it from the // stream if we have one. if (StreamIsValid()) { #if defined(LLVM_ON_WIN32) return _fileno(m_stream); #else return fileno(m_stream); #endif } // Invalid descriptor and invalid stream, return invalid descriptor. return kInvalidDescriptor; } IOObject::WaitableHandle File::GetWaitableHandle() { return m_descriptor; } void File::SetDescriptor(int fd, bool transfer_ownership) { if (IsValid()) Close(); m_descriptor = fd; m_should_close_fd = transfer_ownership; } FILE *File::GetStream() { if (!StreamIsValid()) { if (DescriptorIsValid()) { const char *mode = GetStreamOpenModeFromOptions(m_options); if (mode) { if (!m_should_close_fd) { // We must duplicate the file descriptor if we don't own it because // when you call fdopen, the stream will own the fd #ifdef _WIN32 m_descriptor = ::_dup(GetDescriptor()); #else m_descriptor = dup(GetDescriptor()); #endif m_should_close_fd = true; } - do { - m_stream = ::fdopen(m_descriptor, mode); - } while (m_stream == NULL && errno == EINTR); + m_stream = + llvm::sys::RetryAfterSignal(nullptr, ::fdopen, m_descriptor, mode); // If we got a stream, then we own the stream and should no // longer own the descriptor because fclose() will close it for us if (m_stream) { m_own_stream = true; m_should_close_fd = false; } } } } return m_stream; } void File::SetStream(FILE *fh, bool transfer_ownership) { if (IsValid()) Close(); m_stream = fh; m_own_stream = transfer_ownership; } +static int DoOpen(const char *path, int flags, int mode) { +#ifdef _MSC_VER + std::wstring wpath; + if (!llvm::ConvertUTF8toWide(path, wpath)) + return -1; + int result; + ::_wsopen_s(&result, wpath.c_str(), flags, _SH_DENYNO, mode); + return result; +#else + return ::open(path, flags, mode); +#endif +} + Status File::Open(const char *path, uint32_t options, uint32_t permissions) { Status error; if (IsValid()) Close(); int oflag = 0; const bool read = options & eOpenOptionRead; const bool write = options & eOpenOptionWrite; if (write) { if (read) oflag |= O_RDWR; else oflag |= O_WRONLY; if (options & eOpenOptionAppend) oflag |= O_APPEND; if (options & eOpenOptionTruncate) oflag |= O_TRUNC; if (options & eOpenOptionCanCreate) oflag |= O_CREAT; if (options & eOpenOptionCanCreateNewOnly) oflag |= O_CREAT | O_EXCL; } else if (read) { oflag |= O_RDONLY; #ifndef _WIN32 if (options & eOpenOptionDontFollowSymlinks) oflag |= O_NOFOLLOW; #endif } #ifndef _WIN32 if (options & eOpenOptionNonBlocking) oflag |= O_NONBLOCK; if (options & eOpenOptionCloseOnExec) oflag |= O_CLOEXEC; #else oflag |= O_BINARY; #endif mode_t mode = 0; if (oflag & O_CREAT) { if (permissions & lldb::eFilePermissionsUserRead) mode |= S_IRUSR; if (permissions & lldb::eFilePermissionsUserWrite) mode |= S_IWUSR; if (permissions & lldb::eFilePermissionsUserExecute) mode |= S_IXUSR; if (permissions & lldb::eFilePermissionsGroupRead) mode |= S_IRGRP; if (permissions & lldb::eFilePermissionsGroupWrite) mode |= S_IWGRP; if (permissions & lldb::eFilePermissionsGroupExecute) mode |= S_IXGRP; if (permissions & lldb::eFilePermissionsWorldRead) mode |= S_IROTH; if (permissions & lldb::eFilePermissionsWorldWrite) mode |= S_IWOTH; if (permissions & lldb::eFilePermissionsWorldExecute) mode |= S_IXOTH; } - do { -#ifdef _MSC_VER - std::wstring wpath; - if (!llvm::ConvertUTF8toWide(path, wpath)) { - m_descriptor = -1; - error.SetErrorString("Error converting path to UTF-16"); - return error; - } - ::_wsopen_s(&m_descriptor, wpath.c_str(), oflag, _SH_DENYNO, mode); -#else - m_descriptor = ::open(path, oflag, mode); -#endif - } while (m_descriptor < 0 && errno == EINTR); - + m_descriptor = llvm::sys::RetryAfterSignal(-1, DoOpen, path, oflag, mode); if (!DescriptorIsValid()) error.SetErrorToErrno(); else { m_should_close_fd = true; m_options = options; } return error; } uint32_t File::GetPermissions(const FileSpec &file_spec, Status &error) { if (file_spec) { error.Clear(); auto Perms = llvm::sys::fs::getPermissions(file_spec.GetPath()); if (Perms) return *Perms; error = Status(Perms.getError()); return 0; } else error.SetErrorString("empty file spec"); return 0; } uint32_t File::GetPermissions(Status &error) const { int fd = GetDescriptor(); if (fd != kInvalidDescriptor) { struct stat file_stats; if (::fstat(fd, &file_stats) == -1) error.SetErrorToErrno(); else { error.Clear(); return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); } } else { error.SetErrorString("invalid file descriptor"); } return 0; } Status File::Close() { Status error; if (StreamIsValid() && m_own_stream) { if (::fclose(m_stream) == EOF) error.SetErrorToErrno(); } if (DescriptorIsValid() && m_should_close_fd) { if (::close(m_descriptor) != 0) error.SetErrorToErrno(); } m_descriptor = kInvalidDescriptor; m_stream = kInvalidStream; m_options = 0; m_own_stream = false; m_should_close_fd = false; m_is_interactive = eLazyBoolCalculate; m_is_real_terminal = eLazyBoolCalculate; return error; } void File::Clear() { m_stream = nullptr; m_descriptor = -1; m_options = 0; m_own_stream = false; m_is_interactive = m_supports_colors = m_is_real_terminal = eLazyBoolCalculate; } Status File::GetFileSpec(FileSpec &file_spec) const { Status error; #ifdef F_GETPATH if (IsValid()) { char path[PATH_MAX]; if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1) error.SetErrorToErrno(); else file_spec.SetFile(path, false); } else { error.SetErrorString("invalid file handle"); } #elif defined(__linux__) char proc[64]; char path[PATH_MAX]; if (::snprintf(proc, sizeof(proc), "/proc/self/fd/%d", GetDescriptor()) < 0) error.SetErrorString("cannot resolve file descriptor"); else { ssize_t len; if ((len = ::readlink(proc, path, sizeof(path) - 1)) == -1) error.SetErrorToErrno(); else { path[len] = '\0'; file_spec.SetFile(path, false); } } #else error.SetErrorString("File::GetFileSpec is not supported on this platform"); #endif if (error.Fail()) file_spec.Clear(); return error; } off_t File::SeekFromStart(off_t offset, Status *error_ptr) { off_t result = 0; if (DescriptorIsValid()) { result = ::lseek(m_descriptor, offset, SEEK_SET); if (error_ptr) { if (result == -1) error_ptr->SetErrorToErrno(); else error_ptr->Clear(); } } else if (StreamIsValid()) { result = ::fseek(m_stream, offset, SEEK_SET); if (error_ptr) { if (result == -1) error_ptr->SetErrorToErrno(); else error_ptr->Clear(); } } else if (error_ptr) { error_ptr->SetErrorString("invalid file handle"); } return result; } off_t File::SeekFromCurrent(off_t offset, Status *error_ptr) { off_t result = -1; if (DescriptorIsValid()) { result = ::lseek(m_descriptor, offset, SEEK_CUR); if (error_ptr) { if (result == -1) error_ptr->SetErrorToErrno(); else error_ptr->Clear(); } } else if (StreamIsValid()) { result = ::fseek(m_stream, offset, SEEK_CUR); if (error_ptr) { if (result == -1) error_ptr->SetErrorToErrno(); else error_ptr->Clear(); } } else if (error_ptr) { error_ptr->SetErrorString("invalid file handle"); } return result; } off_t File::SeekFromEnd(off_t offset, Status *error_ptr) { off_t result = -1; if (DescriptorIsValid()) { result = ::lseek(m_descriptor, offset, SEEK_END); if (error_ptr) { if (result == -1) error_ptr->SetErrorToErrno(); else error_ptr->Clear(); } } else if (StreamIsValid()) { result = ::fseek(m_stream, offset, SEEK_END); if (error_ptr) { if (result == -1) error_ptr->SetErrorToErrno(); else error_ptr->Clear(); } } else if (error_ptr) { error_ptr->SetErrorString("invalid file handle"); } return result; } Status File::Flush() { Status error; if (StreamIsValid()) { - int err = 0; - do { - err = ::fflush(m_stream); - } while (err == EOF && errno == EINTR); - - if (err == EOF) + if (llvm::sys::RetryAfterSignal(EOF, ::fflush, m_stream) == EOF) error.SetErrorToErrno(); } else if (!DescriptorIsValid()) { error.SetErrorString("invalid file handle"); } return error; } Status File::Sync() { Status error; if (DescriptorIsValid()) { #ifdef _WIN32 int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor)); if (err == 0) error.SetErrorToGenericError(); #else - int err = 0; - do { - err = ::fsync(m_descriptor); - } while (err == -1 && errno == EINTR); - - if (err == -1) + if (llvm::sys::RetryAfterSignal(-1, ::fsync, m_descriptor) == -1) error.SetErrorToErrno(); #endif } else { error.SetErrorString("invalid file handle"); } return error; } #if defined(__APPLE__) // Darwin kernels only can read/write <= INT_MAX bytes #define MAX_READ_SIZE INT_MAX #define MAX_WRITE_SIZE INT_MAX #endif Status File::Read(void *buf, size_t &num_bytes) { Status error; #if defined(MAX_READ_SIZE) if (num_bytes > MAX_READ_SIZE) { uint8_t *p = (uint8_t *)buf; size_t bytes_left = num_bytes; // Init the num_bytes read to zero num_bytes = 0; while (bytes_left > 0) { size_t curr_num_bytes; if (bytes_left > MAX_READ_SIZE) curr_num_bytes = MAX_READ_SIZE; else curr_num_bytes = bytes_left; error = Read(p + num_bytes, curr_num_bytes); // Update how many bytes were read num_bytes += curr_num_bytes; if (bytes_left < curr_num_bytes) bytes_left = 0; else bytes_left -= curr_num_bytes; if (error.Fail()) break; } return error; } #endif ssize_t bytes_read = -1; if (DescriptorIsValid()) { - do { - bytes_read = ::read(m_descriptor, buf, num_bytes); - } while (bytes_read < 0 && errno == EINTR); - + bytes_read = llvm::sys::RetryAfterSignal(-1, ::read, m_descriptor, buf, num_bytes); if (bytes_read == -1) { error.SetErrorToErrno(); num_bytes = 0; } else num_bytes = bytes_read; } else if (StreamIsValid()) { bytes_read = ::fread(buf, 1, num_bytes, m_stream); if (bytes_read == 0) { if (::feof(m_stream)) error.SetErrorString("feof"); else if (::ferror(m_stream)) error.SetErrorString("ferror"); num_bytes = 0; } else num_bytes = bytes_read; } else { num_bytes = 0; error.SetErrorString("invalid file handle"); } return error; } Status File::Write(const void *buf, size_t &num_bytes) { Status error; #if defined(MAX_WRITE_SIZE) if (num_bytes > MAX_WRITE_SIZE) { const uint8_t *p = (const uint8_t *)buf; size_t bytes_left = num_bytes; // Init the num_bytes written to zero num_bytes = 0; while (bytes_left > 0) { size_t curr_num_bytes; if (bytes_left > MAX_WRITE_SIZE) curr_num_bytes = MAX_WRITE_SIZE; else curr_num_bytes = bytes_left; error = Write(p + num_bytes, curr_num_bytes); // Update how many bytes were read num_bytes += curr_num_bytes; if (bytes_left < curr_num_bytes) bytes_left = 0; else bytes_left -= curr_num_bytes; if (error.Fail()) break; } return error; } #endif ssize_t bytes_written = -1; if (DescriptorIsValid()) { - do { - bytes_written = ::write(m_descriptor, buf, num_bytes); - } while (bytes_written < 0 && errno == EINTR); - + bytes_written = + llvm::sys::RetryAfterSignal(-1, ::write, m_descriptor, buf, num_bytes); if (bytes_written == -1) { error.SetErrorToErrno(); num_bytes = 0; } else num_bytes = bytes_written; } else if (StreamIsValid()) { bytes_written = ::fwrite(buf, 1, num_bytes, m_stream); if (bytes_written == 0) { if (::feof(m_stream)) error.SetErrorString("feof"); else if (::ferror(m_stream)) error.SetErrorString("ferror"); num_bytes = 0; } else num_bytes = bytes_written; } else { num_bytes = 0; error.SetErrorString("invalid file handle"); } return error; } Status File::Read(void *buf, size_t &num_bytes, off_t &offset) { Status error; #if defined(MAX_READ_SIZE) if (num_bytes > MAX_READ_SIZE) { uint8_t *p = (uint8_t *)buf; size_t bytes_left = num_bytes; // Init the num_bytes read to zero num_bytes = 0; while (bytes_left > 0) { size_t curr_num_bytes; if (bytes_left > MAX_READ_SIZE) curr_num_bytes = MAX_READ_SIZE; else curr_num_bytes = bytes_left; error = Read(p + num_bytes, curr_num_bytes, offset); // Update how many bytes were read num_bytes += curr_num_bytes; if (bytes_left < curr_num_bytes) bytes_left = 0; else bytes_left -= curr_num_bytes; if (error.Fail()) break; } return error; } #endif #ifndef _WIN32 int fd = GetDescriptor(); if (fd != kInvalidDescriptor) { - ssize_t bytes_read = -1; - do { - bytes_read = ::pread(fd, buf, num_bytes, offset); - } while (bytes_read < 0 && errno == EINTR); - + ssize_t bytes_read = + llvm::sys::RetryAfterSignal(-1, ::pread, fd, buf, num_bytes, offset); if (bytes_read < 0) { num_bytes = 0; error.SetErrorToErrno(); } else { offset += bytes_read; num_bytes = bytes_read; } } else { num_bytes = 0; error.SetErrorString("invalid file handle"); } #else long cur = ::lseek(m_descriptor, 0, SEEK_CUR); SeekFromStart(offset); error = Read(buf, num_bytes); if (!error.Fail()) SeekFromStart(cur); #endif return error; } Status File::Read(size_t &num_bytes, off_t &offset, bool null_terminate, DataBufferSP &data_buffer_sp) { Status error; if (num_bytes > 0) { int fd = GetDescriptor(); if (fd != kInvalidDescriptor) { struct stat file_stats; if (::fstat(fd, &file_stats) == 0) { if (file_stats.st_size > offset) { const size_t bytes_left = file_stats.st_size - offset; if (num_bytes > bytes_left) num_bytes = bytes_left; size_t num_bytes_plus_nul_char = num_bytes + (null_terminate ? 1 : 0); std::unique_ptr data_heap_ap; data_heap_ap.reset(new DataBufferHeap()); data_heap_ap->SetByteSize(num_bytes_plus_nul_char); if (data_heap_ap.get()) { error = Read(data_heap_ap->GetBytes(), num_bytes, offset); if (error.Success()) { // Make sure we read exactly what we asked for and if we got // less, adjust the array if (num_bytes_plus_nul_char < data_heap_ap->GetByteSize()) data_heap_ap->SetByteSize(num_bytes_plus_nul_char); data_buffer_sp.reset(data_heap_ap.release()); return error; } } } else error.SetErrorString("file is empty"); } else error.SetErrorToErrno(); } else error.SetErrorString("invalid file handle"); } else error.SetErrorString("invalid file handle"); num_bytes = 0; data_buffer_sp.reset(); return error; } Status File::Write(const void *buf, size_t &num_bytes, off_t &offset) { Status error; #if defined(MAX_WRITE_SIZE) if (num_bytes > MAX_WRITE_SIZE) { const uint8_t *p = (const uint8_t *)buf; size_t bytes_left = num_bytes; // Init the num_bytes written to zero num_bytes = 0; while (bytes_left > 0) { size_t curr_num_bytes; if (bytes_left > MAX_WRITE_SIZE) curr_num_bytes = MAX_WRITE_SIZE; else curr_num_bytes = bytes_left; error = Write(p + num_bytes, curr_num_bytes, offset); // Update how many bytes were read num_bytes += curr_num_bytes; if (bytes_left < curr_num_bytes) bytes_left = 0; else bytes_left -= curr_num_bytes; if (error.Fail()) break; } return error; } #endif int fd = GetDescriptor(); if (fd != kInvalidDescriptor) { #ifndef _WIN32 - ssize_t bytes_written = -1; - do { - bytes_written = ::pwrite(m_descriptor, buf, num_bytes, offset); - } while (bytes_written < 0 && errno == EINTR); - + ssize_t bytes_written = + llvm::sys::RetryAfterSignal(-1, ::pwrite, m_descriptor, buf, num_bytes, offset); if (bytes_written < 0) { num_bytes = 0; error.SetErrorToErrno(); } else { offset += bytes_written; num_bytes = bytes_written; } #else long cur = ::lseek(m_descriptor, 0, SEEK_CUR); error = Write(buf, num_bytes); long after = ::lseek(m_descriptor, 0, SEEK_CUR); if (!error.Fail()) SeekFromStart(cur); offset = after; #endif } else { num_bytes = 0; error.SetErrorString("invalid file handle"); } return error; } //------------------------------------------------------------------ // Print some formatted output to the stream. //------------------------------------------------------------------ size_t File::Printf(const char *format, ...) { va_list args; va_start(args, format); size_t result = PrintfVarArg(format, args); va_end(args); return result; } //------------------------------------------------------------------ // Print some formatted output to the stream. //------------------------------------------------------------------ size_t File::PrintfVarArg(const char *format, va_list args) { size_t result = 0; if (DescriptorIsValid()) { char *s = NULL; result = vasprintf(&s, format, args); if (s != NULL) { if (result > 0) { size_t s_len = result; Write(s, s_len); result = s_len; } free(s); } } else if (StreamIsValid()) { result = ::vfprintf(m_stream, format, args); } return result; } mode_t File::ConvertOpenOptionsForPOSIXOpen(uint32_t open_options) { mode_t mode = 0; if (open_options & eOpenOptionRead && open_options & eOpenOptionWrite) mode |= O_RDWR; else if (open_options & eOpenOptionWrite) mode |= O_WRONLY; if (open_options & eOpenOptionAppend) mode |= O_APPEND; if (open_options & eOpenOptionTruncate) mode |= O_TRUNC; if (open_options & eOpenOptionNonBlocking) mode |= O_NONBLOCK; if (open_options & eOpenOptionCanCreateNewOnly) mode |= O_CREAT | O_EXCL; else if (open_options & eOpenOptionCanCreate) mode |= O_CREAT; return mode; } void File::CalculateInteractiveAndTerminal() { const int fd = GetDescriptor(); if (fd >= 0) { m_is_interactive = eLazyBoolNo; m_is_real_terminal = eLazyBoolNo; #if defined(_WIN32) if (_isatty(fd)) { m_is_interactive = eLazyBoolYes; m_is_real_terminal = eLazyBoolYes; } #else if (isatty(fd)) { m_is_interactive = eLazyBoolYes; struct winsize window_size; if (::ioctl(fd, TIOCGWINSZ, &window_size) == 0) { if (window_size.ws_col > 0) { m_is_real_terminal = eLazyBoolYes; if (llvm::sys::Process::FileDescriptorHasColors(fd)) m_supports_colors = eLazyBoolYes; } } } #endif } } bool File::GetIsInteractive() { if (m_is_interactive == eLazyBoolCalculate) CalculateInteractiveAndTerminal(); return m_is_interactive == eLazyBoolYes; } bool File::GetIsRealTerminal() { if (m_is_real_terminal == eLazyBoolCalculate) CalculateInteractiveAndTerminal(); return m_is_real_terminal == eLazyBoolYes; } bool File::GetIsTerminalWithColors() { if (m_supports_colors == eLazyBoolCalculate) CalculateInteractiveAndTerminal(); return m_supports_colors == eLazyBoolYes; } Index: vendor/lldb/dist/source/Host/common/MainLoop.cpp =================================================================== --- vendor/lldb/dist/source/Host/common/MainLoop.cpp (revision 320966) +++ vendor/lldb/dist/source/Host/common/MainLoop.cpp (revision 320967) @@ -1,377 +1,386 @@ //===-- MainLoop.cpp --------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "llvm/Config/llvm-config.h" #include "lldb/Host/MainLoop.h" #include "lldb/Utility/Status.h" #include #include #include #include #include #include // Multiplexing is implemented using kqueue on systems that support it (BSD // variants including OSX). On linux we use ppoll, while android uses pselect // (ppoll is present but not implemented properly). On windows we use WSApoll // (which does not support signals). #if HAVE_SYS_EVENT_H #include #elif defined(LLVM_ON_WIN32) #include #else #include #endif #ifdef LLVM_ON_WIN32 #define POLL WSAPoll #else #define POLL poll #endif #ifdef __ANDROID__ #define FORCE_PSELECT #endif #if SIGNAL_POLLING_UNSUPPORTED #ifdef LLVM_ON_WIN32 typedef int sigset_t; typedef int siginfo_t; #endif int ppoll(struct pollfd *fds, size_t nfds, const struct timespec *timeout_ts, const sigset_t *) { int timeout = (timeout_ts == nullptr) ? -1 : (timeout_ts->tv_sec * 1000 + timeout_ts->tv_nsec / 1000000); return POLL(fds, nfds, timeout); } #endif using namespace lldb; using namespace lldb_private; static sig_atomic_t g_signal_flags[NSIG]; static void SignalHandler(int signo, siginfo_t *info, void *) { assert(signo < NSIG); g_signal_flags[signo] = 1; } class MainLoop::RunImpl { public: RunImpl(MainLoop &loop); ~RunImpl() = default; Status Poll(); void ProcessEvents(); private: MainLoop &loop; #if HAVE_SYS_EVENT_H std::vector in_events; struct kevent out_events[4]; int num_events = -1; #else #ifdef FORCE_PSELECT fd_set read_fd_set; #else std::vector read_fds; #endif sigset_t get_sigmask(); #endif }; #if HAVE_SYS_EVENT_H MainLoop::RunImpl::RunImpl(MainLoop &loop) : loop(loop) { in_events.reserve(loop.m_read_fds.size()); } Status MainLoop::RunImpl::Poll() { in_events.resize(loop.m_read_fds.size()); unsigned i = 0; for (auto &fd : loop.m_read_fds) EV_SET(&in_events[i++], fd.first, EVFILT_READ, EV_ADD, 0, 0, 0); num_events = kevent(loop.m_kqueue, in_events.data(), in_events.size(), out_events, llvm::array_lengthof(out_events), nullptr); if (num_events < 0) return Status("kevent() failed with error %d\n", num_events); return Status(); } void MainLoop::RunImpl::ProcessEvents() { assert(num_events >= 0); for (int i = 0; i < num_events; ++i) { if (loop.m_terminate_request) return; switch (out_events[i].filter) { case EVFILT_READ: loop.ProcessReadObject(out_events[i].ident); break; case EVFILT_SIGNAL: loop.ProcessSignal(out_events[i].ident); break; default: llvm_unreachable("Unknown event"); } } } #else MainLoop::RunImpl::RunImpl(MainLoop &loop) : loop(loop) { #ifndef FORCE_PSELECT read_fds.reserve(loop.m_read_fds.size()); #endif } sigset_t MainLoop::RunImpl::get_sigmask() { #if SIGNAL_POLLING_UNSUPPORTED return 0; #else sigset_t sigmask; int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask); assert(ret == 0); (void) ret; for (const auto &sig : loop.m_signals) sigdelset(&sigmask, sig.first); return sigmask; #endif } #ifdef FORCE_PSELECT Status MainLoop::RunImpl::Poll() { FD_ZERO(&read_fd_set); int nfds = 0; for (const auto &fd : loop.m_read_fds) { FD_SET(fd.first, &read_fd_set); nfds = std::max(nfds, fd.first + 1); } sigset_t sigmask = get_sigmask(); if (pselect(nfds, &read_fd_set, nullptr, nullptr, nullptr, &sigmask) == -1 && errno != EINTR) return Status(errno, eErrorTypePOSIX); return Status(); } #else Status MainLoop::RunImpl::Poll() { read_fds.clear(); sigset_t sigmask = get_sigmask(); for (const auto &fd : loop.m_read_fds) { struct pollfd pfd; pfd.fd = fd.first; pfd.events = POLLIN; pfd.revents = 0; read_fds.push_back(pfd); } if (ppoll(read_fds.data(), read_fds.size(), nullptr, &sigmask) == -1 && errno != EINTR) return Status(errno, eErrorTypePOSIX); return Status(); } #endif void MainLoop::RunImpl::ProcessEvents() { #ifdef FORCE_PSELECT - for (const auto &fd : loop.m_read_fds) { - if (!FD_ISSET(fd.first, &read_fd_set)) - continue; - IOObject::WaitableHandle handle = fd.first; + // Collect first all readable file descriptors into a separate vector and then + // iterate over it to invoke callbacks. Iterating directly over + // loop.m_read_fds is not possible because the callbacks can modify the + // container which could invalidate the iterator. + std::vector fds; + for (const auto &fd : loop.m_read_fds) + if (FD_ISSET(fd.first, &read_fd_set)) + fds.push_back(fd.first); + + for (const auto &handle : fds) { #else for (const auto &fd : read_fds) { if ((fd.revents & POLLIN) == 0) continue; IOObject::WaitableHandle handle = fd.fd; #endif if (loop.m_terminate_request) return; loop.ProcessReadObject(handle); } - for (const auto &entry : loop.m_signals) { + std::vector signals; + for (const auto &entry : loop.m_signals) + if (g_signal_flags[entry.first] != 0) + signals.push_back(entry.first); + + for (const auto &signal : signals) { if (loop.m_terminate_request) return; - if (g_signal_flags[entry.first] == 0) - continue; // No signal - g_signal_flags[entry.first] = 0; - loop.ProcessSignal(entry.first); + g_signal_flags[signal] = 0; + loop.ProcessSignal(signal); } } #endif MainLoop::MainLoop() { #if HAVE_SYS_EVENT_H m_kqueue = kqueue(); assert(m_kqueue >= 0); #endif } MainLoop::~MainLoop() { #if HAVE_SYS_EVENT_H close(m_kqueue); #endif assert(m_read_fds.size() == 0); assert(m_signals.size() == 0); } MainLoop::ReadHandleUP MainLoop::RegisterReadObject(const IOObjectSP &object_sp, const Callback &callback, Status &error) { #ifdef LLVM_ON_WIN32 if (object_sp->GetFdType() != IOObject:: eFDTypeSocket) { error.SetErrorString("MainLoop: non-socket types unsupported on Windows"); return nullptr; } #endif if (!object_sp || !object_sp->IsValid()) { error.SetErrorString("IO object is not valid."); return nullptr; } const bool inserted = m_read_fds.insert({object_sp->GetWaitableHandle(), callback}).second; if (!inserted) { error.SetErrorStringWithFormat("File descriptor %d already monitored.", object_sp->GetWaitableHandle()); return nullptr; } return CreateReadHandle(object_sp); } // We shall block the signal, then install the signal handler. The signal will // be unblocked in // the Run() function to check for signal delivery. MainLoop::SignalHandleUP MainLoop::RegisterSignal(int signo, const Callback &callback, Status &error) { #ifdef SIGNAL_POLLING_UNSUPPORTED error.SetErrorString("Signal polling is not supported on this platform."); return nullptr; #else if (m_signals.find(signo) != m_signals.end()) { error.SetErrorStringWithFormat("Signal %d already monitored.", signo); return nullptr; } SignalInfo info; info.callback = callback; struct sigaction new_action; new_action.sa_sigaction = &SignalHandler; new_action.sa_flags = SA_SIGINFO; sigemptyset(&new_action.sa_mask); sigaddset(&new_action.sa_mask, signo); sigset_t old_set; g_signal_flags[signo] = 0; // Even if using kqueue, the signal handler will still be invoked, so it's // important to replace it with our "bening" handler. int ret = sigaction(signo, &new_action, &info.old_action); assert(ret == 0 && "sigaction failed"); #if HAVE_SYS_EVENT_H struct kevent ev; EV_SET(&ev, signo, EVFILT_SIGNAL, EV_ADD, 0, 0, 0); ret = kevent(m_kqueue, &ev, 1, nullptr, 0, nullptr); assert(ret == 0); #endif // If we're using kqueue, the signal needs to be unblocked in order to recieve // it. If using pselect/ppoll, we need to block it, and later unblock it as a // part of the system call. ret = pthread_sigmask(HAVE_SYS_EVENT_H ? SIG_UNBLOCK : SIG_BLOCK, &new_action.sa_mask, &old_set); assert(ret == 0 && "pthread_sigmask failed"); info.was_blocked = sigismember(&old_set, signo); m_signals.insert({signo, info}); return SignalHandleUP(new SignalHandle(*this, signo)); #endif } void MainLoop::UnregisterReadObject(IOObject::WaitableHandle handle) { bool erased = m_read_fds.erase(handle); UNUSED_IF_ASSERT_DISABLED(erased); assert(erased); } void MainLoop::UnregisterSignal(int signo) { #if SIGNAL_POLLING_UNSUPPORTED Status("Signal polling is not supported on this platform."); #else auto it = m_signals.find(signo); assert(it != m_signals.end()); sigaction(signo, &it->second.old_action, nullptr); sigset_t set; sigemptyset(&set); sigaddset(&set, signo); int ret = pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK, &set, nullptr); assert(ret == 0); (void)ret; #if HAVE_SYS_EVENT_H struct kevent ev; EV_SET(&ev, signo, EVFILT_SIGNAL, EV_DELETE, 0, 0, 0); ret = kevent(m_kqueue, &ev, 1, nullptr, 0, nullptr); assert(ret == 0); #endif m_signals.erase(it); #endif } Status MainLoop::Run() { m_terminate_request = false; Status error; RunImpl impl(*this); // run until termination or until we run out of things to listen to while (!m_terminate_request && (!m_read_fds.empty() || !m_signals.empty())) { error = impl.Poll(); if (error.Fail()) return error; impl.ProcessEvents(); if (m_terminate_request) return Status(); } return Status(); } void MainLoop::ProcessSignal(int signo) { auto it = m_signals.find(signo); if (it != m_signals.end()) it->second.callback(*this); // Do the work } void MainLoop::ProcessReadObject(IOObject::WaitableHandle handle) { auto it = m_read_fds.find(handle); if (it != m_read_fds.end()) it->second(*this); // Do the work } Index: vendor/lldb/dist/source/Host/common/NativeProcessProtocol.cpp =================================================================== --- vendor/lldb/dist/source/Host/common/NativeProcessProtocol.cpp (revision 320966) +++ vendor/lldb/dist/source/Host/common/NativeProcessProtocol.cpp (revision 320967) @@ -1,510 +1,493 @@ //===-- NativeProcessProtocol.cpp -------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/State.h" #include "lldb/Host/Host.h" #include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Host/common/NativeThreadProtocol.h" #include "lldb/Host/common/SoftwareBreakpoint.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Process.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" #include "lldb/lldb-enumerations.h" using namespace lldb; using namespace lldb_private; // ----------------------------------------------------------------------------- // NativeProcessProtocol Members // ----------------------------------------------------------------------------- -NativeProcessProtocol::NativeProcessProtocol(lldb::pid_t pid) - : m_pid(pid), m_threads(), m_current_thread_id(LLDB_INVALID_THREAD_ID), - m_threads_mutex(), m_state(lldb::eStateInvalid), m_state_mutex(), - m_delegates_mutex(), m_delegates(), m_breakpoint_list(), - m_watchpoint_list(), m_terminal_fd(-1), m_stop_id(0) {} +NativeProcessProtocol::NativeProcessProtocol(lldb::pid_t pid, int terminal_fd, + NativeDelegate &delegate) + : m_pid(pid), m_terminal_fd(terminal_fd) { + bool registered = RegisterNativeDelegate(delegate); + assert(registered); + (void)registered; +} lldb_private::Status NativeProcessProtocol::Interrupt() { Status error; #if !defined(SIGSTOP) error.SetErrorString("local host does not support signaling"); return error; #else return Signal(SIGSTOP); #endif } Status NativeProcessProtocol::IgnoreSignals(llvm::ArrayRef signals) { m_signals_to_ignore.clear(); m_signals_to_ignore.insert(signals.begin(), signals.end()); return Status(); } lldb_private::Status NativeProcessProtocol::GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info) { // Default: not implemented. return Status("not implemented"); } llvm::Optional NativeProcessProtocol::GetExitStatus() { if (m_state == lldb::eStateExited) return m_exit_status; return llvm::None; } bool NativeProcessProtocol::SetExitStatus(WaitStatus status, bool bNotifyStateChange) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); LLDB_LOG(log, "status = {0}, notify = {1}", status, bNotifyStateChange); // Exit status already set if (m_state == lldb::eStateExited) { if (m_exit_status) LLDB_LOG(log, "exit status already set to {0}", *m_exit_status); else LLDB_LOG(log, "state is exited, but status not set"); return false; } m_state = lldb::eStateExited; m_exit_status = status; if (bNotifyStateChange) SynchronouslyNotifyProcessStateChanged(lldb::eStateExited); return true; } NativeThreadProtocolSP NativeProcessProtocol::GetThreadAtIndex(uint32_t idx) { std::lock_guard guard(m_threads_mutex); if (idx < m_threads.size()) return m_threads[idx]; return NativeThreadProtocolSP(); } NativeThreadProtocolSP NativeProcessProtocol::GetThreadByIDUnlocked(lldb::tid_t tid) { for (auto thread_sp : m_threads) { if (thread_sp->GetID() == tid) return thread_sp; } return NativeThreadProtocolSP(); } NativeThreadProtocolSP NativeProcessProtocol::GetThreadByID(lldb::tid_t tid) { std::lock_guard guard(m_threads_mutex); return GetThreadByIDUnlocked(tid); } bool NativeProcessProtocol::IsAlive() const { return m_state != eStateDetached && m_state != eStateExited && m_state != eStateInvalid && m_state != eStateUnloaded; } bool NativeProcessProtocol::GetByteOrder(lldb::ByteOrder &byte_order) const { ArchSpec process_arch; if (!GetArchitecture(process_arch)) return false; byte_order = process_arch.GetByteOrder(); return true; } const NativeWatchpointList::WatchpointMap & NativeProcessProtocol::GetWatchpointMap() const { return m_watchpoint_list.GetWatchpointMap(); } llvm::Optional> NativeProcessProtocol::GetHardwareDebugSupportInfo() const { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); // get any thread NativeThreadProtocolSP thread_sp( const_cast(this)->GetThreadAtIndex(0)); if (!thread_sp) { if (log) log->Warning("NativeProcessProtocol::%s (): failed to find a thread to " "grab a NativeRegisterContext!", __FUNCTION__); return llvm::None; } NativeRegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); if (!reg_ctx_sp) { if (log) log->Warning("NativeProcessProtocol::%s (): failed to get a " "RegisterContextNativeProcess from the first thread!", __FUNCTION__); return llvm::None; } return std::make_pair(reg_ctx_sp->NumSupportedHardwareBreakpoints(), reg_ctx_sp->NumSupportedHardwareWatchpoints()); } Status NativeProcessProtocol::SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) { // This default implementation assumes setting the watchpoint for // the process will require setting the watchpoint for each of the // threads. Furthermore, it will track watchpoints set for the // process and will add them to each thread that is attached to // via the (FIXME implement) OnThreadAttached () method. Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); // Update the thread list UpdateThreads(); // Keep track of the threads we successfully set the watchpoint // for. If one of the thread watchpoint setting operations fails, // back off and remove the watchpoint for all the threads that // were successfully set so we get back to a consistent state. std::vector watchpoint_established_threads; // Tell each thread to set a watchpoint. In the event that // hardware watchpoints are requested but the SetWatchpoint fails, // try to set a software watchpoint as a fallback. It's // conceivable that if there are more threads than hardware // watchpoints available, some of the threads will fail to set // hardware watchpoints while software ones may be available. std::lock_guard guard(m_threads_mutex); for (auto thread_sp : m_threads) { assert(thread_sp && "thread list should not have a NULL thread!"); if (!thread_sp) continue; Status thread_error = thread_sp->SetWatchpoint(addr, size, watch_flags, hardware); if (thread_error.Fail() && hardware) { // Try software watchpoints since we failed on hardware watchpoint setting // and we may have just run out of hardware watchpoints. thread_error = thread_sp->SetWatchpoint(addr, size, watch_flags, false); if (thread_error.Success()) { if (log) log->Warning( "hardware watchpoint requested but software watchpoint set"); } } if (thread_error.Success()) { // Remember that we set this watchpoint successfully in // case we need to clear it later. watchpoint_established_threads.push_back(thread_sp); } else { // Unset the watchpoint for each thread we successfully // set so that we get back to a consistent state of "not // set" for the watchpoint. for (auto unwatch_thread_sp : watchpoint_established_threads) { Status remove_error = unwatch_thread_sp->RemoveWatchpoint(addr); if (remove_error.Fail() && log) { log->Warning("NativeProcessProtocol::%s (): RemoveWatchpoint failed " "for pid=%" PRIu64 ", tid=%" PRIu64 ": %s", __FUNCTION__, GetID(), unwatch_thread_sp->GetID(), remove_error.AsCString()); } } return thread_error; } } return m_watchpoint_list.Add(addr, size, watch_flags, hardware); } Status NativeProcessProtocol::RemoveWatchpoint(lldb::addr_t addr) { // Update the thread list UpdateThreads(); Status overall_error; std::lock_guard guard(m_threads_mutex); for (auto thread_sp : m_threads) { assert(thread_sp && "thread list should not have a NULL thread!"); if (!thread_sp) continue; const Status thread_error = thread_sp->RemoveWatchpoint(addr); if (thread_error.Fail()) { // Keep track of the first thread error if any threads // fail. We want to try to remove the watchpoint from // every thread, though, even if one or more have errors. if (!overall_error.Fail()) overall_error = thread_error; } } const Status error = m_watchpoint_list.Remove(addr); return overall_error.Fail() ? overall_error : error; } const HardwareBreakpointMap & NativeProcessProtocol::GetHardwareBreakpointMap() const { return m_hw_breakpoints_map; } Status NativeProcessProtocol::SetHardwareBreakpoint(lldb::addr_t addr, size_t size) { // This default implementation assumes setting a hardware breakpoint for // this process will require setting same hardware breakpoint for each // of its existing threads. New thread will do the same once created. Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); // Update the thread list UpdateThreads(); // Exit here if target does not have required hardware breakpoint capability. auto hw_debug_cap = GetHardwareDebugSupportInfo(); if (hw_debug_cap == llvm::None || hw_debug_cap->first == 0 || hw_debug_cap->first <= m_hw_breakpoints_map.size()) return Status("Target does not have required no of hardware breakpoints"); // Vector below stores all thread pointer for which we have we successfully // set this hardware breakpoint. If any of the current process threads fails // to set this hardware breakpoint then roll back and remove this breakpoint // for all the threads that had already set it successfully. std::vector breakpoint_established_threads; // Request to set a hardware breakpoint for each of current process threads. std::lock_guard guard(m_threads_mutex); for (auto thread_sp : m_threads) { assert(thread_sp && "thread list should not have a NULL thread!"); if (!thread_sp) continue; Status thread_error = thread_sp->SetHardwareBreakpoint(addr, size); if (thread_error.Success()) { // Remember that we set this breakpoint successfully in // case we need to clear it later. breakpoint_established_threads.push_back(thread_sp); } else { // Unset the breakpoint for each thread we successfully // set so that we get back to a consistent state of "not // set" for this hardware breakpoint. for (auto rollback_thread_sp : breakpoint_established_threads) { Status remove_error = rollback_thread_sp->RemoveHardwareBreakpoint(addr); if (remove_error.Fail() && log) { log->Warning("NativeProcessProtocol::%s (): RemoveHardwareBreakpoint" " failed for pid=%" PRIu64 ", tid=%" PRIu64 ": %s", __FUNCTION__, GetID(), rollback_thread_sp->GetID(), remove_error.AsCString()); } } return thread_error; } } // Register new hardware breakpoint into hardware breakpoints map of current // process. m_hw_breakpoints_map[addr] = {addr, size}; return Status(); } Status NativeProcessProtocol::RemoveHardwareBreakpoint(lldb::addr_t addr) { // Update the thread list UpdateThreads(); Status error; std::lock_guard guard(m_threads_mutex); for (auto thread_sp : m_threads) { assert(thread_sp && "thread list should not have a NULL thread!"); if (!thread_sp) continue; error = thread_sp->RemoveHardwareBreakpoint(addr); } // Also remove from hardware breakpoint map of current process. m_hw_breakpoints_map.erase(addr); return error; } bool NativeProcessProtocol::RegisterNativeDelegate( NativeDelegate &native_delegate) { std::lock_guard guard(m_delegates_mutex); if (std::find(m_delegates.begin(), m_delegates.end(), &native_delegate) != m_delegates.end()) return false; m_delegates.push_back(&native_delegate); native_delegate.InitializeDelegate(this); return true; } bool NativeProcessProtocol::UnregisterNativeDelegate( NativeDelegate &native_delegate) { std::lock_guard guard(m_delegates_mutex); const auto initial_size = m_delegates.size(); m_delegates.erase( remove(m_delegates.begin(), m_delegates.end(), &native_delegate), m_delegates.end()); // We removed the delegate if the count of delegates shrank after // removing all copies of the given native_delegate from the vector. return m_delegates.size() < initial_size; } void NativeProcessProtocol::SynchronouslyNotifyProcessStateChanged( lldb::StateType state) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); std::lock_guard guard(m_delegates_mutex); for (auto native_delegate : m_delegates) native_delegate->ProcessStateChanged(this, state); if (log) { if (!m_delegates.empty()) { log->Printf("NativeProcessProtocol::%s: sent state notification [%s] " "from process %" PRIu64, __FUNCTION__, lldb_private::StateAsCString(state), GetID()); } else { log->Printf("NativeProcessProtocol::%s: would send state notification " "[%s] from process %" PRIu64 ", but no delegates", __FUNCTION__, lldb_private::StateAsCString(state), GetID()); } } } void NativeProcessProtocol::NotifyDidExec() { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) log->Printf("NativeProcessProtocol::%s - preparing to call delegates", __FUNCTION__); { std::lock_guard guard(m_delegates_mutex); for (auto native_delegate : m_delegates) native_delegate->DidExec(this); } } Status NativeProcessProtocol::SetSoftwareBreakpoint(lldb::addr_t addr, uint32_t size_hint) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); if (log) log->Printf("NativeProcessProtocol::%s addr = 0x%" PRIx64, __FUNCTION__, addr); return m_breakpoint_list.AddRef( addr, size_hint, false, [this](lldb::addr_t addr, size_t size_hint, bool /* hardware */, NativeBreakpointSP &breakpoint_sp) -> Status { return SoftwareBreakpoint::CreateSoftwareBreakpoint( *this, addr, size_hint, breakpoint_sp); }); } Status NativeProcessProtocol::RemoveBreakpoint(lldb::addr_t addr, bool hardware) { if (hardware) return RemoveHardwareBreakpoint(addr); else return m_breakpoint_list.DecRef(addr); } Status NativeProcessProtocol::EnableBreakpoint(lldb::addr_t addr) { return m_breakpoint_list.EnableBreakpoint(addr); } Status NativeProcessProtocol::DisableBreakpoint(lldb::addr_t addr) { return m_breakpoint_list.DisableBreakpoint(addr); } lldb::StateType NativeProcessProtocol::GetState() const { std::lock_guard guard(m_state_mutex); return m_state; } void NativeProcessProtocol::SetState(lldb::StateType state, bool notify_delegates) { std::lock_guard guard(m_state_mutex); if (state == m_state) return; m_state = state; if (StateIsStoppedState(state, false)) { ++m_stop_id; // Give process a chance to do any stop id bump processing, such as // clearing cached data that is invalidated each time the process runs. // Note if/when we support some threads running, we'll end up needing // to manage this per thread and per process. DoStopIDBumped(m_stop_id); } // Optionally notify delegates of the state change. if (notify_delegates) SynchronouslyNotifyProcessStateChanged(state); } uint32_t NativeProcessProtocol::GetStopID() const { std::lock_guard guard(m_state_mutex); return m_stop_id; } void NativeProcessProtocol::DoStopIDBumped(uint32_t /* newBumpId */) { // Default implementation does nothing. } Status NativeProcessProtocol::ResolveProcessArchitecture(lldb::pid_t pid, ArchSpec &arch) { // Grab process info for the running process. ProcessInstanceInfo process_info; if (!Host::GetProcessInfo(pid, process_info)) return Status("failed to get process info"); // Resolve the executable module. ModuleSpecList module_specs; if (!ObjectFile::GetModuleSpecifications(process_info.GetExecutableFile(), 0, 0, module_specs)) return Status("failed to get module specifications"); lldbassert(module_specs.GetSize() == 1); arch = module_specs.GetModuleSpecRefAtIndex(0).GetArchitecture(); if (arch.IsValid()) return Status(); else return Status( "failed to retrieve a valid architecture from the exe module"); } -#if !defined(__linux__) && !defined(__NetBSD__) -// These need to be implemented to support lldb-gdb-server on a given platform. -// Stubs are -// provided to make the rest of the code link on non-supported platforms. - -Status NativeProcessProtocol::Launch(ProcessLaunchInfo &launch_info, - NativeDelegate &native_delegate, - MainLoop &mainloop, - NativeProcessProtocolSP &process_sp) { - llvm_unreachable("Platform has no NativeProcessProtocol support"); -} - -Status NativeProcessProtocol::Attach(lldb::pid_t pid, - NativeDelegate &native_delegate, - MainLoop &mainloop, - NativeProcessProtocolSP &process_sp) { - llvm_unreachable("Platform has no NativeProcessProtocol support"); -} - -#endif +NativeProcessProtocol::Factory::~Factory() = default; Index: vendor/lldb/dist/source/Host/common/SocketAddress.cpp =================================================================== --- vendor/lldb/dist/source/Host/common/SocketAddress.cpp (revision 320966) +++ vendor/lldb/dist/source/Host/common/SocketAddress.cpp (revision 320967) @@ -1,338 +1,338 @@ //===-- SocketAddress.cpp ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // Note: This file is used on Darwin by debugserver, so it needs to remain as // self contained as possible, and devoid of references to LLVM unless // there is compelling reason. // //===----------------------------------------------------------------------===// #if defined(_MSC_VER) #define _WINSOCK_DEPRECATED_NO_WARNINGS #endif #include "lldb/Host/SocketAddress.h" #include #include // C Includes #if !defined(_WIN32) #include #endif #include #include // C++ Includes // Other libraries and framework includes // Project includes #include "lldb/Host/PosixApi.h" // WindowsXP needs an inet_ntop implementation #ifdef _WIN32 #ifndef INET6_ADDRSTRLEN // might not be defined in older Windows SDKs #define INET6_ADDRSTRLEN 46 #endif // TODO: implement shortened form "::" for runs of zeros const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) { if (size == 0) { return nullptr; } switch (af) { case AF_INET: { { const char *formatted = inet_ntoa(*static_cast(src)); if (formatted && strlen(formatted) < static_cast(size)) { return ::strcpy(dst, formatted); } } return nullptr; case AF_INET6: { char tmp[INET6_ADDRSTRLEN] = {0}; const uint16_t *src16 = static_cast(src); int full_size = ::snprintf( tmp, sizeof(tmp), "%x:%x:%x:%x:%x:%x:%x:%x", ntohs(src16[0]), ntohs(src16[1]), ntohs(src16[2]), ntohs(src16[3]), ntohs(src16[4]), ntohs(src16[5]), ntohs(src16[6]), ntohs(src16[7])); if (full_size < static_cast(size)) { return ::strcpy(dst, tmp); } return nullptr; } } } return nullptr; } #endif using namespace lldb_private; //---------------------------------------------------------------------- // SocketAddress constructor //---------------------------------------------------------------------- SocketAddress::SocketAddress() { Clear(); } SocketAddress::SocketAddress(const struct sockaddr &s) { m_socket_addr.sa = s; } SocketAddress::SocketAddress(const struct sockaddr_in &s) { m_socket_addr.sa_ipv4 = s; } SocketAddress::SocketAddress(const struct sockaddr_in6 &s) { m_socket_addr.sa_ipv6 = s; } SocketAddress::SocketAddress(const struct sockaddr_storage &s) { m_socket_addr.sa_storage = s; } SocketAddress::SocketAddress(const struct addrinfo *addr_info) { *this = addr_info; } //---------------------------------------------------------------------- // SocketAddress copy constructor //---------------------------------------------------------------------- SocketAddress::SocketAddress(const SocketAddress &rhs) : m_socket_addr(rhs.m_socket_addr) {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- SocketAddress::~SocketAddress() {} void SocketAddress::Clear() { memset(&m_socket_addr, 0, sizeof(m_socket_addr)); } bool SocketAddress::IsValid() const { return GetLength() != 0; } static socklen_t GetFamilyLength(sa_family_t family) { switch (family) { case AF_INET: return sizeof(struct sockaddr_in); case AF_INET6: return sizeof(struct sockaddr_in6); } assert(0 && "Unsupported address family"); return 0; } socklen_t SocketAddress::GetLength() const { #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) return m_socket_addr.sa.sa_len; #else return GetFamilyLength(GetFamily()); #endif } socklen_t SocketAddress::GetMaxLength() { return sizeof(sockaddr_t); } sa_family_t SocketAddress::GetFamily() const { return m_socket_addr.sa.sa_family; } void SocketAddress::SetFamily(sa_family_t family) { m_socket_addr.sa.sa_family = family; #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) m_socket_addr.sa.sa_len = GetFamilyLength(family); #endif } std::string SocketAddress::GetIPAddress() const { char str[INET6_ADDRSTRLEN] = {0}; switch (GetFamily()) { case AF_INET: if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv4.sin_addr, str, sizeof(str))) return str; break; case AF_INET6: if (inet_ntop(GetFamily(), &m_socket_addr.sa_ipv6.sin6_addr, str, sizeof(str))) return str; break; } return ""; } uint16_t SocketAddress::GetPort() const { switch (GetFamily()) { case AF_INET: return ntohs(m_socket_addr.sa_ipv4.sin_port); case AF_INET6: return ntohs(m_socket_addr.sa_ipv6.sin6_port); } return 0; } bool SocketAddress::SetPort(uint16_t port) { switch (GetFamily()) { case AF_INET: m_socket_addr.sa_ipv4.sin_port = htons(port); return true; case AF_INET6: m_socket_addr.sa_ipv6.sin6_port = htons(port); return true; } return false; } //---------------------------------------------------------------------- // SocketAddress assignment operator //---------------------------------------------------------------------- const SocketAddress &SocketAddress::operator=(const SocketAddress &rhs) { if (this != &rhs) m_socket_addr = rhs.m_socket_addr; return *this; } const SocketAddress &SocketAddress:: operator=(const struct addrinfo *addr_info) { Clear(); if (addr_info && addr_info->ai_addr && addr_info->ai_addrlen > 0 && - addr_info->ai_addrlen <= sizeof m_socket_addr) { + size_t(addr_info->ai_addrlen) <= sizeof m_socket_addr) { ::memcpy(&m_socket_addr, addr_info->ai_addr, addr_info->ai_addrlen); } return *this; } const SocketAddress &SocketAddress::operator=(const struct sockaddr &s) { m_socket_addr.sa = s; return *this; } const SocketAddress &SocketAddress::operator=(const struct sockaddr_in &s) { m_socket_addr.sa_ipv4 = s; return *this; } const SocketAddress &SocketAddress::operator=(const struct sockaddr_in6 &s) { m_socket_addr.sa_ipv6 = s; return *this; } const SocketAddress &SocketAddress:: operator=(const struct sockaddr_storage &s) { m_socket_addr.sa_storage = s; return *this; } bool SocketAddress::getaddrinfo(const char *host, const char *service, int ai_family, int ai_socktype, int ai_protocol, int ai_flags) { Clear(); auto addresses = GetAddressInfo(host, service, ai_family, ai_socktype, ai_protocol, ai_flags); if (!addresses.empty()) *this = addresses[0]; return IsValid(); } std::vector SocketAddress::GetAddressInfo(const char *hostname, const char *servname, int ai_family, int ai_socktype, int ai_protocol, int ai_flags) { std::vector addr_list; struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = ai_family; hints.ai_socktype = ai_socktype; hints.ai_protocol = ai_protocol; hints.ai_flags = ai_flags; struct addrinfo *service_info_list = NULL; int err = ::getaddrinfo(hostname, servname, &hints, &service_info_list); if (err == 0 && service_info_list) { for (struct addrinfo *service_ptr = service_info_list; service_ptr != NULL; service_ptr = service_ptr->ai_next) { addr_list.emplace_back(SocketAddress(service_ptr)); } } if (service_info_list) ::freeaddrinfo(service_info_list); return addr_list; } bool SocketAddress::SetToLocalhost(sa_family_t family, uint16_t port) { switch (family) { case AF_INET: SetFamily(AF_INET); if (SetPort(port)) { m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); return true; } break; case AF_INET6: SetFamily(AF_INET6); if (SetPort(port)) { m_socket_addr.sa_ipv6.sin6_addr = in6addr_loopback; return true; } break; } Clear(); return false; } bool SocketAddress::SetToAnyAddress(sa_family_t family, uint16_t port) { switch (family) { case AF_INET: SetFamily(AF_INET); if (SetPort(port)) { m_socket_addr.sa_ipv4.sin_addr.s_addr = htonl(INADDR_ANY); return true; } break; case AF_INET6: SetFamily(AF_INET6); if (SetPort(port)) { m_socket_addr.sa_ipv6.sin6_addr = in6addr_any; return true; } break; } Clear(); return false; } bool SocketAddress::IsAnyAddr() const { return (GetFamily() == AF_INET) ? m_socket_addr.sa_ipv4.sin_addr.s_addr == htonl(INADDR_ANY) : 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, &in6addr_any, 16); } bool SocketAddress::operator==(const SocketAddress &rhs) const { if (GetFamily() != rhs.GetFamily()) return false; if (GetLength() != rhs.GetLength()) return false; switch (GetFamily()) { case AF_INET: return m_socket_addr.sa_ipv4.sin_addr.s_addr == rhs.m_socket_addr.sa_ipv4.sin_addr.s_addr; case AF_INET6: return 0 == memcmp(&m_socket_addr.sa_ipv6.sin6_addr, &rhs.m_socket_addr.sa_ipv6.sin6_addr, 16); } return false; } bool SocketAddress::operator!=(const SocketAddress &rhs) const { return !(*this == rhs); } Index: vendor/lldb/dist/source/Host/macosx/Host.mm =================================================================== --- vendor/lldb/dist/source/Host/macosx/Host.mm (revision 320966) +++ vendor/lldb/dist/source/Host/macosx/Host.mm (revision 320967) @@ -1,1744 +1,1742 @@ //===-- Host.mm -------------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/Host/Host.h" #include #if !defined(MAC_OS_X_VERSION_10_7) || \ MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 #define NO_XPC_SERVICES 1 #endif #if !defined(NO_XPC_SERVICES) #define __XPC_PRIVATE_H__ #include #define LaunchUsingXPCRightName "com.apple.dt.Xcode.RootDebuggingXPCService" // These XPC messaging keys are used for communication between Host.mm and the // XPC service. #define LauncherXPCServiceAuthKey "auth-key" #define LauncherXPCServiceArgPrefxKey "arg" #define LauncherXPCServiceEnvPrefxKey "env" #define LauncherXPCServiceCPUTypeKey "cpuType" #define LauncherXPCServicePosixspawnFlagsKey "posixspawnFlags" #define LauncherXPCServiceStdInPathKeyKey "stdInPath" #define LauncherXPCServiceStdOutPathKeyKey "stdOutPath" #define LauncherXPCServiceStdErrPathKeyKey "stdErrPath" #define LauncherXPCServiceChildPIDKey "childPID" #define LauncherXPCServiceErrorTypeKey "errorType" #define LauncherXPCServiceCodeTypeKey "errorCode" #endif #include "llvm/Support/Host.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Communication.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Utility/CleanUp.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Endian.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/NameMatches.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StructuredData.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Errno.h" #include "cfcpp/CFCBundle.h" #include "cfcpp/CFCMutableArray.h" #include "cfcpp/CFCMutableDictionary.h" #include "cfcpp/CFCReleaser.h" #include "cfcpp/CFCString.h" #include #include #include #ifndef _POSIX_SPAWN_DISABLE_ASLR #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 #endif extern "C" { int __pthread_chdir(const char *path); int __pthread_fchdir(int fildes); } using namespace lldb; using namespace lldb_private; bool Host::GetBundleDirectory(const FileSpec &file, FileSpec &bundle_directory) { #if defined(__APPLE__) if (llvm::sys::fs::is_directory(file.GetPath())) { char path[PATH_MAX]; if (file.GetPath(path, sizeof(path))) { CFCBundle bundle(path); if (bundle.GetPath(path, sizeof(path))) { bundle_directory.SetFile(path, false); return true; } } } #endif bundle_directory.Clear(); return false; } bool Host::ResolveExecutableInBundle(FileSpec &file) { #if defined(__APPLE__) if (llvm::sys::fs::is_directory(file.GetPath())) { char path[PATH_MAX]; if (file.GetPath(path, sizeof(path))) { CFCBundle bundle(path); CFCReleaser url(bundle.CopyExecutableURL()); if (url.get()) { if (::CFURLGetFileSystemRepresentation(url.get(), YES, (UInt8 *)path, sizeof(path))) { file.SetFile(path, false); return true; } } } } #endif return false; } static void *AcceptPIDFromInferior(void *arg) { const char *connect_url = (const char *)arg; ConnectionFileDescriptor file_conn; Status error; if (file_conn.Connect(connect_url, &error) == eConnectionStatusSuccess) { char pid_str[256]; ::memset(pid_str, 0, sizeof(pid_str)); ConnectionStatus status; const size_t pid_str_len = file_conn.Read( pid_str, sizeof(pid_str), std::chrono::seconds(0), status, NULL); if (pid_str_len > 0) { int pid = atoi(pid_str); return (void *)(intptr_t)pid; } } return NULL; } static bool WaitForProcessToSIGSTOP(const lldb::pid_t pid, const int timeout_in_seconds) { const int time_delta_usecs = 100000; const int num_retries = timeout_in_seconds / time_delta_usecs; for (int i = 0; i < num_retries; i++) { struct proc_bsdinfo bsd_info; int error = ::proc_pidinfo(pid, PROC_PIDTBSDINFO, (uint64_t)0, &bsd_info, PROC_PIDTBSDINFO_SIZE); switch (error) { case EINVAL: case ENOTSUP: case ESRCH: case EPERM: return false; default: break; case 0: if (bsd_info.pbi_status == SSTOP) return true; } ::usleep(time_delta_usecs); } return false; } #if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) // static lldb::pid_t // LaunchInNewTerminalWithCommandFile //( // const char **argv, // const char **envp, // const char *working_dir, // const ArchSpec *arch_spec, // bool stop_at_entry, // bool disable_aslr //) //{ // if (!argv || !argv[0]) // return LLDB_INVALID_PROCESS_ID; // // OSStatus error = 0; // // FileSpec program (argv[0], false); // // // std::string unix_socket_name; // // char temp_file_path[PATH_MAX]; // const char *tmpdir = ::getenv ("TMPDIR"); // if (tmpdir == NULL) // tmpdir = "/tmp/"; // ::snprintf (temp_file_path, sizeof(temp_file_path), "%s%s-XXXXXX", tmpdir, // program.GetFilename().AsCString()); // // if (::mktemp (temp_file_path) == NULL) // return LLDB_INVALID_PROCESS_ID; // // unix_socket_name.assign (temp_file_path); // // ::strlcat (temp_file_path, ".command", sizeof (temp_file_path)); // // StreamFile command_file; // command_file.GetFile().Open (temp_file_path, // File::eOpenOptionWrite | // File::eOpenOptionCanCreate, // lldb::eFilePermissionsDefault); // // if (!command_file.GetFile().IsValid()) // return LLDB_INVALID_PROCESS_ID; // // FileSpec darwin_debug_file_spec; // if (!HostInfo::GetLLDBPath (ePathTypeSupportExecutableDir, // darwin_debug_file_spec)) // return LLDB_INVALID_PROCESS_ID; // darwin_debug_file_spec.GetFilename().SetCString("darwin-debug"); // // if (!darwin_debug_file_spec.Exists()) // return LLDB_INVALID_PROCESS_ID; // // char launcher_path[PATH_MAX]; // darwin_debug_file_spec.GetPath(launcher_path, sizeof(launcher_path)); // command_file.Printf("\"%s\" ", launcher_path); // // command_file.Printf("--unix-socket=%s ", unix_socket_name.c_str()); // // if (arch_spec && arch_spec->IsValid()) // { // command_file.Printf("--arch=%s ", arch_spec->GetArchitectureName()); // } // // if (disable_aslr) // { // command_file.PutCString("--disable-aslr "); // } // // command_file.PutCString("-- "); // // if (argv) // { // for (size_t i=0; argv[i] != NULL; ++i) // { // command_file.Printf("\"%s\" ", argv[i]); // } // } // command_file.PutCString("\necho Process exited with status $?\n"); // command_file.GetFile().Close(); // if (::chmod (temp_file_path, S_IRWXU | S_IRWXG) != 0) // return LLDB_INVALID_PROCESS_ID; // // CFCMutableDictionary cf_env_dict; // // const bool can_create = true; // if (envp) // { // for (size_t i=0; envp[i] != NULL; ++i) // { // const char *env_entry = envp[i]; // const char *equal_pos = strchr(env_entry, '='); // if (equal_pos) // { // std::string env_key (env_entry, equal_pos); // std::string env_val (equal_pos + 1); // CFCString cf_env_key (env_key.c_str(), kCFStringEncodingUTF8); // CFCString cf_env_val (env_val.c_str(), kCFStringEncodingUTF8); // cf_env_dict.AddValue (cf_env_key.get(), cf_env_val.get(), // can_create); // } // } // } // // LSApplicationParameters app_params; // ::memset (&app_params, 0, sizeof (app_params)); // app_params.flags = kLSLaunchDontAddToRecents | kLSLaunchAsync; // app_params.argv = NULL; // app_params.environment = (CFDictionaryRef)cf_env_dict.get(); // // CFCReleaser command_file_url // (::CFURLCreateFromFileSystemRepresentation (NULL, // (const UInt8 *)temp_file_path, // strlen(temp_file_path), // false)); // // CFCMutableArray urls; // // // Terminal.app will open the ".command" file we have created // // and run our process inside it which will wait at the entry point // // for us to attach. // urls.AppendValue(command_file_url.get()); // // // lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; // // Status lldb_error; // // Sleep and wait a bit for debugserver to start to listen... // char connect_url[128]; // ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", // unix_socket_name.c_str()); // // // Spawn a new thread to accept incoming connection on the connect_url // // so we can grab the pid from the inferior // lldb::thread_t accept_thread = Host::ThreadCreate // (unix_socket_name.c_str(), // AcceptPIDFromInferior, // connect_url, // &lldb_error); // // ProcessSerialNumber psn; // error = LSOpenURLsWithRole(urls.get(), kLSRolesShell, NULL, &app_params, // &psn, 1); // if (error == noErr) // { // thread_result_t accept_thread_result = NULL; // if (Host::ThreadJoin (accept_thread, &accept_thread_result, // &lldb_error)) // { // if (accept_thread_result) // { // pid = (intptr_t)accept_thread_result; // // // Wait for process to be stopped the entry point by watching // // for the process status to be set to SSTOP which indicates // it it // // SIGSTOP'ed at the entry point // WaitForProcessToSIGSTOP (pid, 5); // } // } // } // else // { // Host::ThreadCancel (accept_thread, &lldb_error); // } // // return pid; //} const char *applscript_in_new_tty = "tell application \"Terminal\"\n" " activate\n" " do script \"/bin/bash -c '%s';exit\"\n" "end tell\n"; const char *applscript_in_existing_tty = "\ set the_shell_script to \"/bin/bash -c '%s';exit\"\n\ tell application \"Terminal\"\n\ repeat with the_window in (get windows)\n\ repeat with the_tab in tabs of the_window\n\ set the_tty to tty in the_tab\n\ if the_tty contains \"%s\" then\n\ if the_tab is not busy then\n\ set selected of the_tab to true\n\ set frontmost of the_window to true\n\ do script the_shell_script in the_tab\n\ return\n\ end if\n\ end if\n\ end repeat\n\ end repeat\n\ do script the_shell_script\n\ end tell\n"; static Status LaunchInNewTerminalWithAppleScript(const char *exe_path, ProcessLaunchInfo &launch_info) { Status error; char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX"; if (::mktemp(unix_socket_name) == NULL) { error.SetErrorString("failed to make temporary path for a unix socket"); return error; } StreamString command; FileSpec darwin_debug_file_spec; if (!HostInfo::GetLLDBPath(ePathTypeSupportExecutableDir, darwin_debug_file_spec)) { error.SetErrorString("can't locate the 'darwin-debug' executable"); return error; } darwin_debug_file_spec.GetFilename().SetCString("darwin-debug"); if (!darwin_debug_file_spec.Exists()) { error.SetErrorStringWithFormat( "the 'darwin-debug' executable doesn't exists at '%s'", darwin_debug_file_spec.GetPath().c_str()); return error; } char launcher_path[PATH_MAX]; darwin_debug_file_spec.GetPath(launcher_path, sizeof(launcher_path)); const ArchSpec &arch_spec = launch_info.GetArchitecture(); // Only set the architecture if it is valid and if it isn't Haswell (x86_64h). if (arch_spec.IsValid() && arch_spec.GetCore() != ArchSpec::eCore_x86_64_x86_64h) command.Printf("arch -arch %s ", arch_spec.GetArchitectureName()); command.Printf("'%s' --unix-socket=%s", launcher_path, unix_socket_name); if (arch_spec.IsValid()) command.Printf(" --arch=%s", arch_spec.GetArchitectureName()); FileSpec working_dir{launch_info.GetWorkingDirectory()}; if (working_dir) command.Printf(" --working-dir '%s'", working_dir.GetCString()); else { char cwd[PATH_MAX]; if (getcwd(cwd, PATH_MAX)) command.Printf(" --working-dir '%s'", cwd); } if (launch_info.GetFlags().Test(eLaunchFlagDisableASLR)) command.PutCString(" --disable-aslr"); // We are launching on this host in a terminal. So compare the environment on // the host // to what is supplied in the launch_info. Any items that aren't in the host // environment // need to be sent to darwin-debug. If we send all environment entries, we // might blow the // max command line length, so we only send user modified entries. const char **envp = launch_info.GetEnvironmentEntries().GetConstArgumentVector(); StringList host_env; const size_t host_env_count = Host::GetEnvironment(host_env); if (envp && envp[0]) { const char *env_entry; for (size_t env_idx = 0; (env_entry = envp[env_idx]) != NULL; ++env_idx) { bool add_entry = true; for (size_t i = 0; i < host_env_count; ++i) { const char *host_env_entry = host_env.GetStringAtIndex(i); if (strcmp(env_entry, host_env_entry) == 0) { add_entry = false; break; } } if (add_entry) { command.Printf(" --env='%s'", env_entry); } } } command.PutCString(" -- "); const char **argv = launch_info.GetArguments().GetConstArgumentVector(); if (argv) { for (size_t i = 0; argv[i] != NULL; ++i) { if (i == 0) command.Printf(" '%s'", exe_path); else command.Printf(" '%s'", argv[i]); } } else { command.Printf(" '%s'", exe_path); } command.PutCString(" ; echo Process exited with status $?"); if (launch_info.GetFlags().Test(lldb::eLaunchFlagCloseTTYOnExit)) command.PutCString(" ; exit"); StreamString applescript_source; // if (tty_name && tty_name[0]) // { // applescript_source.Printf (applscript_in_existing_tty, // tty_command, // tty_name); // } // else // { applescript_source.Printf(applscript_in_new_tty, command.GetString().str().c_str()); // } // puts (script_source); NSAppleScript *applescript = [[NSAppleScript alloc] initWithSource:[NSString stringWithCString:applescript_source.GetString() .str() .c_str() encoding:NSUTF8StringEncoding]]; lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; Status lldb_error; // Sleep and wait a bit for debugserver to start to listen... ConnectionFileDescriptor file_conn; char connect_url[128]; ::snprintf(connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name); // Spawn a new thread to accept incoming connection on the connect_url // so we can grab the pid from the inferior. We have to do this because we // are sending an AppleScript that will launch a process in Terminal.app, // in a shell and the shell will fork/exec a couple of times before we get // to the process that we wanted to launch. So when our process actually // gets launched, we will handshake with it and get the process ID for it. HostThread accept_thread = ThreadLauncher::LaunchThread( unix_socket_name, AcceptPIDFromInferior, connect_url, &lldb_error); [applescript executeAndReturnError:nil]; thread_result_t accept_thread_result = NULL; lldb_error = accept_thread.Join(&accept_thread_result); if (lldb_error.Success() && accept_thread_result) { pid = (intptr_t)accept_thread_result; // Wait for process to be stopped at the entry point by watching // for the process status to be set to SSTOP which indicates it it // SIGSTOP'ed at the entry point WaitForProcessToSIGSTOP(pid, 5); } llvm::sys::fs::remove(unix_socket_name); [applescript release]; if (pid != LLDB_INVALID_PROCESS_ID) launch_info.SetProcessID(pid); return error; } #endif // #if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) bool Host::OpenFileInExternalEditor(const FileSpec &file_spec, uint32_t line_no) { #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) return false; #else // We attach this to an 'odoc' event to specify a particular selection typedef struct { int16_t reserved0; // must be zero int16_t fLineNumber; int32_t fSelStart; int32_t fSelEnd; uint32_t reserved1; // must be zero uint32_t reserved2; // must be zero } BabelAESelInfo; Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_HOST)); char file_path[PATH_MAX]; file_spec.GetPath(file_path, PATH_MAX); CFCString file_cfstr(file_path, kCFStringEncodingUTF8); CFCReleaser file_URL(::CFURLCreateWithFileSystemPath( NULL, file_cfstr.get(), kCFURLPOSIXPathStyle, false)); if (log) log->Printf( "Sending source file: \"%s\" and line: %d to external editor.\n", file_path, line_no); long error; BabelAESelInfo file_and_line_info = { 0, // reserved0 (int16_t)(line_no - 1), // fLineNumber (zero based line number) 1, // fSelStart 1024, // fSelEnd 0, // reserved1 0 // reserved2 }; AEKeyDesc file_and_line_desc; error = ::AECreateDesc(typeUTF8Text, &file_and_line_info, sizeof(file_and_line_info), &(file_and_line_desc.descContent)); if (error != noErr) { if (log) log->Printf("Error creating AEDesc: %ld.\n", error); return false; } file_and_line_desc.descKey = keyAEPosition; static std::string g_app_name; static FSRef g_app_fsref; LSApplicationParameters app_params; ::memset(&app_params, 0, sizeof(app_params)); app_params.flags = kLSLaunchDefaults | kLSLaunchDontAddToRecents | kLSLaunchDontSwitch; char *external_editor = ::getenv("LLDB_EXTERNAL_EDITOR"); if (external_editor) { if (log) log->Printf("Looking for external editor \"%s\".\n", external_editor); if (g_app_name.empty() || strcmp(g_app_name.c_str(), external_editor) != 0) { CFCString editor_name(external_editor, kCFStringEncodingUTF8); error = ::LSFindApplicationForInfo(kLSUnknownCreator, NULL, editor_name.get(), &g_app_fsref, NULL); // If we found the app, then store away the name so we don't have to // re-look it up. if (error != noErr) { if (log) log->Printf( "Could not find External Editor application, error: %ld.\n", error); return false; } } app_params.application = &g_app_fsref; } ProcessSerialNumber psn; CFCReleaser file_array( CFArrayCreate(NULL, (const void **)file_URL.ptr_address(false), 1, NULL)); error = ::LSOpenURLsWithRole(file_array.get(), kLSRolesAll, &file_and_line_desc, &app_params, &psn, 1); AEDisposeDesc(&(file_and_line_desc.descContent)); if (error != noErr) { if (log) log->Printf("LSOpenURLsWithRole failed, error: %ld.\n", error); return false; } return true; #endif // #if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) } size_t Host::GetEnvironment(StringList &env) { char **host_env = *_NSGetEnviron(); char *env_entry; size_t i; for (i = 0; (env_entry = host_env[i]) != NULL; ++i) env.AppendString(env_entry); return i; } static bool GetMacOSXProcessCPUType(ProcessInstanceInfo &process_info) { if (process_info.ProcessIDIsValid()) { // Make a new mib to stay thread safe int mib[CTL_MAXNAME] = { 0, }; size_t mib_len = CTL_MAXNAME; if (::sysctlnametomib("sysctl.proc_cputype", mib, &mib_len)) return false; mib[mib_len] = process_info.GetProcessID(); mib_len++; cpu_type_t cpu, sub = 0; size_t len = sizeof(cpu); if (::sysctl(mib, mib_len, &cpu, &len, 0, 0) == 0) { switch (cpu) { case CPU_TYPE_I386: sub = CPU_SUBTYPE_I386_ALL; break; case CPU_TYPE_X86_64: sub = CPU_SUBTYPE_X86_64_ALL; break; #if defined(CPU_TYPE_ARM64) && defined(CPU_SUBTYPE_ARM64_ALL) case CPU_TYPE_ARM64: sub = CPU_SUBTYPE_ARM64_ALL; break; #endif case CPU_TYPE_ARM: { // Note that we fetched the cpu type from the PROCESS but we can't get a // cpusubtype of the // process -- we can only get the host's cpu subtype. uint32_t cpusubtype = 0; len = sizeof(cpusubtype); if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0) sub = cpusubtype; bool host_cpu_is_64bit; 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 = true; else host_cpu_is_64bit = false; // if the host is an armv8 device, its cpusubtype will be in // CPU_SUBTYPE_ARM64 numbering // and we need to rewrite it to a reasonable CPU_SUBTYPE_ARM value // instead. if (host_cpu_is_64bit) { sub = CPU_SUBTYPE_ARM_V7; } } break; default: break; } process_info.GetArchitecture().SetArchitecture(eArchTypeMachO, cpu, sub); return true; } } process_info.GetArchitecture().Clear(); return false; } static bool GetMacOSXProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, ProcessInstanceInfo &process_info) { if (process_info.ProcessIDIsValid()) { int proc_args_mib[3] = {CTL_KERN, KERN_PROCARGS2, (int)process_info.GetProcessID()}; size_t arg_data_size = 0; if (::sysctl(proc_args_mib, 3, nullptr, &arg_data_size, NULL, 0) || arg_data_size == 0) arg_data_size = 8192; // Add a few bytes to the calculated length, I know we need to add at least // one byte // to this number otherwise we get junk back, so add 128 just in case... DataBufferHeap arg_data(arg_data_size + 128, 0); arg_data_size = arg_data.GetByteSize(); if (::sysctl(proc_args_mib, 3, arg_data.GetBytes(), &arg_data_size, NULL, 0) == 0) { DataExtractor data(arg_data.GetBytes(), arg_data_size, endian::InlHostByteOrder(), sizeof(void *)); lldb::offset_t offset = 0; uint32_t argc = data.GetU32(&offset); llvm::Triple &triple = process_info.GetArchitecture().GetTriple(); const llvm::Triple::ArchType triple_arch = triple.getArch(); const bool check_for_ios_simulator = (triple_arch == llvm::Triple::x86 || triple_arch == llvm::Triple::x86_64); const char *cstr = data.GetCStr(&offset); if (cstr) { process_info.GetExecutableFile().SetFile(cstr, false); if (match_info_ptr == NULL || NameMatches( process_info.GetExecutableFile().GetFilename().GetCString(), match_info_ptr->GetNameMatchType(), match_info_ptr->GetProcessInfo().GetName())) { // Skip NULLs while (1) { const uint8_t *p = data.PeekData(offset, 1); if ((p == NULL) || (*p != '\0')) break; ++offset; } // Now extract all arguments Args &proc_args = process_info.GetArguments(); for (int i = 0; i < static_cast(argc); ++i) { cstr = data.GetCStr(&offset); if (cstr) proc_args.AppendArgument(llvm::StringRef(cstr)); } Args &proc_env = process_info.GetEnvironmentEntries(); while ((cstr = data.GetCStr(&offset))) { if (cstr[0] == '\0') break; if (check_for_ios_simulator) { if (strncmp(cstr, "SIMULATOR_UDID=", strlen("SIMULATOR_UDID=")) == 0) process_info.GetArchitecture().GetTriple().setOS( llvm::Triple::IOS); else process_info.GetArchitecture().GetTriple().setOS( llvm::Triple::MacOSX); } proc_env.AppendArgument(llvm::StringRef(cstr)); } return true; } } } } return false; } static bool GetMacOSXProcessUserAndGroup(ProcessInstanceInfo &process_info) { if (process_info.ProcessIDIsValid()) { int mib[4]; mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PID; mib[3] = process_info.GetProcessID(); struct kinfo_proc proc_kinfo; size_t proc_kinfo_size = sizeof(struct kinfo_proc); if (::sysctl(mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) { if (proc_kinfo_size > 0) { process_info.SetParentProcessID(proc_kinfo.kp_eproc.e_ppid); process_info.SetUserID(proc_kinfo.kp_eproc.e_pcred.p_ruid); process_info.SetGroupID(proc_kinfo.kp_eproc.e_pcred.p_rgid); process_info.SetEffectiveUserID(proc_kinfo.kp_eproc.e_ucred.cr_uid); if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0) process_info.SetEffectiveGroupID( proc_kinfo.kp_eproc.e_ucred.cr_groups[0]); else process_info.SetEffectiveGroupID(UINT32_MAX); return true; } } } process_info.SetParentProcessID(LLDB_INVALID_PROCESS_ID); process_info.SetUserID(UINT32_MAX); process_info.SetGroupID(UINT32_MAX); process_info.SetEffectiveUserID(UINT32_MAX); process_info.SetEffectiveGroupID(UINT32_MAX); return false; } uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) { std::vector kinfos; int mib[3] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL}; size_t pid_data_size = 0; if (::sysctl(mib, 4, NULL, &pid_data_size, NULL, 0) != 0) return 0; // Add a few extra in case a few more show up const size_t estimated_pid_count = (pid_data_size / sizeof(struct kinfo_proc)) + 10; kinfos.resize(estimated_pid_count); pid_data_size = kinfos.size() * sizeof(struct kinfo_proc); if (::sysctl(mib, 4, &kinfos[0], &pid_data_size, NULL, 0) != 0) return 0; const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc)); bool all_users = match_info.GetMatchAllUsers(); const lldb::pid_t our_pid = getpid(); const uid_t our_uid = getuid(); for (size_t i = 0; i < actual_pid_count; i++) { const struct kinfo_proc &kinfo = kinfos[i]; bool kinfo_user_matches = false; if (all_users) kinfo_user_matches = true; else kinfo_user_matches = kinfo.kp_eproc.e_pcred.p_ruid == our_uid; // Special case, if lldb is being run as root we can attach to anything. if (our_uid == 0) kinfo_user_matches = true; if (kinfo_user_matches == false || // Make sure the user is acceptable static_cast(kinfo.kp_proc.p_pid) == our_pid || // Skip this process kinfo.kp_proc.p_pid == 0 || // Skip kernel (kernel pid is zero) kinfo.kp_proc.p_stat == SZOMB || // Zombies are bad, they like brains... kinfo.kp_proc.p_flag & P_TRACED || // Being debugged? kinfo.kp_proc.p_flag & P_WEXIT || // Working on exiting? kinfo.kp_proc.p_flag & P_TRANSLATED) // Skip translated ppc (Rosetta) continue; ProcessInstanceInfo process_info; process_info.SetProcessID(kinfo.kp_proc.p_pid); process_info.SetParentProcessID(kinfo.kp_eproc.e_ppid); process_info.SetUserID(kinfo.kp_eproc.e_pcred.p_ruid); process_info.SetGroupID(kinfo.kp_eproc.e_pcred.p_rgid); process_info.SetEffectiveUserID(kinfo.kp_eproc.e_ucred.cr_uid); if (kinfo.kp_eproc.e_ucred.cr_ngroups > 0) process_info.SetEffectiveGroupID(kinfo.kp_eproc.e_ucred.cr_groups[0]); else process_info.SetEffectiveGroupID(UINT32_MAX); // Make sure our info matches before we go fetch the name and cpu type if (match_info.Matches(process_info)) { // Get CPU type first so we can know to look for iOS simulator is we have // x86 or x86_64 if (GetMacOSXProcessCPUType(process_info)) { if (GetMacOSXProcessArgs(&match_info, process_info)) { if (match_info.Matches(process_info)) process_infos.Append(process_info); } } } } return process_infos.GetSize(); } bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) { process_info.SetProcessID(pid); bool success = false; // Get CPU type first so we can know to look for iOS simulator is we have x86 // or x86_64 if (GetMacOSXProcessCPUType(process_info)) success = true; if (GetMacOSXProcessArgs(NULL, process_info)) success = true; if (GetMacOSXProcessUserAndGroup(process_info)) success = true; if (success) return true; process_info.Clear(); return false; } #if !NO_XPC_SERVICES static void PackageXPCArguments(xpc_object_t message, const char *prefix, const Args &args) { size_t count = args.GetArgumentCount(); char buf[50]; // long enough for 'argXXX' memset(buf, 0, 50); sprintf(buf, "%sCount", prefix); xpc_dictionary_set_int64(message, buf, count); for (size_t i = 0; i < count; i++) { memset(buf, 0, 50); sprintf(buf, "%s%zi", prefix, i); xpc_dictionary_set_string(message, buf, args.GetArgumentAtIndex(i)); } } /* A valid authorizationRef means that - there is the LaunchUsingXPCRightName rights in the /etc/authorization - we have successfully copied the rights to be send over the XPC wire Once obtained, it will be valid for as long as the process lives. */ static AuthorizationRef authorizationRef = NULL; static Status getXPCAuthorization(ProcessLaunchInfo &launch_info) { Status error; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS)); if ((launch_info.GetUserID() == 0) && !authorizationRef) { OSStatus createStatus = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef); if (createStatus != errAuthorizationSuccess) { error.SetError(1, eErrorTypeGeneric); error.SetErrorString("Can't create authorizationRef."); LLDB_LOG(log, "error: {0}", error); return error; } OSStatus rightsStatus = AuthorizationRightGet(LaunchUsingXPCRightName, NULL); if (rightsStatus != errAuthorizationSuccess) { // No rights in the security database, Create it with the right prompt. CFStringRef prompt = CFSTR("Xcode is trying to take control of a root process."); CFStringRef keys[] = {CFSTR("en")}; CFTypeRef values[] = {prompt}; CFDictionaryRef promptDict = CFDictionaryCreate( kCFAllocatorDefault, (const void **)keys, (const void **)values, 1, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef keys1[] = {CFSTR("class"), CFSTR("group"), CFSTR("comment"), CFSTR("default-prompt"), CFSTR("shared")}; CFTypeRef values1[] = {CFSTR("user"), CFSTR("admin"), CFSTR(LaunchUsingXPCRightName), promptDict, kCFBooleanFalse}; CFDictionaryRef dict = CFDictionaryCreate( kCFAllocatorDefault, (const void **)keys1, (const void **)values1, 5, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); rightsStatus = AuthorizationRightSet( authorizationRef, LaunchUsingXPCRightName, dict, NULL, NULL, NULL); CFRelease(promptDict); CFRelease(dict); } OSStatus copyRightStatus = errAuthorizationDenied; if (rightsStatus == errAuthorizationSuccess) { AuthorizationItem item1 = {LaunchUsingXPCRightName, 0, NULL, 0}; AuthorizationItem items[] = {item1}; AuthorizationRights requestedRights = {1, items}; AuthorizationFlags authorizationFlags = kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights; copyRightStatus = AuthorizationCopyRights( authorizationRef, &requestedRights, kAuthorizationEmptyEnvironment, authorizationFlags, NULL); } if (copyRightStatus != errAuthorizationSuccess) { // Eventually when the commandline supports running as root and the user // is not // logged in in the current audit session, we will need the trick in gdb // where // we ask the user to type in the root passwd in the terminal. error.SetError(2, eErrorTypeGeneric); error.SetErrorStringWithFormat( "Launching as root needs root authorization."); LLDB_LOG(log, "error: {0}", error); if (authorizationRef) { AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults); authorizationRef = NULL; } } } return error; } #endif static short GetPosixspawnFlags(const ProcessLaunchInfo &launch_info) { short flags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; if (launch_info.GetFlags().Test(eLaunchFlagExec)) flags |= POSIX_SPAWN_SETEXEC; // Darwin specific posix_spawn flag if (launch_info.GetFlags().Test(eLaunchFlagDebug)) flags |= POSIX_SPAWN_START_SUSPENDED; // Darwin specific posix_spawn flag if (launch_info.GetFlags().Test(eLaunchFlagDisableASLR)) flags |= _POSIX_SPAWN_DISABLE_ASLR; // Darwin specific posix_spawn flag if (launch_info.GetLaunchInSeparateProcessGroup()) flags |= POSIX_SPAWN_SETPGROUP; #ifdef POSIX_SPAWN_CLOEXEC_DEFAULT #if defined(__x86_64__) || defined(__i386__) static LazyBool g_use_close_on_exec_flag = eLazyBoolCalculate; if (g_use_close_on_exec_flag == eLazyBoolCalculate) { g_use_close_on_exec_flag = eLazyBoolNo; uint32_t major, minor, update; if (HostInfo::GetOSVersion(major, minor, update)) { // Kernel panic if we use the POSIX_SPAWN_CLOEXEC_DEFAULT on 10.7 or // earlier if (major > 10 || (major == 10 && minor > 7)) { // Only enable for 10.8 and later OS versions g_use_close_on_exec_flag = eLazyBoolYes; } } } #else static LazyBool g_use_close_on_exec_flag = eLazyBoolYes; #endif // defined(__x86_64__) || defined(__i386__) // Close all files exception those with file actions if this is supported. if (g_use_close_on_exec_flag == eLazyBoolYes) flags |= POSIX_SPAWN_CLOEXEC_DEFAULT; #endif // ifdef POSIX_SPAWN_CLOEXEC_DEFAULT return flags; } static Status LaunchProcessXPC(const char *exe_path, ProcessLaunchInfo &launch_info, lldb::pid_t &pid) { #if !NO_XPC_SERVICES Status error = getXPCAuthorization(launch_info); if (error.Fail()) return error; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS)); uid_t requested_uid = launch_info.GetUserID(); const char *xpc_service = nil; bool send_auth = false; AuthorizationExternalForm extForm; if (requested_uid == 0) { if (AuthorizationMakeExternalForm(authorizationRef, &extForm) == errAuthorizationSuccess) { send_auth = true; } else { error.SetError(3, eErrorTypeGeneric); error.SetErrorStringWithFormat("Launching root via XPC needs to " "externalize authorization reference."); LLDB_LOG(log, "error: {0}", error); return error; } xpc_service = LaunchUsingXPCRightName; } else { error.SetError(4, eErrorTypeGeneric); error.SetErrorStringWithFormat( "Launching via XPC is only currently available for root."); LLDB_LOG(log, "error: {0}", error); return error; } xpc_connection_t conn = xpc_connection_create(xpc_service, NULL); xpc_connection_set_event_handler(conn, ^(xpc_object_t event) { xpc_type_t type = xpc_get_type(event); if (type == XPC_TYPE_ERROR) { if (event == XPC_ERROR_CONNECTION_INTERRUPTED) { // The service has either canceled itself, crashed, or been terminated. // The XPC connection is still valid and sending a message to it will // re-launch the service. // If the service is state-full, this is the time to initialize the new // service. return; } else if (event == XPC_ERROR_CONNECTION_INVALID) { // The service is invalid. Either the service name supplied to // xpc_connection_create() is incorrect // or we (this process) have canceled the service; we can do any cleanup // of application state at this point. // printf("Service disconnected"); return; } else { // printf("Unexpected error from service: %s", // xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION)); } } else { // printf("Received unexpected event in handler"); } }); xpc_connection_set_finalizer_f(conn, xpc_finalizer_t(xpc_release)); xpc_connection_resume(conn); xpc_object_t message = xpc_dictionary_create(nil, nil, 0); if (send_auth) { xpc_dictionary_set_data(message, LauncherXPCServiceAuthKey, extForm.bytes, sizeof(AuthorizationExternalForm)); } PackageXPCArguments(message, LauncherXPCServiceArgPrefxKey, launch_info.GetArguments()); PackageXPCArguments(message, LauncherXPCServiceEnvPrefxKey, launch_info.GetEnvironmentEntries()); // Posix spawn stuff. xpc_dictionary_set_int64(message, LauncherXPCServiceCPUTypeKey, launch_info.GetArchitecture().GetMachOCPUType()); xpc_dictionary_set_int64(message, LauncherXPCServicePosixspawnFlagsKey, GetPosixspawnFlags(launch_info)); const FileAction *file_action = launch_info.GetFileActionForFD(STDIN_FILENO); if (file_action && !file_action->GetPath().empty()) { xpc_dictionary_set_string(message, LauncherXPCServiceStdInPathKeyKey, file_action->GetPath().str().c_str()); } file_action = launch_info.GetFileActionForFD(STDOUT_FILENO); if (file_action && !file_action->GetPath().empty()) { xpc_dictionary_set_string(message, LauncherXPCServiceStdOutPathKeyKey, file_action->GetPath().str().c_str()); } file_action = launch_info.GetFileActionForFD(STDERR_FILENO); if (file_action && !file_action->GetPath().empty()) { xpc_dictionary_set_string(message, LauncherXPCServiceStdErrPathKeyKey, file_action->GetPath().str().c_str()); } xpc_object_t reply = xpc_connection_send_message_with_reply_sync(conn, message); xpc_type_t returnType = xpc_get_type(reply); if (returnType == XPC_TYPE_DICTIONARY) { pid = xpc_dictionary_get_int64(reply, LauncherXPCServiceChildPIDKey); if (pid == 0) { int errorType = xpc_dictionary_get_int64(reply, LauncherXPCServiceErrorTypeKey); int errorCode = xpc_dictionary_get_int64(reply, LauncherXPCServiceCodeTypeKey); error.SetError(errorCode, eErrorTypeGeneric); error.SetErrorStringWithFormat( "Problems with launching via XPC. Error type : %i, code : %i", errorType, errorCode); LLDB_LOG(log, "error: {0}", error); if (authorizationRef) { AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults); authorizationRef = NULL; } } } else if (returnType == XPC_TYPE_ERROR) { error.SetError(5, eErrorTypeGeneric); error.SetErrorStringWithFormat( "Problems with launching via XPC. XPC error : %s", xpc_dictionary_get_string(reply, XPC_ERROR_KEY_DESCRIPTION)); LLDB_LOG(log, "error: {0}", error); } return error; #else Status error; return error; #endif } static bool AddPosixSpawnFileAction(void *_file_actions, const FileAction *info, Log *log, Status &error) { if (info == NULL) return false; posix_spawn_file_actions_t *file_actions = reinterpret_cast(_file_actions); switch (info->GetAction()) { case FileAction::eFileActionNone: error.Clear(); break; case FileAction::eFileActionClose: if (info->GetFD() == -1) error.SetErrorString( "invalid fd for posix_spawn_file_actions_addclose(...)"); else { error.SetError( ::posix_spawn_file_actions_addclose(file_actions, info->GetFD()), eErrorTypePOSIX); if (error.Fail()) LLDB_LOG(log, "error: {0}, posix_spawn_file_actions_addclose " "(action={1}, fd={2})", error, file_actions, info->GetFD()); } break; case FileAction::eFileActionDuplicate: if (info->GetFD() == -1) error.SetErrorString( "invalid fd for posix_spawn_file_actions_adddup2(...)"); else if (info->GetActionArgument() == -1) error.SetErrorString( "invalid duplicate fd for posix_spawn_file_actions_adddup2(...)"); else { error.SetError( ::posix_spawn_file_actions_adddup2(file_actions, info->GetFD(), info->GetActionArgument()), eErrorTypePOSIX); if (error.Fail()) LLDB_LOG(log, "error: {0}, posix_spawn_file_actions_adddup2 " "(action={1}, fd={2}, dup_fd={3})", error, file_actions, info->GetFD(), info->GetActionArgument()); } break; case FileAction::eFileActionOpen: if (info->GetFD() == -1) error.SetErrorString( "invalid fd in posix_spawn_file_actions_addopen(...)"); else { int oflag = info->GetActionArgument(); mode_t mode = 0; if (oflag & O_CREAT) mode = 0640; error.SetError(::posix_spawn_file_actions_addopen( file_actions, info->GetFD(), info->GetPath().str().c_str(), oflag, mode), eErrorTypePOSIX); if (error.Fail()) LLDB_LOG(log, "error: {0}, posix_spawn_file_actions_addopen (action={1}, " "fd={2}, path='{3}', oflag={4}, mode={5})", error, file_actions, info->GetFD(), info->GetPath(), oflag, mode); } break; } return error.Success(); } static Status LaunchProcessPosixSpawn(const char *exe_path, const ProcessLaunchInfo &launch_info, lldb::pid_t &pid) { Status error; Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS)); posix_spawnattr_t attr; error.SetError(::posix_spawnattr_init(&attr), eErrorTypePOSIX); if (error.Fail()) { LLDB_LOG(log, "error: {0}, ::posix_spawnattr_init ( &attr )", error); return error; } // Make a quick class that will cleanup the posix spawn attributes in case // we return in the middle of this function. lldb_utility::CleanUp posix_spawnattr_cleanup( &attr, posix_spawnattr_destroy); 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); short flags = GetPosixspawnFlags(launch_info); error.SetError(::posix_spawnattr_setflags(&attr, flags), eErrorTypePOSIX); if (error.Fail()) { LLDB_LOG(log, "error: {0}, ::posix_spawnattr_setflags ( &attr, flags={1:x} )", error, flags); return error; } // posix_spawnattr_setbinpref_np appears to be an Apple extension per: // http://www.unix.com/man-page/OSX/3/posix_spawnattr_setbinpref_np/ #if !defined(__arm__) // Don't set the binpref if a shell was provided. After all, that's only // going to affect what version of the shell // is launched, not what fork of the binary is launched. We insert "arch // --arch as part of the shell invocation // to do that job on OSX. if (launch_info.GetShell() == nullptr) { // 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... const ArchSpec &arch_spec = launch_info.GetArchitecture(); cpu_type_t cpu = arch_spec.GetMachOCPUType(); cpu_type_t sub = arch_spec.GetMachOCPUSubType(); if (cpu != 0 && cpu != static_cast(UINT32_MAX) && cpu != static_cast(LLDB_INVALID_CPUTYPE) && !(cpu == 0x01000007 && sub == 8)) // If haswell is specified, don't try // to set the CPU type or we will fail { size_t ocount = 0; error.SetError(::posix_spawnattr_setbinpref_np(&attr, 1, &cpu, &ocount), eErrorTypePOSIX); if (error.Fail()) LLDB_LOG(log, "error: {0}, ::posix_spawnattr_setbinpref_np ( &attr, 1, " "cpu_type = {1:x}, count => {2} )", error, cpu, ocount); if (error.Fail() || ocount != 1) return error; } } #endif // !defined(__arm__) const char *tmp_argv[2]; char *const *argv = const_cast( launch_info.GetArguments().GetConstArgumentVector()); char *const *envp = const_cast( launch_info.GetEnvironmentEntries().GetConstArgumentVector()); if (argv == NULL) { // posix_spawn gets very unhappy if it doesn't have at least the program // name in argv[0]. One of the side affects I have noticed is the // environment // variables don't make it into the child process if "argv == NULL"!!! tmp_argv[0] = exe_path; tmp_argv[1] = NULL; argv = const_cast(tmp_argv); } FileSpec working_dir{launch_info.GetWorkingDirectory()}; if (working_dir) { // Set the working directory on this thread only if (__pthread_chdir(working_dir.GetCString()) < 0) { if (errno == ENOENT) { error.SetErrorStringWithFormat("No such file or directory: %s", working_dir.GetCString()); } else if (errno == ENOTDIR) { error.SetErrorStringWithFormat("Path doesn't name a directory: %s", working_dir.GetCString()); } else { error.SetErrorStringWithFormat("An unknown error occurred when " "changing directory for process " "execution."); } return error; } } ::pid_t result_pid = LLDB_INVALID_PROCESS_ID; const size_t num_file_actions = launch_info.GetNumFileActions(); if (num_file_actions > 0) { posix_spawn_file_actions_t file_actions; error.SetError(::posix_spawn_file_actions_init(&file_actions), eErrorTypePOSIX); if (error.Fail()) { LLDB_LOG(log, "error: {0}, ::posix_spawn_file_actions_init ( &file_actions )", error); return error; } // Make a quick class that will cleanup the posix spawn attributes in case // we return in the middle of this function. lldb_utility::CleanUp posix_spawn_file_actions_cleanup(&file_actions, posix_spawn_file_actions_destroy); for (size_t i = 0; i < num_file_actions; ++i) { const FileAction *launch_file_action = launch_info.GetFileActionAtIndex(i); if (launch_file_action) { if (!AddPosixSpawnFileAction(&file_actions, launch_file_action, log, error)) return error; } } error.SetError( ::posix_spawnp(&result_pid, exe_path, &file_actions, &attr, argv, envp), eErrorTypePOSIX); if (error.Fail()) { LLDB_LOG(log, "error: {0}, ::posix_spawnp(pid => {1}, path = '{2}', " "file_actions = {3}, " "attr = {4}, argv = {5}, envp = {6} )", error, result_pid, exe_path, &file_actions, &attr, argv, envp); if (log) { for (int ii = 0; argv[ii]; ++ii) LLDB_LOG(log, "argv[{0}] = '{1}'", ii, argv[ii]); } } } else { error.SetError( ::posix_spawnp(&result_pid, exe_path, NULL, &attr, argv, envp), eErrorTypePOSIX); if (error.Fail()) { LLDB_LOG(log, "error: {0}, ::posix_spawnp ( pid => {1}, path = '{2}', " "file_actions = NULL, attr = {3}, argv = {4}, envp = {5} )", error, result_pid, exe_path, &attr, argv, envp); if (log) { for (int ii = 0; argv[ii]; ++ii) LLDB_LOG(log, "argv[{0}] = '{1}'", ii, argv[ii]); } } } pid = result_pid; if (working_dir) { // No more thread specific current working directory __pthread_fchdir(-1); } return error; } static bool ShouldLaunchUsingXPC(ProcessLaunchInfo &launch_info) { bool result = false; #if !NO_XPC_SERVICES bool launchingAsRoot = launch_info.GetUserID() == 0; bool currentUserIsRoot = HostInfo::GetEffectiveUserID() == 0; if (launchingAsRoot && !currentUserIsRoot) { // If current user is already root, we don't need XPC's help. result = true; } #endif return result; } Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) { Status error; char exe_path[PATH_MAX]; PlatformSP host_platform_sp(Platform::GetHostPlatform()); ModuleSpec exe_module_spec(launch_info.GetExecutableFile(), launch_info.GetArchitecture()); if (!llvm::sys::fs::is_regular_file( exe_module_spec.GetFileSpec().GetPath())) { lldb::ModuleSP exe_module_sp; error = host_platform_sp->ResolveExecutable(exe_module_spec, exe_module_sp, NULL); if (error.Fail()) return error; if (exe_module_sp) exe_module_spec.GetFileSpec() = exe_module_sp->GetFileSpec(); } if (exe_module_spec.GetFileSpec().Exists()) { exe_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path)); } else { launch_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); error.SetErrorStringWithFormat("executable doesn't exist: '%s'", exe_path); return error; } if (launch_info.GetFlags().Test(eLaunchFlagLaunchInTTY)) { #if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) return LaunchInNewTerminalWithAppleScript(exe_path, launch_info); #else error.SetErrorString("launching a process in a new terminal is not " "supported on iOS devices"); return error; #endif } lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; if (ShouldLaunchUsingXPC(launch_info)) { error = LaunchProcessXPC(exe_path, launch_info, pid); } else { error = LaunchProcessPosixSpawn(exe_path, launch_info, pid); } if (pid != LLDB_INVALID_PROCESS_ID) { // If all went well, then set the process ID into the launch info launch_info.SetProcessID(pid); // Make sure we reap any processes we spawn or we will have zombies. if (!launch_info.MonitorProcess()) { const bool monitor_signals = false; Host::MonitorChildProcessCallback callback = nullptr; if (!launch_info.GetFlags().Test(lldb::eLaunchFlagDontSetExitStatus)) callback = Process::SetProcessExitStatus; StartMonitoringChildProcess(callback, pid, monitor_signals); } } else { // Invalid process ID, something didn't go well if (error.Success()) error.SetErrorString("process launch failed for unknown reasons"); } return error; } Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) { Status error; if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments)) { FileSpec expand_tool_spec; if (!HostInfo::GetLLDBPath(lldb::ePathTypeSupportExecutableDir, expand_tool_spec)) { error.SetErrorString( "could not get support executable directory for lldb-argdumper tool"); return error; } expand_tool_spec.AppendPathComponent("lldb-argdumper"); if (!expand_tool_spec.Exists()) { error.SetErrorStringWithFormat( "could not find the lldb-argdumper tool: %s", expand_tool_spec.GetPath().c_str()); return error; } StreamString expand_tool_spec_stream; expand_tool_spec_stream.Printf("\"%s\"", expand_tool_spec.GetPath().c_str()); Args expand_command(expand_tool_spec_stream.GetData()); expand_command.AppendArguments(launch_info.GetArguments()); int status; std::string output; FileSpec cwd(launch_info.GetWorkingDirectory()); if (!cwd.Exists()) { char *wd = getcwd(nullptr, 0); if (wd == nullptr) { error.SetErrorStringWithFormat( "cwd does not exist; cannot launch with shell argument expansion"); return error; } else { FileSpec working_dir(wd, false); free(wd); launch_info.SetWorkingDirectory(working_dir); } } RunShellCommand(expand_command, cwd, &status, nullptr, &output, 10); if (status != 0) { error.SetErrorStringWithFormat("lldb-argdumper exited with error %d", status); return error; } auto data_sp = StructuredData::ParseJSON(output); if (!data_sp) { error.SetErrorString("invalid JSON"); return error; } auto dict_sp = data_sp->GetAsDictionary(); if (!data_sp) { error.SetErrorString("invalid JSON"); return error; } auto args_sp = dict_sp->GetObjectForDotSeparatedPath("arguments"); if (!args_sp) { error.SetErrorString("invalid JSON"); return error; } auto args_array_sp = args_sp->GetAsArray(); if (!args_array_sp) { error.SetErrorString("invalid JSON"); return error; } launch_info.GetArguments().Clear(); for (size_t i = 0; i < args_array_sp->GetSize(); i++) { auto item_sp = args_array_sp->GetItemAtIndex(i); if (!item_sp) continue; auto str_sp = item_sp->GetAsString(); if (!str_sp) continue; launch_info.GetArguments().AppendArgument(str_sp->GetValue()); } } return error; } HostThread Host::StartMonitoringChildProcess( const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid, bool monitor_signals) { unsigned long mask = DISPATCH_PROC_EXIT; if (monitor_signals) mask |= DISPATCH_PROC_SIGNAL; Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS)); dispatch_source_t source = ::dispatch_source_create( DISPATCH_SOURCE_TYPE_PROC, pid, mask, ::dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); if (log) log->Printf("Host::StartMonitoringChildProcess " "(callback, pid=%i, monitor_signals=%i) " "source = %p\n", static_cast(pid), monitor_signals, reinterpret_cast(source)); if (source) { Host::MonitorChildProcessCallback callback_copy = callback; ::dispatch_source_set_cancel_handler(source, ^{ dispatch_release(source); }); ::dispatch_source_set_event_handler(source, ^{ int status = 0; int wait_pid = 0; bool cancel = false; bool exited = false; - do { - wait_pid = ::waitpid(pid, &status, 0); - } while (wait_pid < 0 && errno == EINTR); - + wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &status, 0); if (wait_pid >= 0) { int signal = 0; int exit_status = 0; const char *status_cstr = NULL; if (WIFSTOPPED(status)) { signal = WSTOPSIG(status); status_cstr = "STOPPED"; } else if (WIFEXITED(status)) { exit_status = WEXITSTATUS(status); status_cstr = "EXITED"; exited = true; } else if (WIFSIGNALED(status)) { signal = WTERMSIG(status); status_cstr = "SIGNALED"; exited = true; exit_status = -1; } else { status_cstr = "???"; } if (log) log->Printf("::waitpid (pid = %llu, &status, 0) => pid = %i, status " "= 0x%8.8x (%s), signal = %i, exit_status = %i", pid, wait_pid, status, status_cstr, signal, exit_status); if (callback_copy) cancel = callback_copy(pid, exited, signal, exit_status); if (exited || cancel) { ::dispatch_source_cancel(source); } } }); ::dispatch_resume(source); } return HostThread(); } //---------------------------------------------------------------------- // Log to both stderr and to ASL Logging when running on MacOSX. //---------------------------------------------------------------------- void Host::SystemLog(SystemLogType type, const char *format, va_list args) { if (format && format[0]) { 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.LLDB.framework"); ::asl_set(g_aslmsg, ASL_KEY_SENDER, asl_key_sender); } // Copy the va_list so we can log this message twice va_list copy_args; va_copy(copy_args, args); // Log to stderr ::vfprintf(stderr, format, copy_args); va_end(copy_args); int asl_level; switch (type) { case eSystemLogError: asl_level = ASL_LEVEL_ERR; break; case eSystemLogWarning: asl_level = ASL_LEVEL_WARNING; break; } // Log to ASL ::asl_vlog(NULL, g_aslmsg, asl_level, format, args); } } Index: vendor/lldb/dist/source/Host/posix/ConnectionFileDescriptorPosix.cpp =================================================================== --- vendor/lldb/dist/source/Host/posix/ConnectionFileDescriptorPosix.cpp (revision 320966) +++ vendor/lldb/dist/source/Host/posix/ConnectionFileDescriptorPosix.cpp (revision 320967) @@ -1,791 +1,784 @@ //===-- ConnectionFileDescriptorPosix.cpp -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #if defined(__APPLE__) // Enable this special support for Apple builds where we can have unlimited // select bounds. We tried switching to poll() and kqueue and we were panicing // the kernel, so we have to stick with select for now. #define _DARWIN_UNLIMITED_SELECT #endif #include "lldb/Host/posix/ConnectionFileDescriptorPosix.h" #include "lldb/Host/Config.h" #include "lldb/Host/Socket.h" #include "lldb/Host/SocketAddress.h" #include "lldb/Utility/SelectHelper.h" #include "lldb/Utility/Timeout.h" // C Includes #include #include #include #include #include #ifndef LLDB_DISABLE_POSIX #include #endif // C++ Includes #include // Other libraries and framework includes #include "llvm/Support/Errno.h" #include "llvm/Support/ErrorHandling.h" #if defined(__APPLE__) #include "llvm/ADT/SmallVector.h" #endif // Project includes #include "lldb/Host/Host.h" #include "lldb/Host/Socket.h" #include "lldb/Host/common/TCPSocket.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" using namespace lldb; using namespace lldb_private; const char *ConnectionFileDescriptor::LISTEN_SCHEME = "listen"; const char *ConnectionFileDescriptor::ACCEPT_SCHEME = "accept"; const char *ConnectionFileDescriptor::UNIX_ACCEPT_SCHEME = "unix-accept"; const char *ConnectionFileDescriptor::CONNECT_SCHEME = "connect"; const char *ConnectionFileDescriptor::TCP_CONNECT_SCHEME = "tcp-connect"; const char *ConnectionFileDescriptor::UDP_SCHEME = "udp"; const char *ConnectionFileDescriptor::UNIX_CONNECT_SCHEME = "unix-connect"; const char *ConnectionFileDescriptor::UNIX_ABSTRACT_CONNECT_SCHEME = "unix-abstract-connect"; const char *ConnectionFileDescriptor::FD_SCHEME = "fd"; const char *ConnectionFileDescriptor::FILE_SCHEME = "file"; namespace { llvm::Optional GetURLAddress(llvm::StringRef url, llvm::StringRef scheme) { if (!url.consume_front(scheme)) return llvm::None; if (!url.consume_front("://")) return llvm::None; return url; } } ConnectionFileDescriptor::ConnectionFileDescriptor(bool child_processes_inherit) : Connection(), m_pipe(), m_mutex(), m_shutting_down(false), m_waiting_for_accept(false), m_child_processes_inherit(child_processes_inherit) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); if (log) log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor ()", static_cast(this)); } ConnectionFileDescriptor::ConnectionFileDescriptor(int fd, bool owns_fd) : Connection(), m_pipe(), m_mutex(), m_shutting_down(false), m_waiting_for_accept(false), m_child_processes_inherit(false) { m_write_sp.reset(new File(fd, owns_fd)); m_read_sp.reset(new File(fd, false)); Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); if (log) log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = " "%i, owns_fd = %i)", static_cast(this), fd, owns_fd); OpenCommandPipe(); } ConnectionFileDescriptor::ConnectionFileDescriptor(Socket *socket) : Connection(), m_pipe(), m_mutex(), m_shutting_down(false), m_waiting_for_accept(false), m_child_processes_inherit(false) { InitializeSocket(socket); } ConnectionFileDescriptor::~ConnectionFileDescriptor() { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); if (log) log->Printf("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", static_cast(this)); Disconnect(NULL); CloseCommandPipe(); } void ConnectionFileDescriptor::OpenCommandPipe() { CloseCommandPipe(); Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); // Make the command file descriptor here: Status result = m_pipe.CreateNew(m_child_processes_inherit); if (!result.Success()) { if (log) log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe () - could not " "make pipe: %s", static_cast(this), result.AsCString()); } else { if (log) log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe() - success " "readfd=%d writefd=%d", static_cast(this), m_pipe.GetReadFileDescriptor(), m_pipe.GetWriteFileDescriptor()); } } void ConnectionFileDescriptor::CloseCommandPipe() { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); if (log) log->Printf("%p ConnectionFileDescriptor::CloseCommandPipe()", static_cast(this)); m_pipe.Close(); } bool ConnectionFileDescriptor::IsConnected() const { return (m_read_sp && m_read_sp->IsValid()) || (m_write_sp && m_write_sp->IsValid()); } ConnectionStatus ConnectionFileDescriptor::Connect(llvm::StringRef path, Status *error_ptr) { std::lock_guard guard(m_mutex); Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); if (log) log->Printf("%p ConnectionFileDescriptor::Connect (url = '%s')", static_cast(this), path.str().c_str()); OpenCommandPipe(); if (!path.empty()) { llvm::Optional addr; if ((addr = GetURLAddress(path, LISTEN_SCHEME))) { // listen://HOST:PORT return SocketListenAndAccept(*addr, error_ptr); } else if ((addr = GetURLAddress(path, ACCEPT_SCHEME))) { // unix://SOCKNAME return NamedSocketAccept(*addr, error_ptr); } else if ((addr = GetURLAddress(path, UNIX_ACCEPT_SCHEME))) { // unix://SOCKNAME return NamedSocketAccept(*addr, error_ptr); } else if ((addr = GetURLAddress(path, CONNECT_SCHEME))) { return ConnectTCP(*addr, error_ptr); } else if ((addr = GetURLAddress(path, TCP_CONNECT_SCHEME))) { return ConnectTCP(*addr, error_ptr); } else if ((addr = GetURLAddress(path, UDP_SCHEME))) { return ConnectUDP(*addr, error_ptr); } else if ((addr = GetURLAddress(path, UNIX_CONNECT_SCHEME))) { // unix-connect://SOCKNAME return NamedSocketConnect(*addr, error_ptr); } else if ((addr = GetURLAddress(path, UNIX_ABSTRACT_CONNECT_SCHEME))) { // unix-abstract-connect://SOCKNAME return UnixAbstractSocketConnect(*addr, error_ptr); } #ifndef LLDB_DISABLE_POSIX else if ((addr = GetURLAddress(path, FD_SCHEME))) { // Just passing a native file descriptor within this current process // that is already opened (possibly from a service or other source). int fd = -1; if (!addr->getAsInteger(0, fd)) { // We have what looks to be a valid file descriptor, but we // should make sure it is. We currently are doing this by trying to // get the flags from the file descriptor and making sure it // isn't a bad fd. errno = 0; int flags = ::fcntl(fd, F_GETFL, 0); if (flags == -1 || errno == EBADF) { if (error_ptr) error_ptr->SetErrorStringWithFormat("stale file descriptor: %s", path.str().c_str()); m_read_sp.reset(); m_write_sp.reset(); return eConnectionStatusError; } else { // Don't take ownership of a file descriptor that gets passed // to us since someone else opened the file descriptor and // handed it to us. // TODO: Since are using a URL to open connection we should // eventually parse options using the web standard where we // have "fd://123?opt1=value;opt2=value" and we can have an // option be "owns=1" or "owns=0" or something like this to // allow us to specify this. For now, we assume we must // assume we don't own it. std::unique_ptr tcp_socket; tcp_socket.reset(new TCPSocket(fd, false, false)); // Try and get a socket option from this file descriptor to // see if this is a socket and set m_is_socket accordingly. int resuse; bool is_socket = !!tcp_socket->GetOption(SOL_SOCKET, SO_REUSEADDR, resuse); if (is_socket) { m_read_sp = std::move(tcp_socket); m_write_sp = m_read_sp; } else { m_read_sp.reset(new File(fd, false)); m_write_sp.reset(new File(fd, false)); } m_uri = *addr; return eConnectionStatusSuccess; } } if (error_ptr) error_ptr->SetErrorStringWithFormat("invalid file descriptor: \"%s\"", path.str().c_str()); m_read_sp.reset(); m_write_sp.reset(); return eConnectionStatusError; } else if ((addr = GetURLAddress(path, FILE_SCHEME))) { std::string addr_str = addr->str(); // file:///PATH - int fd = -1; - do { - fd = ::open(addr_str.c_str(), O_RDWR); - } while (fd == -1 && errno == EINTR); - + int fd = llvm::sys::RetryAfterSignal(-1, ::open, addr_str.c_str(), O_RDWR); if (fd == -1) { if (error_ptr) error_ptr->SetErrorToErrno(); return eConnectionStatusError; } if (::isatty(fd)) { // Set up serial terminal emulation struct termios options; ::tcgetattr(fd, &options); // Set port speed to maximum ::cfsetospeed(&options, B115200); ::cfsetispeed(&options, B115200); // Raw input, disable echo and signals options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // Make sure only one character is needed to return from a read options.c_cc[VMIN] = 1; options.c_cc[VTIME] = 0; ::tcsetattr(fd, TCSANOW, &options); } int flags = ::fcntl(fd, F_GETFL, 0); if (flags >= 0) { if ((flags & O_NONBLOCK) == 0) { flags |= O_NONBLOCK; ::fcntl(fd, F_SETFL, flags); } } m_read_sp.reset(new File(fd, true)); m_write_sp.reset(new File(fd, false)); return eConnectionStatusSuccess; } #endif if (error_ptr) error_ptr->SetErrorStringWithFormat("unsupported connection URL: '%s'", path.str().c_str()); return eConnectionStatusError; } if (error_ptr) error_ptr->SetErrorString("invalid connect arguments"); return eConnectionStatusError; } bool ConnectionFileDescriptor::InterruptRead() { size_t bytes_written = 0; Status result = m_pipe.Write("i", 1, bytes_written); return result.Success(); } ConnectionStatus ConnectionFileDescriptor::Disconnect(Status *error_ptr) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); if (log) log->Printf("%p ConnectionFileDescriptor::Disconnect ()", static_cast(this)); ConnectionStatus status = eConnectionStatusSuccess; if (!IsConnected()) { if (log) log->Printf( "%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect", static_cast(this)); return eConnectionStatusSuccess; } if (m_read_sp && m_read_sp->IsValid() && m_read_sp->GetFdType() == IOObject::eFDTypeSocket) static_cast(*m_read_sp).PreDisconnect(); // Try to get the ConnectionFileDescriptor's mutex. If we fail, that is quite // likely // because somebody is doing a blocking read on our file descriptor. If // that's the case, // then send the "q" char to the command file channel so the read will wake up // and the connection // will then know to shut down. m_shutting_down = true; std::unique_lock locker(m_mutex, std::defer_lock); if (!locker.try_lock()) { if (m_pipe.CanWrite()) { size_t bytes_written = 0; Status result = m_pipe.Write("q", 1, bytes_written); if (log) log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get " "the lock, sent 'q' to %d, error = '%s'.", static_cast(this), m_pipe.GetWriteFileDescriptor(), result.AsCString()); } else if (log) { log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the " "lock, but no command pipe is available.", static_cast(this)); } locker.lock(); } Status error = m_read_sp->Close(); Status error2 = m_write_sp->Close(); if (error.Fail() || error2.Fail()) status = eConnectionStatusError; if (error_ptr) *error_ptr = error.Fail() ? error : error2; // Close any pipes we were using for async interrupts m_pipe.Close(); m_uri.clear(); m_shutting_down = false; return status; } size_t ConnectionFileDescriptor::Read(void *dst, size_t dst_len, const Timeout &timeout, ConnectionStatus &status, Status *error_ptr) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); std::unique_lock locker(m_mutex, std::defer_lock); if (!locker.try_lock()) { if (log) log->Printf("%p ConnectionFileDescriptor::Read () failed to get the " "connection lock.", static_cast(this)); if (error_ptr) error_ptr->SetErrorString("failed to get the connection lock for read."); status = eConnectionStatusTimedOut; return 0; } if (m_shutting_down) { status = eConnectionStatusError; return 0; } status = BytesAvailable(timeout, error_ptr); if (status != eConnectionStatusSuccess) return 0; Status error; size_t bytes_read = dst_len; error = m_read_sp->Read(dst, bytes_read); if (log) { log->Printf("%p ConnectionFileDescriptor::Read() fd = %" PRIu64 ", dst = %p, dst_len = %" PRIu64 ") => %" PRIu64 ", error = %s", static_cast(this), static_cast(m_read_sp->GetWaitableHandle()), static_cast(dst), static_cast(dst_len), static_cast(bytes_read), error.AsCString()); } if (bytes_read == 0) { error.Clear(); // End-of-file. Do not automatically close; pass along for // the end-of-file handlers. status = eConnectionStatusEndOfFile; } if (error_ptr) *error_ptr = error; if (error.Fail()) { uint32_t error_value = error.GetError(); switch (error_value) { case EAGAIN: // The file was marked for non-blocking I/O, and no data were // ready to be read. if (m_read_sp->GetFdType() == IOObject::eFDTypeSocket) status = eConnectionStatusTimedOut; else status = eConnectionStatusSuccess; return 0; case EFAULT: // Buf points outside the allocated address space. case EINTR: // A read from a slow device was interrupted before any data // arrived by the delivery of a signal. case EINVAL: // The pointer associated with fildes was negative. case EIO: // An I/O error occurred while reading from the file system. // The process group is orphaned. // The file is a regular file, nbyte is greater than 0, // the starting position is before the end-of-file, and // the starting position is greater than or equal to the // offset maximum established for the open file // descriptor associated with fildes. case EISDIR: // An attempt is made to read a directory. case ENOBUFS: // An attempt to allocate a memory buffer fails. case ENOMEM: // Insufficient memory is available. status = eConnectionStatusError; break; // Break to close.... case ENOENT: // no such file or directory case EBADF: // fildes is not a valid file or socket descriptor open for // reading. case ENXIO: // An action is requested of a device that does not exist.. // A requested action cannot be performed by the device. case ECONNRESET: // The connection is closed by the peer during a read // attempt on a socket. case ENOTCONN: // A read is attempted on an unconnected socket. status = eConnectionStatusLostConnection; break; // Break to close.... case ETIMEDOUT: // A transmission timeout occurs during a read attempt on a // socket. status = eConnectionStatusTimedOut; return 0; default: LLDB_LOG(log, "this = {0}, unexpected error: {1}", this, llvm::sys::StrError(error_value)); status = eConnectionStatusError; break; // Break to close.... } return 0; } return bytes_read; } size_t ConnectionFileDescriptor::Write(const void *src, size_t src_len, ConnectionStatus &status, Status *error_ptr) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); if (log) log->Printf( "%p ConnectionFileDescriptor::Write (src = %p, src_len = %" PRIu64 ")", static_cast(this), static_cast(src), static_cast(src_len)); if (!IsConnected()) { if (error_ptr) error_ptr->SetErrorString("not connected"); status = eConnectionStatusNoConnection; return 0; } Status error; size_t bytes_sent = src_len; error = m_write_sp->Write(src, bytes_sent); if (log) { log->Printf("%p ConnectionFileDescriptor::Write(fd = %" PRIu64 ", src = %p, src_len = %" PRIu64 ") => %" PRIu64 " (error = %s)", static_cast(this), static_cast(m_write_sp->GetWaitableHandle()), static_cast(src), static_cast(src_len), static_cast(bytes_sent), error.AsCString()); } if (error_ptr) *error_ptr = error; if (error.Fail()) { switch (error.GetError()) { case EAGAIN: case EINTR: status = eConnectionStatusSuccess; return 0; case ECONNRESET: // The connection is closed by the peer during a read // attempt on a socket. case ENOTCONN: // A read is attempted on an unconnected socket. status = eConnectionStatusLostConnection; break; // Break to close.... default: status = eConnectionStatusError; break; // Break to close.... } return 0; } status = eConnectionStatusSuccess; return bytes_sent; } std::string ConnectionFileDescriptor::GetURI() { return m_uri; } // This ConnectionFileDescriptor::BytesAvailable() uses select() via // SelectHelper // // PROS: // - select is consistent across most unix platforms // - The Apple specific version allows for unlimited fds in the fd_sets by // setting the _DARWIN_UNLIMITED_SELECT define prior to including the // required header files. // CONS: // - on non-Apple platforms, only supports file descriptors up to FD_SETSIZE. // This implementation will assert if it runs into that hard limit to let // users know that another ConnectionFileDescriptor::BytesAvailable() should // be used or a new version of ConnectionFileDescriptor::BytesAvailable() // should be written for the system that is running into the limitations. ConnectionStatus ConnectionFileDescriptor::BytesAvailable(const Timeout &timeout, Status *error_ptr) { // Don't need to take the mutex here separately since we are only called from // Read. If we // ever get used more generally we will need to lock here as well. Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_CONNECTION)); LLDB_LOG(log, "this = {0}, timeout = {1}", this, timeout); // Make a copy of the file descriptors to make sure we don't // have another thread change these values out from under us // and cause problems in the loop below where like in FS_SET() const IOObject::WaitableHandle handle = m_read_sp->GetWaitableHandle(); const int pipe_fd = m_pipe.GetReadFileDescriptor(); if (handle != IOObject::kInvalidHandleValue) { SelectHelper select_helper; if (timeout) select_helper.SetTimeout(*timeout); select_helper.FDSetRead(handle); #if defined(_MSC_VER) // select() won't accept pipes on Windows. The entire Windows codepath // needs to be // converted over to using WaitForMultipleObjects and event HANDLEs, but for // now at least // this will allow ::select() to not return an error. const bool have_pipe_fd = false; #else const bool have_pipe_fd = pipe_fd >= 0; #endif if (have_pipe_fd) select_helper.FDSetRead(pipe_fd); while (handle == m_read_sp->GetWaitableHandle()) { Status error = select_helper.Select(); if (error_ptr) *error_ptr = error; if (error.Fail()) { switch (error.GetError()) { case EBADF: // One of the descriptor sets specified an invalid // descriptor. return eConnectionStatusLostConnection; case EINVAL: // The specified time limit is invalid. One of its // components is negative or too large. default: // Other unknown error return eConnectionStatusError; case ETIMEDOUT: return eConnectionStatusTimedOut; case EAGAIN: // The kernel was (perhaps temporarily) unable to // allocate the requested number of file descriptors, // or we have non-blocking IO case EINTR: // A signal was delivered before the time limit // expired and before any of the selected events // occurred. break; // Lets keep reading to until we timeout } } else { if (select_helper.FDIsSetRead(handle)) return eConnectionStatusSuccess; if (select_helper.FDIsSetRead(pipe_fd)) { // There is an interrupt or exit command in the command pipe // Read the data from that pipe: - char buffer[1]; + char c; - ssize_t bytes_read; - - do { - bytes_read = ::read(pipe_fd, buffer, sizeof(buffer)); - } while (bytes_read < 0 && errno == EINTR); - - switch (buffer[0]) { + ssize_t bytes_read = llvm::sys::RetryAfterSignal(-1, ::read, pipe_fd, &c, 1); + assert(bytes_read == 1); + (void)bytes_read; + switch (c) { case 'q': if (log) log->Printf("%p ConnectionFileDescriptor::BytesAvailable() " "got data: %c from the command channel.", - static_cast(this), buffer[0]); + static_cast(this), c); return eConnectionStatusEndOfFile; case 'i': // Interrupt the current read return eConnectionStatusInterrupted; } } } } } if (error_ptr) error_ptr->SetErrorString("not connected"); return eConnectionStatusLostConnection; } ConnectionStatus ConnectionFileDescriptor::NamedSocketAccept(llvm::StringRef socket_name, Status *error_ptr) { Socket *socket = nullptr; Status error = Socket::UnixDomainAccept(socket_name, m_child_processes_inherit, socket); if (error_ptr) *error_ptr = error; m_write_sp.reset(socket); m_read_sp = m_write_sp; if (error.Fail()) { return eConnectionStatusError; } m_uri.assign(socket_name); return eConnectionStatusSuccess; } ConnectionStatus ConnectionFileDescriptor::NamedSocketConnect(llvm::StringRef socket_name, Status *error_ptr) { Socket *socket = nullptr; Status error = Socket::UnixDomainConnect(socket_name, m_child_processes_inherit, socket); if (error_ptr) *error_ptr = error; m_write_sp.reset(socket); m_read_sp = m_write_sp; if (error.Fail()) { return eConnectionStatusError; } m_uri.assign(socket_name); return eConnectionStatusSuccess; } lldb::ConnectionStatus ConnectionFileDescriptor::UnixAbstractSocketConnect(llvm::StringRef socket_name, Status *error_ptr) { Socket *socket = nullptr; Status error = Socket::UnixAbstractConnect(socket_name, m_child_processes_inherit, socket); if (error_ptr) *error_ptr = error; m_write_sp.reset(socket); m_read_sp = m_write_sp; if (error.Fail()) { return eConnectionStatusError; } m_uri.assign(socket_name); return eConnectionStatusSuccess; } ConnectionStatus ConnectionFileDescriptor::SocketListenAndAccept(llvm::StringRef s, Status *error_ptr) { m_port_predicate.SetValue(0, eBroadcastNever); Socket *socket = nullptr; m_waiting_for_accept = true; Status error = Socket::TcpListen(s, m_child_processes_inherit, socket, &m_port_predicate); if (error_ptr) *error_ptr = error; if (error.Fail()) return eConnectionStatusError; std::unique_ptr listening_socket_up; listening_socket_up.reset(socket); socket = nullptr; error = listening_socket_up->Accept(socket); listening_socket_up.reset(); if (error_ptr) *error_ptr = error; if (error.Fail()) return eConnectionStatusError; InitializeSocket(socket); return eConnectionStatusSuccess; } ConnectionStatus ConnectionFileDescriptor::ConnectTCP(llvm::StringRef s, Status *error_ptr) { Socket *socket = nullptr; Status error = Socket::TcpConnect(s, m_child_processes_inherit, socket); if (error_ptr) *error_ptr = error; m_write_sp.reset(socket); m_read_sp = m_write_sp; if (error.Fail()) { return eConnectionStatusError; } m_uri.assign(s); return eConnectionStatusSuccess; } ConnectionStatus ConnectionFileDescriptor::ConnectUDP(llvm::StringRef s, Status *error_ptr) { Socket *socket = nullptr; Status error = Socket::UdpConnect(s, m_child_processes_inherit, socket); if (error_ptr) *error_ptr = error; m_write_sp.reset(socket); m_read_sp = m_write_sp; if (error.Fail()) { return eConnectionStatusError; } m_uri.assign(s); return eConnectionStatusSuccess; } uint16_t ConnectionFileDescriptor::GetListeningPort(uint32_t timeout_sec) { uint16_t bound_port = 0; if (timeout_sec == UINT32_MAX) m_port_predicate.WaitForValueNotEqualTo(0, bound_port); else m_port_predicate.WaitForValueNotEqualTo(0, bound_port, std::chrono::seconds(timeout_sec)); return bound_port; } bool ConnectionFileDescriptor::GetChildProcessesInherit() const { return m_child_processes_inherit; } void ConnectionFileDescriptor::SetChildProcessesInherit( bool child_processes_inherit) { m_child_processes_inherit = child_processes_inherit; } void ConnectionFileDescriptor::InitializeSocket(Socket *socket) { assert(socket->GetSocketProtocol() == Socket::ProtocolTcp); TCPSocket *tcp_socket = static_cast(socket); m_write_sp.reset(socket); m_read_sp = m_write_sp; StreamString strm; strm.Printf("connect://%s:%u", tcp_socket->GetRemoteIPAddress().c_str(), tcp_socket->GetRemotePortNumber()); m_uri = strm.GetString(); } Index: vendor/lldb/dist/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp (revision 320967) @@ -1,154 +1,154 @@ //===-- AuxVector.cpp -------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // C Includes #include #include #include // C++ Includes // Other libraries and framework includes #include "lldb/Target/Process.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Log.h" #if defined(__linux__) || defined(__FreeBSD__) #include "Plugins/Process/elf-core/ProcessElfCore.h" #endif #include "AuxVector.h" using namespace lldb; using namespace lldb_private; static bool GetMaxU64(DataExtractor &data, lldb::offset_t *offset_ptr, uint64_t *value, unsigned int byte_size) { lldb::offset_t saved_offset = *offset_ptr; *value = data.GetMaxU64(offset_ptr, byte_size); return *offset_ptr != saved_offset; } static bool ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry, lldb::offset_t *offset_ptr, unsigned int byte_size) { if (!GetMaxU64(data, offset_ptr, &entry.type, byte_size)) return false; if (!GetMaxU64(data, offset_ptr, &entry.value, byte_size)) return false; return true; } DataBufferSP AuxVector::GetAuxvData() { if (m_process) return m_process->GetAuxvData(); else return DataBufferSP(); } void AuxVector::ParseAuxv(DataExtractor &data) { const unsigned int byte_size = m_process->GetAddressByteSize(); lldb::offset_t offset = 0; for (;;) { Entry entry; if (!ParseAuxvEntry(data, entry, &offset, byte_size)) break; - if (entry.type == AT_NULL) + if (entry.type == AUXV_AT_NULL) break; - if (entry.type == AT_IGNORE) + if (entry.type == AUXV_AT_IGNORE) continue; m_auxv.push_back(entry); } } AuxVector::AuxVector(Process *process) : m_process(process) { DataExtractor data; Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); data.SetData(GetAuxvData()); data.SetByteOrder(m_process->GetByteOrder()); data.SetAddressByteSize(m_process->GetAddressByteSize()); ParseAuxv(data); if (log) DumpToLog(log); } AuxVector::iterator AuxVector::FindEntry(EntryType type) const { for (iterator I = begin(); I != end(); ++I) { if (I->type == static_cast(type)) return I; } return end(); } void AuxVector::DumpToLog(Log *log) const { if (!log) return; log->PutCString("AuxVector: "); for (iterator I = begin(); I != end(); ++I) { log->Printf(" %s [%" PRIu64 "]: %" PRIx64, GetEntryName(*I), I->type, I->value); } } const char *AuxVector::GetEntryName(EntryType type) { const char *name = "AT_???"; -#define ENTRY_NAME(_type) \ - _type: \ - name = #_type +#define ENTRY_NAME(_type) \ + _type: \ + name = #_type + 5 switch (type) { - case ENTRY_NAME(AT_NULL); break; - case ENTRY_NAME(AT_IGNORE); break; - case ENTRY_NAME(AT_EXECFD); break; - case ENTRY_NAME(AT_PHDR); break; - case ENTRY_NAME(AT_PHENT); break; - case ENTRY_NAME(AT_PHNUM); break; - case ENTRY_NAME(AT_PAGESZ); break; - case ENTRY_NAME(AT_BASE); break; - case ENTRY_NAME(AT_FLAGS); break; - case ENTRY_NAME(AT_ENTRY); break; - case ENTRY_NAME(AT_NOTELF); break; - case ENTRY_NAME(AT_UID); break; - case ENTRY_NAME(AT_EUID); break; - case ENTRY_NAME(AT_GID); break; - case ENTRY_NAME(AT_EGID); break; - case ENTRY_NAME(AT_CLKTCK); break; - case ENTRY_NAME(AT_PLATFORM); break; - case ENTRY_NAME(AT_HWCAP); break; - case ENTRY_NAME(AT_FPUCW); break; - case ENTRY_NAME(AT_DCACHEBSIZE); break; - case ENTRY_NAME(AT_ICACHEBSIZE); break; - case ENTRY_NAME(AT_UCACHEBSIZE); break; - case ENTRY_NAME(AT_IGNOREPPC); break; - case ENTRY_NAME(AT_SECURE); break; - case ENTRY_NAME(AT_BASE_PLATFORM); break; - case ENTRY_NAME(AT_RANDOM); break; - case ENTRY_NAME(AT_EXECFN); break; - case ENTRY_NAME(AT_SYSINFO); break; - case ENTRY_NAME(AT_SYSINFO_EHDR); break; - case ENTRY_NAME(AT_L1I_CACHESHAPE); break; - case ENTRY_NAME(AT_L1D_CACHESHAPE); break; - case ENTRY_NAME(AT_L2_CACHESHAPE); break; - case ENTRY_NAME(AT_L3_CACHESHAPE); break; + case ENTRY_NAME(AUXV_AT_NULL); break; + case ENTRY_NAME(AUXV_AT_IGNORE); break; + case ENTRY_NAME(AUXV_AT_EXECFD); break; + case ENTRY_NAME(AUXV_AT_PHDR); break; + case ENTRY_NAME(AUXV_AT_PHENT); break; + case ENTRY_NAME(AUXV_AT_PHNUM); break; + case ENTRY_NAME(AUXV_AT_PAGESZ); break; + case ENTRY_NAME(AUXV_AT_BASE); break; + case ENTRY_NAME(AUXV_AT_FLAGS); break; + case ENTRY_NAME(AUXV_AT_ENTRY); break; + case ENTRY_NAME(AUXV_AT_NOTELF); break; + case ENTRY_NAME(AUXV_AT_UID); break; + case ENTRY_NAME(AUXV_AT_EUID); break; + case ENTRY_NAME(AUXV_AT_GID); break; + case ENTRY_NAME(AUXV_AT_EGID); break; + case ENTRY_NAME(AUXV_AT_CLKTCK); break; + case ENTRY_NAME(AUXV_AT_PLATFORM); break; + case ENTRY_NAME(AUXV_AT_HWCAP); break; + case ENTRY_NAME(AUXV_AT_FPUCW); break; + case ENTRY_NAME(AUXV_AT_DCACHEBSIZE); break; + case ENTRY_NAME(AUXV_AT_ICACHEBSIZE); break; + case ENTRY_NAME(AUXV_AT_UCACHEBSIZE); break; + case ENTRY_NAME(AUXV_AT_IGNOREPPC); break; + case ENTRY_NAME(AUXV_AT_SECURE); break; + case ENTRY_NAME(AUXV_AT_BASE_PLATFORM); break; + case ENTRY_NAME(AUXV_AT_RANDOM); break; + case ENTRY_NAME(AUXV_AT_EXECFN); break; + case ENTRY_NAME(AUXV_AT_SYSINFO); break; + case ENTRY_NAME(AUXV_AT_SYSINFO_EHDR); break; + case ENTRY_NAME(AUXV_AT_L1I_CACHESHAPE); break; + case ENTRY_NAME(AUXV_AT_L1D_CACHESHAPE); break; + case ENTRY_NAME(AUXV_AT_L2_CACHESHAPE); break; + case ENTRY_NAME(AUXV_AT_L3_CACHESHAPE); break; } #undef ENTRY_NAME return name; } Index: vendor/lldb/dist/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h =================================================================== --- vendor/lldb/dist/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h (revision 320966) +++ vendor/lldb/dist/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h (revision 320967) @@ -1,110 +1,111 @@ //===-- AuxVector.h ---------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef liblldb_AuxVector_H_ #define liblldb_AuxVector_H_ // C Includes // C++ Includes #include // Other libraries and framework includes #include "lldb/lldb-forward.h" namespace lldb_private { class DataExtractor; } /// @class AuxVector /// @brief Represents a processes auxiliary vector. /// /// When a process is loaded on Linux a vector of values is placed onto the /// stack communicating operating system specific information. On construction /// this class locates and parses this information and provides a simple /// read-only interface to the entries found. class AuxVector { public: AuxVector(lldb_private::Process *process); struct Entry { uint64_t type; uint64_t value; Entry() : type(0), value(0) {} }; /// Constants describing the type of entry. /// On Linux, running "LD_SHOW_AUXV=1 ./executable" will spew AUX information. + /// Added AUXV prefix to avoid potential conflicts with system-defined macros enum EntryType { - AT_NULL = 0, ///< End of auxv. - AT_IGNORE = 1, ///< Ignore entry. - AT_EXECFD = 2, ///< File descriptor of program. - AT_PHDR = 3, ///< Program headers. - AT_PHENT = 4, ///< Size of program header. - AT_PHNUM = 5, ///< Number of program headers. - AT_PAGESZ = 6, ///< Page size. - AT_BASE = 7, ///< Interpreter base address. - AT_FLAGS = 8, ///< Flags. - AT_ENTRY = 9, ///< Program entry point. - AT_NOTELF = 10, ///< Set if program is not an ELF. - AT_UID = 11, ///< UID. - AT_EUID = 12, ///< Effective UID. - AT_GID = 13, ///< GID. - AT_EGID = 14, ///< Effective GID. - AT_CLKTCK = 17, ///< Clock frequency (e.g. times(2)). - AT_PLATFORM = 15, ///< String identifying platform. - AT_HWCAP = 16, ///< Machine dependent hints about processor capabilities. - AT_FPUCW = 18, ///< Used FPU control word. - AT_DCACHEBSIZE = 19, ///< Data cache block size. - AT_ICACHEBSIZE = 20, ///< Instruction cache block size. - AT_UCACHEBSIZE = 21, ///< Unified cache block size. - AT_IGNOREPPC = 22, ///< Entry should be ignored. - AT_SECURE = 23, ///< Boolean, was exec setuid-like? - AT_BASE_PLATFORM = 24, ///< String identifying real platforms. - AT_RANDOM = 25, ///< Address of 16 random bytes. - AT_EXECFN = 31, ///< Filename of executable. - AT_SYSINFO = 32, ///< Pointer to the global system page used for system - ///calls and other nice things. - AT_SYSINFO_EHDR = 33, - AT_L1I_CACHESHAPE = 34, ///< Shapes of the caches. - AT_L1D_CACHESHAPE = 35, - AT_L2_CACHESHAPE = 36, - AT_L3_CACHESHAPE = 37, + AUXV_AT_NULL = 0, ///< End of auxv. + AUXV_AT_IGNORE = 1, ///< Ignore entry. + AUXV_AT_EXECFD = 2, ///< File descriptor of program. + AUXV_AT_PHDR = 3, ///< Program headers. + AUXV_AT_PHENT = 4, ///< Size of program header. + AUXV_AT_PHNUM = 5, ///< Number of program headers. + AUXV_AT_PAGESZ = 6, ///< Page size. + AUXV_AT_BASE = 7, ///< Interpreter base address. + AUXV_AT_FLAGS = 8, ///< Flags. + AUXV_AT_ENTRY = 9, ///< Program entry point. + AUXV_AT_NOTELF = 10, ///< Set if program is not an ELF. + AUXV_AT_UID = 11, ///< UID. + AUXV_AT_EUID = 12, ///< Effective UID. + AUXV_AT_GID = 13, ///< GID. + AUXV_AT_EGID = 14, ///< Effective GID. + AUXV_AT_CLKTCK = 17, ///< Clock frequency (e.g. times(2)). + AUXV_AT_PLATFORM = 15, ///< String identifying platform. + AUXV_AT_HWCAP = 16, ///< Machine dependent hints about processor capabilities. + AUXV_AT_FPUCW = 18, ///< Used FPU control word. + AUXV_AT_DCACHEBSIZE = 19, ///< Data cache block size. + AUXV_AT_ICACHEBSIZE = 20, ///< Instruction cache block size. + AUXV_AT_UCACHEBSIZE = 21, ///< Unified cache block size. + AUXV_AT_IGNOREPPC = 22, ///< Entry should be ignored. + AUXV_AT_SECURE = 23, ///< Boolean, was exec setuid-like? + AUXV_AT_BASE_PLATFORM = 24, ///< String identifying real platforms. + AUXV_AT_RANDOM = 25, ///< Address of 16 random bytes. + AUXV_AT_EXECFN = 31, ///< Filename of executable. + AUXV_AT_SYSINFO = 32, ///< Pointer to the global system page used for system + ///calls and other nice things. + AUXV_AT_SYSINFO_EHDR = 33, + AUXV_AT_L1I_CACHESHAPE = 34, ///< Shapes of the caches. + AUXV_AT_L1D_CACHESHAPE = 35, + AUXV_AT_L2_CACHESHAPE = 36, + AUXV_AT_L3_CACHESHAPE = 37, }; private: typedef std::vector EntryVector; public: typedef EntryVector::const_iterator iterator; iterator begin() const { return m_auxv.begin(); } iterator end() const { return m_auxv.end(); } iterator FindEntry(EntryType type) const; static const char *GetEntryName(const Entry &entry) { return GetEntryName(static_cast(entry.type)); } static const char *GetEntryName(EntryType type); void DumpToLog(lldb_private::Log *log) const; private: lldb_private::Process *m_process; EntryVector m_auxv; lldb::DataBufferSP GetAuxvData(); void ParseAuxv(lldb_private::DataExtractor &data); }; #endif Index: vendor/lldb/dist/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp (revision 320967) @@ -1,720 +1,720 @@ //===-- DynamicLoaderPOSIXDYLD.cpp ------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // Main header include #include "DynamicLoaderPOSIXDYLD.h" // Project includes #include "AuxVector.h" // Other libraries and framework includes #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlanRunToAddress.h" #include "lldb/Utility/Log.h" // C++ Includes // C Includes using namespace lldb; using namespace lldb_private; void DynamicLoaderPOSIXDYLD::Initialize() { PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance); } void DynamicLoaderPOSIXDYLD::Terminate() {} lldb_private::ConstString DynamicLoaderPOSIXDYLD::GetPluginName() { return GetPluginNameStatic(); } lldb_private::ConstString DynamicLoaderPOSIXDYLD::GetPluginNameStatic() { static ConstString g_name("linux-dyld"); return g_name; } const char *DynamicLoaderPOSIXDYLD::GetPluginDescriptionStatic() { return "Dynamic loader plug-in that watches for shared library " "loads/unloads in POSIX processes."; } uint32_t DynamicLoaderPOSIXDYLD::GetPluginVersion() { return 1; } DynamicLoader *DynamicLoaderPOSIXDYLD::CreateInstance(Process *process, bool force) { bool create = force; if (!create) { const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); if (triple_ref.getOS() == llvm::Triple::FreeBSD || triple_ref.getOS() == llvm::Triple::Linux || triple_ref.getOS() == llvm::Triple::NetBSD) create = true; } if (create) return new DynamicLoaderPOSIXDYLD(process); return NULL; } DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process) : DynamicLoader(process), m_rendezvous(process), m_load_offset(LLDB_INVALID_ADDRESS), m_entry_point(LLDB_INVALID_ADDRESS), m_auxv(), m_dyld_bid(LLDB_INVALID_BREAK_ID), m_vdso_base(LLDB_INVALID_ADDRESS) {} DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD() { if (m_dyld_bid != LLDB_INVALID_BREAK_ID) { m_process->GetTarget().RemoveBreakpointByID(m_dyld_bid); m_dyld_bid = LLDB_INVALID_BREAK_ID; } } void DynamicLoaderPOSIXDYLD::DidAttach() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64, __FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); m_auxv.reset(new AuxVector(m_process)); if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " reloaded auxv data", __FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); // ask the process if it can load any of its own modules m_process->LoadModules(); ModuleSP executable_sp = GetTargetExecutable(); ResolveExecutableModule(executable_sp); // find the main process load offset addr_t load_offset = ComputeLoadOffset(); if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " executable '%s', load_offset 0x%" PRIx64, __FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, executable_sp ? executable_sp->GetFileSpec().GetPath().c_str() : "", load_offset); EvalVdsoStatus(); // if we dont have a load address we cant re-base bool rebase_exec = (load_offset == LLDB_INVALID_ADDRESS) ? false : true; // if we have a valid executable if (executable_sp.get()) { lldb_private::ObjectFile *obj = executable_sp->GetObjectFile(); if (obj) { // don't rebase if the module already has a load address Target &target = m_process->GetTarget(); Address addr = obj->GetImageInfoAddress(&target); if (addr.GetLoadAddress(&target) != LLDB_INVALID_ADDRESS) rebase_exec = false; } } else { // no executable, nothing to re-base rebase_exec = false; } // if the target executable should be re-based if (rebase_exec) { ModuleList module_list; module_list.Append(executable_sp); if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " added executable '%s' to module load list", __FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, executable_sp->GetFileSpec().GetPath().c_str()); UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset, true); // When attaching to a target, there are two possible states: // (1) We already crossed the entry point and therefore the rendezvous // structure is ready to be used and we can load the list of modules // and place the rendezvous breakpoint. // (2) We didn't cross the entry point yet, so these structures are not // ready; we should behave as if we just launched the target and // call ProbeEntry(). This will place a breakpoint on the entry // point which itself will be hit after the rendezvous structure is // set up and will perform actions described in (1). if (m_rendezvous.Resolve()) { if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64 " rendezvous could resolve: attach assuming dynamic loader " "info is available now", __FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); LoadAllCurrentModules(); SetRendezvousBreakpoint(); } else { if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64 " rendezvous could not yet resolve: adding breakpoint to " "catch future rendezvous setup", __FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); ProbeEntry(); } m_process->GetTarget().ModulesDidLoad(module_list); if (log) { log->Printf("DynamicLoaderPOSIXDYLD::%s told the target about the " "modules that loaded:", __FUNCTION__); for (auto module_sp : module_list.Modules()) { log->Printf("-- [module] %s (pid %" PRIu64 ")", module_sp ? module_sp->GetFileSpec().GetPath().c_str() : "", m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); } } } } void DynamicLoaderPOSIXDYLD::DidLaunch() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s()", __FUNCTION__); ModuleSP executable; addr_t load_offset; m_auxv.reset(new AuxVector(m_process)); executable = GetTargetExecutable(); load_offset = ComputeLoadOffset(); EvalVdsoStatus(); if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) { ModuleList module_list; module_list.Append(executable); UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true); if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()", __FUNCTION__); ProbeEntry(); m_process->GetTarget().ModulesDidLoad(module_list); } } Status DynamicLoaderPOSIXDYLD::CanLoadImage() { return Status(); } void DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr, bool base_addr_is_offset) { m_loaded_modules[module] = link_map_addr; UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset); } void DynamicLoaderPOSIXDYLD::UnloadSections(const ModuleSP module) { m_loaded_modules.erase(module); UnloadSectionsCommon(module); } void DynamicLoaderPOSIXDYLD::ProbeEntry() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); const addr_t entry = GetEntryPoint(); if (entry == LLDB_INVALID_ADDRESS) { if (log) log->Printf( "DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " GetEntryPoint() returned no address, not setting entry breakpoint", __FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID); return; } if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " GetEntryPoint() returned address 0x%" PRIx64 ", setting entry breakpoint", __FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, entry); if (m_process) { Breakpoint *const entry_break = m_process->GetTarget().CreateBreakpoint(entry, true, false).get(); entry_break->SetCallback(EntryBreakpointHit, this, true); entry_break->SetBreakpointKind("shared-library-event"); // Shoudn't hit this more than once. entry_break->SetOneShot(true); } } // The runtime linker has run and initialized the rendezvous structure once the // process has hit its entry point. When we hit the corresponding breakpoint we // interrogate the rendezvous structure to get the load addresses of all // dependent modules for the process. Similarly, we can discover the runtime // linker function and setup a breakpoint to notify us of any dynamically loaded // modules (via dlopen). bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit( void *baton, StoppointCallbackContext *context, user_id_t break_id, user_id_t break_loc_id) { assert(baton && "null baton"); if (!baton) return false; Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); DynamicLoaderPOSIXDYLD *const dyld_instance = static_cast(baton); if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64, __FUNCTION__, dyld_instance->m_process ? dyld_instance->m_process->GetID() : LLDB_INVALID_PROCESS_ID); // Disable the breakpoint --- if a stop happens right after this, which we've // seen on occasion, we don't // want the breakpoint stepping thread-plan logic to show a breakpoint // instruction at the disassembled // entry point to the program. Disabling it prevents it. (One-shot is not // enough - one-shot removal logic // only happens after the breakpoint goes public, which wasn't happening in // our scenario). if (dyld_instance->m_process) { BreakpointSP breakpoint_sp = dyld_instance->m_process->GetTarget().GetBreakpointByID(break_id); if (breakpoint_sp) { if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " disabling breakpoint id %" PRIu64, __FUNCTION__, dyld_instance->m_process->GetID(), break_id); breakpoint_sp->SetEnabled(false); } else { if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " failed to find breakpoint for breakpoint id %" PRIu64, __FUNCTION__, dyld_instance->m_process->GetID(), break_id); } } else { if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s breakpoint id %" PRIu64 " no Process instance! Cannot disable breakpoint", __FUNCTION__, break_id); } dyld_instance->LoadAllCurrentModules(); dyld_instance->SetRendezvousBreakpoint(); return false; // Continue running. } void DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); addr_t break_addr = m_rendezvous.GetBreakAddress(); Target &target = m_process->GetTarget(); if (m_dyld_bid == LLDB_INVALID_BREAK_ID) { if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " setting rendezvous break address at 0x%" PRIx64, __FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, break_addr); Breakpoint *dyld_break = target.CreateBreakpoint(break_addr, true, false).get(); dyld_break->SetCallback(RendezvousBreakpointHit, this, true); dyld_break->SetBreakpointKind("shared-library-event"); m_dyld_bid = dyld_break->GetID(); } else { if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " reusing break id %" PRIu32 ", address at 0x%" PRIx64, __FUNCTION__, m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID, m_dyld_bid, break_addr); } // Make sure our breakpoint is at the right address. assert(target.GetBreakpointByID(m_dyld_bid) ->FindLocationByAddress(break_addr) ->GetBreakpoint() .GetID() == m_dyld_bid); } bool DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit( void *baton, StoppointCallbackContext *context, user_id_t break_id, user_id_t break_loc_id) { assert(baton && "null baton"); if (!baton) return false; Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); DynamicLoaderPOSIXDYLD *const dyld_instance = static_cast(baton); if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s called for pid %" PRIu64, __FUNCTION__, dyld_instance->m_process ? dyld_instance->m_process->GetID() : LLDB_INVALID_PROCESS_ID); dyld_instance->RefreshModules(); // Return true to stop the target, false to just let the target run. const bool stop_when_images_change = dyld_instance->GetStopWhenImagesChange(); if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " stop_when_images_change=%s", __FUNCTION__, dyld_instance->m_process ? dyld_instance->m_process->GetID() : LLDB_INVALID_PROCESS_ID, stop_when_images_change ? "true" : "false"); return stop_when_images_change; } void DynamicLoaderPOSIXDYLD::RefreshModules() { if (!m_rendezvous.Resolve()) return; DYLDRendezvous::iterator I; DYLDRendezvous::iterator E; ModuleList &loaded_modules = m_process->GetTarget().GetImages(); if (m_rendezvous.ModulesDidLoad()) { ModuleList new_modules; E = m_rendezvous.loaded_end(); for (I = m_rendezvous.loaded_begin(); I != E; ++I) { ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true); if (module_sp.get()) { loaded_modules.AppendIfNeeded(module_sp); new_modules.Append(module_sp); } } m_process->GetTarget().ModulesDidLoad(new_modules); } if (m_rendezvous.ModulesDidUnload()) { ModuleList old_modules; E = m_rendezvous.unloaded_end(); for (I = m_rendezvous.unloaded_begin(); I != E; ++I) { ModuleSpec module_spec{I->file_spec}; ModuleSP module_sp = loaded_modules.FindFirstModule(module_spec); if (module_sp.get()) { old_modules.Append(module_sp); UnloadSections(module_sp); } } loaded_modules.Remove(old_modules); m_process->GetTarget().ModulesDidUnload(old_modules, false); } } ThreadPlanSP DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop) { ThreadPlanSP thread_plan_sp; StackFrame *frame = thread.GetStackFrameAtIndex(0).get(); const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol); Symbol *sym = context.symbol; if (sym == NULL || !sym->IsTrampoline()) return thread_plan_sp; ConstString sym_name = sym->GetName(); if (!sym_name) return thread_plan_sp; SymbolContextList target_symbols; Target &target = thread.GetProcess()->GetTarget(); const ModuleList &images = target.GetImages(); images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols); size_t num_targets = target_symbols.GetSize(); if (!num_targets) return thread_plan_sp; typedef std::vector AddressVector; AddressVector addrs; for (size_t i = 0; i < num_targets; ++i) { SymbolContext context; AddressRange range; if (target_symbols.GetContextAtIndex(i, context)) { context.GetAddressRange(eSymbolContextEverything, 0, false, range); lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target); if (addr != LLDB_INVALID_ADDRESS) addrs.push_back(addr); } } if (addrs.size() > 0) { AddressVector::iterator start = addrs.begin(); AddressVector::iterator end = addrs.end(); std::sort(start, end); addrs.erase(std::unique(start, end), end); thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop)); } return thread_plan_sp; } void DynamicLoaderPOSIXDYLD::LoadVDSO(ModuleList &modules) { if (m_vdso_base == LLDB_INVALID_ADDRESS) return; FileSpec file("[vdso]", false); MemoryRegionInfo info; Status status = m_process->GetMemoryRegionInfo(m_vdso_base, info); if (status.Fail()) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); LLDB_LOG(log, "Failed to get vdso region info: {0}", status); return; } if (ModuleSP module_sp = m_process->ReadModuleFromMemory( file, m_vdso_base, info.GetRange().GetByteSize())) { UpdateLoadedSections(module_sp, LLDB_INVALID_ADDRESS, m_vdso_base, false); m_process->GetTarget().GetImages().AppendIfNeeded(module_sp); } } void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() { DYLDRendezvous::iterator I; DYLDRendezvous::iterator E; ModuleList module_list; if (!m_rendezvous.Resolve()) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s unable to resolve POSIX DYLD " "rendezvous address", __FUNCTION__); return; } // The rendezvous class doesn't enumerate the main module, so track // that ourselves here. ModuleSP executable = GetTargetExecutable(); m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress(); LoadVDSO(module_list); std::vector module_names; for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) module_names.push_back(I->file_spec); m_process->PrefetchModuleSpecs( module_names, m_process->GetTarget().GetArchitecture().GetTriple()); for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) { ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true); if (module_sp.get()) { module_list.Append(module_sp); } else { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); if (log) log->Printf( "DynamicLoaderPOSIXDYLD::%s failed loading module %s at 0x%" PRIx64, __FUNCTION__, I->file_spec.GetCString(), I->base_addr); } } m_process->GetTarget().ModulesDidLoad(module_list); } addr_t DynamicLoaderPOSIXDYLD::ComputeLoadOffset() { addr_t virt_entry; if (m_load_offset != LLDB_INVALID_ADDRESS) return m_load_offset; if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) return LLDB_INVALID_ADDRESS; ModuleSP module = m_process->GetTarget().GetExecutableModule(); if (!module) return LLDB_INVALID_ADDRESS; ObjectFile *exe = module->GetObjectFile(); if (!exe) return LLDB_INVALID_ADDRESS; Address file_entry = exe->GetEntryPointAddress(); if (!file_entry.IsValid()) return LLDB_INVALID_ADDRESS; m_load_offset = virt_entry - file_entry.GetFileAddress(); return m_load_offset; } void DynamicLoaderPOSIXDYLD::EvalVdsoStatus() { - AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_SYSINFO_EHDR); + AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AUXV_AT_SYSINFO_EHDR); if (I != m_auxv->end()) m_vdso_base = I->value; } addr_t DynamicLoaderPOSIXDYLD::GetEntryPoint() { if (m_entry_point != LLDB_INVALID_ADDRESS) return m_entry_point; if (m_auxv.get() == NULL) return LLDB_INVALID_ADDRESS; - AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY); + AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AUXV_AT_ENTRY); if (I == m_auxv->end()) return LLDB_INVALID_ADDRESS; m_entry_point = static_cast(I->value); const ArchSpec &arch = m_process->GetTarget().GetArchitecture(); // On ppc64, the entry point is actually a descriptor. Dereference it. if (arch.GetMachine() == llvm::Triple::ppc64) m_entry_point = ReadUnsignedIntWithSizeInBytes(m_entry_point, 8); return m_entry_point; } lldb::addr_t DynamicLoaderPOSIXDYLD::GetThreadLocalData(const lldb::ModuleSP module_sp, const lldb::ThreadSP thread, lldb::addr_t tls_file_addr) { auto it = m_loaded_modules.find(module_sp); if (it == m_loaded_modules.end()) return LLDB_INVALID_ADDRESS; addr_t link_map = it->second; if (link_map == LLDB_INVALID_ADDRESS) return LLDB_INVALID_ADDRESS; const DYLDRendezvous::ThreadInfo &metadata = m_rendezvous.GetThreadInfo(); if (!metadata.valid) return LLDB_INVALID_ADDRESS; // Get the thread pointer. addr_t tp = thread->GetThreadPointer(); if (tp == LLDB_INVALID_ADDRESS) return LLDB_INVALID_ADDRESS; // Find the module's modid. int modid_size = 4; // FIXME(spucci): This isn't right for big-endian 64-bit int64_t modid = ReadUnsignedIntWithSizeInBytes( link_map + metadata.modid_offset, modid_size); if (modid == -1) return LLDB_INVALID_ADDRESS; // Lookup the DTV structure for this thread. addr_t dtv_ptr = tp + metadata.dtv_offset; addr_t dtv = ReadPointer(dtv_ptr); if (dtv == LLDB_INVALID_ADDRESS) return LLDB_INVALID_ADDRESS; // Find the TLS block for this module. addr_t dtv_slot = dtv + metadata.dtv_slot_size * modid; addr_t tls_block = ReadPointer(dtv_slot + metadata.tls_offset); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); if (log) log->Printf("DynamicLoaderPOSIXDYLD::Performed TLS lookup: " "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 ", modid=%" PRId64 ", tls_block=0x%" PRIx64 "\n", module_sp->GetObjectName().AsCString(""), link_map, tp, (int64_t)modid, tls_block); if (tls_block == LLDB_INVALID_ADDRESS) return LLDB_INVALID_ADDRESS; else return tls_block + tls_file_addr; } void DynamicLoaderPOSIXDYLD::ResolveExecutableModule( lldb::ModuleSP &module_sp) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); if (m_process == nullptr) return; auto &target = m_process->GetTarget(); const auto platform_sp = target.GetPlatform(); ProcessInstanceInfo process_info; if (!m_process->GetProcessInfo(process_info)) { if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s - failed to get process info for " "pid %" PRIu64, __FUNCTION__, m_process->GetID()); return; } if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s - got executable by pid %" PRIu64 ": %s", __FUNCTION__, m_process->GetID(), process_info.GetExecutableFile().GetPath().c_str()); ModuleSpec module_spec(process_info.GetExecutableFile(), process_info.GetArchitecture()); if (module_sp && module_sp->MatchesModuleSpec(module_spec)) return; const auto executable_search_paths(Target::GetDefaultExecutableSearchPaths()); auto error = platform_sp->ResolveExecutable( module_spec, module_sp, !executable_search_paths.IsEmpty() ? &executable_search_paths : nullptr); if (error.Fail()) { StreamString stream; module_spec.Dump(stream); if (log) log->Printf("DynamicLoaderPOSIXDYLD::%s - failed to resolve executable " "with module spec \"%s\": %s", __FUNCTION__, stream.GetData(), error.AsCString()); return; } target.SetExecutableModule(module_sp, false); } bool DynamicLoaderPOSIXDYLD::AlwaysRelyOnEHUnwindInfo( lldb_private::SymbolContext &sym_ctx) { ModuleSP module_sp; if (sym_ctx.symbol) module_sp = sym_ctx.symbol->GetAddressRef().GetModule(); if (!module_sp && sym_ctx.function) module_sp = sym_ctx.function->GetAddressRange().GetBaseAddress().GetModule(); if (!module_sp) return false; return module_sp->GetFileSpec().GetPath() == "[vdso]"; } Index: vendor/lldb/dist/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp (revision 320967) @@ -1,323 +1,327 @@ //===-- ASanRuntime.cpp -----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "ASanRuntime.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObject.h" #include "lldb/Expression/UserExpression.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/InstrumentationRuntimeStopInfo.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" #include "llvm/ADT/StringSwitch.h" using namespace lldb; using namespace lldb_private; lldb::InstrumentationRuntimeSP AddressSanitizerRuntime::CreateInstance(const lldb::ProcessSP &process_sp) { return InstrumentationRuntimeSP(new AddressSanitizerRuntime(process_sp)); } void AddressSanitizerRuntime::Initialize() { PluginManager::RegisterPlugin( GetPluginNameStatic(), "AddressSanitizer instrumentation runtime plugin.", CreateInstance, GetTypeStatic); } void AddressSanitizerRuntime::Terminate() { PluginManager::UnregisterPlugin(CreateInstance); } lldb_private::ConstString AddressSanitizerRuntime::GetPluginNameStatic() { return ConstString("AddressSanitizer"); } lldb::InstrumentationRuntimeType AddressSanitizerRuntime::GetTypeStatic() { return eInstrumentationRuntimeTypeAddressSanitizer; } AddressSanitizerRuntime::~AddressSanitizerRuntime() { Deactivate(); } const RegularExpression & AddressSanitizerRuntime::GetPatternForRuntimeLibrary() { // FIXME: This shouldn't include the "dylib" suffix. static RegularExpression regex( llvm::StringRef("libclang_rt.asan_(.*)_dynamic\\.dylib")); return regex; } bool AddressSanitizerRuntime::CheckIfRuntimeIsValid( const lldb::ModuleSP module_sp) { const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType( ConstString("__asan_get_alloc_stack"), lldb::eSymbolTypeAny); return symbol != nullptr; } static constexpr std::chrono::seconds g_retrieve_report_data_function_timeout(2); const char *address_sanitizer_retrieve_report_data_prefix = R"( extern "C" { int __asan_report_present(); void *__asan_get_report_pc(); void *__asan_get_report_bp(); void *__asan_get_report_sp(); void *__asan_get_report_address(); const char *__asan_get_report_description(); int __asan_get_report_access_type(); size_t __asan_get_report_access_size(); } )"; const char *address_sanitizer_retrieve_report_data_command = R"( struct { int present; int access_type; void *pc; void *bp; void *sp; void *address; size_t access_size; const char *description; } t; t.present = __asan_report_present(); t.access_type = __asan_get_report_access_type(); t.pc = __asan_get_report_pc(); t.bp = __asan_get_report_bp(); t.sp = __asan_get_report_sp(); t.address = __asan_get_report_address(); t.access_size = __asan_get_report_access_size(); t.description = __asan_get_report_description(); t )"; StructuredData::ObjectSP AddressSanitizerRuntime::RetrieveReportData() { ProcessSP process_sp = GetProcessSP(); if (!process_sp) return StructuredData::ObjectSP(); ThreadSP thread_sp = process_sp->GetThreadList().GetExpressionExecutionThread(); StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); if (!frame_sp) return StructuredData::ObjectSP(); EvaluateExpressionOptions options; options.SetUnwindOnError(true); options.SetTryAllThreads(true); options.SetStopOthers(true); options.SetIgnoreBreakpoints(true); options.SetTimeout(g_retrieve_report_data_function_timeout); options.SetPrefix(address_sanitizer_retrieve_report_data_prefix); options.SetAutoApplyFixIts(false); options.SetLanguage(eLanguageTypeObjC_plus_plus); ValueObjectSP return_value_sp; ExecutionContext exe_ctx; Status eval_error; frame_sp->CalculateExecutionContext(exe_ctx); ExpressionResults result = UserExpression::Evaluate( exe_ctx, options, address_sanitizer_retrieve_report_data_command, "", return_value_sp, eval_error); if (result != eExpressionCompleted) { process_sp->GetTarget().GetDebugger().GetAsyncOutputStream()->Printf( "Warning: Cannot evaluate AddressSanitizer expression:\n%s\n", eval_error.AsCString()); return StructuredData::ObjectSP(); } int present = return_value_sp->GetValueForExpressionPath(".present") ->GetValueAsUnsigned(0); if (present != 1) return StructuredData::ObjectSP(); addr_t pc = return_value_sp->GetValueForExpressionPath(".pc")->GetValueAsUnsigned(0); /* commented out because rdar://problem/18533301 addr_t bp = return_value_sp->GetValueForExpressionPath(".bp")->GetValueAsUnsigned(0); addr_t sp = return_value_sp->GetValueForExpressionPath(".sp")->GetValueAsUnsigned(0); */ addr_t address = return_value_sp->GetValueForExpressionPath(".address") ->GetValueAsUnsigned(0); addr_t access_type = return_value_sp->GetValueForExpressionPath(".access_type") ->GetValueAsUnsigned(0); addr_t access_size = return_value_sp->GetValueForExpressionPath(".access_size") ->GetValueAsUnsigned(0); addr_t description_ptr = return_value_sp->GetValueForExpressionPath(".description") ->GetValueAsUnsigned(0); std::string description; Status error; process_sp->ReadCStringFromMemory(description_ptr, description, error); StructuredData::Dictionary *dict = new StructuredData::Dictionary(); dict->AddStringItem("instrumentation_class", "AddressSanitizer"); dict->AddStringItem("stop_type", "fatal_error"); dict->AddIntegerItem("pc", pc); /* commented out because rdar://problem/18533301 dict->AddIntegerItem("bp", bp); dict->AddIntegerItem("sp", sp); */ dict->AddIntegerItem("address", address); dict->AddIntegerItem("access_type", access_type); dict->AddIntegerItem("access_size", access_size); dict->AddStringItem("description", description); return StructuredData::ObjectSP(dict); } std::string AddressSanitizerRuntime::FormatDescription(StructuredData::ObjectSP report) { std::string description = report->GetAsDictionary() ->GetValueForKey("description") ->GetAsString() ->GetValue(); return llvm::StringSwitch(description) .Case("heap-use-after-free", "Use of deallocated memory") .Case("heap-buffer-overflow", "Heap buffer overflow") .Case("stack-buffer-underflow", "Stack buffer underflow") .Case("initialization-order-fiasco", "Initialization order problem") .Case("stack-buffer-overflow", "Stack buffer overflow") .Case("stack-use-after-return", "Use of stack memory after return") .Case("use-after-poison", "Use of poisoned memory") .Case("container-overflow", "Container overflow") .Case("stack-use-after-scope", "Use of out-of-scope stack memory") .Case("global-buffer-overflow", "Global buffer overflow") .Case("unknown-crash", "Invalid memory access") .Case("stack-overflow", "Stack space exhausted") .Case("null-deref", "Dereference of null pointer") .Case("wild-jump", "Jump to non-executable address") .Case("wild-addr-write", "Write through wild pointer") .Case("wild-addr-read", "Read from wild pointer") .Case("wild-addr", "Access through wild pointer") .Case("signal", "Deadly signal") .Case("double-free", "Deallocation of freed memory") .Case("new-delete-type-mismatch", "Deallocation size different from allocation size") .Case("bad-free", "Deallocation of non-allocated memory") .Case("alloc-dealloc-mismatch", "Mismatch between allocation and deallocation APIs") .Case("bad-malloc_usable_size", "Invalid argument to malloc_usable_size") .Case("bad-__sanitizer_get_allocated_size", "Invalid argument to __sanitizer_get_allocated_size") .Case("param-overlap", "Call to function disallowing overlapping memory ranges") .Case("negative-size-param", "Negative size used when accessing memory") .Case("bad-__sanitizer_annotate_contiguous_container", "Invalid argument to __sanitizer_annotate_contiguous_container") .Case("odr-violation", "Symbol defined in multiple translation units") .Case( "invalid-pointer-pair", "Comparison or arithmetic on pointers from different memory regions") // for unknown report codes just show the code .Default("AddressSanitizer detected: " + description); } bool AddressSanitizerRuntime::NotifyBreakpointHit( void *baton, StoppointCallbackContext *context, user_id_t break_id, user_id_t break_loc_id) { assert(baton && "null baton"); if (!baton) return false; AddressSanitizerRuntime *const instance = static_cast(baton); + ProcessSP process_sp = instance->GetProcessSP(); + + if (process_sp->GetModIDRef().IsLastResumeForUserExpression()) + return false; + StructuredData::ObjectSP report = instance->RetrieveReportData(); std::string description; if (report) { description = instance->FormatDescription(report); } - ProcessSP process_sp = instance->GetProcessSP(); // Make sure this is the right process if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP()) { ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP(); if (thread_sp) thread_sp->SetStopInfo(InstrumentationRuntimeStopInfo:: CreateStopReasonWithInstrumentationData( *thread_sp, description, report)); StreamFileSP stream_sp( process_sp->GetTarget().GetDebugger().GetOutputFile()); if (stream_sp) { stream_sp->Printf("AddressSanitizer report breakpoint hit. Use 'thread " "info -s' to get extended information about the " "report.\n"); } return true; // Return true to stop the target } else return false; // Let target run } void AddressSanitizerRuntime::Activate() { if (IsActive()) return; ProcessSP process_sp = GetProcessSP(); if (!process_sp) return; ConstString symbol_name("__asan::AsanDie()"); const Symbol *symbol = GetRuntimeModuleSP()->FindFirstSymbolWithNameAndType( symbol_name, eSymbolTypeCode); if (symbol == NULL) return; if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid()) return; Target &target = process_sp->GetTarget(); addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target); if (symbol_address == LLDB_INVALID_ADDRESS) return; bool internal = true; bool hardware = false; Breakpoint *breakpoint = process_sp->GetTarget() .CreateBreakpoint(symbol_address, internal, hardware) .get(); breakpoint->SetCallback(AddressSanitizerRuntime::NotifyBreakpointHit, this, true); breakpoint->SetBreakpointKind("address-sanitizer-report"); SetBreakpointID(breakpoint->GetID()); SetActive(true); } void AddressSanitizerRuntime::Deactivate() { if (GetBreakpointID() != LLDB_INVALID_BREAK_ID) { ProcessSP process_sp = GetProcessSP(); if (process_sp) { process_sp->GetTarget().RemoveBreakpointByID(GetBreakpointID()); SetBreakpointID(LLDB_INVALID_BREAK_ID); } } SetActive(false); } Index: vendor/lldb/dist/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp (revision 320967) @@ -1,273 +1,276 @@ //===-- MainThreadCheckerRuntime.cpp ----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "MainThreadCheckerRuntime.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Variable.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/InstrumentationRuntimeStopInfo.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/RegularExpression.h" #include "Plugins/Process/Utility/HistoryThread.h" using namespace lldb; using namespace lldb_private; MainThreadCheckerRuntime::~MainThreadCheckerRuntime() { Deactivate(); } lldb::InstrumentationRuntimeSP MainThreadCheckerRuntime::CreateInstance(const lldb::ProcessSP &process_sp) { return InstrumentationRuntimeSP(new MainThreadCheckerRuntime(process_sp)); } void MainThreadCheckerRuntime::Initialize() { PluginManager::RegisterPlugin( GetPluginNameStatic(), "MainThreadChecker instrumentation runtime plugin.", CreateInstance, GetTypeStatic); } void MainThreadCheckerRuntime::Terminate() { PluginManager::UnregisterPlugin(CreateInstance); } lldb_private::ConstString MainThreadCheckerRuntime::GetPluginNameStatic() { return ConstString("MainThreadChecker"); } lldb::InstrumentationRuntimeType MainThreadCheckerRuntime::GetTypeStatic() { return eInstrumentationRuntimeTypeMainThreadChecker; } const RegularExpression & MainThreadCheckerRuntime::GetPatternForRuntimeLibrary() { static RegularExpression regex(llvm::StringRef("libMainThreadChecker.dylib")); return regex; } bool MainThreadCheckerRuntime::CheckIfRuntimeIsValid( const lldb::ModuleSP module_sp) { static ConstString test_sym("__main_thread_checker_on_report"); const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType(test_sym, lldb::eSymbolTypeAny); return symbol != nullptr; } StructuredData::ObjectSP MainThreadCheckerRuntime::RetrieveReportData(ExecutionContextRef exe_ctx_ref) { ProcessSP process_sp = GetProcessSP(); if (!process_sp) return StructuredData::ObjectSP(); ThreadSP thread_sp = exe_ctx_ref.GetThreadSP(); StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); ModuleSP runtime_module_sp = GetRuntimeModuleSP(); Target &target = process_sp->GetTarget(); if (!frame_sp) return StructuredData::ObjectSP(); RegisterContextSP regctx_sp = frame_sp->GetRegisterContext(); if (!regctx_sp) return StructuredData::ObjectSP(); const RegisterInfo *reginfo = regctx_sp->GetRegisterInfoByName("arg1"); if (!reginfo) return StructuredData::ObjectSP(); uint64_t apiname_ptr = regctx_sp->ReadRegisterAsUnsigned(reginfo, 0); if (!apiname_ptr) return StructuredData::ObjectSP(); std::string apiName = ""; Status read_error; target.ReadCStringFromMemory(apiname_ptr, apiName, read_error); if (read_error.Fail()) return StructuredData::ObjectSP(); std::string className = ""; std::string selector = ""; if (apiName.substr(0, 2) == "-[") { size_t spacePos = apiName.find(" "); if (spacePos != std::string::npos) { className = apiName.substr(2, spacePos - 2); selector = apiName.substr(spacePos + 1, apiName.length() - spacePos - 2); } } // Gather the PCs of the user frames in the backtrace. StructuredData::Array *trace = new StructuredData::Array(); auto trace_sp = StructuredData::ObjectSP(trace); StackFrameSP responsible_frame; for (unsigned I = 0; I < thread_sp->GetStackFrameCount(); ++I) { StackFrameSP frame = thread_sp->GetStackFrameAtIndex(I); Address addr = frame->GetFrameCodeAddress(); if (addr.GetModule() == runtime_module_sp) // Skip PCs from the runtime. continue; // The first non-runtime frame is responsible for the bug. if (!responsible_frame) responsible_frame = frame; // First frame in stacktrace should point to a real PC, not return address. if (I != 0 && trace->GetSize() == 0) { addr.Slide(-1); } lldb::addr_t PC = addr.GetLoadAddress(&target); trace->AddItem(StructuredData::ObjectSP(new StructuredData::Integer(PC))); } auto *d = new StructuredData::Dictionary(); auto dict_sp = StructuredData::ObjectSP(d); d->AddStringItem("instrumentation_class", "MainThreadChecker"); d->AddStringItem("api_name", apiName); d->AddStringItem("class_name", className); d->AddStringItem("selector", selector); d->AddStringItem("description", - apiName + " must be called from main thread only"); + apiName + " must be used from main thread only"); d->AddIntegerItem("tid", thread_sp->GetIndexID()); d->AddItem("trace", trace_sp); return dict_sp; } bool MainThreadCheckerRuntime::NotifyBreakpointHit( void *baton, StoppointCallbackContext *context, user_id_t break_id, user_id_t break_loc_id) { assert(baton && "null baton"); if (!baton) return false; //< false => resume execution. MainThreadCheckerRuntime *const instance = static_cast(baton); ProcessSP process_sp = instance->GetProcessSP(); ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP(); if (!process_sp || !thread_sp || process_sp != context->exe_ctx_ref.GetProcessSP()) + return false; + + if (process_sp->GetModIDRef().IsLastResumeForUserExpression()) return false; StructuredData::ObjectSP report = instance->RetrieveReportData(context->exe_ctx_ref); if (report) { std::string description = report->GetAsDictionary() ->GetValueForKey("description") ->GetAsString() ->GetValue(); thread_sp->SetStopInfo( InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData( *thread_sp, description, report)); return true; } return false; } void MainThreadCheckerRuntime::Activate() { if (IsActive()) return; ProcessSP process_sp = GetProcessSP(); if (!process_sp) return; ModuleSP runtime_module_sp = GetRuntimeModuleSP(); ConstString symbol_name("__main_thread_checker_on_report"); const Symbol *symbol = runtime_module_sp->FindFirstSymbolWithNameAndType( symbol_name, eSymbolTypeCode); if (symbol == nullptr) return; if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid()) return; Target &target = process_sp->GetTarget(); addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target); if (symbol_address == LLDB_INVALID_ADDRESS) return; Breakpoint *breakpoint = process_sp->GetTarget() .CreateBreakpoint(symbol_address, /*internal=*/true, /*hardware=*/false) .get(); breakpoint->SetCallback(MainThreadCheckerRuntime::NotifyBreakpointHit, this, true); breakpoint->SetBreakpointKind("main-thread-checker-report"); SetBreakpointID(breakpoint->GetID()); SetActive(true); } void MainThreadCheckerRuntime::Deactivate() { SetActive(false); auto BID = GetBreakpointID(); if (BID == LLDB_INVALID_BREAK_ID) return; if (ProcessSP process_sp = GetProcessSP()) { process_sp->GetTarget().RemoveBreakpointByID(BID); SetBreakpointID(LLDB_INVALID_BREAK_ID); } } lldb::ThreadCollectionSP MainThreadCheckerRuntime::GetBacktracesFromExtendedStopInfo( StructuredData::ObjectSP info) { ThreadCollectionSP threads; threads.reset(new ThreadCollection()); ProcessSP process_sp = GetProcessSP(); if (info->GetObjectForDotSeparatedPath("instrumentation_class") ->GetStringValue() != "MainThreadChecker") return threads; std::vector PCs; auto trace = info->GetObjectForDotSeparatedPath("trace")->GetAsArray(); trace->ForEach([&PCs](StructuredData::Object *PC) -> bool { PCs.push_back(PC->GetAsInteger()->GetValue()); return true; }); if (PCs.empty()) return threads; StructuredData::ObjectSP thread_id_obj = info->GetObjectForDotSeparatedPath("tid"); tid_t tid = thread_id_obj ? thread_id_obj->GetIntegerValue() : 0; uint32_t stop_id = 0; bool stop_id_is_valid = false; HistoryThread *history_thread = new HistoryThread(*process_sp, tid, PCs, stop_id, stop_id_is_valid); ThreadSP new_thread_sp(history_thread); // Save this in the Process' ExtendedThreadList so a strong pointer // retains the object process_sp->GetExtendedThreadList().AddThread(new_thread_sp); threads->AddThread(new_thread_sp); return threads; } Index: vendor/lldb/dist/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp (revision 320967) @@ -1,1066 +1,1070 @@ //===-- TSanRuntime.cpp -----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "TSanRuntime.h" #include "Plugins/Process/Utility/HistoryThread.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObject.h" #include "lldb/Expression/UserExpression.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Variable.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/InstrumentationRuntimeStopInfo.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" using namespace lldb; using namespace lldb_private; lldb::InstrumentationRuntimeSP ThreadSanitizerRuntime::CreateInstance(const lldb::ProcessSP &process_sp) { return InstrumentationRuntimeSP(new ThreadSanitizerRuntime(process_sp)); } void ThreadSanitizerRuntime::Initialize() { PluginManager::RegisterPlugin( GetPluginNameStatic(), "ThreadSanitizer instrumentation runtime plugin.", CreateInstance, GetTypeStatic); } void ThreadSanitizerRuntime::Terminate() { PluginManager::UnregisterPlugin(CreateInstance); } lldb_private::ConstString ThreadSanitizerRuntime::GetPluginNameStatic() { return ConstString("ThreadSanitizer"); } lldb::InstrumentationRuntimeType ThreadSanitizerRuntime::GetTypeStatic() { return eInstrumentationRuntimeTypeThreadSanitizer; } ThreadSanitizerRuntime::~ThreadSanitizerRuntime() { Deactivate(); } static constexpr std::chrono::seconds g_retrieve_data_function_timeout(2); const char *thread_sanitizer_retrieve_report_data_prefix = R"( extern "C" { void *__tsan_get_current_report(); int __tsan_get_report_data(void *report, const char **description, int *count, int *stack_count, int *mop_count, int *loc_count, int *mutex_count, int *thread_count, int *unique_tid_count, void **sleep_trace, unsigned long trace_size); int __tsan_get_report_stack(void *report, unsigned long idx, void **trace, unsigned long trace_size); int __tsan_get_report_mop(void *report, unsigned long idx, int *tid, void **addr, int *size, int *write, int *atomic, void **trace, unsigned long trace_size); int __tsan_get_report_loc(void *report, unsigned long idx, const char **type, void **addr, unsigned long *start, unsigned long *size, int *tid, int *fd, int *suppressable, void **trace, unsigned long trace_size); int __tsan_get_report_mutex(void *report, unsigned long idx, unsigned long *mutex_id, void **addr, int *destroyed, void **trace, unsigned long trace_size); int __tsan_get_report_thread(void *report, unsigned long idx, int *tid, unsigned long *os_id, int *running, const char **name, int *parent_tid, void **trace, unsigned long trace_size); int __tsan_get_report_unique_tid(void *report, unsigned long idx, int *tid); // TODO: dlsym won't work on Windows. void *dlsym(void* handle, const char* symbol); int (*ptr__tsan_get_report_loc_object_type)(void *report, unsigned long idx, const char **object_type); } const int REPORT_TRACE_SIZE = 128; const int REPORT_ARRAY_SIZE = 4; struct data { void *report; const char *description; int report_count; void *sleep_trace[REPORT_TRACE_SIZE]; int stack_count; struct { int idx; void *trace[REPORT_TRACE_SIZE]; } stacks[REPORT_ARRAY_SIZE]; int mop_count; struct { int idx; int tid; int size; int write; int atomic; void *addr; void *trace[REPORT_TRACE_SIZE]; } mops[REPORT_ARRAY_SIZE]; int loc_count; struct { int idx; const char *type; void *addr; unsigned long start; unsigned long size; int tid; int fd; int suppressable; void *trace[REPORT_TRACE_SIZE]; const char *object_type; } locs[REPORT_ARRAY_SIZE]; int mutex_count; struct { int idx; unsigned long mutex_id; void *addr; int destroyed; void *trace[REPORT_TRACE_SIZE]; } mutexes[REPORT_ARRAY_SIZE]; int thread_count; struct { int idx; int tid; unsigned long os_id; int running; const char *name; int parent_tid; void *trace[REPORT_TRACE_SIZE]; } threads[REPORT_ARRAY_SIZE]; int unique_tid_count; struct { int idx; int tid; } unique_tids[REPORT_ARRAY_SIZE]; }; )"; const char *thread_sanitizer_retrieve_report_data_command = R"( data t = {0}; ptr__tsan_get_report_loc_object_type = (typeof(ptr__tsan_get_report_loc_object_type))(void *)dlsym((void*)-2 /*RTLD_DEFAULT*/, "__tsan_get_report_loc_object_type"); t.report = __tsan_get_current_report(); __tsan_get_report_data(t.report, &t.description, &t.report_count, &t.stack_count, &t.mop_count, &t.loc_count, &t.mutex_count, &t.thread_count, &t.unique_tid_count, t.sleep_trace, REPORT_TRACE_SIZE); if (t.stack_count > REPORT_ARRAY_SIZE) t.stack_count = REPORT_ARRAY_SIZE; for (int i = 0; i < t.stack_count; i++) { t.stacks[i].idx = i; __tsan_get_report_stack(t.report, i, t.stacks[i].trace, REPORT_TRACE_SIZE); } if (t.mop_count > REPORT_ARRAY_SIZE) t.mop_count = REPORT_ARRAY_SIZE; for (int i = 0; i < t.mop_count; i++) { t.mops[i].idx = i; __tsan_get_report_mop(t.report, i, &t.mops[i].tid, &t.mops[i].addr, &t.mops[i].size, &t.mops[i].write, &t.mops[i].atomic, t.mops[i].trace, REPORT_TRACE_SIZE); } if (t.loc_count > REPORT_ARRAY_SIZE) t.loc_count = REPORT_ARRAY_SIZE; for (int i = 0; i < t.loc_count; i++) { t.locs[i].idx = i; __tsan_get_report_loc(t.report, i, &t.locs[i].type, &t.locs[i].addr, &t.locs[i].start, &t.locs[i].size, &t.locs[i].tid, &t.locs[i].fd, &t.locs[i].suppressable, t.locs[i].trace, REPORT_TRACE_SIZE); if (ptr__tsan_get_report_loc_object_type) ptr__tsan_get_report_loc_object_type(t.report, i, &t.locs[i].object_type); } if (t.mutex_count > REPORT_ARRAY_SIZE) t.mutex_count = REPORT_ARRAY_SIZE; for (int i = 0; i < t.mutex_count; i++) { t.mutexes[i].idx = i; __tsan_get_report_mutex(t.report, i, &t.mutexes[i].mutex_id, &t.mutexes[i].addr, &t.mutexes[i].destroyed, t.mutexes[i].trace, REPORT_TRACE_SIZE); } if (t.thread_count > REPORT_ARRAY_SIZE) t.thread_count = REPORT_ARRAY_SIZE; for (int i = 0; i < t.thread_count; i++) { t.threads[i].idx = i; __tsan_get_report_thread(t.report, i, &t.threads[i].tid, &t.threads[i].os_id, &t.threads[i].running, &t.threads[i].name, &t.threads[i].parent_tid, t.threads[i].trace, REPORT_TRACE_SIZE); } if (t.unique_tid_count > REPORT_ARRAY_SIZE) t.unique_tid_count = REPORT_ARRAY_SIZE; for (int i = 0; i < t.unique_tid_count; i++) { t.unique_tids[i].idx = i; __tsan_get_report_unique_tid(t.report, i, &t.unique_tids[i].tid); } t; )"; static StructuredData::Array * CreateStackTrace(ValueObjectSP o, const std::string &trace_item_name = ".trace") { StructuredData::Array *trace = new StructuredData::Array(); ValueObjectSP trace_value_object = o->GetValueForExpressionPath(trace_item_name.c_str()); size_t count = trace_value_object->GetNumChildren(); for (size_t j = 0; j < count; j++) { addr_t trace_addr = trace_value_object->GetChildAtIndex(j, true)->GetValueAsUnsigned(0); if (trace_addr == 0) break; trace->AddItem( StructuredData::ObjectSP(new StructuredData::Integer(trace_addr))); } return trace; } static StructuredData::Array *ConvertToStructuredArray( ValueObjectSP return_value_sp, const std::string &items_name, const std::string &count_name, std::function const &callback) { StructuredData::Array *array = new StructuredData::Array(); unsigned int count = return_value_sp->GetValueForExpressionPath(count_name.c_str()) ->GetValueAsUnsigned(0); ValueObjectSP objects = return_value_sp->GetValueForExpressionPath(items_name.c_str()); for (unsigned int i = 0; i < count; i++) { ValueObjectSP o = objects->GetChildAtIndex(i, true); StructuredData::Dictionary *dict = new StructuredData::Dictionary(); callback(o, dict); array->AddItem(StructuredData::ObjectSP(dict)); } return array; } static std::string RetrieveString(ValueObjectSP return_value_sp, ProcessSP process_sp, const std::string &expression_path) { addr_t ptr = return_value_sp->GetValueForExpressionPath(expression_path.c_str()) ->GetValueAsUnsigned(0); std::string str; Status error; process_sp->ReadCStringFromMemory(ptr, str, error); return str; } static void GetRenumberedThreadIds(ProcessSP process_sp, ValueObjectSP data, std::map &thread_id_map) { ConvertToStructuredArray( data, ".threads", ".thread_count", [process_sp, &thread_id_map](ValueObjectSP o, StructuredData::Dictionary *dict) { uint64_t thread_id = o->GetValueForExpressionPath(".tid")->GetValueAsUnsigned(0); uint64_t thread_os_id = o->GetValueForExpressionPath(".os_id")->GetValueAsUnsigned(0); user_id_t lldb_user_id = 0; bool can_update = true; ThreadSP lldb_thread = process_sp->GetThreadList().FindThreadByID( thread_os_id, can_update); if (lldb_thread) { lldb_user_id = lldb_thread->GetIndexID(); } else { // This isn't a live thread anymore. Ask process to assign a new // Index ID (or return an old one if we've already seen this // thread_os_id). // It will also make sure that no new threads are assigned this Index // ID. lldb_user_id = process_sp->AssignIndexIDToThread(thread_os_id); } thread_id_map[thread_id] = lldb_user_id; }); } static user_id_t Renumber(uint64_t id, std::map &thread_id_map) { auto IT = thread_id_map.find(id); if (IT == thread_id_map.end()) return 0; return IT->second; } StructuredData::ObjectSP ThreadSanitizerRuntime::RetrieveReportData(ExecutionContextRef exe_ctx_ref) { ProcessSP process_sp = GetProcessSP(); if (!process_sp) return StructuredData::ObjectSP(); ThreadSP thread_sp = exe_ctx_ref.GetThreadSP(); StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); if (!frame_sp) return StructuredData::ObjectSP(); EvaluateExpressionOptions options; options.SetUnwindOnError(true); options.SetTryAllThreads(true); options.SetStopOthers(true); options.SetIgnoreBreakpoints(true); options.SetTimeout(g_retrieve_data_function_timeout); options.SetPrefix(thread_sanitizer_retrieve_report_data_prefix); options.SetAutoApplyFixIts(false); options.SetLanguage(eLanguageTypeObjC_plus_plus); ValueObjectSP main_value; ExecutionContext exe_ctx; Status eval_error; frame_sp->CalculateExecutionContext(exe_ctx); ExpressionResults result = UserExpression::Evaluate( exe_ctx, options, thread_sanitizer_retrieve_report_data_command, "", main_value, eval_error); if (result != eExpressionCompleted) { process_sp->GetTarget().GetDebugger().GetAsyncOutputStream()->Printf( "Warning: Cannot evaluate ThreadSanitizer expression:\n%s\n", eval_error.AsCString()); return StructuredData::ObjectSP(); } std::map thread_id_map; GetRenumberedThreadIds(process_sp, main_value, thread_id_map); StructuredData::Dictionary *dict = new StructuredData::Dictionary(); dict->AddStringItem("instrumentation_class", "ThreadSanitizer"); dict->AddStringItem("issue_type", RetrieveString(main_value, process_sp, ".description")); dict->AddIntegerItem("report_count", main_value->GetValueForExpressionPath(".report_count") ->GetValueAsUnsigned(0)); dict->AddItem("sleep_trace", StructuredData::ObjectSP(CreateStackTrace( main_value, ".sleep_trace"))); StructuredData::Array *stacks = ConvertToStructuredArray( main_value, ".stacks", ".stack_count", [thread_sp](ValueObjectSP o, StructuredData::Dictionary *dict) { dict->AddIntegerItem( "index", o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); // "stacks" happen on the current thread dict->AddIntegerItem("thread_id", thread_sp->GetIndexID()); }); dict->AddItem("stacks", StructuredData::ObjectSP(stacks)); StructuredData::Array *mops = ConvertToStructuredArray( main_value, ".mops", ".mop_count", [&thread_id_map](ValueObjectSP o, StructuredData::Dictionary *dict) { dict->AddIntegerItem( "index", o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); dict->AddIntegerItem( "thread_id", Renumber( o->GetValueForExpressionPath(".tid")->GetValueAsUnsigned(0), thread_id_map)); dict->AddIntegerItem( "size", o->GetValueForExpressionPath(".size")->GetValueAsUnsigned(0)); dict->AddBooleanItem( "is_write", o->GetValueForExpressionPath(".write")->GetValueAsUnsigned(0)); dict->AddBooleanItem( "is_atomic", o->GetValueForExpressionPath(".atomic")->GetValueAsUnsigned(0)); dict->AddIntegerItem( "address", o->GetValueForExpressionPath(".addr")->GetValueAsUnsigned(0)); dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); }); dict->AddItem("mops", StructuredData::ObjectSP(mops)); StructuredData::Array *locs = ConvertToStructuredArray( main_value, ".locs", ".loc_count", [process_sp, &thread_id_map](ValueObjectSP o, StructuredData::Dictionary *dict) { dict->AddIntegerItem( "index", o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); dict->AddStringItem("type", RetrieveString(o, process_sp, ".type")); dict->AddIntegerItem( "address", o->GetValueForExpressionPath(".addr")->GetValueAsUnsigned(0)); dict->AddIntegerItem( "start", o->GetValueForExpressionPath(".start")->GetValueAsUnsigned(0)); dict->AddIntegerItem( "size", o->GetValueForExpressionPath(".size")->GetValueAsUnsigned(0)); dict->AddIntegerItem( "thread_id", Renumber( o->GetValueForExpressionPath(".tid")->GetValueAsUnsigned(0), thread_id_map)); dict->AddIntegerItem( "file_descriptor", o->GetValueForExpressionPath(".fd")->GetValueAsUnsigned(0)); dict->AddIntegerItem("suppressable", o->GetValueForExpressionPath(".suppressable") ->GetValueAsUnsigned(0)); dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); dict->AddStringItem("object_type", RetrieveString(o, process_sp, ".object_type")); }); dict->AddItem("locs", StructuredData::ObjectSP(locs)); StructuredData::Array *mutexes = ConvertToStructuredArray( main_value, ".mutexes", ".mutex_count", [](ValueObjectSP o, StructuredData::Dictionary *dict) { dict->AddIntegerItem( "index", o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); dict->AddIntegerItem( "mutex_id", o->GetValueForExpressionPath(".mutex_id")->GetValueAsUnsigned(0)); dict->AddIntegerItem( "address", o->GetValueForExpressionPath(".addr")->GetValueAsUnsigned(0)); dict->AddIntegerItem( "destroyed", o->GetValueForExpressionPath(".destroyed")->GetValueAsUnsigned(0)); dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); }); dict->AddItem("mutexes", StructuredData::ObjectSP(mutexes)); StructuredData::Array *threads = ConvertToStructuredArray( main_value, ".threads", ".thread_count", [process_sp, &thread_id_map](ValueObjectSP o, StructuredData::Dictionary *dict) { dict->AddIntegerItem( "index", o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); dict->AddIntegerItem( "thread_id", Renumber( o->GetValueForExpressionPath(".tid")->GetValueAsUnsigned(0), thread_id_map)); dict->AddIntegerItem( "thread_os_id", o->GetValueForExpressionPath(".os_id")->GetValueAsUnsigned(0)); dict->AddIntegerItem( "running", o->GetValueForExpressionPath(".running")->GetValueAsUnsigned(0)); dict->AddStringItem("name", RetrieveString(o, process_sp, ".name")); dict->AddIntegerItem( "parent_thread_id", Renumber(o->GetValueForExpressionPath(".parent_tid") ->GetValueAsUnsigned(0), thread_id_map)); dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); }); dict->AddItem("threads", StructuredData::ObjectSP(threads)); StructuredData::Array *unique_tids = ConvertToStructuredArray( main_value, ".unique_tids", ".unique_tid_count", [&thread_id_map](ValueObjectSP o, StructuredData::Dictionary *dict) { dict->AddIntegerItem( "index", o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); dict->AddIntegerItem( "tid", Renumber( o->GetValueForExpressionPath(".tid")->GetValueAsUnsigned(0), thread_id_map)); }); dict->AddItem("unique_tids", StructuredData::ObjectSP(unique_tids)); return StructuredData::ObjectSP(dict); } std::string ThreadSanitizerRuntime::FormatDescription(StructuredData::ObjectSP report) { std::string description = report->GetAsDictionary() ->GetValueForKey("issue_type") ->GetAsString() ->GetValue(); if (description == "data-race") { return "Data race"; } else if (description == "data-race-vptr") { return "Data race on C++ virtual pointer"; } else if (description == "heap-use-after-free") { return "Use of deallocated memory"; } else if (description == "heap-use-after-free-vptr") { return "Use of deallocated C++ virtual pointer"; } else if (description == "thread-leak") { return "Thread leak"; } else if (description == "locked-mutex-destroy") { return "Destruction of a locked mutex"; } else if (description == "mutex-double-lock") { return "Double lock of a mutex"; } else if (description == "mutex-invalid-access") { return "Use of an uninitialized or destroyed mutex"; } else if (description == "mutex-bad-unlock") { return "Unlock of an unlocked mutex (or by a wrong thread)"; } else if (description == "mutex-bad-read-lock") { return "Read lock of a write locked mutex"; } else if (description == "mutex-bad-read-unlock") { return "Read unlock of a write locked mutex"; } else if (description == "signal-unsafe-call") { return "Signal-unsafe call inside a signal handler"; } else if (description == "errno-in-signal-handler") { return "Overwrite of errno in a signal handler"; } else if (description == "lock-order-inversion") { return "Lock order inversion (potential deadlock)"; } else if (description == "external-race") { return "Race on a library object"; } else if (description == "swift-access-race") { return "Swift access race"; } // for unknown report codes just show the code return description; } static std::string Sprintf(const char *format, ...) { StreamString s; va_list args; va_start(args, format); s.PrintfVarArg(format, args); va_end(args); return s.GetString(); } static std::string GetSymbolNameFromAddress(ProcessSP process_sp, addr_t addr) { lldb_private::Address so_addr; if (!process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) return ""; lldb_private::Symbol *symbol = so_addr.CalculateSymbolContextSymbol(); if (!symbol) return ""; std::string sym_name = symbol->GetName().GetCString(); return sym_name; } static void GetSymbolDeclarationFromAddress(ProcessSP process_sp, addr_t addr, Declaration &decl) { lldb_private::Address so_addr; if (!process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) return; lldb_private::Symbol *symbol = so_addr.CalculateSymbolContextSymbol(); if (!symbol) return; ConstString sym_name = symbol->GetMangled().GetName( lldb::eLanguageTypeUnknown, Mangled::ePreferMangled); ModuleSP module = symbol->CalculateSymbolContextModule(); if (!module) return; VariableList var_list; module->FindGlobalVariables(sym_name, nullptr, true, 1U, var_list); if (var_list.GetSize() < 1) return; VariableSP var = var_list.GetVariableAtIndex(0); decl = var->GetDeclaration(); } addr_t ThreadSanitizerRuntime::GetFirstNonInternalFramePc( StructuredData::ObjectSP trace, bool skip_one_frame) { ProcessSP process_sp = GetProcessSP(); ModuleSP runtime_module_sp = GetRuntimeModuleSP(); StructuredData::Array *trace_array = trace->GetAsArray(); for (size_t i = 0; i < trace_array->GetSize(); i++) { if (skip_one_frame && i == 0) continue; addr_t addr; if (!trace_array->GetItemAtIndexAsInteger(i, addr)) continue; lldb_private::Address so_addr; if (!process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress( addr, so_addr)) continue; if (so_addr.GetModule() == runtime_module_sp) continue; return addr; } return 0; } std::string ThreadSanitizerRuntime::GenerateSummary(StructuredData::ObjectSP report) { ProcessSP process_sp = GetProcessSP(); std::string summary = report->GetAsDictionary() ->GetValueForKey("description") ->GetAsString() ->GetValue(); bool skip_one_frame = report->GetObjectForDotSeparatedPath("issue_type")->GetStringValue() == "external-race"; addr_t pc = 0; if (report->GetAsDictionary() ->GetValueForKey("mops") ->GetAsArray() ->GetSize() > 0) pc = GetFirstNonInternalFramePc(report->GetAsDictionary() ->GetValueForKey("mops") ->GetAsArray() ->GetItemAtIndex(0) ->GetAsDictionary() ->GetValueForKey("trace"), skip_one_frame); if (report->GetAsDictionary() ->GetValueForKey("stacks") ->GetAsArray() ->GetSize() > 0) pc = GetFirstNonInternalFramePc(report->GetAsDictionary() ->GetValueForKey("stacks") ->GetAsArray() ->GetItemAtIndex(0) ->GetAsDictionary() ->GetValueForKey("trace"), skip_one_frame); if (pc != 0) { summary = summary + " in " + GetSymbolNameFromAddress(process_sp, pc); } if (report->GetAsDictionary() ->GetValueForKey("locs") ->GetAsArray() ->GetSize() > 0) { StructuredData::ObjectSP loc = report->GetAsDictionary() ->GetValueForKey("locs") ->GetAsArray() ->GetItemAtIndex(0); std::string object_type = loc->GetAsDictionary() ->GetValueForKey("object_type") ->GetAsString() ->GetValue(); if (!object_type.empty()) { summary = "Race on " + object_type + " object"; } addr_t addr = loc->GetAsDictionary() ->GetValueForKey("address") ->GetAsInteger() ->GetValue(); if (addr == 0) addr = loc->GetAsDictionary() ->GetValueForKey("start") ->GetAsInteger() ->GetValue(); if (addr != 0) { std::string global_name = GetSymbolNameFromAddress(process_sp, addr); if (!global_name.empty()) { summary = summary + " at " + global_name; } else { summary = summary + " at " + Sprintf("0x%llx", addr); } } else { int fd = loc->GetAsDictionary() ->GetValueForKey("file_descriptor") ->GetAsInteger() ->GetValue(); if (fd != 0) { summary = summary + " on file descriptor " + Sprintf("%d", fd); } } } return summary; } addr_t ThreadSanitizerRuntime::GetMainRacyAddress(StructuredData::ObjectSP report) { addr_t result = (addr_t)-1; report->GetObjectForDotSeparatedPath("mops")->GetAsArray()->ForEach( [&result](StructuredData::Object *o) -> bool { addr_t addr = o->GetObjectForDotSeparatedPath("address")->GetIntegerValue(); if (addr < result) result = addr; return true; }); return (result == (addr_t)-1) ? 0 : result; } std::string ThreadSanitizerRuntime::GetLocationDescription( StructuredData::ObjectSP report, addr_t &global_addr, std::string &global_name, std::string &filename, uint32_t &line) { std::string result = ""; ProcessSP process_sp = GetProcessSP(); if (report->GetAsDictionary() ->GetValueForKey("locs") ->GetAsArray() ->GetSize() > 0) { StructuredData::ObjectSP loc = report->GetAsDictionary() ->GetValueForKey("locs") ->GetAsArray() ->GetItemAtIndex(0); std::string type = loc->GetAsDictionary()->GetValueForKey("type")->GetStringValue(); if (type == "global") { global_addr = loc->GetAsDictionary() ->GetValueForKey("address") ->GetAsInteger() ->GetValue(); global_name = GetSymbolNameFromAddress(process_sp, global_addr); if (!global_name.empty()) { result = Sprintf("'%s' is a global variable (0x%llx)", global_name.c_str(), global_addr); } else { result = Sprintf("0x%llx is a global variable", global_addr); } Declaration decl; GetSymbolDeclarationFromAddress(process_sp, global_addr, decl); if (decl.GetFile()) { filename = decl.GetFile().GetPath(); line = decl.GetLine(); } } else if (type == "heap") { addr_t addr = loc->GetAsDictionary() ->GetValueForKey("start") ->GetAsInteger() ->GetValue(); long size = loc->GetAsDictionary() ->GetValueForKey("size") ->GetAsInteger() ->GetValue(); std::string object_type = loc->GetAsDictionary() ->GetValueForKey("object_type") ->GetAsString() ->GetValue(); if (!object_type.empty()) { result = Sprintf("Location is a %ld-byte %s object at 0x%llx", size, object_type.c_str(), addr); } else { result = Sprintf("Location is a %ld-byte heap object at 0x%llx", size, addr); } } else if (type == "stack") { int tid = loc->GetAsDictionary() ->GetValueForKey("thread_id") ->GetAsInteger() ->GetValue(); result = Sprintf("Location is stack of thread %d", tid); } else if (type == "tls") { int tid = loc->GetAsDictionary() ->GetValueForKey("thread_id") ->GetAsInteger() ->GetValue(); result = Sprintf("Location is TLS of thread %d", tid); } else if (type == "fd") { int fd = loc->GetAsDictionary() ->GetValueForKey("file_descriptor") ->GetAsInteger() ->GetValue(); result = Sprintf("Location is file descriptor %d", fd); } } return result; } bool ThreadSanitizerRuntime::NotifyBreakpointHit( void *baton, StoppointCallbackContext *context, user_id_t break_id, user_id_t break_loc_id) { assert(baton && "null baton"); if (!baton) return false; ThreadSanitizerRuntime *const instance = static_cast(baton); + ProcessSP process_sp = instance->GetProcessSP(); + + if (process_sp->GetModIDRef().IsLastResumeForUserExpression()) + return false; + StructuredData::ObjectSP report = instance->RetrieveReportData(context->exe_ctx_ref); std::string stop_reason_description; if (report) { std::string issue_description = instance->FormatDescription(report); report->GetAsDictionary()->AddStringItem("description", issue_description); stop_reason_description = issue_description + " detected"; report->GetAsDictionary()->AddStringItem("stop_description", stop_reason_description); std::string summary = instance->GenerateSummary(report); report->GetAsDictionary()->AddStringItem("summary", summary); addr_t main_address = instance->GetMainRacyAddress(report); report->GetAsDictionary()->AddIntegerItem("memory_address", main_address); addr_t global_addr = 0; std::string global_name = ""; std::string location_filename = ""; uint32_t location_line = 0; std::string location_description = instance->GetLocationDescription( report, global_addr, global_name, location_filename, location_line); report->GetAsDictionary()->AddStringItem("location_description", location_description); if (global_addr != 0) { report->GetAsDictionary()->AddIntegerItem("global_address", global_addr); } if (!global_name.empty()) { report->GetAsDictionary()->AddStringItem("global_name", global_name); } if (location_filename != "") { report->GetAsDictionary()->AddStringItem("location_filename", location_filename); report->GetAsDictionary()->AddIntegerItem("location_line", location_line); } bool all_addresses_are_same = true; report->GetObjectForDotSeparatedPath("mops")->GetAsArray()->ForEach( [&all_addresses_are_same, main_address](StructuredData::Object *o) -> bool { addr_t addr = o->GetObjectForDotSeparatedPath("address")->GetIntegerValue(); if (main_address != addr) all_addresses_are_same = false; return true; }); report->GetAsDictionary()->AddBooleanItem("all_addresses_are_same", all_addresses_are_same); } - ProcessSP process_sp = instance->GetProcessSP(); // Make sure this is the right process if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP()) { ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP(); if (thread_sp) thread_sp->SetStopInfo( InstrumentationRuntimeStopInfo:: CreateStopReasonWithInstrumentationData( *thread_sp, stop_reason_description, report)); StreamFileSP stream_sp( process_sp->GetTarget().GetDebugger().GetOutputFile()); if (stream_sp) { stream_sp->Printf("ThreadSanitizer report breakpoint hit. Use 'thread " "info -s' to get extended information about the " "report.\n"); } return true; // Return true to stop the target } else return false; // Let target run } const RegularExpression &ThreadSanitizerRuntime::GetPatternForRuntimeLibrary() { static RegularExpression regex(llvm::StringRef("libclang_rt.tsan_")); return regex; } bool ThreadSanitizerRuntime::CheckIfRuntimeIsValid( const lldb::ModuleSP module_sp) { static ConstString g_tsan_get_current_report("__tsan_get_current_report"); const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType( g_tsan_get_current_report, lldb::eSymbolTypeAny); return symbol != nullptr; } void ThreadSanitizerRuntime::Activate() { if (IsActive()) return; ProcessSP process_sp = GetProcessSP(); if (!process_sp) return; ConstString symbol_name("__tsan_on_report"); const Symbol *symbol = GetRuntimeModuleSP()->FindFirstSymbolWithNameAndType( symbol_name, eSymbolTypeCode); if (symbol == NULL) return; if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid()) return; Target &target = process_sp->GetTarget(); addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target); if (symbol_address == LLDB_INVALID_ADDRESS) return; bool internal = true; bool hardware = false; Breakpoint *breakpoint = process_sp->GetTarget() .CreateBreakpoint(symbol_address, internal, hardware) .get(); breakpoint->SetCallback(ThreadSanitizerRuntime::NotifyBreakpointHit, this, true); breakpoint->SetBreakpointKind("thread-sanitizer-report"); SetBreakpointID(breakpoint->GetID()); SetActive(true); } void ThreadSanitizerRuntime::Deactivate() { if (GetBreakpointID() != LLDB_INVALID_BREAK_ID) { ProcessSP process_sp = GetProcessSP(); if (process_sp) { process_sp->GetTarget().RemoveBreakpointByID(GetBreakpointID()); SetBreakpointID(LLDB_INVALID_BREAK_ID); } } SetActive(false); } static std::string GenerateThreadName(const std::string &path, StructuredData::Object *o, StructuredData::ObjectSP main_info) { std::string result = "additional information"; if (path == "mops") { int size = o->GetObjectForDotSeparatedPath("size")->GetIntegerValue(); int thread_id = o->GetObjectForDotSeparatedPath("thread_id")->GetIntegerValue(); bool is_write = o->GetObjectForDotSeparatedPath("is_write")->GetBooleanValue(); bool is_atomic = o->GetObjectForDotSeparatedPath("is_atomic")->GetBooleanValue(); addr_t addr = o->GetObjectForDotSeparatedPath("address")->GetIntegerValue(); std::string addr_string = Sprintf(" at 0x%llx", addr); if (main_info->GetObjectForDotSeparatedPath("all_addresses_are_same") ->GetBooleanValue()) { addr_string = ""; } if (main_info->GetObjectForDotSeparatedPath("issue_type") ->GetStringValue() == "external-race") { result = Sprintf("%s access by thread %d", is_write ? "mutating" : "read-only", thread_id); } else if (main_info->GetObjectForDotSeparatedPath("issue_type") ->GetStringValue() == "swift-access-race") { result = Sprintf("modifying access by thread %d", thread_id); } else { result = Sprintf("%s%s of size %d%s by thread %d", is_atomic ? "atomic " : "", is_write ? "write" : "read", size, addr_string.c_str(), thread_id); } } if (path == "threads") { int thread_id = o->GetObjectForDotSeparatedPath("thread_id")->GetIntegerValue(); result = Sprintf("Thread %d created", thread_id); } if (path == "locs") { std::string type = o->GetAsDictionary()->GetValueForKey("type")->GetStringValue(); int thread_id = o->GetObjectForDotSeparatedPath("thread_id")->GetIntegerValue(); int fd = o->GetObjectForDotSeparatedPath("file_descriptor")->GetIntegerValue(); if (type == "heap") { result = Sprintf("Heap block allocated by thread %d", thread_id); } else if (type == "fd") { result = Sprintf("File descriptor %d created by thread %t", fd, thread_id); } } if (path == "mutexes") { int mutex_id = o->GetObjectForDotSeparatedPath("mutex_id")->GetIntegerValue(); result = Sprintf("Mutex M%d created", mutex_id); } if (path == "stacks") { int thread_id = o->GetObjectForDotSeparatedPath("thread_id")->GetIntegerValue(); result = Sprintf("Thread %d", thread_id); } result[0] = toupper(result[0]); return result; } static void AddThreadsForPath(const std::string &path, ThreadCollectionSP threads, ProcessSP process_sp, StructuredData::ObjectSP info) { info->GetObjectForDotSeparatedPath(path)->GetAsArray()->ForEach( [process_sp, threads, path, info](StructuredData::Object *o) -> bool { std::vector pcs; o->GetObjectForDotSeparatedPath("trace")->GetAsArray()->ForEach( [&pcs](StructuredData::Object *pc) -> bool { pcs.push_back(pc->GetAsInteger()->GetValue()); return true; }); if (pcs.size() == 0) return true; StructuredData::ObjectSP thread_id_obj = o->GetObjectForDotSeparatedPath("thread_os_id"); tid_t tid = thread_id_obj ? thread_id_obj->GetIntegerValue() : 0; uint32_t stop_id = 0; bool stop_id_is_valid = false; HistoryThread *history_thread = new HistoryThread(*process_sp, tid, pcs, stop_id, stop_id_is_valid); ThreadSP new_thread_sp(history_thread); new_thread_sp->SetName(GenerateThreadName(path, o, info).c_str()); // Save this in the Process' ExtendedThreadList so a strong pointer // retains the object process_sp->GetExtendedThreadList().AddThread(new_thread_sp); threads->AddThread(new_thread_sp); return true; }); } lldb::ThreadCollectionSP ThreadSanitizerRuntime::GetBacktracesFromExtendedStopInfo( StructuredData::ObjectSP info) { ThreadCollectionSP threads; threads.reset(new ThreadCollection()); if (info->GetObjectForDotSeparatedPath("instrumentation_class") ->GetStringValue() != "ThreadSanitizer") return threads; ProcessSP process_sp = GetProcessSP(); AddThreadsForPath("stacks", threads, process_sp, info); AddThreadsForPath("mops", threads, process_sp, info); AddThreadsForPath("locs", threads, process_sp, info); AddThreadsForPath("mutexes", threads, process_sp, info); AddThreadsForPath("threads", threads, process_sp, info); return threads; } Index: vendor/lldb/dist/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp (revision 320967) @@ -1,340 +1,343 @@ //===-- UBSanRuntime.cpp ----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "UBSanRuntime.h" #include "Plugins/Process/Utility/HistoryThread.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObject.h" #include "lldb/Expression/UserExpression.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Variable.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/InstrumentationRuntimeStopInfo.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" #include using namespace lldb; using namespace lldb_private; UndefinedBehaviorSanitizerRuntime::~UndefinedBehaviorSanitizerRuntime() { Deactivate(); } lldb::InstrumentationRuntimeSP UndefinedBehaviorSanitizerRuntime::CreateInstance( const lldb::ProcessSP &process_sp) { return InstrumentationRuntimeSP( new UndefinedBehaviorSanitizerRuntime(process_sp)); } void UndefinedBehaviorSanitizerRuntime::Initialize() { PluginManager::RegisterPlugin( GetPluginNameStatic(), "UndefinedBehaviorSanitizer instrumentation runtime plugin.", CreateInstance, GetTypeStatic); } void UndefinedBehaviorSanitizerRuntime::Terminate() { PluginManager::UnregisterPlugin(CreateInstance); } lldb_private::ConstString UndefinedBehaviorSanitizerRuntime::GetPluginNameStatic() { return ConstString("UndefinedBehaviorSanitizer"); } lldb::InstrumentationRuntimeType UndefinedBehaviorSanitizerRuntime::GetTypeStatic() { return eInstrumentationRuntimeTypeUndefinedBehaviorSanitizer; } static const char *ub_sanitizer_retrieve_report_data_prefix = R"( extern "C" { void __ubsan_get_current_report_data(const char **OutIssueKind, const char **OutMessage, const char **OutFilename, unsigned *OutLine, unsigned *OutCol, char **OutMemoryAddr); } struct data { const char *issue_kind; const char *message; const char *filename; unsigned line; unsigned col; char *memory_addr; }; )"; static const char *ub_sanitizer_retrieve_report_data_command = R"( data t; __ubsan_get_current_report_data(&t.issue_kind, &t.message, &t.filename, &t.line, &t.col, &t.memory_addr); t; )"; static addr_t RetrieveUnsigned(ValueObjectSP return_value_sp, ProcessSP process_sp, const std::string &expression_path) { return return_value_sp->GetValueForExpressionPath(expression_path.c_str()) ->GetValueAsUnsigned(0); } static std::string RetrieveString(ValueObjectSP return_value_sp, ProcessSP process_sp, const std::string &expression_path) { addr_t ptr = RetrieveUnsigned(return_value_sp, process_sp, expression_path); std::string str; Status error; process_sp->ReadCStringFromMemory(ptr, str, error); return str; } StructuredData::ObjectSP UndefinedBehaviorSanitizerRuntime::RetrieveReportData( ExecutionContextRef exe_ctx_ref) { ProcessSP process_sp = GetProcessSP(); if (!process_sp) return StructuredData::ObjectSP(); ThreadSP thread_sp = exe_ctx_ref.GetThreadSP(); StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); ModuleSP runtime_module_sp = GetRuntimeModuleSP(); Target &target = process_sp->GetTarget(); if (!frame_sp) return StructuredData::ObjectSP(); StreamFileSP Stream(target.GetDebugger().GetOutputFile()); EvaluateExpressionOptions options; options.SetUnwindOnError(true); options.SetTryAllThreads(true); options.SetStopOthers(true); options.SetIgnoreBreakpoints(true); options.SetTimeout(std::chrono::seconds(2)); options.SetPrefix(ub_sanitizer_retrieve_report_data_prefix); options.SetAutoApplyFixIts(false); options.SetLanguage(eLanguageTypeObjC_plus_plus); ValueObjectSP main_value; ExecutionContext exe_ctx; Status eval_error; frame_sp->CalculateExecutionContext(exe_ctx); ExpressionResults result = UserExpression::Evaluate( exe_ctx, options, ub_sanitizer_retrieve_report_data_command, "", main_value, eval_error); if (result != eExpressionCompleted) { target.GetDebugger().GetAsyncOutputStream()->Printf( "Warning: Cannot evaluate UndefinedBehaviorSanitizer expression:\n%s\n", eval_error.AsCString()); return StructuredData::ObjectSP(); } // Gather the PCs of the user frames in the backtrace. StructuredData::Array *trace = new StructuredData::Array(); auto trace_sp = StructuredData::ObjectSP(trace); for (unsigned I = 0; I < thread_sp->GetStackFrameCount(); ++I) { const Address FCA = thread_sp->GetStackFrameAtIndex(I)->GetFrameCodeAddress(); if (FCA.GetModule() == runtime_module_sp) // Skip PCs from the runtime. continue; lldb::addr_t PC = FCA.GetLoadAddress(&target); trace->AddItem(StructuredData::ObjectSP(new StructuredData::Integer(PC))); } std::string IssueKind = RetrieveString(main_value, process_sp, ".issue_kind"); std::string ErrMessage = RetrieveString(main_value, process_sp, ".message"); std::string Filename = RetrieveString(main_value, process_sp, ".filename"); unsigned Line = RetrieveUnsigned(main_value, process_sp, ".line"); unsigned Col = RetrieveUnsigned(main_value, process_sp, ".col"); uintptr_t MemoryAddr = RetrieveUnsigned(main_value, process_sp, ".memory_addr"); auto *d = new StructuredData::Dictionary(); auto dict_sp = StructuredData::ObjectSP(d); d->AddStringItem("instrumentation_class", "UndefinedBehaviorSanitizer"); d->AddStringItem("description", IssueKind); d->AddStringItem("summary", ErrMessage); d->AddStringItem("filename", Filename); d->AddIntegerItem("line", Line); d->AddIntegerItem("col", Col); d->AddIntegerItem("memory_address", MemoryAddr); d->AddIntegerItem("tid", thread_sp->GetID()); d->AddItem("trace", trace_sp); return dict_sp; } static std::string GetStopReasonDescription(StructuredData::ObjectSP report) { llvm::StringRef stop_reason_description_ref; report->GetAsDictionary()->GetValueForKeyAsString("description", stop_reason_description_ref); std::string stop_reason_description = stop_reason_description_ref; if (!stop_reason_description.size()) { stop_reason_description = "Undefined behavior detected"; } else { stop_reason_description[0] = toupper(stop_reason_description[0]); for (unsigned I = 1; I < stop_reason_description.size(); ++I) if (stop_reason_description[I] == '-') stop_reason_description[I] = ' '; } return stop_reason_description; } bool UndefinedBehaviorSanitizerRuntime::NotifyBreakpointHit( void *baton, StoppointCallbackContext *context, user_id_t break_id, user_id_t break_loc_id) { assert(baton && "null baton"); if (!baton) return false; //< false => resume execution. UndefinedBehaviorSanitizerRuntime *const instance = static_cast(baton); ProcessSP process_sp = instance->GetProcessSP(); ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP(); if (!process_sp || !thread_sp || process_sp != context->exe_ctx_ref.GetProcessSP()) return false; + if (process_sp->GetModIDRef().IsLastResumeForUserExpression()) + return false; + StructuredData::ObjectSP report = instance->RetrieveReportData(context->exe_ctx_ref); if (report) { thread_sp->SetStopInfo( InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData( *thread_sp, GetStopReasonDescription(report), report)); return true; } return false; } const RegularExpression & UndefinedBehaviorSanitizerRuntime::GetPatternForRuntimeLibrary() { static RegularExpression regex(llvm::StringRef("libclang_rt\\.(a|t|ub)san_")); return regex; } bool UndefinedBehaviorSanitizerRuntime::CheckIfRuntimeIsValid( const lldb::ModuleSP module_sp) { static ConstString ubsan_test_sym("__ubsan_on_report"); const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType( ubsan_test_sym, lldb::eSymbolTypeAny); return symbol != nullptr; } // FIXME: Factor out all the logic we have in common with the {a,t}san plugins. void UndefinedBehaviorSanitizerRuntime::Activate() { if (IsActive()) return; ProcessSP process_sp = GetProcessSP(); if (!process_sp) return; ModuleSP runtime_module_sp = GetRuntimeModuleSP(); ConstString symbol_name("__ubsan_on_report"); const Symbol *symbol = runtime_module_sp->FindFirstSymbolWithNameAndType( symbol_name, eSymbolTypeCode); if (symbol == nullptr) return; if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid()) return; Target &target = process_sp->GetTarget(); addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target); if (symbol_address == LLDB_INVALID_ADDRESS) return; Breakpoint *breakpoint = process_sp->GetTarget() .CreateBreakpoint(symbol_address, /*internal=*/true, /*hardware=*/false) .get(); breakpoint->SetCallback( UndefinedBehaviorSanitizerRuntime::NotifyBreakpointHit, this, true); breakpoint->SetBreakpointKind("undefined-behavior-sanitizer-report"); SetBreakpointID(breakpoint->GetID()); SetActive(true); } void UndefinedBehaviorSanitizerRuntime::Deactivate() { SetActive(false); auto BID = GetBreakpointID(); if (BID == LLDB_INVALID_BREAK_ID) return; if (ProcessSP process_sp = GetProcessSP()) { process_sp->GetTarget().RemoveBreakpointByID(BID); SetBreakpointID(LLDB_INVALID_BREAK_ID); } } lldb::ThreadCollectionSP UndefinedBehaviorSanitizerRuntime::GetBacktracesFromExtendedStopInfo( StructuredData::ObjectSP info) { ThreadCollectionSP threads; threads.reset(new ThreadCollection()); ProcessSP process_sp = GetProcessSP(); if (info->GetObjectForDotSeparatedPath("instrumentation_class") ->GetStringValue() != "UndefinedBehaviorSanitizer") return threads; std::vector PCs; auto trace = info->GetObjectForDotSeparatedPath("trace")->GetAsArray(); trace->ForEach([&PCs](StructuredData::Object *PC) -> bool { PCs.push_back(PC->GetAsInteger()->GetValue()); return true; }); if (PCs.empty()) return threads; StructuredData::ObjectSP thread_id_obj = info->GetObjectForDotSeparatedPath("tid"); tid_t tid = thread_id_obj ? thread_id_obj->GetIntegerValue() : 0; uint32_t stop_id = 0; bool stop_id_is_valid = false; HistoryThread *history_thread = new HistoryThread(*process_sp, tid, PCs, stop_id, stop_id_is_valid); ThreadSP new_thread_sp(history_thread); std::string stop_reason_description = GetStopReasonDescription(info); new_thread_sp->SetName(stop_reason_description.c_str()); // Save this in the Process' ExtendedThreadList so a strong pointer // retains the object process_sp->GetExtendedThreadList().AddThread(new_thread_sp); threads->AddThread(new_thread_sp); return threads; } Index: vendor/lldb/dist/source/Plugins/Language/ObjC/Cocoa.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/Language/ObjC/Cocoa.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/Language/ObjC/Cocoa.cpp (revision 320967) @@ -1,1030 +1,1036 @@ //===-- Cocoa.cpp -----------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // C Includes // C++ Includes // Other libraries and framework includes // Project includes #include "Cocoa.h" #include "lldb/Core/Mangled.h" #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/DataFormatters/FormattersHelpers.h" #include "lldb/DataFormatters/StringPrinter.h" #include "lldb/DataFormatters/TypeSummary.h" #include "lldb/Host/Time.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Target/Language.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/ProcessStructReader.h" #include "lldb/Target/Target.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/Endian.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/Stream.h" #include "llvm/ADT/APInt.h" #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h" #include "NSString.h" using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; bool lldb_private::formatters::NSBundleSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime( lldb::eLanguageTypeObjC); if (!runtime) return false; ObjCLanguageRuntime::ClassDescriptorSP descriptor( runtime->GetClassDescriptor(valobj)); if (!descriptor || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); if (!valobj_addr) return false; const char *class_name = descriptor->GetClassName().GetCString(); if (!class_name || !*class_name) return false; if (!strcmp(class_name, "NSBundle")) { uint64_t offset = 5 * ptr_size; ValueObjectSP text(valobj.GetSyntheticChildAtOffset( offset, valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID), true)); StreamString summary_stream; bool was_nsstring_ok = NSStringSummaryProvider(*text, summary_stream, options); if (was_nsstring_ok && summary_stream.GetSize() > 0) { stream.Printf("%s", summary_stream.GetData()); return true; } } return false; } bool lldb_private::formatters::NSTimeZoneSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime( lldb::eLanguageTypeObjC); if (!runtime) return false; ObjCLanguageRuntime::ClassDescriptorSP descriptor( runtime->GetClassDescriptor(valobj)); if (!descriptor || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); if (!valobj_addr) return false; const char *class_name = descriptor->GetClassName().GetCString(); if (!class_name || !*class_name) return false; if (!strcmp(class_name, "__NSTimeZone")) { uint64_t offset = ptr_size; ValueObjectSP text(valobj.GetSyntheticChildAtOffset( offset, valobj.GetCompilerType(), true)); StreamString summary_stream; bool was_nsstring_ok = NSStringSummaryProvider(*text, summary_stream, options); if (was_nsstring_ok && summary_stream.GetSize() > 0) { stream.Printf("%s", summary_stream.GetData()); return true; } } return false; } bool lldb_private::formatters::NSNotificationSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime( lldb::eLanguageTypeObjC); if (!runtime) return false; ObjCLanguageRuntime::ClassDescriptorSP descriptor( runtime->GetClassDescriptor(valobj)); if (!descriptor || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); if (!valobj_addr) return false; const char *class_name = descriptor->GetClassName().GetCString(); if (!class_name || !*class_name) return false; if (!strcmp(class_name, "NSConcreteNotification")) { uint64_t offset = ptr_size; ValueObjectSP text(valobj.GetSyntheticChildAtOffset( offset, valobj.GetCompilerType(), true)); StreamString summary_stream; bool was_nsstring_ok = NSStringSummaryProvider(*text, summary_stream, options); if (was_nsstring_ok && summary_stream.GetSize() > 0) { stream.Printf("%s", summary_stream.GetData()); return true; } } return false; } bool lldb_private::formatters::NSMachPortSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime( lldb::eLanguageTypeObjC); if (!runtime) return false; ObjCLanguageRuntime::ClassDescriptorSP descriptor( runtime->GetClassDescriptor(valobj)); if (!descriptor || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); if (!valobj_addr) return false; const char *class_name = descriptor->GetClassName().GetCString(); if (!class_name || !*class_name) return false; uint64_t port_number = 0; if (!strcmp(class_name, "NSMachPort")) { uint64_t offset = (ptr_size == 4 ? 12 : 20); Status error; port_number = process_sp->ReadUnsignedIntegerFromMemory( offset + valobj_addr, 4, 0, error); if (error.Success()) { stream.Printf("mach port: %u", (uint32_t)(port_number & 0x00000000FFFFFFFF)); return true; } } return false; } bool lldb_private::formatters::NSIndexSetSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime( lldb::eLanguageTypeObjC); if (!runtime) return false; ObjCLanguageRuntime::ClassDescriptorSP descriptor( runtime->GetClassDescriptor(valobj)); if (!descriptor || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); if (!valobj_addr) return false; const char *class_name = descriptor->GetClassName().GetCString(); if (!class_name || !*class_name) return false; uint64_t count = 0; do { if (!strcmp(class_name, "NSIndexSet") || !strcmp(class_name, "NSMutableIndexSet")) { Status error; uint32_t mode = process_sp->ReadUnsignedIntegerFromMemory( valobj_addr + ptr_size, 4, 0, error); if (error.Fail()) return false; // this means the set is empty - count = 0 if ((mode & 1) == 1) { count = 0; break; } if ((mode & 2) == 2) mode = 1; // this means the set only has one range else mode = 2; // this means the set has multiple ranges if (mode == 1) { count = process_sp->ReadUnsignedIntegerFromMemory( valobj_addr + 3 * ptr_size, ptr_size, 0, error); if (error.Fail()) return false; } else { // read a pointer to the data at 2*ptr_size count = process_sp->ReadUnsignedIntegerFromMemory( valobj_addr + 2 * ptr_size, ptr_size, 0, error); if (error.Fail()) return false; // read the data at 2*ptr_size from the first location count = process_sp->ReadUnsignedIntegerFromMemory(count + 2 * ptr_size, ptr_size, 0, error); if (error.Fail()) return false; } } else return false; } while (false); stream.Printf("%" PRIu64 " index%s", count, (count == 1 ? "" : "es")); return true; } static void NSNumber_FormatChar(ValueObject &valobj, Stream &stream, char value, lldb::LanguageType lang) { static ConstString g_TypeHint("NSNumber:char"); std::string prefix, suffix; if (Language *language = Language::FindPlugin(lang)) { if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) { prefix.clear(); suffix.clear(); } } stream.Printf("%s%hhd%s", prefix.c_str(), value, suffix.c_str()); } static void NSNumber_FormatShort(ValueObject &valobj, Stream &stream, short value, lldb::LanguageType lang) { static ConstString g_TypeHint("NSNumber:short"); std::string prefix, suffix; if (Language *language = Language::FindPlugin(lang)) { if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) { prefix.clear(); suffix.clear(); } } stream.Printf("%s%hd%s", prefix.c_str(), value, suffix.c_str()); } static void NSNumber_FormatInt(ValueObject &valobj, Stream &stream, int value, lldb::LanguageType lang) { static ConstString g_TypeHint("NSNumber:int"); std::string prefix, suffix; if (Language *language = Language::FindPlugin(lang)) { if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) { prefix.clear(); suffix.clear(); } } stream.Printf("%s%d%s", prefix.c_str(), value, suffix.c_str()); } static void NSNumber_FormatLong(ValueObject &valobj, Stream &stream, uint64_t value, lldb::LanguageType lang) { static ConstString g_TypeHint("NSNumber:long"); std::string prefix, suffix; if (Language *language = Language::FindPlugin(lang)) { if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) { prefix.clear(); suffix.clear(); } } stream.Printf("%s%" PRId64 "%s", prefix.c_str(), value, suffix.c_str()); } static void NSNumber_FormatInt128(ValueObject &valobj, Stream &stream, const llvm::APInt &value, lldb::LanguageType lang) { static ConstString g_TypeHint("NSNumber:int128_t"); std::string prefix, suffix; if (Language *language = Language::FindPlugin(lang)) { if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) { prefix.clear(); suffix.clear(); } } stream.PutCString(prefix.c_str()); const int radix = 10; const bool isSigned = true; std::string str = value.toString(radix, isSigned); stream.PutCString(str.c_str()); stream.PutCString(suffix.c_str()); } static void NSNumber_FormatFloat(ValueObject &valobj, Stream &stream, float value, lldb::LanguageType lang) { static ConstString g_TypeHint("NSNumber:float"); std::string prefix, suffix; if (Language *language = Language::FindPlugin(lang)) { if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) { prefix.clear(); suffix.clear(); } } stream.Printf("%s%f%s", prefix.c_str(), value, suffix.c_str()); } static void NSNumber_FormatDouble(ValueObject &valobj, Stream &stream, double value, lldb::LanguageType lang) { static ConstString g_TypeHint("NSNumber:double"); std::string prefix, suffix; if (Language *language = Language::FindPlugin(lang)) { if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) { prefix.clear(); suffix.clear(); } } stream.Printf("%s%g%s", prefix.c_str(), value, suffix.c_str()); } bool lldb_private::formatters::NSNumberSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime( lldb::eLanguageTypeObjC); if (!runtime) return false; ObjCLanguageRuntime::ClassDescriptorSP descriptor( runtime->GetClassDescriptor(valobj)); if (!descriptor || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); if (!valobj_addr) return false; const char *class_name = descriptor->GetClassName().GetCString(); if (!class_name || !*class_name) return false; if (!strcmp(class_name, "__NSCFBoolean")) return ObjCBooleanSummaryProvider(valobj, stream, options); if (!strcmp(class_name, "NSNumber") || !strcmp(class_name, "__NSCFNumber")) { uint64_t value = 0; uint64_t i_bits = 0; if (descriptor->GetTaggedPointerInfo(&i_bits, &value)) { switch (i_bits) { case 0: NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage()); break; case 1: case 4: NSNumber_FormatShort(valobj, stream, (short)value, options.GetLanguage()); break; case 2: case 8: NSNumber_FormatInt(valobj, stream, (int)value, options.GetLanguage()); break; case 3: case 12: NSNumber_FormatLong(valobj, stream, value, options.GetLanguage()); break; default: return false; } return true; } else { Status error; AppleObjCRuntime *runtime = llvm::dyn_cast_or_null( process_sp->GetObjCLanguageRuntime()); const bool new_format = (runtime && runtime->GetFoundationVersion() >= 1400); enum class TypeCodes : int { sint8 = 0x0, sint16 = 0x1, sint32 = 0x2, sint64 = 0x3, f32 = 0x4, f64 = 0x5, sint128 = 0x6 }; uint64_t data_location = valobj_addr + 2 * ptr_size; TypeCodes type_code; if (new_format) { uint64_t cfinfoa = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); if (error.Fail()) return false; bool is_preserved_number = cfinfoa & 0x8; if (is_preserved_number) { lldbassert(!static_cast("We should handle preserved numbers!")); return false; } type_code = static_cast(cfinfoa & 0x7); } else { uint8_t data_type = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 1, 0, error) & 0x1F; if (error.Fail()) return false; switch (data_type) { case 1: type_code = TypeCodes::sint8; break; case 2: type_code = TypeCodes::sint16; break; case 3: type_code = TypeCodes::sint32; break; case 17: data_location += 8; LLVM_FALLTHROUGH; case 4: type_code = TypeCodes::sint64; break; case 5: type_code = TypeCodes::f32; break; case 6: type_code = TypeCodes::f64; break; default: return false; } } uint64_t value = 0; + bool success = false; switch (type_code) { case TypeCodes::sint8: value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0, error); if (error.Fail()) return false; NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage()); + success = true; break; case TypeCodes::sint16: value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0, error); if (error.Fail()) return false; NSNumber_FormatShort(valobj, stream, (short)value, options.GetLanguage()); + success = true; break; case TypeCodes::sint32: value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0, error); if (error.Fail()) return false; NSNumber_FormatInt(valobj, stream, (int)value, options.GetLanguage()); + success = true; break; case TypeCodes::sint64: value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, error); if (error.Fail()) return false; NSNumber_FormatLong(valobj, stream, value, options.GetLanguage()); + success = true; break; case TypeCodes::f32: { uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory( data_location, 4, 0, error); if (error.Fail()) return false; float flt_value = 0.0f; memcpy(&flt_value, &flt_as_int, sizeof(flt_as_int)); NSNumber_FormatFloat(valobj, stream, flt_value, options.GetLanguage()); + success = true; break; } case TypeCodes::f64: { uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory( data_location, 8, 0, error); if (error.Fail()) return false; double dbl_value = 0.0; memcpy(&dbl_value, &dbl_as_lng, sizeof(dbl_as_lng)); NSNumber_FormatDouble(valobj, stream, dbl_value, options.GetLanguage()); + success = true; break; } case TypeCodes::sint128: // internally, this is the same { uint64_t words[2]; words[1] = process_sp->ReadUnsignedIntegerFromMemory( data_location, 8, 0, error); if (error.Fail()) return false; words[0] = process_sp->ReadUnsignedIntegerFromMemory( data_location + 8, 8, 0, error); if (error.Fail()) return false; llvm::APInt i128_value(128, words); NSNumber_FormatInt128(valobj, stream, i128_value, options.GetLanguage()); + success = true; break; } - default: - return false; } - return true; + return success; } } return false; } bool lldb_private::formatters::NSURLSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime( lldb::eLanguageTypeObjC); if (!runtime) return false; ObjCLanguageRuntime::ClassDescriptorSP descriptor( runtime->GetClassDescriptor(valobj)); if (!descriptor || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); if (!valobj_addr) return false; llvm::StringRef class_name = descriptor->GetClassName().GetStringRef(); if (!class_name.equals("NSURL")) return false; uint64_t offset_text = ptr_size + ptr_size + 8; // ISA + pointer + 8 bytes of data (even on 32bit) uint64_t offset_base = offset_text + ptr_size; CompilerType type(valobj.GetCompilerType()); ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset_text, type, true)); ValueObjectSP base(valobj.GetSyntheticChildAtOffset(offset_base, type, true)); if (!text) return false; if (text->GetValueAsUnsigned(0) == 0) return false; StreamString summary; if (!NSStringSummaryProvider(*text, summary, options)) return false; if (base && base->GetValueAsUnsigned(0)) { std::string summary_str = summary.GetString(); if (!summary_str.empty()) summary_str.pop_back(); summary_str += " -- "; StreamString base_summary; if (NSURLSummaryProvider(*base, base_summary, options) && !base_summary.Empty()) { llvm::StringRef base_str = base_summary.GetString(); if (base_str.size() > 2) base_str = base_str.drop_front(2); summary_str += base_str; } summary.Clear(); summary.PutCString(summary_str); } if (!summary.Empty()) { stream.PutCString(summary.GetString()); return true; } return false; } bool lldb_private::formatters::NSDateSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime( lldb::eLanguageTypeObjC); if (!runtime) return false; ObjCLanguageRuntime::ClassDescriptorSP descriptor( runtime->GetClassDescriptor(valobj)); if (!descriptor || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); if (!valobj_addr) return false; uint64_t date_value_bits = 0; double date_value = 0.0; ConstString class_name = descriptor->GetClassName(); static const ConstString g_NSDate("NSDate"); static const ConstString g___NSDate("__NSDate"); static const ConstString g___NSTaggedDate("__NSTaggedDate"); static const ConstString g_NSCalendarDate("NSCalendarDate"); if (class_name.IsEmpty()) return false; if ((class_name == g_NSDate) || (class_name == g___NSDate) || (class_name == g___NSTaggedDate)) { uint64_t info_bits = 0, value_bits = 0; if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits)) { date_value_bits = ((value_bits << 8) | (info_bits << 4)); memcpy(&date_value, &date_value_bits, sizeof(date_value_bits)); } else { llvm::Triple triple( process_sp->GetTarget().GetArchitecture().GetTriple()); uint32_t delta = (triple.isWatchOS() && triple.isWatchABI()) ? 8 : ptr_size; Status error; date_value_bits = process_sp->ReadUnsignedIntegerFromMemory( valobj_addr + delta, 8, 0, error); memcpy(&date_value, &date_value_bits, sizeof(date_value_bits)); if (error.Fail()) return false; } } else if (class_name == g_NSCalendarDate) { Status error; date_value_bits = process_sp->ReadUnsignedIntegerFromMemory( valobj_addr + 2 * ptr_size, 8, 0, error); memcpy(&date_value, &date_value_bits, sizeof(date_value_bits)); if (error.Fail()) return false; } else return false; if (date_value == -63114076800) { stream.Printf("0001-12-30 00:00:00 +0000"); return true; } // this snippet of code assumes that time_t == seconds since Jan-1-1970 // this is generally true and POSIXly happy, but might break if a library // vendor decides to get creative time_t epoch = GetOSXEpoch(); epoch = epoch + (time_t)date_value; tm *tm_date = gmtime(&epoch); if (!tm_date) return false; std::string buffer(1024, 0); if (strftime(&buffer[0], 1023, "%Z", tm_date) == 0) return false; stream.Printf("%04d-%02d-%02d %02d:%02d:%02d %s", tm_date->tm_year + 1900, tm_date->tm_mon + 1, tm_date->tm_mday, tm_date->tm_hour, tm_date->tm_min, tm_date->tm_sec, buffer.c_str()); return true; } bool lldb_private::formatters::ObjCClassSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime( lldb::eLanguageTypeObjC); if (!runtime) return false; ObjCLanguageRuntime::ClassDescriptorSP descriptor( runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0))); if (!descriptor || !descriptor->IsValid()) return false; ConstString class_name = descriptor->GetClassName(); if (class_name.IsEmpty()) return false; if (ConstString cs = Mangled(class_name).GetDemangledName(lldb::eLanguageTypeUnknown)) class_name = cs; stream.Printf("%s", class_name.AsCString("")); return true; } class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd { public: ObjCClassSyntheticChildrenFrontEnd(lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp) {} ~ObjCClassSyntheticChildrenFrontEnd() override = default; size_t CalculateNumChildren() override { return 0; } lldb::ValueObjectSP GetChildAtIndex(size_t idx) override { return lldb::ValueObjectSP(); } bool Update() override { return false; } bool MightHaveChildren() override { return false; } size_t GetIndexOfChildWithName(const ConstString &name) override { return UINT32_MAX; } }; SyntheticChildrenFrontEnd * lldb_private::formatters::ObjCClassSyntheticFrontEndCreator( CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp); } template bool lldb_private::formatters::NSDataSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime( lldb::eLanguageTypeObjC); if (!runtime) return false; ObjCLanguageRuntime::ClassDescriptorSP descriptor( runtime->GetClassDescriptor(valobj)); if (!descriptor || !descriptor->IsValid()) return false; bool is_64bit = (process_sp->GetAddressByteSize() == 8); lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); if (!valobj_addr) return false; uint64_t value = 0; const char *class_name = descriptor->GetClassName().GetCString(); if (!class_name || !*class_name) return false; if (!strcmp(class_name, "NSConcreteData") || !strcmp(class_name, "NSConcreteMutableData") || !strcmp(class_name, "__NSCFData")) { uint32_t offset = (is_64bit ? 16 : 8); Status error; value = process_sp->ReadUnsignedIntegerFromMemory( valobj_addr + offset, is_64bit ? 8 : 4, 0, error); if (error.Fail()) return false; } else if (!strcmp(class_name, "_NSInlineData")) { uint32_t offset = (is_64bit ? 8 : 4); Status error; value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, 2, 0, error); if (error.Fail()) return false; } else if (!strcmp(class_name, "_NSZeroData")) { value = 0; } else return false; stream.Printf("%s%" PRIu64 " byte%s%s", (needs_at ? "@\"" : ""), value, (value != 1 ? "s" : ""), (needs_at ? "\"" : "")); return true; } bool lldb_private::formatters::ObjCBOOLSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { const uint32_t type_info = valobj.GetCompilerType().GetTypeInfo(); ValueObjectSP real_guy_sp = valobj.GetSP(); if (type_info & eTypeIsPointer) { Status err; real_guy_sp = valobj.Dereference(err); if (err.Fail() || !real_guy_sp) return false; } else if (type_info & eTypeIsReference) { real_guy_sp = valobj.GetChildAtIndex(0, true); if (!real_guy_sp) return false; } uint8_t value = (real_guy_sp->GetValueAsUnsigned(0) & 0xFF); switch (value) { case 0: stream.Printf("NO"); break; case 1: stream.Printf("YES"); break; default: stream.Printf("%u", value); break; } return true; } bool lldb_private::formatters::ObjCBooleanSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { lldb::addr_t valobj_ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); if (valobj_ptr_value == LLDB_INVALID_ADDRESS) return false; ProcessSP process_sp(valobj.GetProcessSP()); if (!process_sp) return false; if (AppleObjCRuntime *objc_runtime = (AppleObjCRuntime *)process_sp->GetObjCLanguageRuntime()) { lldb::addr_t cf_true = LLDB_INVALID_ADDRESS, cf_false = LLDB_INVALID_ADDRESS; objc_runtime->GetValuesForGlobalCFBooleans(cf_true, cf_false); if (valobj_ptr_value == cf_true) { stream.PutCString("YES"); return true; } if (valobj_ptr_value == cf_false) { stream.PutCString("NO"); return true; } } return false; } template bool lldb_private::formatters::ObjCSELSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) { lldb::ValueObjectSP valobj_sp; CompilerType charstar(valobj.GetCompilerType() .GetBasicTypeFromAST(eBasicTypeChar) .GetPointerType()); if (!charstar) return false; ExecutionContext exe_ctx(valobj.GetExecutionContextRef()); if (is_sel_ptr) { lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); if (data_address == LLDB_INVALID_ADDRESS) return false; valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar); } else { DataExtractor data; Status error; valobj.GetData(data, error); if (error.Fail()) return false; valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar); } if (!valobj_sp) return false; stream.Printf("%s", valobj_sp->GetSummaryAsCString()); return true; } // POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001 // this call gives the POSIX equivalent of the Cocoa epoch time_t lldb_private::formatters::GetOSXEpoch() { static time_t epoch = 0; if (!epoch) { #ifndef _WIN32 tzset(); tm tm_epoch; tm_epoch.tm_sec = 0; tm_epoch.tm_hour = 0; tm_epoch.tm_min = 0; tm_epoch.tm_mon = 0; tm_epoch.tm_mday = 1; tm_epoch.tm_year = 2001 - 1900; tm_epoch.tm_isdst = -1; tm_epoch.tm_gmtoff = 0; tm_epoch.tm_zone = nullptr; epoch = timegm(&tm_epoch); #endif } return epoch; } template bool lldb_private::formatters::NSDataSummaryProvider( ValueObject &, Stream &, const TypeSummaryOptions &); template bool lldb_private::formatters::NSDataSummaryProvider( ValueObject &, Stream &, const TypeSummaryOptions &); template bool lldb_private::formatters::ObjCSELSummaryProvider( ValueObject &, Stream &, const TypeSummaryOptions &); template bool lldb_private::formatters::ObjCSELSummaryProvider( ValueObject &, Stream &, const TypeSummaryOptions &); Index: vendor/lldb/dist/source/Plugins/Platform/Android/PlatformAndroid.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/Platform/Android/PlatformAndroid.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/Platform/Android/PlatformAndroid.cpp (revision 320967) @@ -1,385 +1,389 @@ //===-- PlatformAndroid.cpp -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Scalar.h" #include "lldb/Core/Section.h" #include "lldb/Core/ValueObject.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/StringConvert.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/UriParser.h" // Project includes #include "AdbClient.h" #include "PlatformAndroid.h" #include "PlatformAndroidRemoteGDBServer.h" using namespace lldb; using namespace lldb_private; using namespace lldb_private::platform_android; using namespace std::chrono; static uint32_t g_initialize_count = 0; static const unsigned int g_android_default_cache_size = 2048; // Fits inside 4k adb packet. void PlatformAndroid::Initialize() { PlatformLinux::Initialize(); if (g_initialize_count++ == 0) { #if defined(__ANDROID__) PlatformSP default_platform_sp(new PlatformAndroid(true)); default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); Platform::SetHostPlatform(default_platform_sp); #endif PluginManager::RegisterPlugin( PlatformAndroid::GetPluginNameStatic(false), PlatformAndroid::GetPluginDescriptionStatic(false), PlatformAndroid::CreateInstance); } } void PlatformAndroid::Terminate() { if (g_initialize_count > 0) { if (--g_initialize_count == 0) { PluginManager::UnregisterPlugin(PlatformAndroid::CreateInstance); } } PlatformLinux::Terminate(); } PlatformSP PlatformAndroid::CreateInstance(bool force, const ArchSpec *arch) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); if (log) { const char *arch_name; if (arch && arch->GetArchitectureName()) arch_name = arch->GetArchitectureName(); else arch_name = ""; const char *triple_cstr = arch ? arch->GetTriple().getTriple().c_str() : ""; log->Printf("PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr); } bool create = force; if (create == false && arch && arch->IsValid()) { const llvm::Triple &triple = arch->GetTriple(); switch (triple.getVendor()) { case llvm::Triple::PC: create = true; break; #if defined(__ANDROID__) // Only accept "unknown" for the vendor if the host is android and // it "unknown" wasn't specified (it was just returned because it // was NOT specified_ case llvm::Triple::VendorType::UnknownVendor: create = !arch->TripleVendorWasSpecified(); break; #endif default: break; } if (create) { switch (triple.getOS()) { case llvm::Triple::Android: break; #if defined(__ANDROID__) // Only accept "unknown" for the OS if the host is android and // it "unknown" wasn't specified (it was just returned because it // was NOT specified) case llvm::Triple::OSType::UnknownOS: create = !arch->TripleOSWasSpecified(); break; #endif default: create = false; break; } } } if (create) { if (log) log->Printf("PlatformAndroid::%s() creating remote-android platform", __FUNCTION__); return PlatformSP(new PlatformAndroid(false)); } if (log) log->Printf( "PlatformAndroid::%s() aborting creation of remote-android platform", __FUNCTION__); return PlatformSP(); } PlatformAndroid::PlatformAndroid(bool is_host) : PlatformLinux(is_host), m_sdk_version(0) {} PlatformAndroid::~PlatformAndroid() {} ConstString PlatformAndroid::GetPluginNameStatic(bool is_host) { if (is_host) { static ConstString g_host_name(Platform::GetHostPlatformName()); return g_host_name; } else { static ConstString g_remote_name("remote-android"); return g_remote_name; } } const char *PlatformAndroid::GetPluginDescriptionStatic(bool is_host) { if (is_host) return "Local Android user platform plug-in."; else return "Remote Android user platform plug-in."; } ConstString PlatformAndroid::GetPluginName() { return GetPluginNameStatic(IsHost()); } Status PlatformAndroid::ConnectRemote(Args &args) { m_device_id.clear(); if (IsHost()) { return Status("can't connect to the host platform '%s', always connected", GetPluginName().GetCString()); } if (!m_remote_platform_sp) m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer()); int port; llvm::StringRef scheme, host, path; const char *url = args.GetArgumentAtIndex(0); if (!url) return Status("URL is null."); if (!UriParser::Parse(url, scheme, host, port, path)) return Status("Invalid URL: %s", url); if (host != "localhost") m_device_id = host; auto error = PlatformLinux::ConnectRemote(args); if (error.Success()) { AdbClient adb; error = AdbClient::CreateByDeviceID(m_device_id, adb); if (error.Fail()) return error; m_device_id = adb.GetDeviceID(); } return error; } Status PlatformAndroid::GetFile(const FileSpec &source, const FileSpec &destination) { if (IsHost() || !m_remote_platform_sp) return PlatformLinux::GetFile(source, destination); FileSpec source_spec(source.GetPath(false), false, FileSpec::ePathSyntaxPosix); if (source_spec.IsRelative()) source_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent( source_spec.GetCString(false)); Status error; auto sync_service = GetSyncService(error); if (error.Fail()) return error; uint32_t mode = 0, size = 0, mtime = 0; error = sync_service->Stat(source_spec, mode, size, mtime); if (error.Fail()) return error; if (mode != 0) return sync_service->PullFile(source_spec, destination); auto source_file = source_spec.GetCString(false); Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); if (log) log->Printf("Got mode == 0 on '%s': try to get file via 'shell cat'", source_file); if (strchr(source_file, '\'') != nullptr) return Status("Doesn't support single-quotes in filenames"); // mode == 0 can signify that adbd cannot access the file // due security constraints - try "cat ..." as a fallback. AdbClient adb(m_device_id); char cmd[PATH_MAX]; snprintf(cmd, sizeof(cmd), "cat '%s'", source_file); return adb.ShellToFile(cmd, minutes(1), destination); } Status PlatformAndroid::PutFile(const FileSpec &source, const FileSpec &destination, uint32_t uid, uint32_t gid) { if (IsHost() || !m_remote_platform_sp) return PlatformLinux::PutFile(source, destination, uid, gid); FileSpec destination_spec(destination.GetPath(false), false, FileSpec::ePathSyntaxPosix); if (destination_spec.IsRelative()) destination_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent( destination_spec.GetCString(false)); // TODO: Set correct uid and gid on remote file. Status error; auto sync_service = GetSyncService(error); if (error.Fail()) return error; return sync_service->PushFile(source, destination_spec); } const char *PlatformAndroid::GetCacheHostname() { return m_device_id.c_str(); } Status PlatformAndroid::DownloadModuleSlice(const FileSpec &src_file_spec, const uint64_t src_offset, const uint64_t src_size, const FileSpec &dst_file_spec) { if (src_offset != 0) return Status("Invalid offset - %" PRIu64, src_offset); return GetFile(src_file_spec, dst_file_spec); } Status PlatformAndroid::DisconnectRemote() { Status error = PlatformLinux::DisconnectRemote(); if (error.Success()) { m_device_id.clear(); m_sdk_version = 0; } return error; } uint32_t PlatformAndroid::GetDefaultMemoryCacheLineSize() { return g_android_default_cache_size; } uint32_t PlatformAndroid::GetSdkVersion() { if (!IsConnected()) return 0; if (m_sdk_version != 0) return m_sdk_version; std::string version_string; AdbClient adb(m_device_id); Status error = adb.Shell("getprop ro.build.version.sdk", seconds(5), &version_string); version_string = llvm::StringRef(version_string).trim().str(); if (error.Fail() || version_string.empty()) { Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM); if (log) log->Printf("Get SDK version failed. (error: %s, output: %s)", error.AsCString(), version_string.c_str()); return 0; } m_sdk_version = StringConvert::ToUInt32(version_string.c_str()); return m_sdk_version; } Status PlatformAndroid::DownloadSymbolFile(const lldb::ModuleSP &module_sp, const FileSpec &dst_file_spec) { // For oat file we can try to fetch additional debug info from the device ConstString extension = module_sp->GetFileSpec().GetFileNameExtension(); if (extension != ConstString("oat") && extension != ConstString("odex")) return Status( "Symbol file downloading only supported for oat and odex files"); // If we have no information about the platform file we can't execute oatdump if (!module_sp->GetPlatformFileSpec()) return Status("No platform file specified"); // Symbolizer isn't available before SDK version 23 if (GetSdkVersion() < 23) return Status("Symbol file generation only supported on SDK 23+"); // If we already have symtab then we don't have to try and generate one if (module_sp->GetSectionList()->FindSectionByName(ConstString(".symtab")) != nullptr) return Status("Symtab already available in the module"); AdbClient adb(m_device_id); std::string tmpdir; Status error = adb.Shell("mktemp --directory --tmpdir /data/local/tmp", seconds(5), &tmpdir); if (error.Fail() || tmpdir.empty()) return Status("Failed to generate temporary directory on the device (%s)", error.AsCString()); tmpdir = llvm::StringRef(tmpdir).trim().str(); // Create file remover for the temporary directory created on the device std::unique_ptr> tmpdir_remover(&tmpdir, [&adb](std::string *s) { StreamString command; command.Printf("rm -rf %s", s->c_str()); Status error = adb.Shell(command.GetData(), seconds(5), nullptr); Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); if (log && error.Fail()) log->Printf("Failed to remove temp directory: %s", error.AsCString()); }); FileSpec symfile_platform_filespec(tmpdir, false); symfile_platform_filespec.AppendPathComponent("symbolized.oat"); // Execute oatdump on the remote device to generate a file with symtab StreamString command; command.Printf("oatdump --symbolize=%s --output=%s", module_sp->GetPlatformFileSpec().GetCString(false), symfile_platform_filespec.GetCString(false)); error = adb.Shell(command.GetData(), minutes(1), nullptr); if (error.Fail()) return Status("Oatdump failed: %s", error.AsCString()); // Download the symbolfile from the remote device return GetFile(symfile_platform_filespec, dst_file_spec); } bool PlatformAndroid::GetRemoteOSVersion() { m_major_os_version = GetSdkVersion(); m_minor_os_version = 0; m_update_os_version = 0; return m_major_os_version != 0; } -const char *PlatformAndroid::GetLibdlFunctionDeclarations() const { - return R"( +llvm::StringRef PlatformAndroid::GetLibdlFunctionDeclarations() { + // Older platform versions have the dl function symbols mangled + if (GetSdkVersion() < 26) + return R"( extern "C" void* dlopen(const char*, int) asm("__dl_dlopen"); extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym"); extern "C" int dlclose(void*) asm("__dl_dlclose"); extern "C" char* dlerror(void) asm("__dl_dlerror"); )"; + + return PlatformPOSIX::GetLibdlFunctionDeclarations(); } AdbClient::SyncService *PlatformAndroid::GetSyncService(Status &error) { if (m_adb_sync_svc && m_adb_sync_svc->IsConnected()) return m_adb_sync_svc.get(); AdbClient adb(m_device_id); m_adb_sync_svc = adb.GetSyncService(error); return (error.Success()) ? m_adb_sync_svc.get() : nullptr; } Index: vendor/lldb/dist/source/Plugins/Platform/Android/PlatformAndroid.h =================================================================== --- vendor/lldb/dist/source/Plugins/Platform/Android/PlatformAndroid.h (revision 320966) +++ vendor/lldb/dist/source/Plugins/Platform/Android/PlatformAndroid.h (revision 320967) @@ -1,94 +1,94 @@ //===-- PlatformAndroid.h ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef liblldb_PlatformAndroid_h_ #define liblldb_PlatformAndroid_h_ // C Includes // C++ Includes #include #include // Other libraries and framework includes // Project includes #include "Plugins/Platform/Linux/PlatformLinux.h" #include "AdbClient.h" namespace lldb_private { namespace platform_android { class PlatformAndroid : public platform_linux::PlatformLinux { public: PlatformAndroid(bool is_host); ~PlatformAndroid() override; static void Initialize(); static void Terminate(); //------------------------------------------------------------ // lldb_private::PluginInterface functions //------------------------------------------------------------ static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch); static ConstString GetPluginNameStatic(bool is_host); static const char *GetPluginDescriptionStatic(bool is_host); ConstString GetPluginName() override; uint32_t GetPluginVersion() override { return 1; } //------------------------------------------------------------ // lldb_private::Platform functions //------------------------------------------------------------ Status ConnectRemote(Args &args) override; Status GetFile(const FileSpec &source, const FileSpec &destination) override; Status PutFile(const FileSpec &source, const FileSpec &destination, uint32_t uid = UINT32_MAX, uint32_t gid = UINT32_MAX) override; uint32_t GetSdkVersion(); bool GetRemoteOSVersion() override; Status DisconnectRemote() override; uint32_t GetDefaultMemoryCacheLineSize() override; protected: const char *GetCacheHostname() override; Status DownloadModuleSlice(const FileSpec &src_file_spec, const uint64_t src_offset, const uint64_t src_size, const FileSpec &dst_file_spec) override; Status DownloadSymbolFile(const lldb::ModuleSP &module_sp, const FileSpec &dst_file_spec) override; - const char *GetLibdlFunctionDeclarations() const override; + llvm::StringRef GetLibdlFunctionDeclarations() override; private: AdbClient::SyncService *GetSyncService(Status &error); std::unique_ptr m_adb_sync_svc; std::string m_device_id; uint32_t m_sdk_version; DISALLOW_COPY_AND_ASSIGN(PlatformAndroid); }; } // namespace platofor_android } // namespace lldb_private #endif // liblldb_PlatformAndroid_h_ Index: vendor/lldb/dist/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp (revision 320967) @@ -1,1050 +1,1050 @@ //===-- PlatformPOSIX.cpp ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "PlatformPOSIX.h" // C Includes // C++ Includes // Other libraries and framework includes // Project includes #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/ValueObject.h" #include "lldb/Expression/UserExpression.h" #include "lldb/Host/File.h" #include "lldb/Host/FileCache.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" using namespace lldb; using namespace lldb_private; //------------------------------------------------------------------ /// Default Constructor //------------------------------------------------------------------ PlatformPOSIX::PlatformPOSIX(bool is_host) : Platform(is_host), // This is the local host platform m_option_group_platform_rsync(new OptionGroupPlatformRSync()), m_option_group_platform_ssh(new OptionGroupPlatformSSH()), m_option_group_platform_caching(new OptionGroupPlatformCaching()), m_remote_platform_sp() {} //------------------------------------------------------------------ /// Destructor. /// /// The destructor is virtual since this class is designed to be /// inherited from by the plug-in instance. //------------------------------------------------------------------ PlatformPOSIX::~PlatformPOSIX() {} bool PlatformPOSIX::GetModuleSpec(const FileSpec &module_file_spec, const ArchSpec &arch, ModuleSpec &module_spec) { if (m_remote_platform_sp) return m_remote_platform_sp->GetModuleSpec(module_file_spec, arch, module_spec); return Platform::GetModuleSpec(module_file_spec, arch, module_spec); } lldb_private::OptionGroupOptions *PlatformPOSIX::GetConnectionOptions( lldb_private::CommandInterpreter &interpreter) { auto iter = m_options.find(&interpreter), end = m_options.end(); if (iter == end) { std::unique_ptr options( new OptionGroupOptions()); options->Append(m_option_group_platform_rsync.get()); options->Append(m_option_group_platform_ssh.get()); options->Append(m_option_group_platform_caching.get()); m_options[&interpreter] = std::move(options); } return m_options.at(&interpreter).get(); } bool PlatformPOSIX::IsConnected() const { if (IsHost()) return true; else if (m_remote_platform_sp) return m_remote_platform_sp->IsConnected(); return false; } lldb_private::Status PlatformPOSIX::RunShellCommand( const char *command, // Shouldn't be NULL const FileSpec & working_dir, // Pass empty FileSpec to use the current working directory int *status_ptr, // Pass NULL if you don't want the process exit status int *signo_ptr, // Pass NULL if you don't want the signal that caused the // process to exit std::string *command_output, // Pass NULL if you don't want the command output uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish { if (IsHost()) return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); else { if (m_remote_platform_sp) return m_remote_platform_sp->RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); else return Status("unable to run a remote command without a platform"); } } Status PlatformPOSIX::ResolveExecutable(const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp, const FileSpecList *module_search_paths_ptr) { Status error; // Nothing special to do here, just use the actual file and architecture char exe_path[PATH_MAX]; ModuleSpec resolved_module_spec(module_spec); if (IsHost()) { // If we have "ls" as the exe_file, resolve the executable location based on // the current path variables if (!resolved_module_spec.GetFileSpec().Exists()) { resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path)); resolved_module_spec.GetFileSpec().SetFile(exe_path, true); } if (!resolved_module_spec.GetFileSpec().Exists()) resolved_module_spec.GetFileSpec().ResolveExecutableLocation(); // Resolve any executable within a bundle on MacOSX Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec()); if (resolved_module_spec.GetFileSpec().Exists()) error.Clear(); else { const uint32_t permissions = resolved_module_spec.GetFileSpec().GetPermissions(); if (permissions && (permissions & eFilePermissionsEveryoneR) == 0) error.SetErrorStringWithFormat( "executable '%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str()); else error.SetErrorStringWithFormat( "unable to find executable for '%s'", resolved_module_spec.GetFileSpec().GetPath().c_str()); } } else { if (m_remote_platform_sp) { error = GetCachedExecutable(resolved_module_spec, exe_module_sp, module_search_paths_ptr, *m_remote_platform_sp); } else { // We may connect to a process and use the provided executable (Don't use // local $PATH). // Resolve any executable within a bundle on MacOSX Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec()); if (resolved_module_spec.GetFileSpec().Exists()) error.Clear(); else error.SetErrorStringWithFormat("the platform is not currently " "connected, and '%s' doesn't exist in " "the system root.", exe_path); } } if (error.Success()) { if (resolved_module_spec.GetArchitecture().IsValid()) { error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, module_search_paths_ptr, nullptr, nullptr); if (error.Fail()) { // If we failed, it may be because the vendor and os aren't known. If // that is the case, try setting them to the host architecture and give // it another try. llvm::Triple &module_triple = resolved_module_spec.GetArchitecture().GetTriple(); bool is_vendor_specified = (module_triple.getVendor() != llvm::Triple::UnknownVendor); bool is_os_specified = (module_triple.getOS() != llvm::Triple::UnknownOS); if (!is_vendor_specified || !is_os_specified) { const llvm::Triple &host_triple = HostInfo::GetArchitecture(HostInfo::eArchKindDefault).GetTriple(); if (!is_vendor_specified) module_triple.setVendorName(host_triple.getVendorName()); if (!is_os_specified) module_triple.setOSName(host_triple.getOSName()); error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, module_search_paths_ptr, nullptr, nullptr); } } // TODO find out why exe_module_sp might be NULL if (error.Fail() || !exe_module_sp || !exe_module_sp->GetObjectFile()) { exe_module_sp.reset(); error.SetErrorStringWithFormat( "'%s' doesn't contain the architecture %s", resolved_module_spec.GetFileSpec().GetPath().c_str(), resolved_module_spec.GetArchitecture().GetArchitectureName()); } } else { // No valid architecture was specified, ask the platform for // the architectures that we should be using (in the correct order) // and see if we can find a match that way StreamString arch_names; for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( idx, resolved_module_spec.GetArchitecture()); ++idx) { error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, module_search_paths_ptr, nullptr, nullptr); // Did we find an executable using one of the if (error.Success()) { if (exe_module_sp && exe_module_sp->GetObjectFile()) break; else error.SetErrorToGenericError(); } if (idx > 0) arch_names.PutCString(", "); arch_names.PutCString( resolved_module_spec.GetArchitecture().GetArchitectureName()); } if (error.Fail() || !exe_module_sp) { if (resolved_module_spec.GetFileSpec().Readable()) { error.SetErrorStringWithFormat( "'%s' doesn't contain any '%s' platform architectures: %s", resolved_module_spec.GetFileSpec().GetPath().c_str(), GetPluginName().GetCString(), arch_names.GetData()); } else { error.SetErrorStringWithFormat( "'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str()); } } } } return error; } Status PlatformPOSIX::GetFileWithUUID(const FileSpec &platform_file, const UUID *uuid_ptr, FileSpec &local_file) { if (IsRemote() && m_remote_platform_sp) return m_remote_platform_sp->GetFileWithUUID(platform_file, uuid_ptr, local_file); // Default to the local case local_file = platform_file; return Status(); } bool PlatformPOSIX::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) { if (IsHost()) return Platform::GetProcessInfo(pid, process_info); if (m_remote_platform_sp) return m_remote_platform_sp->GetProcessInfo(pid, process_info); return false; } uint32_t PlatformPOSIX::FindProcesses(const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) { if (IsHost()) return Platform::FindProcesses(match_info, process_infos); if (m_remote_platform_sp) return m_remote_platform_sp->FindProcesses(match_info, process_infos); return 0; } Status PlatformPOSIX::MakeDirectory(const FileSpec &file_spec, uint32_t file_permissions) { if (m_remote_platform_sp) return m_remote_platform_sp->MakeDirectory(file_spec, file_permissions); else return Platform::MakeDirectory(file_spec, file_permissions); } Status PlatformPOSIX::GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions) { if (m_remote_platform_sp) return m_remote_platform_sp->GetFilePermissions(file_spec, file_permissions); else return Platform::GetFilePermissions(file_spec, file_permissions); } Status PlatformPOSIX::SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions) { if (m_remote_platform_sp) return m_remote_platform_sp->SetFilePermissions(file_spec, file_permissions); else return Platform::SetFilePermissions(file_spec, file_permissions); } lldb::user_id_t PlatformPOSIX::OpenFile(const FileSpec &file_spec, uint32_t flags, uint32_t mode, Status &error) { if (IsHost()) return FileCache::GetInstance().OpenFile(file_spec, flags, mode, error); else if (m_remote_platform_sp) return m_remote_platform_sp->OpenFile(file_spec, flags, mode, error); else return Platform::OpenFile(file_spec, flags, mode, error); } bool PlatformPOSIX::CloseFile(lldb::user_id_t fd, Status &error) { if (IsHost()) return FileCache::GetInstance().CloseFile(fd, error); else if (m_remote_platform_sp) return m_remote_platform_sp->CloseFile(fd, error); else return Platform::CloseFile(fd, error); } uint64_t PlatformPOSIX::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst, uint64_t dst_len, Status &error) { if (IsHost()) return FileCache::GetInstance().ReadFile(fd, offset, dst, dst_len, error); else if (m_remote_platform_sp) return m_remote_platform_sp->ReadFile(fd, offset, dst, dst_len, error); else return Platform::ReadFile(fd, offset, dst, dst_len, error); } uint64_t PlatformPOSIX::WriteFile(lldb::user_id_t fd, uint64_t offset, const void *src, uint64_t src_len, Status &error) { if (IsHost()) return FileCache::GetInstance().WriteFile(fd, offset, src, src_len, error); else if (m_remote_platform_sp) return m_remote_platform_sp->WriteFile(fd, offset, src, src_len, error); else return Platform::WriteFile(fd, offset, src, src_len, error); } static uint32_t chown_file(Platform *platform, const char *path, uint32_t uid = UINT32_MAX, uint32_t gid = UINT32_MAX) { if (!platform || !path || *path == 0) return UINT32_MAX; if (uid == UINT32_MAX && gid == UINT32_MAX) return 0; // pretend I did chown correctly - actually I just didn't care StreamString command; command.PutCString("chown "); if (uid != UINT32_MAX) command.Printf("%d", uid); if (gid != UINT32_MAX) command.Printf(":%d", gid); command.Printf("%s", path); int status; platform->RunShellCommand(command.GetData(), NULL, &status, NULL, NULL, 10); return status; } lldb_private::Status PlatformPOSIX::PutFile(const lldb_private::FileSpec &source, const lldb_private::FileSpec &destination, uint32_t uid, uint32_t gid) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); if (IsHost()) { if (FileSpec::Equal(source, destination, true)) return Status(); // cp src dst // chown uid:gid dst std::string src_path(source.GetPath()); if (src_path.empty()) return Status("unable to get file path for source"); std::string dst_path(destination.GetPath()); if (dst_path.empty()) return Status("unable to get file path for destination"); StreamString command; command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); int status; RunShellCommand(command.GetData(), NULL, &status, NULL, NULL, 10); if (status != 0) return Status("unable to perform copy"); if (uid == UINT32_MAX && gid == UINT32_MAX) return Status(); if (chown_file(this, dst_path.c_str(), uid, gid) != 0) return Status("unable to perform chown"); return Status(); } else if (m_remote_platform_sp) { if (GetSupportsRSync()) { std::string src_path(source.GetPath()); if (src_path.empty()) return Status("unable to get file path for source"); std::string dst_path(destination.GetPath()); if (dst_path.empty()) return Status("unable to get file path for destination"); StreamString command; if (GetIgnoresRemoteHostname()) { if (!GetRSyncPrefix()) command.Printf("rsync %s %s %s", GetRSyncOpts(), src_path.c_str(), dst_path.c_str()); else command.Printf("rsync %s %s %s%s", GetRSyncOpts(), src_path.c_str(), GetRSyncPrefix(), dst_path.c_str()); } else command.Printf("rsync %s %s %s:%s", GetRSyncOpts(), src_path.c_str(), GetHostname(), dst_path.c_str()); if (log) log->Printf("[PutFile] Running command: %s\n", command.GetData()); int retcode; Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL, 60); if (retcode == 0) { // Don't chown a local file for a remote system // if (chown_file(this,dst_path.c_str(),uid,gid) != 0) // return Status("unable to perform chown"); return Status(); } // if we are still here rsync has failed - let's try the slow way before // giving up } } return Platform::PutFile(source, destination, uid, gid); } lldb::user_id_t PlatformPOSIX::GetFileSize(const FileSpec &file_spec) { if (IsHost()) { uint64_t Size; if (llvm::sys::fs::file_size(file_spec.GetPath(), Size)) return 0; return Size; } else if (m_remote_platform_sp) return m_remote_platform_sp->GetFileSize(file_spec); else return Platform::GetFileSize(file_spec); } Status PlatformPOSIX::CreateSymlink(const FileSpec &src, const FileSpec &dst) { if (IsHost()) return FileSystem::Symlink(src, dst); else if (m_remote_platform_sp) return m_remote_platform_sp->CreateSymlink(src, dst); else return Platform::CreateSymlink(src, dst); } bool PlatformPOSIX::GetFileExists(const FileSpec &file_spec) { if (IsHost()) return file_spec.Exists(); else if (m_remote_platform_sp) return m_remote_platform_sp->GetFileExists(file_spec); else return Platform::GetFileExists(file_spec); } Status PlatformPOSIX::Unlink(const FileSpec &file_spec) { if (IsHost()) return llvm::sys::fs::remove(file_spec.GetPath()); else if (m_remote_platform_sp) return m_remote_platform_sp->Unlink(file_spec); else return Platform::Unlink(file_spec); } lldb_private::Status PlatformPOSIX::GetFile( const lldb_private::FileSpec &source, // remote file path const lldb_private::FileSpec &destination) // local file path { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); // Check the args, first. std::string src_path(source.GetPath()); if (src_path.empty()) return Status("unable to get file path for source"); std::string dst_path(destination.GetPath()); if (dst_path.empty()) return Status("unable to get file path for destination"); if (IsHost()) { if (FileSpec::Equal(source, destination, true)) return Status("local scenario->source and destination are the same file " "path: no operation performed"); // cp src dst StreamString cp_command; cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str()); int status; RunShellCommand(cp_command.GetData(), NULL, &status, NULL, NULL, 10); if (status != 0) return Status("unable to perform copy"); return Status(); } else if (m_remote_platform_sp) { if (GetSupportsRSync()) { StreamString command; if (GetIgnoresRemoteHostname()) { if (!GetRSyncPrefix()) command.Printf("rsync %s %s %s", GetRSyncOpts(), src_path.c_str(), dst_path.c_str()); else command.Printf("rsync %s %s%s %s", GetRSyncOpts(), GetRSyncPrefix(), src_path.c_str(), dst_path.c_str()); } else command.Printf("rsync %s %s:%s %s", GetRSyncOpts(), m_remote_platform_sp->GetHostname(), src_path.c_str(), dst_path.c_str()); if (log) log->Printf("[GetFile] Running command: %s\n", command.GetData()); int retcode; Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL, 60); if (retcode == 0) return Status(); // If we are here, rsync has failed - let's try the slow way before giving // up } // open src and dst // read/write, read/write, read/write, ... // close src // close dst if (log) log->Printf("[GetFile] Using block by block transfer....\n"); Status error; user_id_t fd_src = OpenFile(source, File::eOpenOptionRead, lldb::eFilePermissionsFileDefault, error); if (fd_src == UINT64_MAX) return Status("unable to open source file"); uint32_t permissions = 0; error = GetFilePermissions(source, permissions); if (permissions == 0) permissions = lldb::eFilePermissionsFileDefault; user_id_t fd_dst = FileCache::GetInstance().OpenFile( destination, File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate, permissions, error); if (fd_dst == UINT64_MAX) { if (error.Success()) error.SetErrorString("unable to open destination file"); } if (error.Success()) { lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); uint64_t offset = 0; error.Clear(); while (error.Success()) { const uint64_t n_read = ReadFile(fd_src, offset, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), error); if (error.Fail()) break; if (n_read == 0) break; if (FileCache::GetInstance().WriteFile(fd_dst, offset, buffer_sp->GetBytes(), n_read, error) != n_read) { if (!error.Fail()) error.SetErrorString("unable to write to destination file"); break; } offset += n_read; } } // Ignore the close error of src. if (fd_src != UINT64_MAX) CloseFile(fd_src, error); // And close the dst file descriptot. if (fd_dst != UINT64_MAX && !FileCache::GetInstance().CloseFile(fd_dst, error)) { if (!error.Fail()) error.SetErrorString("unable to close destination file"); } return error; } return Platform::GetFile(source, destination); } std::string PlatformPOSIX::GetPlatformSpecificConnectionInformation() { StreamString stream; if (GetSupportsRSync()) { stream.PutCString("rsync"); if ((GetRSyncOpts() && *GetRSyncOpts()) || (GetRSyncPrefix() && *GetRSyncPrefix()) || GetIgnoresRemoteHostname()) { stream.Printf(", options: "); if (GetRSyncOpts() && *GetRSyncOpts()) stream.Printf("'%s' ", GetRSyncOpts()); stream.Printf(", prefix: "); if (GetRSyncPrefix() && *GetRSyncPrefix()) stream.Printf("'%s' ", GetRSyncPrefix()); if (GetIgnoresRemoteHostname()) stream.Printf("ignore remote-hostname "); } } if (GetSupportsSSH()) { stream.PutCString("ssh"); if (GetSSHOpts() && *GetSSHOpts()) stream.Printf(", options: '%s' ", GetSSHOpts()); } if (GetLocalCacheDirectory() && *GetLocalCacheDirectory()) stream.Printf("cache dir: %s", GetLocalCacheDirectory()); if (stream.GetSize()) return stream.GetString(); else return ""; } bool PlatformPOSIX::CalculateMD5(const FileSpec &file_spec, uint64_t &low, uint64_t &high) { if (IsHost()) return Platform::CalculateMD5(file_spec, low, high); if (m_remote_platform_sp) return m_remote_platform_sp->CalculateMD5(file_spec, low, high); return false; } const lldb::UnixSignalsSP &PlatformPOSIX::GetRemoteUnixSignals() { if (IsRemote() && m_remote_platform_sp) return m_remote_platform_sp->GetRemoteUnixSignals(); return Platform::GetRemoteUnixSignals(); } FileSpec PlatformPOSIX::GetRemoteWorkingDirectory() { if (IsRemote() && m_remote_platform_sp) return m_remote_platform_sp->GetRemoteWorkingDirectory(); else return Platform::GetRemoteWorkingDirectory(); } bool PlatformPOSIX::SetRemoteWorkingDirectory(const FileSpec &working_dir) { if (IsRemote() && m_remote_platform_sp) return m_remote_platform_sp->SetRemoteWorkingDirectory(working_dir); else return Platform::SetRemoteWorkingDirectory(working_dir); } bool PlatformPOSIX::GetRemoteOSVersion() { if (m_remote_platform_sp) return m_remote_platform_sp->GetOSVersion( m_major_os_version, m_minor_os_version, m_update_os_version); return false; } bool PlatformPOSIX::GetRemoteOSBuildString(std::string &s) { if (m_remote_platform_sp) return m_remote_platform_sp->GetRemoteOSBuildString(s); s.clear(); return false; } size_t PlatformPOSIX::GetEnvironment(StringList &env) { if (IsRemote()) { if (m_remote_platform_sp) return m_remote_platform_sp->GetEnvironment(env); return 0; } return Host::GetEnvironment(env); } bool PlatformPOSIX::GetRemoteOSKernelDescription(std::string &s) { if (m_remote_platform_sp) return m_remote_platform_sp->GetRemoteOSKernelDescription(s); s.clear(); return false; } // Remote Platform subclasses need to override this function ArchSpec PlatformPOSIX::GetRemoteSystemArchitecture() { if (m_remote_platform_sp) return m_remote_platform_sp->GetRemoteSystemArchitecture(); return ArchSpec(); } const char *PlatformPOSIX::GetHostname() { if (IsHost()) return Platform::GetHostname(); if (m_remote_platform_sp) return m_remote_platform_sp->GetHostname(); return NULL; } const char *PlatformPOSIX::GetUserName(uint32_t uid) { // Check the cache in Platform in case we have already looked this uid up const char *user_name = Platform::GetUserName(uid); if (user_name) return user_name; if (IsRemote() && m_remote_platform_sp) return m_remote_platform_sp->GetUserName(uid); return NULL; } const char *PlatformPOSIX::GetGroupName(uint32_t gid) { const char *group_name = Platform::GetGroupName(gid); if (group_name) return group_name; if (IsRemote() && m_remote_platform_sp) return m_remote_platform_sp->GetGroupName(gid); return NULL; } Status PlatformPOSIX::ConnectRemote(Args &args) { Status error; if (IsHost()) { error.SetErrorStringWithFormat( "can't connect to the host platform '%s', always connected", GetPluginName().GetCString()); } else { if (!m_remote_platform_sp) m_remote_platform_sp = Platform::Create(ConstString("remote-gdb-server"), error); if (m_remote_platform_sp && error.Success()) error = m_remote_platform_sp->ConnectRemote(args); else error.SetErrorString("failed to create a 'remote-gdb-server' platform"); if (error.Fail()) m_remote_platform_sp.reset(); } if (error.Success() && m_remote_platform_sp) { if (m_option_group_platform_rsync.get() && m_option_group_platform_ssh.get() && m_option_group_platform_caching.get()) { if (m_option_group_platform_rsync->m_rsync) { SetSupportsRSync(true); SetRSyncOpts(m_option_group_platform_rsync->m_rsync_opts.c_str()); SetRSyncPrefix(m_option_group_platform_rsync->m_rsync_prefix.c_str()); SetIgnoresRemoteHostname( m_option_group_platform_rsync->m_ignores_remote_hostname); } if (m_option_group_platform_ssh->m_ssh) { SetSupportsSSH(true); SetSSHOpts(m_option_group_platform_ssh->m_ssh_opts.c_str()); } SetLocalCacheDirectory( m_option_group_platform_caching->m_cache_dir.c_str()); } } return error; } Status PlatformPOSIX::DisconnectRemote() { Status error; if (IsHost()) { error.SetErrorStringWithFormat( "can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString()); } else { if (m_remote_platform_sp) error = m_remote_platform_sp->DisconnectRemote(); else error.SetErrorString("the platform is not currently connected"); } return error; } Status PlatformPOSIX::LaunchProcess(ProcessLaunchInfo &launch_info) { Status error; if (IsHost()) { error = Platform::LaunchProcess(launch_info); } else { if (m_remote_platform_sp) error = m_remote_platform_sp->LaunchProcess(launch_info); else error.SetErrorString("the platform is not currently connected"); } return error; } lldb_private::Status PlatformPOSIX::KillProcess(const lldb::pid_t pid) { if (IsHost()) return Platform::KillProcess(pid); if (m_remote_platform_sp) return m_remote_platform_sp->KillProcess(pid); return Status("the platform is not currently connected"); } lldb::ProcessSP PlatformPOSIX::Attach(ProcessAttachInfo &attach_info, Debugger &debugger, Target *target, Status &error) { lldb::ProcessSP process_sp; Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); if (IsHost()) { if (target == NULL) { TargetSP new_target_sp; error = debugger.GetTargetList().CreateTarget(debugger, "", "", false, NULL, new_target_sp); target = new_target_sp.get(); if (log) log->Printf("PlatformPOSIX::%s created new target", __FUNCTION__); } else { error.Clear(); if (log) log->Printf("PlatformPOSIX::%s target already existed, setting target", __FUNCTION__); } if (target && error.Success()) { debugger.GetTargetList().SetSelectedTarget(target); if (log) { ModuleSP exe_module_sp = target->GetExecutableModule(); log->Printf("PlatformPOSIX::%s set selected target to %p %s", __FUNCTION__, (void *)target, exe_module_sp ? exe_module_sp->GetFileSpec().GetPath().c_str() : ""); } process_sp = target->CreateProcess(attach_info.GetListenerForProcess(debugger), attach_info.GetProcessPluginName(), NULL); if (process_sp) { ListenerSP listener_sp = attach_info.GetHijackListener(); if (listener_sp == nullptr) { listener_sp = Listener::MakeListener("lldb.PlatformPOSIX.attach.hijack"); attach_info.SetHijackListener(listener_sp); } process_sp->HijackProcessEvents(listener_sp); error = process_sp->Attach(attach_info); } } } else { if (m_remote_platform_sp) process_sp = m_remote_platform_sp->Attach(attach_info, debugger, target, error); else error.SetErrorString("the platform is not currently connected"); } return process_sp; } lldb::ProcessSP PlatformPOSIX::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, Target *target, // Can be NULL, if NULL create a new // target, else use existing one Status &error) { ProcessSP process_sp; if (IsHost()) { // We are going to hand this process off to debugserver which will be in // charge of setting the exit status. // We still need to reap it from lldb but if we let the monitor thread also // set the exit status, we set up a // race between debugserver & us for who will find out about the debugged // process's death. launch_info.GetFlags().Set(eLaunchFlagDontSetExitStatus); process_sp = Platform::DebugProcess(launch_info, debugger, target, error); } else { if (m_remote_platform_sp) process_sp = m_remote_platform_sp->DebugProcess(launch_info, debugger, target, error); else error.SetErrorString("the platform is not currently connected"); } return process_sp; } void PlatformPOSIX::CalculateTrapHandlerSymbolNames() { m_trap_handlers.push_back(ConstString("_sigtramp")); } Status PlatformPOSIX::EvaluateLibdlExpression( lldb_private::Process *process, const char *expr_cstr, - const char *expr_prefix, lldb::ValueObjectSP &result_valobj_sp) { + llvm::StringRef expr_prefix, lldb::ValueObjectSP &result_valobj_sp) { DynamicLoader *loader = process->GetDynamicLoader(); if (loader) { Status error = loader->CanLoadImage(); if (error.Fail()) return error; } ThreadSP thread_sp(process->GetThreadList().GetExpressionExecutionThread()); if (!thread_sp) return Status("Selected thread isn't valid"); StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0)); if (!frame_sp) return Status("Frame 0 isn't valid"); ExecutionContext exe_ctx; frame_sp->CalculateExecutionContext(exe_ctx); EvaluateExpressionOptions expr_options; expr_options.SetUnwindOnError(true); expr_options.SetIgnoreBreakpoints(true); expr_options.SetExecutionPolicy(eExecutionPolicyAlways); expr_options.SetLanguage(eLanguageTypeC_plus_plus); expr_options.SetTrapExceptions(false); // dlopen can't throw exceptions, so // don't do the work to trap them. expr_options.SetTimeout(std::chrono::seconds(2)); Status expr_error; ExpressionResults result = UserExpression::Evaluate(exe_ctx, expr_options, expr_cstr, expr_prefix, result_valobj_sp, expr_error); if (result != eExpressionCompleted) return expr_error; if (result_valobj_sp->GetError().Fail()) return result_valobj_sp->GetError(); return Status(); } uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, const lldb_private::FileSpec &remote_file, lldb_private::Status &error) { char path[PATH_MAX]; remote_file.GetPath(path, sizeof(path)); StreamString expr; expr.Printf(R"( struct __lldb_dlopen_result { void *image_ptr; const char *error_str; } the_result; the_result.image_ptr = dlopen ("%s", 2); if (the_result.image_ptr == (void *) 0x0) { the_result.error_str = dlerror(); } else { the_result.error_str = (const char *) 0x0; } the_result; )", path); - const char *prefix = GetLibdlFunctionDeclarations(); + llvm::StringRef prefix = GetLibdlFunctionDeclarations(); lldb::ValueObjectSP result_valobj_sp; error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp); if (error.Fail()) return LLDB_INVALID_IMAGE_TOKEN; error = result_valobj_sp->GetError(); if (error.Fail()) return LLDB_INVALID_IMAGE_TOKEN; Scalar scalar; ValueObjectSP image_ptr_sp = result_valobj_sp->GetChildAtIndex(0, true); if (!image_ptr_sp || !image_ptr_sp->ResolveValue(scalar)) { error.SetErrorStringWithFormat("unable to load '%s'", path); return LLDB_INVALID_IMAGE_TOKEN; } addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS); if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS) return process->AddImageToken(image_ptr); if (image_ptr == 0) { ValueObjectSP error_str_sp = result_valobj_sp->GetChildAtIndex(1, true); if (error_str_sp) { DataBufferSP buffer_sp(new DataBufferHeap(10240, 0)); size_t num_chars = error_str_sp->ReadPointedString(buffer_sp, error, 10240).first; if (error.Success() && num_chars > 0) error.SetErrorStringWithFormat("dlopen error: %s", buffer_sp->GetBytes()); else error.SetErrorStringWithFormat("dlopen failed for unknown reasons."); return LLDB_INVALID_IMAGE_TOKEN; } } error.SetErrorStringWithFormat("unable to load '%s'", path); return LLDB_INVALID_IMAGE_TOKEN; } Status PlatformPOSIX::UnloadImage(lldb_private::Process *process, uint32_t image_token) { const addr_t image_addr = process->GetImagePtrFromToken(image_token); if (image_addr == LLDB_INVALID_ADDRESS) return Status("Invalid image token"); StreamString expr; expr.Printf("dlclose((void *)0x%" PRIx64 ")", image_addr); - const char *prefix = GetLibdlFunctionDeclarations(); + llvm::StringRef prefix = GetLibdlFunctionDeclarations(); lldb::ValueObjectSP result_valobj_sp; Status error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp); if (error.Fail()) return error; if (result_valobj_sp->GetError().Fail()) return result_valobj_sp->GetError(); Scalar scalar; if (result_valobj_sp->ResolveValue(scalar)) { if (scalar.UInt(1)) return Status("expression failed: \"%s\"", expr.GetData()); process->ResetImageToken(image_token); } return Status(); } lldb::ProcessSP PlatformPOSIX::ConnectProcess(llvm::StringRef connect_url, llvm::StringRef plugin_name, lldb_private::Debugger &debugger, lldb_private::Target *target, lldb_private::Status &error) { if (m_remote_platform_sp) return m_remote_platform_sp->ConnectProcess(connect_url, plugin_name, debugger, target, error); return Platform::ConnectProcess(connect_url, plugin_name, debugger, target, error); } -const char *PlatformPOSIX::GetLibdlFunctionDeclarations() const { +llvm::StringRef PlatformPOSIX::GetLibdlFunctionDeclarations() { return R"( extern "C" void* dlopen(const char*, int); extern "C" void* dlsym(void*, const char*); extern "C" int dlclose(void*); extern "C" char* dlerror(void); )"; } size_t PlatformPOSIX::ConnectToWaitingProcesses(Debugger &debugger, Status &error) { if (m_remote_platform_sp) return m_remote_platform_sp->ConnectToWaitingProcesses(debugger, error); return Platform::ConnectToWaitingProcesses(debugger, error); } ConstString PlatformPOSIX::GetFullNameForDylib(ConstString basename) { if (basename.IsEmpty()) return basename; StreamString stream; stream.Printf("lib%s.so", basename.GetCString()); return ConstString(stream.GetString()); } Index: vendor/lldb/dist/source/Plugins/Platform/POSIX/PlatformPOSIX.h =================================================================== --- vendor/lldb/dist/source/Plugins/Platform/POSIX/PlatformPOSIX.h (revision 320966) +++ vendor/lldb/dist/source/Plugins/Platform/POSIX/PlatformPOSIX.h (revision 320967) @@ -1,210 +1,210 @@ //===-- PlatformPOSIX.h -----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef liblldb_PlatformPOSIX_h_ #define liblldb_PlatformPOSIX_h_ // C Includes // C++ Includes #include #include // Other libraries and framework includes // Project includes #include "lldb/Interpreter/Options.h" #include "lldb/Target/Platform.h" class PlatformPOSIX : public lldb_private::Platform { public: PlatformPOSIX(bool is_host); ~PlatformPOSIX() override; //------------------------------------------------------------ // lldb_private::Platform functions //------------------------------------------------------------ bool GetModuleSpec(const lldb_private::FileSpec &module_file_spec, const lldb_private::ArchSpec &arch, lldb_private::ModuleSpec &module_spec) override; lldb_private::OptionGroupOptions * GetConnectionOptions(lldb_private::CommandInterpreter &interpreter) override; const char *GetHostname() override; const char *GetUserName(uint32_t uid) override; const char *GetGroupName(uint32_t gid) override; lldb_private::Status PutFile(const lldb_private::FileSpec &source, const lldb_private::FileSpec &destination, uint32_t uid = UINT32_MAX, uint32_t gid = UINT32_MAX) override; lldb::user_id_t OpenFile(const lldb_private::FileSpec &file_spec, uint32_t flags, uint32_t mode, lldb_private::Status &error) override; bool CloseFile(lldb::user_id_t fd, lldb_private::Status &error) override; uint64_t ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst, uint64_t dst_len, lldb_private::Status &error) override; uint64_t WriteFile(lldb::user_id_t fd, uint64_t offset, const void *src, uint64_t src_len, lldb_private::Status &error) override; lldb::user_id_t GetFileSize(const lldb_private::FileSpec &file_spec) override; lldb_private::Status CreateSymlink(const lldb_private::FileSpec &src, const lldb_private::FileSpec &dst) override; lldb_private::Status GetFile(const lldb_private::FileSpec &source, const lldb_private::FileSpec &destination) override; lldb_private::FileSpec GetRemoteWorkingDirectory() override; bool SetRemoteWorkingDirectory(const lldb_private::FileSpec &working_dir) override; bool GetRemoteOSVersion() override; bool GetRemoteOSBuildString(std::string &s) override; bool GetRemoteOSKernelDescription(std::string &s) override; lldb_private::ArchSpec GetRemoteSystemArchitecture() override; const lldb::UnixSignalsSP &GetRemoteUnixSignals() override; size_t GetEnvironment(lldb_private::StringList &environment) override; bool IsConnected() const override; lldb_private::Status RunShellCommand( const char *command, // Shouldn't be nullptr const lldb_private::FileSpec &working_dir, // Pass empty FileSpec to use // the current working // directory int *status_ptr, // Pass nullptr if you don't want the process exit status int *signo_ptr, // Pass nullptr if you don't want the signal that caused // the process to exit std::string *command_output, // Pass nullptr if you don't want the command output uint32_t timeout_sec) override; // Timeout in seconds to wait for shell program to finish lldb_private::Status ResolveExecutable( const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp, const lldb_private::FileSpecList *module_search_paths_ptr) override; lldb_private::Status GetFileWithUUID(const lldb_private::FileSpec &platform_file, const lldb_private::UUID *uuid, lldb_private::FileSpec &local_file) override; bool GetProcessInfo(lldb::pid_t pid, lldb_private::ProcessInstanceInfo &proc_info) override; uint32_t FindProcesses(const lldb_private::ProcessInstanceInfoMatch &match_info, lldb_private::ProcessInstanceInfoList &process_infos) override; lldb_private::Status MakeDirectory(const lldb_private::FileSpec &file_spec, uint32_t mode) override; lldb_private::Status GetFilePermissions(const lldb_private::FileSpec &file_spec, uint32_t &file_permissions) override; lldb_private::Status SetFilePermissions(const lldb_private::FileSpec &file_spec, uint32_t file_permissions) override; bool GetFileExists(const lldb_private::FileSpec &file_spec) override; lldb_private::Status Unlink(const lldb_private::FileSpec &file_spec) override; lldb_private::Status LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) override; lldb_private::Status KillProcess(const lldb::pid_t pid) override; lldb::ProcessSP Attach(lldb_private::ProcessAttachInfo &attach_info, lldb_private::Debugger &debugger, lldb_private::Target *target, // Can be nullptr, if // nullptr create a new // target, else use // existing one lldb_private::Status &error) override; lldb::ProcessSP DebugProcess(lldb_private::ProcessLaunchInfo &launch_info, lldb_private::Debugger &debugger, lldb_private::Target *target, // Can be nullptr, // if nullptr // create a new // target, else use // existing one lldb_private::Status &error) override; std::string GetPlatformSpecificConnectionInformation() override; bool CalculateMD5(const lldb_private::FileSpec &file_spec, uint64_t &low, uint64_t &high) override; void CalculateTrapHandlerSymbolNames() override; lldb_private::Status ConnectRemote(lldb_private::Args &args) override; lldb_private::Status DisconnectRemote() override; uint32_t DoLoadImage(lldb_private::Process *process, const lldb_private::FileSpec &remote_file, lldb_private::Status &error) override; lldb_private::Status UnloadImage(lldb_private::Process *process, uint32_t image_token) override; lldb::ProcessSP ConnectProcess(llvm::StringRef connect_url, llvm::StringRef plugin_name, lldb_private::Debugger &debugger, lldb_private::Target *target, lldb_private::Status &error) override; size_t ConnectToWaitingProcesses(lldb_private::Debugger &debugger, lldb_private::Status &error) override; lldb_private::ConstString GetFullNameForDylib(lldb_private::ConstString basename) override; protected: std::unique_ptr m_option_group_platform_rsync; std::unique_ptr m_option_group_platform_ssh; std::unique_ptr m_option_group_platform_caching; std::map> m_options; lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a // remote POSIX-compliant OS lldb_private::Status EvaluateLibdlExpression(lldb_private::Process *process, const char *expr_cstr, - const char *expr_prefix, + llvm::StringRef expr_prefix, lldb::ValueObjectSP &result_valobj_sp); - virtual const char *GetLibdlFunctionDeclarations() const; + virtual llvm::StringRef GetLibdlFunctionDeclarations(); private: DISALLOW_COPY_AND_ASSIGN(PlatformPOSIX); }; #endif // liblldb_PlatformPOSIX_h_ Index: vendor/lldb/dist/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (revision 320967) @@ -1,1462 +1,1450 @@ //===-- ProcessMonitor.cpp ------------------------------------ -*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // C Includes #include #include #include #include #include #include #include #include #include #include // C++ Includes // Other libraries and framework includes #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" #include "lldb/Host/Host.h" #include "lldb/Host/PseudoTerminal.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Thread.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/Status.h" #include "llvm/Support/Errno.h" #include "FreeBSDThread.h" #include "Plugins/Process/POSIX/CrashReason.h" #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #include "ProcessFreeBSD.h" #include "ProcessMonitor.h" extern "C" { extern char **environ; } using namespace lldb; using namespace lldb_private; // We disable the tracing of ptrace calls for integration builds to // avoid the additional indirection and checks. #ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION // Wrapper for ptrace to catch errors and log calls. const char *Get_PT_IO_OP(int op) { switch (op) { case PIOD_READ_D: return "READ_D"; case PIOD_WRITE_D: return "WRITE_D"; case PIOD_READ_I: return "READ_I"; case PIOD_WRITE_I: return "WRITE_I"; default: return "Unknown op"; } } // Wrapper for ptrace to catch errors and log calls. // Note that ptrace sets errno on error because -1 is reserved as a valid // result. extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, const char *reqName, const char *file, int line) { long int result; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); if (log) { log->Printf("ptrace(%s, %" PRIu64 ", %p, %x) called from file %s line %d", reqName, pid, addr, data, file, line); if (req == PT_IO) { struct ptrace_io_desc *pi = (struct ptrace_io_desc *)addr; log->Printf("PT_IO: op=%s offs=%zx size=%zu", Get_PT_IO_OP(pi->piod_op), (size_t)pi->piod_offs, pi->piod_len); } } // PtraceDisplayBytes(req, data); errno = 0; result = ptrace(req, pid, (caddr_t)addr, data); // PtraceDisplayBytes(req, data); if (log && errno != 0) { const char *str; switch (errno) { case ESRCH: str = "ESRCH"; break; case EINVAL: str = "EINVAL"; break; case EBUSY: str = "EBUSY"; break; case EPERM: str = "EPERM"; break; default: str = ""; } log->Printf("ptrace() failed; errno=%d (%s)", errno, str); } if (log) { #ifdef __amd64__ if (req == PT_GETREGS) { struct reg *r = (struct reg *)addr; log->Printf("PT_GETREGS: rip=0x%lx rsp=0x%lx rbp=0x%lx rax=0x%lx", r->r_rip, r->r_rsp, r->r_rbp, r->r_rax); } if (req == PT_GETDBREGS || req == PT_SETDBREGS) { struct dbreg *r = (struct dbreg *)addr; char setget = (req == PT_GETDBREGS) ? 'G' : 'S'; for (int i = 0; i <= 7; i++) log->Printf("PT_%cETDBREGS: dr[%d]=0x%lx", setget, i, r->dr[i]); } #endif } return result; } // Wrapper for ptrace when logging is not required. // Sets errno to 0 prior to calling ptrace. extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data) { long result = 0; errno = 0; result = ptrace(req, pid, (caddr_t)addr, data); return result; } #define PTRACE(req, pid, addr, data) \ PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__) #else PtraceWrapper((req), (pid), (addr), (data)) #endif //------------------------------------------------------------------------------ // Static implementations of ProcessMonitor::ReadMemory and // ProcessMonitor::WriteMemory. This enables mutual recursion between these // functions without needed to go thru the thread funnel. static size_t DoReadMemory(lldb::pid_t pid, lldb::addr_t vm_addr, void *buf, size_t size, Status &error) { struct ptrace_io_desc pi_desc; pi_desc.piod_op = PIOD_READ_D; pi_desc.piod_offs = (void *)vm_addr; pi_desc.piod_addr = buf; pi_desc.piod_len = size; if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) error.SetErrorToErrno(); return pi_desc.piod_len; } static size_t DoWriteMemory(lldb::pid_t pid, lldb::addr_t vm_addr, const void *buf, size_t size, Status &error) { struct ptrace_io_desc pi_desc; pi_desc.piod_op = PIOD_WRITE_D; pi_desc.piod_offs = (void *)vm_addr; pi_desc.piod_addr = (void *)buf; pi_desc.piod_len = size; if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) error.SetErrorToErrno(); return pi_desc.piod_len; } // Simple helper function to ensure flags are enabled on the given file // descriptor. static bool EnsureFDFlags(int fd, int flags, Status &error) { int status; if ((status = fcntl(fd, F_GETFL)) == -1) { error.SetErrorToErrno(); return false; } if (fcntl(fd, F_SETFL, status | flags) == -1) { error.SetErrorToErrno(); return false; } return true; } //------------------------------------------------------------------------------ /// @class Operation /// @brief Represents a ProcessMonitor operation. /// /// Under FreeBSD, it is not possible to ptrace() from any other thread but the /// one that spawned or attached to the process from the start. Therefore, when /// a ProcessMonitor is asked to deliver or change the state of an inferior /// process the operation must be "funneled" to a specific thread to perform the /// task. The Operation class provides an abstract base for all services the /// ProcessMonitor must perform via the single virtual function Execute, thus /// encapsulating the code that needs to run in the privileged context. class Operation { public: virtual ~Operation() {} virtual void Execute(ProcessMonitor *monitor) = 0; }; //------------------------------------------------------------------------------ /// @class ReadOperation /// @brief Implements ProcessMonitor::ReadMemory. class ReadOperation : public Operation { public: ReadOperation(lldb::addr_t addr, void *buff, size_t size, Status &error, size_t &result) : m_addr(addr), m_buff(buff), m_size(size), m_error(error), m_result(result) {} void Execute(ProcessMonitor *monitor); private: lldb::addr_t m_addr; void *m_buff; size_t m_size; Status &m_error; size_t &m_result; }; void ReadOperation::Execute(ProcessMonitor *monitor) { lldb::pid_t pid = monitor->GetPID(); m_result = DoReadMemory(pid, m_addr, m_buff, m_size, m_error); } //------------------------------------------------------------------------------ /// @class WriteOperation /// @brief Implements ProcessMonitor::WriteMemory. class WriteOperation : public Operation { public: WriteOperation(lldb::addr_t addr, const void *buff, size_t size, Status &error, size_t &result) : m_addr(addr), m_buff(buff), m_size(size), m_error(error), m_result(result) {} void Execute(ProcessMonitor *monitor); private: lldb::addr_t m_addr; const void *m_buff; size_t m_size; Status &m_error; size_t &m_result; }; void WriteOperation::Execute(ProcessMonitor *monitor) { lldb::pid_t pid = monitor->GetPID(); m_result = DoWriteMemory(pid, m_addr, m_buff, m_size, m_error); } //------------------------------------------------------------------------------ /// @class ReadRegOperation /// @brief Implements ProcessMonitor::ReadRegisterValue. class ReadRegOperation : public Operation { public: ReadRegOperation(lldb::tid_t tid, unsigned offset, unsigned size, RegisterValue &value, bool &result) : m_tid(tid), m_offset(offset), m_size(size), m_value(value), m_result(result) {} void Execute(ProcessMonitor *monitor); private: lldb::tid_t m_tid; unsigned m_offset; unsigned m_size; RegisterValue &m_value; bool &m_result; }; void ReadRegOperation::Execute(ProcessMonitor *monitor) { struct reg regs; int rc; if ((rc = PTRACE(PT_GETREGS, m_tid, (caddr_t)®s, 0)) < 0) { m_result = false; } else { // 'struct reg' contains only 32- or 64-bit register values. Punt on // others. Also, not all entries may be uintptr_t sized, such as 32-bit // processes on powerpc64 (probably the same for i386 on amd64) if (m_size == sizeof(uint32_t)) m_value = *(uint32_t *)(((caddr_t)®s) + m_offset); else if (m_size == sizeof(uint64_t)) m_value = *(uint64_t *)(((caddr_t)®s) + m_offset); else memcpy((void *)&m_value, (((caddr_t)®s) + m_offset), m_size); m_result = true; } } //------------------------------------------------------------------------------ /// @class WriteRegOperation /// @brief Implements ProcessMonitor::WriteRegisterValue. class WriteRegOperation : public Operation { public: WriteRegOperation(lldb::tid_t tid, unsigned offset, const RegisterValue &value, bool &result) : m_tid(tid), m_offset(offset), m_value(value), m_result(result) {} void Execute(ProcessMonitor *monitor); private: lldb::tid_t m_tid; unsigned m_offset; const RegisterValue &m_value; bool &m_result; }; void WriteRegOperation::Execute(ProcessMonitor *monitor) { struct reg regs; if (PTRACE(PT_GETREGS, m_tid, (caddr_t)®s, 0) < 0) { m_result = false; return; } *(uintptr_t *)(((caddr_t)®s) + m_offset) = (uintptr_t)m_value.GetAsUInt64(); if (PTRACE(PT_SETREGS, m_tid, (caddr_t)®s, 0) < 0) m_result = false; else m_result = true; } //------------------------------------------------------------------------------ /// @class ReadDebugRegOperation /// @brief Implements ProcessMonitor::ReadDebugRegisterValue. class ReadDebugRegOperation : public Operation { public: ReadDebugRegOperation(lldb::tid_t tid, unsigned offset, unsigned size, RegisterValue &value, bool &result) : m_tid(tid), m_offset(offset), m_size(size), m_value(value), m_result(result) {} void Execute(ProcessMonitor *monitor); private: lldb::tid_t m_tid; unsigned m_offset; unsigned m_size; RegisterValue &m_value; bool &m_result; }; void ReadDebugRegOperation::Execute(ProcessMonitor *monitor) { struct dbreg regs; int rc; if ((rc = PTRACE(PT_GETDBREGS, m_tid, (caddr_t)®s, 0)) < 0) { m_result = false; } else { if (m_size == sizeof(uintptr_t)) m_value = *(uintptr_t *)(((caddr_t)®s) + m_offset); else memcpy((void *)&m_value, (((caddr_t)®s) + m_offset), m_size); m_result = true; } } //------------------------------------------------------------------------------ /// @class WriteDebugRegOperation /// @brief Implements ProcessMonitor::WriteDebugRegisterValue. class WriteDebugRegOperation : public Operation { public: WriteDebugRegOperation(lldb::tid_t tid, unsigned offset, const RegisterValue &value, bool &result) : m_tid(tid), m_offset(offset), m_value(value), m_result(result) {} void Execute(ProcessMonitor *monitor); private: lldb::tid_t m_tid; unsigned m_offset; const RegisterValue &m_value; bool &m_result; }; void WriteDebugRegOperation::Execute(ProcessMonitor *monitor) { struct dbreg regs; if (PTRACE(PT_GETDBREGS, m_tid, (caddr_t)®s, 0) < 0) { m_result = false; return; } *(uintptr_t *)(((caddr_t)®s) + m_offset) = (uintptr_t)m_value.GetAsUInt64(); if (PTRACE(PT_SETDBREGS, m_tid, (caddr_t)®s, 0) < 0) m_result = false; else m_result = true; } //------------------------------------------------------------------------------ /// @class ReadGPROperation /// @brief Implements ProcessMonitor::ReadGPR. class ReadGPROperation : public Operation { public: ReadGPROperation(lldb::tid_t tid, void *buf, bool &result) : m_tid(tid), m_buf(buf), m_result(result) {} void Execute(ProcessMonitor *monitor); private: lldb::tid_t m_tid; void *m_buf; bool &m_result; }; void ReadGPROperation::Execute(ProcessMonitor *monitor) { int rc; errno = 0; rc = PTRACE(PT_GETREGS, m_tid, (caddr_t)m_buf, 0); if (errno != 0) m_result = false; else m_result = true; } //------------------------------------------------------------------------------ /// @class ReadFPROperation /// @brief Implements ProcessMonitor::ReadFPR. class ReadFPROperation : public Operation { public: ReadFPROperation(lldb::tid_t tid, void *buf, bool &result) : m_tid(tid), m_buf(buf), m_result(result) {} void Execute(ProcessMonitor *monitor); private: lldb::tid_t m_tid; void *m_buf; bool &m_result; }; void ReadFPROperation::Execute(ProcessMonitor *monitor) { if (PTRACE(PT_GETFPREGS, m_tid, (caddr_t)m_buf, 0) < 0) m_result = false; else m_result = true; } //------------------------------------------------------------------------------ /// @class WriteGPROperation /// @brief Implements ProcessMonitor::WriteGPR. class WriteGPROperation : public Operation { public: WriteGPROperation(lldb::tid_t tid, void *buf, bool &result) : m_tid(tid), m_buf(buf), m_result(result) {} void Execute(ProcessMonitor *monitor); private: lldb::tid_t m_tid; void *m_buf; bool &m_result; }; void WriteGPROperation::Execute(ProcessMonitor *monitor) { if (PTRACE(PT_SETREGS, m_tid, (caddr_t)m_buf, 0) < 0) m_result = false; else m_result = true; } //------------------------------------------------------------------------------ /// @class WriteFPROperation /// @brief Implements ProcessMonitor::WriteFPR. class WriteFPROperation : public Operation { public: WriteFPROperation(lldb::tid_t tid, void *buf, bool &result) : m_tid(tid), m_buf(buf), m_result(result) {} void Execute(ProcessMonitor *monitor); private: lldb::tid_t m_tid; void *m_buf; bool &m_result; }; void WriteFPROperation::Execute(ProcessMonitor *monitor) { if (PTRACE(PT_SETFPREGS, m_tid, (caddr_t)m_buf, 0) < 0) m_result = false; else m_result = true; } //------------------------------------------------------------------------------ /// @class ResumeOperation /// @brief Implements ProcessMonitor::Resume. class ResumeOperation : public Operation { public: ResumeOperation(uint32_t signo, bool &result) : m_signo(signo), m_result(result) {} void Execute(ProcessMonitor *monitor); private: uint32_t m_signo; bool &m_result; }; void ResumeOperation::Execute(ProcessMonitor *monitor) { lldb::pid_t pid = monitor->GetPID(); int data = 0; if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) data = m_signo; if (PTRACE(PT_CONTINUE, pid, (caddr_t)1, data)) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); LLDB_LOG(log, "ResumeOperation ({0}) failed: {1}", pid, llvm::sys::StrError(errno)); m_result = false; } else m_result = true; } //------------------------------------------------------------------------------ /// @class SingleStepOperation /// @brief Implements ProcessMonitor::SingleStep. class SingleStepOperation : public Operation { public: SingleStepOperation(uint32_t signo, bool &result) : m_signo(signo), m_result(result) {} void Execute(ProcessMonitor *monitor); private: uint32_t m_signo; bool &m_result; }; void SingleStepOperation::Execute(ProcessMonitor *monitor) { lldb::pid_t pid = monitor->GetPID(); int data = 0; if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) data = m_signo; if (PTRACE(PT_STEP, pid, NULL, data)) m_result = false; else m_result = true; } //------------------------------------------------------------------------------ /// @class LwpInfoOperation /// @brief Implements ProcessMonitor::GetLwpInfo. class LwpInfoOperation : public Operation { public: LwpInfoOperation(lldb::tid_t tid, void *info, bool &result, int &ptrace_err) : m_tid(tid), m_info(info), m_result(result), m_err(ptrace_err) {} void Execute(ProcessMonitor *monitor); private: lldb::tid_t m_tid; void *m_info; bool &m_result; int &m_err; }; void LwpInfoOperation::Execute(ProcessMonitor *monitor) { struct ptrace_lwpinfo plwp; if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) { m_result = false; m_err = errno; } else { memcpy(m_info, &plwp, sizeof(plwp)); m_result = true; } } //------------------------------------------------------------------------------ /// @class ThreadSuspendOperation /// @brief Implements ProcessMonitor::ThreadSuspend. class ThreadSuspendOperation : public Operation { public: ThreadSuspendOperation(lldb::tid_t tid, bool suspend, bool &result) : m_tid(tid), m_suspend(suspend), m_result(result) {} void Execute(ProcessMonitor *monitor); private: lldb::tid_t m_tid; bool m_suspend; bool &m_result; }; void ThreadSuspendOperation::Execute(ProcessMonitor *monitor) { m_result = !PTRACE(m_suspend ? PT_SUSPEND : PT_RESUME, m_tid, NULL, 0); } //------------------------------------------------------------------------------ /// @class EventMessageOperation /// @brief Implements ProcessMonitor::GetEventMessage. class EventMessageOperation : public Operation { public: EventMessageOperation(lldb::tid_t tid, unsigned long *message, bool &result) : m_tid(tid), m_message(message), m_result(result) {} void Execute(ProcessMonitor *monitor); private: lldb::tid_t m_tid; unsigned long *m_message; bool &m_result; }; void EventMessageOperation::Execute(ProcessMonitor *monitor) { struct ptrace_lwpinfo plwp; if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) m_result = false; else { if (plwp.pl_flags & PL_FLAG_FORKED) { *m_message = plwp.pl_child_pid; m_result = true; } else m_result = false; } } //------------------------------------------------------------------------------ /// @class KillOperation /// @brief Implements ProcessMonitor::Kill. class KillOperation : public Operation { public: KillOperation(bool &result) : m_result(result) {} void Execute(ProcessMonitor *monitor); private: bool &m_result; }; void KillOperation::Execute(ProcessMonitor *monitor) { lldb::pid_t pid = monitor->GetPID(); if (PTRACE(PT_KILL, pid, NULL, 0)) m_result = false; else m_result = true; } //------------------------------------------------------------------------------ /// @class DetachOperation /// @brief Implements ProcessMonitor::Detach. class DetachOperation : public Operation { public: DetachOperation(Status &result) : m_error(result) {} void Execute(ProcessMonitor *monitor); private: Status &m_error; }; void DetachOperation::Execute(ProcessMonitor *monitor) { lldb::pid_t pid = monitor->GetPID(); if (PTRACE(PT_DETACH, pid, NULL, 0) < 0) m_error.SetErrorToErrno(); } ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor) : m_monitor(monitor) { sem_init(&m_semaphore, 0, 0); } ProcessMonitor::OperationArgs::~OperationArgs() { sem_destroy(&m_semaphore); } ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor, lldb_private::Module *module, char const **argv, char const **envp, const FileSpec &stdin_file_spec, const FileSpec &stdout_file_spec, const FileSpec &stderr_file_spec, const FileSpec &working_dir) : OperationArgs(monitor), m_module(module), m_argv(argv), m_envp(envp), m_stdin_file_spec(stdin_file_spec), m_stdout_file_spec(stdout_file_spec), m_stderr_file_spec(stderr_file_spec), m_working_dir(working_dir) {} ProcessMonitor::LaunchArgs::~LaunchArgs() {} ProcessMonitor::AttachArgs::AttachArgs(ProcessMonitor *monitor, lldb::pid_t pid) : OperationArgs(monitor), m_pid(pid) {} ProcessMonitor::AttachArgs::~AttachArgs() {} //------------------------------------------------------------------------------ /// The basic design of the ProcessMonitor is built around two threads. /// /// One thread (@see SignalThread) simply blocks on a call to waitpid() looking /// for changes in the debugee state. When a change is detected a /// ProcessMessage is sent to the associated ProcessFreeBSD instance. This /// thread /// "drives" state changes in the debugger. /// /// The second thread (@see OperationThread) is responsible for two things 1) /// launching or attaching to the inferior process, and then 2) servicing /// operations such as register reads/writes, stepping, etc. See the comments /// on the Operation class for more info as to why this is needed. ProcessMonitor::ProcessMonitor( ProcessFreeBSD *process, Module *module, const char *argv[], const char *envp[], const FileSpec &stdin_file_spec, const FileSpec &stdout_file_spec, const FileSpec &stderr_file_spec, const FileSpec &working_dir, const lldb_private::ProcessLaunchInfo & /* launch_info */, lldb_private::Status &error) : m_process(static_cast(process)), m_pid(LLDB_INVALID_PROCESS_ID), m_terminal_fd(-1), m_operation(0) { using namespace std::placeholders; std::unique_ptr args( new LaunchArgs(this, module, argv, envp, stdin_file_spec, stdout_file_spec, stderr_file_spec, working_dir)); sem_init(&m_operation_pending, 0, 0); sem_init(&m_operation_done, 0, 0); StartLaunchOpThread(args.get(), error); if (!error.Success()) return; -WAIT_AGAIN: - // Wait for the operation thread to initialize. - if (sem_wait(&args->m_semaphore)) { - if (errno == EINTR) - goto WAIT_AGAIN; - else { - error.SetErrorToErrno(); - return; - } + if (llvm::sys::RetryAfterSignal(-1, sem_wait, &args->m_semaphore) == -1) { + error.SetErrorToErrno(); + return; } // Check that the launch was a success. if (!args->m_error.Success()) { StopOpThread(); error = args->m_error; return; } // Finally, start monitoring the child process for change in state. m_monitor_thread = Host::StartMonitoringChildProcess( std::bind(&ProcessMonitor::MonitorCallback, this, _1, _2, _3, _4), GetPID(), true); if (!m_monitor_thread.IsJoinable()) { error.SetErrorToGenericError(); error.SetErrorString("Process launch failed."); return; } } ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process, lldb::pid_t pid, lldb_private::Status &error) : m_process(static_cast(process)), m_pid(pid), m_terminal_fd(-1), m_operation(0) { using namespace std::placeholders; sem_init(&m_operation_pending, 0, 0); sem_init(&m_operation_done, 0, 0); std::unique_ptr args(new AttachArgs(this, pid)); StartAttachOpThread(args.get(), error); if (!error.Success()) return; -WAIT_AGAIN: - // Wait for the operation thread to initialize. - if (sem_wait(&args->m_semaphore)) { - if (errno == EINTR) - goto WAIT_AGAIN; - else { - error.SetErrorToErrno(); - return; - } + if (llvm::sys::RetryAfterSignal(-1, sem_wait, &args->m_semaphore) == -1) { + error.SetErrorToErrno(); + return; } // Check that the attach was a success. if (!args->m_error.Success()) { StopOpThread(); error = args->m_error; return; } // Finally, start monitoring the child process for change in state. m_monitor_thread = Host::StartMonitoringChildProcess( std::bind(&ProcessMonitor::MonitorCallback, this, _1, _2, _3, _4), GetPID(), true); if (!m_monitor_thread.IsJoinable()) { error.SetErrorToGenericError(); error.SetErrorString("Process attach failed."); return; } } ProcessMonitor::~ProcessMonitor() { StopMonitor(); } //------------------------------------------------------------------------------ // Thread setup and tear down. void ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Status &error) { static const char *g_thread_name = "lldb.process.freebsd.operation"; if (m_operation_thread.IsJoinable()) return; m_operation_thread = ThreadLauncher::LaunchThread(g_thread_name, LaunchOpThread, args, &error); } void *ProcessMonitor::LaunchOpThread(void *arg) { LaunchArgs *args = static_cast(arg); if (!Launch(args)) { sem_post(&args->m_semaphore); return NULL; } ServeOperation(args); return NULL; } bool ProcessMonitor::Launch(LaunchArgs *args) { ProcessMonitor *monitor = args->m_monitor; ProcessFreeBSD &process = monitor->GetProcess(); const char **argv = args->m_argv; const char **envp = args->m_envp; const FileSpec &stdin_file_spec = args->m_stdin_file_spec; const FileSpec &stdout_file_spec = args->m_stdout_file_spec; const FileSpec &stderr_file_spec = args->m_stderr_file_spec; const FileSpec &working_dir = args->m_working_dir; lldb_utility::PseudoTerminal terminal; const size_t err_len = 1024; char err_str[err_len]; ::pid_t pid; // Propagate the environment if one is not supplied. if (envp == NULL || envp[0] == NULL) envp = const_cast(environ); if ((pid = terminal.Fork(err_str, err_len)) == -1) { args->m_error.SetErrorToGenericError(); args->m_error.SetErrorString("Process fork failed."); goto FINISH; } // Recognized child exit status codes. enum { ePtraceFailed = 1, eDupStdinFailed, eDupStdoutFailed, eDupStderrFailed, eChdirFailed, eExecFailed, eSetGidFailed }; // Child process. if (pid == 0) { // Trace this process. if (PTRACE(PT_TRACE_ME, 0, NULL, 0) < 0) exit(ePtraceFailed); // terminal has already dupped the tty descriptors to stdin/out/err. // This closes original fd from which they were copied (and avoids // leaking descriptors to the debugged process. terminal.CloseSlaveFileDescriptor(); // Do not inherit setgid powers. if (setgid(getgid()) != 0) exit(eSetGidFailed); // Let us have our own process group. setpgid(0, 0); // Dup file descriptors if needed. // // FIXME: If two or more of the paths are the same we needlessly open // the same file multiple times. if (stdin_file_spec) if (!DupDescriptor(stdin_file_spec, STDIN_FILENO, O_RDONLY)) exit(eDupStdinFailed); if (stdout_file_spec) if (!DupDescriptor(stdout_file_spec, STDOUT_FILENO, O_WRONLY | O_CREAT)) exit(eDupStdoutFailed); if (stderr_file_spec) if (!DupDescriptor(stderr_file_spec, STDERR_FILENO, O_WRONLY | O_CREAT)) exit(eDupStderrFailed); // Change working directory if (working_dir && 0 != ::chdir(working_dir.GetCString())) exit(eChdirFailed); // Execute. We should never return. execve(argv[0], const_cast(argv), const_cast(envp)); exit(eExecFailed); } // Wait for the child process to to trap on its call to execve. ::pid_t wpid; int status; if ((wpid = waitpid(pid, &status, 0)) < 0) { args->m_error.SetErrorToErrno(); goto FINISH; } else if (WIFEXITED(status)) { // open, dup or execve likely failed for some reason. args->m_error.SetErrorToGenericError(); switch (WEXITSTATUS(status)) { case ePtraceFailed: args->m_error.SetErrorString("Child ptrace failed."); break; case eDupStdinFailed: args->m_error.SetErrorString("Child open stdin failed."); break; case eDupStdoutFailed: args->m_error.SetErrorString("Child open stdout failed."); break; case eDupStderrFailed: args->m_error.SetErrorString("Child open stderr failed."); break; case eChdirFailed: args->m_error.SetErrorString("Child failed to set working directory."); break; case eExecFailed: args->m_error.SetErrorString("Child exec failed."); break; case eSetGidFailed: args->m_error.SetErrorString("Child setgid failed."); break; default: args->m_error.SetErrorString("Child returned unknown exit status."); break; } goto FINISH; } assert(WIFSTOPPED(status) && wpid == (::pid_t)pid && "Could not sync with inferior process."); #ifdef notyet // Have the child raise an event on exit. This is used to keep the child in // limbo until it is destroyed. if (PTRACE(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACEEXIT) < 0) { args->m_error.SetErrorToErrno(); goto FINISH; } #endif // Release the master terminal descriptor and pass it off to the // ProcessMonitor instance. Similarly stash the inferior pid. monitor->m_terminal_fd = terminal.ReleaseMasterFileDescriptor(); monitor->m_pid = pid; // Set the terminal fd to be in non blocking mode (it simplifies the // implementation of ProcessFreeBSD::GetSTDOUT to have a non-blocking // descriptor to read from). if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error)) goto FINISH; process.SendMessage(ProcessMessage::Attach(pid)); FINISH: return args->m_error.Success(); } void ProcessMonitor::StartAttachOpThread(AttachArgs *args, lldb_private::Status &error) { static const char *g_thread_name = "lldb.process.freebsd.operation"; if (m_operation_thread.IsJoinable()) return; m_operation_thread = ThreadLauncher::LaunchThread(g_thread_name, AttachOpThread, args, &error); } void *ProcessMonitor::AttachOpThread(void *arg) { AttachArgs *args = static_cast(arg); Attach(args); ServeOperation(args); return NULL; } void ProcessMonitor::Attach(AttachArgs *args) { lldb::pid_t pid = args->m_pid; ProcessMonitor *monitor = args->m_monitor; ProcessFreeBSD &process = monitor->GetProcess(); if (pid <= 1) { args->m_error.SetErrorToGenericError(); args->m_error.SetErrorString("Attaching to process 1 is not allowed."); return; } // Attach to the requested process. if (PTRACE(PT_ATTACH, pid, NULL, 0) < 0) { args->m_error.SetErrorToErrno(); return; } int status; if ((status = waitpid(pid, NULL, 0)) < 0) { args->m_error.SetErrorToErrno(); return; } process.SendMessage(ProcessMessage::Attach(pid)); } size_t ProcessMonitor::GetCurrentThreadIDs(std::vector &thread_ids) { lwpid_t *tids; int tdcnt; thread_ids.clear(); tdcnt = PTRACE(PT_GETNUMLWPS, m_pid, NULL, 0); if (tdcnt <= 0) return 0; tids = (lwpid_t *)malloc(tdcnt * sizeof(*tids)); if (tids == NULL) return 0; if (PTRACE(PT_GETLWPLIST, m_pid, (void *)tids, tdcnt) < 0) { free(tids); return 0; } thread_ids = std::vector(tids, tids + tdcnt); free(tids); return thread_ids.size(); } bool ProcessMonitor::MonitorCallback(ProcessMonitor *monitor, lldb::pid_t pid, bool exited, int signal, int status) { ProcessMessage message; ProcessFreeBSD *process = monitor->m_process; assert(process); bool stop_monitoring; struct ptrace_lwpinfo plwp; int ptrace_err; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); if (exited) { if (log) log->Printf("ProcessMonitor::%s() got exit signal, tid = %" PRIu64, __FUNCTION__, pid); message = ProcessMessage::Exit(pid, status); process->SendMessage(message); return pid == process->GetID(); } if (!monitor->GetLwpInfo(pid, &plwp, ptrace_err)) stop_monitoring = true; // pid is gone. Bail. else { switch (plwp.pl_siginfo.si_signo) { case SIGTRAP: message = MonitorSIGTRAP(monitor, &plwp.pl_siginfo, plwp.pl_lwpid); break; default: message = MonitorSignal(monitor, &plwp.pl_siginfo, plwp.pl_lwpid); break; } process->SendMessage(message); stop_monitoring = message.GetKind() == ProcessMessage::eExitMessage; } return stop_monitoring; } ProcessMessage ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor, const siginfo_t *info, lldb::tid_t tid) { ProcessMessage message; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); assert(monitor); assert(info && info->si_signo == SIGTRAP && "Unexpected child signal!"); switch (info->si_code) { default: assert(false && "Unexpected SIGTRAP code!"); break; case (SIGTRAP /* | (PTRACE_EVENT_EXIT << 8) */): { // The inferior process is about to exit. Maintain the process in a // state of "limbo" until we are explicitly commanded to detach, // destroy, resume, etc. unsigned long data = 0; if (!monitor->GetEventMessage(tid, &data)) data = -1; if (log) log->Printf("ProcessMonitor::%s() received exit? event, data = %lx, tid " "= %" PRIu64, __FUNCTION__, data, tid); message = ProcessMessage::Limbo(tid, (data >> 8)); break; } case 0: case TRAP_TRACE: #ifdef TRAP_CAP // Map TRAP_CAP to a trace trap in the absense of a more specific handler. case TRAP_CAP: #endif if (log) log->Printf("ProcessMonitor::%s() received trace event, tid = %" PRIu64 " : si_code = %d", __FUNCTION__, tid, info->si_code); message = ProcessMessage::Trace(tid); break; case SI_KERNEL: case TRAP_BRKPT: if (monitor->m_process->IsSoftwareStepBreakpoint(tid)) { if (log) log->Printf("ProcessMonitor::%s() received sw single step breakpoint " "event, tid = %" PRIu64, __FUNCTION__, tid); message = ProcessMessage::Trace(tid); } else { if (log) log->Printf( "ProcessMonitor::%s() received breakpoint event, tid = %" PRIu64, __FUNCTION__, tid); message = ProcessMessage::Break(tid); } break; } return message; } ProcessMessage ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, const siginfo_t *info, lldb::tid_t tid) { ProcessMessage message; int signo = info->si_signo; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); // POSIX says that process behaviour is undefined after it ignores a SIGFPE, // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a // kill(2) or raise(3). Similarly for tgkill(2) on FreeBSD. // // IOW, user generated signals never generate what we consider to be a // "crash". // // Similarly, ACK signals generated by this monitor. if (info->si_code == SI_USER) { if (log) log->Printf( "ProcessMonitor::%s() received signal %s with code %s, pid = %d", __FUNCTION__, monitor->m_process->GetUnixSignals()->GetSignalAsCString(signo), "SI_USER", info->si_pid); if (info->si_pid == getpid()) return ProcessMessage::SignalDelivered(tid, signo); else return ProcessMessage::Signal(tid, signo); } if (log) log->Printf( "ProcessMonitor::%s() received signal %s", __FUNCTION__, monitor->m_process->GetUnixSignals()->GetSignalAsCString(signo)); switch (signo) { case SIGSEGV: case SIGILL: case SIGFPE: case SIGBUS: lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); const auto reason = GetCrashReason(*info); return ProcessMessage::Crash(tid, reason, signo, fault_addr); } // Everything else is "normal" and does not require any special action on // our part. return ProcessMessage::Signal(tid, signo); } void ProcessMonitor::ServeOperation(OperationArgs *args) { ProcessMonitor *monitor = args->m_monitor; // We are finised with the arguments and are ready to go. Sync with the // parent thread and start serving operations on the inferior. sem_post(&args->m_semaphore); for (;;) { // wait for next pending operation sem_wait(&monitor->m_operation_pending); monitor->m_operation->Execute(monitor); // notify calling thread that operation is complete sem_post(&monitor->m_operation_done); } } void ProcessMonitor::DoOperation(Operation *op) { std::lock_guard guard(m_operation_mutex); m_operation = op; // notify operation thread that an operation is ready to be processed sem_post(&m_operation_pending); // wait for operation to complete sem_wait(&m_operation_done); } size_t ProcessMonitor::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, Status &error) { size_t result; ReadOperation op(vm_addr, buf, size, error, result); DoOperation(&op); return result; } size_t ProcessMonitor::WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, lldb_private::Status &error) { size_t result; WriteOperation op(vm_addr, buf, size, error, result); DoOperation(&op); return result; } bool ProcessMonitor::ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name, unsigned size, RegisterValue &value) { bool result; ReadRegOperation op(tid, offset, size, value, result); DoOperation(&op); return result; } bool ProcessMonitor::WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name, const RegisterValue &value) { bool result; WriteRegOperation op(tid, offset, value, result); DoOperation(&op); return result; } bool ProcessMonitor::ReadDebugRegisterValue( lldb::tid_t tid, unsigned offset, const char *reg_name, unsigned size, lldb_private::RegisterValue &value) { bool result; ReadDebugRegOperation op(tid, offset, size, value, result); DoOperation(&op); return result; } bool ProcessMonitor::WriteDebugRegisterValue( lldb::tid_t tid, unsigned offset, const char *reg_name, const lldb_private::RegisterValue &value) { bool result; WriteDebugRegOperation op(tid, offset, value, result); DoOperation(&op); return result; } bool ProcessMonitor::ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size) { bool result; ReadGPROperation op(tid, buf, result); DoOperation(&op); return result; } bool ProcessMonitor::ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size) { bool result; ReadFPROperation op(tid, buf, result); DoOperation(&op); return result; } bool ProcessMonitor::ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) { return false; } bool ProcessMonitor::WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size) { bool result; WriteGPROperation op(tid, buf, result); DoOperation(&op); return result; } bool ProcessMonitor::WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size) { bool result; WriteFPROperation op(tid, buf, result); DoOperation(&op); return result; } bool ProcessMonitor::WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) { return false; } bool ProcessMonitor::ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value) { return false; } bool ProcessMonitor::Resume(lldb::tid_t unused, uint32_t signo) { bool result; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); if (log) { const char *signame = m_process->GetUnixSignals()->GetSignalAsCString(signo); if (signame == nullptr) signame = ""; log->Printf("ProcessMonitor::%s() resuming pid %" PRIu64 " with signal %s", __FUNCTION__, GetPID(), signame); } ResumeOperation op(signo, result); DoOperation(&op); if (log) log->Printf("ProcessMonitor::%s() resuming result = %s", __FUNCTION__, result ? "true" : "false"); return result; } bool ProcessMonitor::SingleStep(lldb::tid_t unused, uint32_t signo) { bool result; SingleStepOperation op(signo, result); DoOperation(&op); return result; } bool ProcessMonitor::Kill() { bool result; KillOperation op(result); DoOperation(&op); return result; } bool ProcessMonitor::GetLwpInfo(lldb::tid_t tid, void *lwpinfo, int &ptrace_err) { bool result; LwpInfoOperation op(tid, lwpinfo, result, ptrace_err); DoOperation(&op); return result; } bool ProcessMonitor::ThreadSuspend(lldb::tid_t tid, bool suspend) { bool result; ThreadSuspendOperation op(tid, suspend, result); DoOperation(&op); return result; } bool ProcessMonitor::GetEventMessage(lldb::tid_t tid, unsigned long *message) { bool result; EventMessageOperation op(tid, message, result); DoOperation(&op); return result; } lldb_private::Status ProcessMonitor::Detach(lldb::tid_t tid) { lldb_private::Status error; if (tid != LLDB_INVALID_THREAD_ID) { DetachOperation op(error); DoOperation(&op); } return error; } bool ProcessMonitor::DupDescriptor(const FileSpec &file_spec, int fd, int flags) { int target_fd = open(file_spec.GetCString(), flags, 0666); if (target_fd == -1) return false; if (dup2(target_fd, fd) == -1) return false; return (close(target_fd) == -1) ? false : true; } void ProcessMonitor::StopMonitoringChildProcess() { if (m_monitor_thread.IsJoinable()) { m_monitor_thread.Cancel(); m_monitor_thread.Join(nullptr); m_monitor_thread.Reset(); } } void ProcessMonitor::StopMonitor() { StopMonitoringChildProcess(); StopOpThread(); sem_destroy(&m_operation_pending); sem_destroy(&m_operation_done); if (m_terminal_fd >= 0) { close(m_terminal_fd); m_terminal_fd = -1; } } // FIXME: On Linux, when a new thread is created, we receive to notifications, // (1) a SIGTRAP|PTRACE_EVENT_CLONE from the main process thread with the // child thread id as additional information, and (2) a SIGSTOP|SI_USER from // the new child thread indicating that it has is stopped because we attached. // We have no guarantee of the order in which these arrive, but we need both // before we are ready to proceed. We currently keep a list of threads which // have sent the initial SIGSTOP|SI_USER event. Then when we receive the // SIGTRAP|PTRACE_EVENT_CLONE notification, if the initial stop has not occurred // we call ProcessMonitor::WaitForInitialTIDStop() to wait for it. // // Right now, the above logic is in ProcessPOSIX, so we need a definition of // this function in the FreeBSD ProcessMonitor implementation even if it isn't // logically needed. // // We really should figure out what actually happens on FreeBSD and move the // Linux-specific logic out of ProcessPOSIX as needed. bool ProcessMonitor::WaitForInitialTIDStop(lldb::tid_t tid) { return true; } void ProcessMonitor::StopOpThread() { if (!m_operation_thread.IsJoinable()) return; m_operation_thread.Cancel(); m_operation_thread.Join(nullptr); m_operation_thread.Reset(); } Index: vendor/lldb/dist/source/Plugins/Process/Linux/NativeProcessLinux.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/Process/Linux/NativeProcessLinux.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/Process/Linux/NativeProcessLinux.cpp (revision 320967) @@ -1,2685 +1,2580 @@ //===-- NativeProcessLinux.cpp -------------------------------- -*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "NativeProcessLinux.h" // C Includes #include #include #include #include // C++ Includes #include #include #include #include #include // Other libraries and framework includes #include "lldb/Core/EmulateInstruction.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/State.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostProcess.h" #include "lldb/Host/PseudoTerminal.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/common/NativeBreakpoint.h" #include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Host/linux/Ptrace.h" #include "lldb/Host/linux/Uio.h" #include "lldb/Host/posix/ProcessLauncherPosixFork.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Process.h" #include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Target/Target.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StringExtractor.h" #include "llvm/Support/Errno.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Threading.h" #include "NativeThreadLinux.h" #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #include "Procfs.h" #include #include #include #include #include #include // Support hardware breakpoints in case it has not been defined #ifndef TRAP_HWBKPT #define TRAP_HWBKPT 4 #endif using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_linux; using namespace llvm; // Private bits we only need internally. static bool ProcessVmReadvSupported() { static bool is_supported; static llvm::once_flag flag; llvm::call_once(flag, [] { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); uint32_t source = 0x47424742; uint32_t dest = 0; struct iovec local, remote; remote.iov_base = &source; local.iov_base = &dest; remote.iov_len = local.iov_len = sizeof source; // We shall try if cross-process-memory reads work by attempting to read a // value from our own process. ssize_t res = process_vm_readv(getpid(), &local, 1, &remote, 1, 0); is_supported = (res == sizeof(source) && source == dest); if (is_supported) LLDB_LOG(log, "Detected kernel support for process_vm_readv syscall. " "Fast memory reads enabled."); else LLDB_LOG(log, "syscall process_vm_readv failed (error: {0}). Fast memory " "reads disabled.", llvm::sys::StrError()); }); return is_supported; } namespace { void MaybeLogLaunchInfo(const ProcessLaunchInfo &info) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); if (!log) return; if (const FileAction *action = info.GetFileActionForFD(STDIN_FILENO)) LLDB_LOG(log, "setting STDIN to '{0}'", action->GetFileSpec()); else LLDB_LOG(log, "leaving STDIN as is"); if (const FileAction *action = info.GetFileActionForFD(STDOUT_FILENO)) LLDB_LOG(log, "setting STDOUT to '{0}'", action->GetFileSpec()); else LLDB_LOG(log, "leaving STDOUT as is"); if (const FileAction *action = info.GetFileActionForFD(STDERR_FILENO)) LLDB_LOG(log, "setting STDERR to '{0}'", action->GetFileSpec()); else LLDB_LOG(log, "leaving STDERR as is"); int i = 0; for (const char **args = info.GetArguments().GetConstArgumentVector(); *args; ++args, ++i) LLDB_LOG(log, "arg {0}: '{1}'", i, *args); } void DisplayBytes(StreamString &s, void *bytes, uint32_t count) { uint8_t *ptr = (uint8_t *)bytes; const uint32_t loop_count = std::min(DEBUG_PTRACE_MAXBYTES, count); for (uint32_t i = 0; i < loop_count; i++) { s.Printf("[%x]", *ptr); ptr++; } } void PtraceDisplayBytes(int &req, void *data, size_t data_size) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); if (!log) return; StreamString buf; switch (req) { case PTRACE_POKETEXT: { DisplayBytes(buf, &data, 8); LLDB_LOGV(log, "PTRACE_POKETEXT {0}", buf.GetData()); break; } case PTRACE_POKEDATA: { DisplayBytes(buf, &data, 8); LLDB_LOGV(log, "PTRACE_POKEDATA {0}", buf.GetData()); break; } case PTRACE_POKEUSER: { DisplayBytes(buf, &data, 8); LLDB_LOGV(log, "PTRACE_POKEUSER {0}", buf.GetData()); break; } case PTRACE_SETREGS: { DisplayBytes(buf, data, data_size); LLDB_LOGV(log, "PTRACE_SETREGS {0}", buf.GetData()); break; } case PTRACE_SETFPREGS: { DisplayBytes(buf, data, data_size); LLDB_LOGV(log, "PTRACE_SETFPREGS {0}", buf.GetData()); break; } case PTRACE_SETSIGINFO: { DisplayBytes(buf, data, sizeof(siginfo_t)); LLDB_LOGV(log, "PTRACE_SETSIGINFO {0}", buf.GetData()); break; } case PTRACE_SETREGSET: { // Extract iov_base from data, which is a pointer to the struct IOVEC DisplayBytes(buf, *(void **)data, data_size); LLDB_LOGV(log, "PTRACE_SETREGSET {0}", buf.GetData()); break; } default: {} } } static constexpr unsigned k_ptrace_word_size = sizeof(void *); static_assert(sizeof(long) >= k_ptrace_word_size, "Size of long must be larger than ptrace word size"); } // end of anonymous namespace // Simple helper function to ensure flags are enabled on the given file // descriptor. static Status EnsureFDFlags(int fd, int flags) { Status error; int status = fcntl(fd, F_GETFL); if (status == -1) { error.SetErrorToErrno(); return error; } if (fcntl(fd, F_SETFL, status | flags) == -1) { error.SetErrorToErrno(); return error; } return error; } // ----------------------------------------------------------------------------- // Public Static Methods // ----------------------------------------------------------------------------- -Status NativeProcessProtocol::Launch( - ProcessLaunchInfo &launch_info, - NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop, - NativeProcessProtocolSP &native_process_sp) { +llvm::Expected +NativeProcessLinux::Factory::Launch(ProcessLaunchInfo &launch_info, + NativeDelegate &native_delegate, + MainLoop &mainloop) const { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - Status error; + MaybeLogLaunchInfo(launch_info); - // Verify the working directory is valid if one was specified. - FileSpec working_dir{launch_info.GetWorkingDirectory()}; - if (working_dir && (!working_dir.ResolvePath() || - !llvm::sys::fs::is_directory(working_dir.GetPath()))) { - error.SetErrorStringWithFormat("No such file or directory: %s", - working_dir.GetCString()); - return error; + Status status; + ::pid_t pid = ProcessLauncherPosixFork() + .LaunchProcess(launch_info, status) + .GetProcessId(); + LLDB_LOG(log, "pid = {0:x}", pid); + if (status.Fail()) { + LLDB_LOG(log, "failed to launch process: {0}", status); + return status.ToError(); } - // Create the NativeProcessLinux in launch mode. - native_process_sp.reset(new NativeProcessLinux()); - - if (!native_process_sp->RegisterNativeDelegate(native_delegate)) { - native_process_sp.reset(); - error.SetErrorStringWithFormat("failed to register the native delegate"); - return error; + // Wait for the child process to trap on its call to execve. + int wstatus; + ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0); + assert(wpid == pid); + (void)wpid; + if (!WIFSTOPPED(wstatus)) { + LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}", + WaitStatus::Decode(wstatus)); + return llvm::make_error("Could not sync with inferior process", + llvm::inconvertibleErrorCode()); } + LLDB_LOG(log, "inferior started, now in stopped state"); - error = std::static_pointer_cast(native_process_sp) - ->LaunchInferior(mainloop, launch_info); + ArchSpec arch; + if ((status = ResolveProcessArchitecture(pid, arch)).Fail()) + return status.ToError(); - if (error.Fail()) { - native_process_sp.reset(); - LLDB_LOG(log, "failed to launch process: {0}", error); - return error; + // Set the architecture to the exe architecture. + LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid, + arch.GetArchitectureName()); + + status = SetDefaultPtraceOpts(pid); + if (status.Fail()) { + LLDB_LOG(log, "failed to set default ptrace options: {0}", status); + return status.ToError(); } - launch_info.SetProcessID(native_process_sp->GetID()); - - return error; + std::shared_ptr process_sp(new NativeProcessLinux( + pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate, + arch, mainloop)); + process_sp->InitializeThreads({pid}); + return process_sp; } -Status NativeProcessProtocol::Attach( +llvm::Expected NativeProcessLinux::Factory::Attach( lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) { + MainLoop &mainloop) const { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); LLDB_LOG(log, "pid = {0:x}", pid); // Retrieve the architecture for the running process. - ArchSpec process_arch; - Status error = ResolveProcessArchitecture(pid, process_arch); - if (!error.Success()) - return error; + ArchSpec arch; + Status status = ResolveProcessArchitecture(pid, arch); + if (!status.Success()) + return status.ToError(); - std::shared_ptr native_process_linux_sp( - new NativeProcessLinux()); + auto tids_or = NativeProcessLinux::Attach(pid); + if (!tids_or) + return tids_or.takeError(); - if (!native_process_linux_sp->RegisterNativeDelegate(native_delegate)) { - error.SetErrorStringWithFormat("failed to register the native delegate"); - return error; - } - - native_process_linux_sp->AttachToInferior(mainloop, pid, error); - if (!error.Success()) - return error; - - native_process_sp = native_process_linux_sp; - return error; + std::shared_ptr process_sp( + new NativeProcessLinux(pid, -1, native_delegate, arch, mainloop)); + process_sp->InitializeThreads(*tids_or); + return process_sp; } // ----------------------------------------------------------------------------- // Public Instance Methods // ----------------------------------------------------------------------------- -NativeProcessLinux::NativeProcessLinux() - : NativeProcessProtocol(LLDB_INVALID_PROCESS_ID), m_arch(), - m_supports_mem_region(eLazyBoolCalculate), m_mem_region_cache(), - m_pending_notification_tid(LLDB_INVALID_THREAD_ID), - m_pt_proces_trace_id(LLDB_INVALID_UID) {} +NativeProcessLinux::NativeProcessLinux(::pid_t pid, int terminal_fd, + NativeDelegate &delegate, + const ArchSpec &arch, MainLoop &mainloop) + : NativeProcessProtocol(pid, terminal_fd, delegate), m_arch(arch) { + if (m_terminal_fd != -1) { + Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); + assert(status.Success()); + } -void NativeProcessLinux::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, - Status &error) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - LLDB_LOG(log, "pid = {0:x}", pid); - + Status status; m_sigchld_handle = mainloop.RegisterSignal( - SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); - if (!m_sigchld_handle) - return; - - error = ResolveProcessArchitecture(pid, m_arch); - if (!error.Success()) - return; - - // Set the architecture to the exe architecture. - LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid, - m_arch.GetArchitectureName()); - m_pid = pid; - SetState(eStateAttaching); - - Attach(pid, error); + SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status); + assert(m_sigchld_handle && status.Success()); } -Status NativeProcessLinux::LaunchInferior(MainLoop &mainloop, - ProcessLaunchInfo &launch_info) { - Status error; - m_sigchld_handle = mainloop.RegisterSignal( - SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); - if (!m_sigchld_handle) - return error; - - SetState(eStateLaunching); - - MaybeLogLaunchInfo(launch_info); - - ::pid_t pid = - ProcessLauncherPosixFork().LaunchProcess(launch_info, error).GetProcessId(); - if (error.Fail()) - return error; - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - - // Wait for the child process to trap on its call to execve. - ::pid_t wpid; - int status; - if ((wpid = waitpid(pid, &status, 0)) < 0) { - error.SetErrorToErrno(); - LLDB_LOG(log, "waitpid for inferior failed with %s", error); - - // Mark the inferior as invalid. - // FIXME this could really use a new state - eStateLaunchFailure. For now, - // using eStateInvalid. - SetState(StateType::eStateInvalid); - - return error; +void NativeProcessLinux::InitializeThreads(llvm::ArrayRef<::pid_t> tids) { + for (const auto &tid : tids) { + NativeThreadLinuxSP thread_sp = AddThread(tid); + assert(thread_sp && "AddThread() returned a nullptr thread"); + thread_sp->SetStoppedBySignal(SIGSTOP); + ThreadWasCreated(*thread_sp); } - assert(WIFSTOPPED(status) && (wpid == static_cast<::pid_t>(pid)) && - "Could not sync with inferior process."); - LLDB_LOG(log, "inferior started, now in stopped state"); - error = SetDefaultPtraceOpts(pid); - if (error.Fail()) { - LLDB_LOG(log, "failed to set default ptrace options: {0}", error); - - // Mark the inferior as invalid. - // FIXME this could really use a new state - eStateLaunchFailure. For now, - // using eStateInvalid. - SetState(StateType::eStateInvalid); - - return error; - } - - // Release the master terminal descriptor and pass it off to the - // NativeProcessLinux instance. Similarly stash the inferior pid. - m_terminal_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); - m_pid = pid; - launch_info.SetProcessID(pid); - - if (m_terminal_fd != -1) { - error = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); - if (error.Fail()) { - LLDB_LOG(log, - "inferior EnsureFDFlags failed for ensuring terminal " - "O_NONBLOCK setting: {0}", - error); - - // Mark the inferior as invalid. - // FIXME this could really use a new state - eStateLaunchFailure. For - // now, using eStateInvalid. - SetState(StateType::eStateInvalid); - - return error; - } - } - - LLDB_LOG(log, "adding pid = {0}", pid); - ResolveProcessArchitecture(m_pid, m_arch); - NativeThreadLinuxSP thread_sp = AddThread(pid); - assert(thread_sp && "AddThread() returned a nullptr thread"); - thread_sp->SetStoppedBySignal(SIGSTOP); - ThreadWasCreated(*thread_sp); - // Let our process instance know the thread has stopped. - SetCurrentThreadID(thread_sp->GetID()); - SetState(StateType::eStateStopped); + SetCurrentThreadID(tids[0]); + SetState(StateType::eStateStopped, false); - if (error.Fail()) - LLDB_LOG(log, "inferior launching failed {0}", error); - return error; + // Proccess any signals we received before installing our handler + SigchldHandler(); } -::pid_t NativeProcessLinux::Attach(lldb::pid_t pid, Status &error) { +llvm::Expected> NativeProcessLinux::Attach(::pid_t pid) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + Status status; // Use a map to keep track of the threads which we have attached/need to // attach. Host::TidMap tids_to_attach; - if (pid <= 1) { - error.SetErrorToGenericError(); - error.SetErrorString("Attaching to process 1 is not allowed."); - return -1; - } - while (Host::FindProcessThreads(pid, tids_to_attach)) { for (Host::TidMap::iterator it = tids_to_attach.begin(); it != tids_to_attach.end();) { if (it->second == false) { lldb::tid_t tid = it->first; // Attach to the requested process. // An attach will cause the thread to stop with a SIGSTOP. - error = PtraceWrapper(PTRACE_ATTACH, tid); - if (error.Fail()) { + if ((status = PtraceWrapper(PTRACE_ATTACH, tid)).Fail()) { // No such thread. The thread may have exited. // More error handling may be needed. - if (error.GetError() == ESRCH) { + if (status.GetError() == ESRCH) { it = tids_to_attach.erase(it); continue; - } else - return -1; + } + return status.ToError(); } - int status; + int wpid = + llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, nullptr, __WALL); // Need to use __WALL otherwise we receive an error with errno=ECHLD // At this point we should have a thread stopped if waitpid succeeds. - if ((status = waitpid(tid, NULL, __WALL)) < 0) { + if (wpid < 0) { // No such thread. The thread may have exited. // More error handling may be needed. if (errno == ESRCH) { it = tids_to_attach.erase(it); continue; - } else { - error.SetErrorToErrno(); - return -1; } + return llvm::errorCodeToError( + std::error_code(errno, std::generic_category())); } - error = SetDefaultPtraceOpts(tid); - if (error.Fail()) - return -1; + if ((status = SetDefaultPtraceOpts(tid)).Fail()) + return status.ToError(); LLDB_LOG(log, "adding tid = {0}", tid); it->second = true; - - // Create the thread, mark it as stopped. - NativeThreadLinuxSP thread_sp(AddThread(static_cast(tid))); - assert(thread_sp && "AddThread() returned a nullptr"); - - // This will notify this is a new thread and tell the system it is - // stopped. - thread_sp->SetStoppedBySignal(SIGSTOP); - ThreadWasCreated(*thread_sp); - SetCurrentThreadID(thread_sp->GetID()); } // move the loop forward ++it; } } - if (tids_to_attach.size() > 0) { - m_pid = pid; - // Let our process instance know the thread has stopped. - SetState(StateType::eStateStopped); - } else { - error.SetErrorToGenericError(); - error.SetErrorString("No such process."); - return -1; - } + size_t tid_count = tids_to_attach.size(); + if (tid_count == 0) + return llvm::make_error("No such process", + llvm::inconvertibleErrorCode()); - return pid; + std::vector<::pid_t> tids; + tids.reserve(tid_count); + for (const auto &p : tids_to_attach) + tids.push_back(p.first); + return std::move(tids); } Status NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid) { long ptrace_opts = 0; // Have the child raise an event on exit. This is used to keep the child in // limbo until it is destroyed. ptrace_opts |= PTRACE_O_TRACEEXIT; // Have the tracer trace threads which spawn in the inferior process. // TODO: if we want to support tracing the inferiors' child, add the // appropriate ptrace flags here (PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK) ptrace_opts |= PTRACE_O_TRACECLONE; // Have the tracer notify us before execve returns // (needed to disable legacy SIGTRAP generation) ptrace_opts |= PTRACE_O_TRACEEXEC; return PtraceWrapper(PTRACE_SETOPTIONS, pid, nullptr, (void *)ptrace_opts); } // Handles all waitpid events from the inferior process. void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited, WaitStatus status) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); // Certain activities differ based on whether the pid is the tid of the main // thread. const bool is_main_thread = (pid == GetID()); // Handle when the thread exits. if (exited) { LLDB_LOG(log, "got exit signal({0}) , tid = {1} ({2} main thread)", signal, pid, is_main_thread ? "is" : "is not"); // This is a thread that exited. Ensure we're not tracking it anymore. const bool thread_found = StopTrackingThread(pid); if (is_main_thread) { // We only set the exit status and notify the delegate if we haven't // already set the process // state to an exited state. We normally should have received a SIGTRAP | // (PTRACE_EVENT_EXIT << 8) // for the main thread. const bool already_notified = (GetState() == StateType::eStateExited) || (GetState() == StateType::eStateCrashed); if (!already_notified) { LLDB_LOG( log, "tid = {0} handling main thread exit ({1}), expected exit state " "already set but state was {2} instead, setting exit state now", pid, thread_found ? "stopped tracking thread metadata" : "thread metadata not found", GetState()); // The main thread exited. We're done monitoring. Report to delegate. SetExitStatus(status, true); // Notify delegate that our process has exited. SetState(StateType::eStateExited, true); } else LLDB_LOG(log, "tid = {0} main thread now exited (%s)", pid, thread_found ? "stopped tracking thread metadata" : "thread metadata not found"); } else { // Do we want to report to the delegate in this case? I think not. If // this was an orderly thread exit, we would already have received the // SIGTRAP | (PTRACE_EVENT_EXIT << 8) signal, and we would have done an // all-stop then. LLDB_LOG(log, "tid = {0} handling non-main thread exit (%s)", pid, thread_found ? "stopped tracking thread metadata" : "thread metadata not found"); } return; } siginfo_t info; const auto info_err = GetSignalInfo(pid, &info); auto thread_sp = GetThreadByID(pid); if (!thread_sp) { // Normally, the only situation when we cannot find the thread is if we have // just received a new thread notification. This is indicated by // GetSignalInfo() returning si_code == SI_USER and si_pid == 0 LLDB_LOG(log, "received notification about an unknown tid {0}.", pid); if (info_err.Fail()) { LLDB_LOG(log, "(tid {0}) GetSignalInfo failed ({1}). " "Ingoring this notification.", pid, info_err); return; } LLDB_LOG(log, "tid {0}, si_code: {1}, si_pid: {2}", pid, info.si_code, info.si_pid); auto thread_sp = AddThread(pid); // Resume the newly created thread. ResumeThread(*thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); ThreadWasCreated(*thread_sp); return; } // Get details on the signal raised. if (info_err.Success()) { // We have retrieved the signal info. Dispatch appropriately. if (info.si_signo == SIGTRAP) MonitorSIGTRAP(info, *thread_sp); else MonitorSignal(info, *thread_sp, exited); } else { if (info_err.GetError() == EINVAL) { // This is a group stop reception for this tid. // We can reach here if we reinject SIGSTOP, SIGSTP, SIGTTIN or SIGTTOU // into the tracee, triggering the group-stop mechanism. Normally // receiving these would stop the process, pending a SIGCONT. Simulating // this state in a debugger is hard and is generally not needed (one use // case is debugging background task being managed by a shell). For // general use, it is sufficient to stop the process in a signal-delivery // stop which happens before the group stop. This done by MonitorSignal // and works correctly for all signals. LLDB_LOG(log, "received a group stop for pid {0} tid {1}. Transparent " "handling of group stops not supported, resuming the " "thread.", GetID(), pid); ResumeThread(*thread_sp, thread_sp->GetState(), LLDB_INVALID_SIGNAL_NUMBER); } else { // ptrace(GETSIGINFO) failed (but not due to group-stop). // A return value of ESRCH means the thread/process is no longer on the // system, so it was killed somehow outside of our control. Either way, // we can't do anything with it anymore. // Stop tracking the metadata for the thread since it's entirely off the // system now. const bool thread_found = StopTrackingThread(pid); LLDB_LOG(log, "GetSignalInfo failed: {0}, tid = {1}, signal = {2}, " "status = {3}, main_thread = {4}, thread_found: {5}", info_err, pid, signal, status, is_main_thread, thread_found); if (is_main_thread) { // Notify the delegate - our process is not available but appears to // have been killed outside // our control. Is eStateExited the right exit state in this case? SetExitStatus(status, true); SetState(StateType::eStateExited, true); } else { // This thread was pulled out from underneath us. Anything to do here? // Do we want to do an all stop? LLDB_LOG(log, "pid {0} tid {1} non-main thread exit occurred, didn't " "tell delegate anything since thread disappeared out " "from underneath us", GetID(), pid); } } } } void NativeProcessLinux::WaitForNewThread(::pid_t tid) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); NativeThreadLinuxSP new_thread_sp = GetThreadByID(tid); if (new_thread_sp) { // We are already tracking the thread - we got the event on the new thread // (see // MonitorSignal) before this one. We are done. return; } // The thread is not tracked yet, let's wait for it to appear. int status = -1; - ::pid_t wait_pid; - do { - LLDB_LOG(log, - "received thread creation event for tid {0}. tid not tracked " - "yet, waiting for thread to appear...", - tid); - wait_pid = waitpid(tid, &status, __WALL); - } while (wait_pid == -1 && errno == EINTR); + LLDB_LOG(log, + "received thread creation event for tid {0}. tid not tracked " + "yet, waiting for thread to appear...", + tid); + ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, &status, __WALL); // Since we are waiting on a specific tid, this must be the creation event. // But let's do some checks just in case. if (wait_pid != tid) { LLDB_LOG(log, "waiting for tid {0} failed. Assuming the thread has " "disappeared in the meantime", tid); // The only way I know of this could happen is if the whole process was // SIGKILLed in the mean time. In any case, we can't do anything about that // now. return; } if (WIFEXITED(status)) { LLDB_LOG(log, "waiting for tid {0} returned an 'exited' event. Not " "tracking the thread.", tid); // Also a very improbable event. return; } LLDB_LOG(log, "pid = {0}: tracking new thread tid {1}", GetID(), tid); new_thread_sp = AddThread(tid); ResumeThread(*new_thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); ThreadWasCreated(*new_thread_sp); } void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, NativeThreadLinux &thread) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); const bool is_main_thread = (thread.GetID() == GetID()); assert(info.si_signo == SIGTRAP && "Unexpected child signal!"); switch (info.si_code) { // TODO: these two cases are required if we want to support tracing of the // inferiors' children. We'd need this to debug a monitor. // case (SIGTRAP | (PTRACE_EVENT_FORK << 8)): // case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)): case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)): { // This is the notification on the parent thread which informs us of new // thread // creation. // We don't want to do anything with the parent thread so we just resume it. // In case we // want to implement "break on thread creation" functionality, we would need // to stop // here. unsigned long event_message = 0; if (GetEventMessage(thread.GetID(), &event_message).Fail()) { LLDB_LOG(log, "pid {0} received thread creation event but " "GetEventMessage failed so we don't know the new tid", thread.GetID()); } else WaitForNewThread(event_message); ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER); break; } case (SIGTRAP | (PTRACE_EVENT_EXEC << 8)): { NativeThreadLinuxSP main_thread_sp; LLDB_LOG(log, "received exec event, code = {0}", info.si_code ^ SIGTRAP); // Exec clears any pending notifications. m_pending_notification_tid = LLDB_INVALID_THREAD_ID; // Remove all but the main thread here. Linux fork creates a new process // which only copies the main thread. LLDB_LOG(log, "exec received, stop tracking all but main thread"); for (auto thread_sp : m_threads) { const bool is_main_thread = thread_sp && thread_sp->GetID() == GetID(); if (is_main_thread) { main_thread_sp = std::static_pointer_cast(thread_sp); LLDB_LOG(log, "found main thread with tid {0}, keeping", main_thread_sp->GetID()); } else { LLDB_LOG(log, "discarding non-main-thread tid {0} due to exec", thread_sp->GetID()); } } m_threads.clear(); if (main_thread_sp) { m_threads.push_back(main_thread_sp); SetCurrentThreadID(main_thread_sp->GetID()); main_thread_sp->SetStoppedByExec(); } else { SetCurrentThreadID(LLDB_INVALID_THREAD_ID); LLDB_LOG(log, "pid {0} no main thread found, discarded all threads, " "we're in a no-thread state!", GetID()); } // Tell coordinator about about the "new" (since exec) stopped main thread. ThreadWasCreated(*main_thread_sp); // Let our delegate know we have just exec'd. NotifyDidExec(); // If we have a main thread, indicate we are stopped. assert(main_thread_sp && "exec called during ptraced process but no main " "thread metadata tracked"); // Let the process know we're stopped. StopRunningThreads(main_thread_sp->GetID()); break; } case (SIGTRAP | (PTRACE_EVENT_EXIT << 8)): { // The inferior process or one of its threads is about to exit. // We don't want to do anything with the thread so we just resume it. In // case we // want to implement "break on thread exit" functionality, we would need to // stop // here. unsigned long data = 0; if (GetEventMessage(thread.GetID(), &data).Fail()) data = -1; LLDB_LOG(log, "received PTRACE_EVENT_EXIT, data = {0:x}, WIFEXITED={1}, " "WIFSIGNALED={2}, pid = {3}, main_thread = {4}", data, WIFEXITED(data), WIFSIGNALED(data), thread.GetID(), is_main_thread); if (is_main_thread) SetExitStatus(WaitStatus::Decode(data), true); StateType state = thread.GetState(); if (!StateIsRunningState(state)) { // Due to a kernel bug, we may sometimes get this stop after the inferior // gets a // SIGKILL. This confuses our state tracking logic in ResumeThread(), // since normally, // we should not be receiving any ptrace events while the inferior is // stopped. This // makes sure that the inferior is resumed and exits normally. state = eStateRunning; } ResumeThread(thread, state, LLDB_INVALID_SIGNAL_NUMBER); break; } case 0: case TRAP_TRACE: // We receive this on single stepping. case TRAP_HWBKPT: // We receive this on watchpoint hit { // If a watchpoint was hit, report it uint32_t wp_index; Status error = thread.GetRegisterContext()->GetWatchpointHitIndex( wp_index, (uintptr_t)info.si_addr); if (error.Fail()) LLDB_LOG(log, "received error while checking for watchpoint hits, pid = " "{0}, error = {1}", thread.GetID(), error); if (wp_index != LLDB_INVALID_INDEX32) { MonitorWatchpoint(thread, wp_index); break; } // If a breakpoint was hit, report it uint32_t bp_index; error = thread.GetRegisterContext()->GetHardwareBreakHitIndex( bp_index, (uintptr_t)info.si_addr); if (error.Fail()) LLDB_LOG(log, "received error while checking for hardware " "breakpoint hits, pid = {0}, error = {1}", thread.GetID(), error); if (bp_index != LLDB_INVALID_INDEX32) { MonitorBreakpoint(thread); break; } // Otherwise, report step over MonitorTrace(thread); break; } case SI_KERNEL: #if defined __mips__ // For mips there is no special signal for watchpoint // So we check for watchpoint in kernel trap { // If a watchpoint was hit, report it uint32_t wp_index; Status error = thread.GetRegisterContext()->GetWatchpointHitIndex( wp_index, LLDB_INVALID_ADDRESS); if (error.Fail()) LLDB_LOG(log, "received error while checking for watchpoint hits, pid = " "{0}, error = {1}", thread.GetID(), error); if (wp_index != LLDB_INVALID_INDEX32) { MonitorWatchpoint(thread, wp_index); break; } } // NO BREAK #endif case TRAP_BRKPT: MonitorBreakpoint(thread); break; case SIGTRAP: case (SIGTRAP | 0x80): LLDB_LOG( log, "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}, resuming", info.si_code, GetID(), thread.GetID()); // Ignore these signals until we know more about them. ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER); break; default: - LLDB_LOG( - log, - "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}, resuming", - info.si_code, GetID(), thread.GetID()); - llvm_unreachable("Unexpected SIGTRAP code!"); + LLDB_LOG(log, "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}", + info.si_code, GetID(), thread.GetID()); + MonitorSignal(info, thread, false); break; } } void NativeProcessLinux::MonitorTrace(NativeThreadLinux &thread) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); LLDB_LOG(log, "received trace event, pid = {0}", thread.GetID()); // This thread is currently stopped. thread.SetStoppedByTrace(); StopRunningThreads(thread.GetID()); } void NativeProcessLinux::MonitorBreakpoint(NativeThreadLinux &thread) { Log *log( GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_BREAKPOINTS)); LLDB_LOG(log, "received breakpoint event, pid = {0}", thread.GetID()); // Mark the thread as stopped at breakpoint. thread.SetStoppedByBreakpoint(); Status error = FixupBreakpointPCAsNeeded(thread); if (error.Fail()) LLDB_LOG(log, "pid = {0} fixup: {1}", thread.GetID(), error); if (m_threads_stepping_with_breakpoint.find(thread.GetID()) != m_threads_stepping_with_breakpoint.end()) thread.SetStoppedByTrace(); StopRunningThreads(thread.GetID()); } void NativeProcessLinux::MonitorWatchpoint(NativeThreadLinux &thread, uint32_t wp_index) { Log *log( GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_WATCHPOINTS)); LLDB_LOG(log, "received watchpoint event, pid = {0}, wp_index = {1}", thread.GetID(), wp_index); // Mark the thread as stopped at watchpoint. // The address is at (lldb::addr_t)info->si_addr if we need it. thread.SetStoppedByWatchpoint(wp_index); // We need to tell all other running threads before we notify the delegate // about this stop. StopRunningThreads(thread.GetID()); } void NativeProcessLinux::MonitorSignal(const siginfo_t &info, NativeThreadLinux &thread, bool exited) { const int signo = info.si_signo; const bool is_from_llgs = info.si_pid == getpid(); Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); // POSIX says that process behaviour is undefined after it ignores a SIGFPE, // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a // kill(2) or raise(3). Similarly for tgkill(2) on Linux. // // IOW, user generated signals never generate what we consider to be a // "crash". // // Similarly, ACK signals generated by this monitor. // Handle the signal. LLDB_LOG(log, "received signal {0} ({1}) with code {2}, (siginfo pid = {3}, " "waitpid pid = {4})", Host::GetSignalAsCString(signo), signo, info.si_code, thread.GetID()); // Check for thread stop notification. if (is_from_llgs && (info.si_code == SI_TKILL) && (signo == SIGSTOP)) { // This is a tgkill()-based stop. LLDB_LOG(log, "pid {0} tid {1}, thread stopped", GetID(), thread.GetID()); // Check that we're not already marked with a stop reason. // Note this thread really shouldn't already be marked as stopped - if we // were, that would imply that the kernel signaled us with the thread // stopping which we handled and marked as stopped, and that, without an // intervening resume, we received another stop. It is more likely that we // are missing the marking of a run state somewhere if we find that the // thread was marked as stopped. const StateType thread_state = thread.GetState(); if (!StateIsStoppedState(thread_state, false)) { // An inferior thread has stopped because of a SIGSTOP we have sent it. // Generally, these are not important stops and we don't want to report // them as they are just used to stop other threads when one thread (the // one with the *real* stop reason) hits a breakpoint (watchpoint, // etc...). However, in the case of an asynchronous Interrupt(), this *is* // the real stop reason, so we leave the signal intact if this is the // thread that was chosen as the triggering thread. if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID) { if (m_pending_notification_tid == thread.GetID()) thread.SetStoppedBySignal(SIGSTOP, &info); else thread.SetStoppedWithNoReason(); SetCurrentThreadID(thread.GetID()); SignalIfAllThreadsStopped(); } else { // We can end up here if stop was initiated by LLGS but by this time a // thread stop has occurred - maybe initiated by another event. Status error = ResumeThread(thread, thread.GetState(), 0); if (error.Fail()) LLDB_LOG(log, "failed to resume thread {0}: {1}", thread.GetID(), error); } } else { LLDB_LOG(log, "pid {0} tid {1}, thread was already marked as a stopped " "state (state={2}), leaving stop signal as is", GetID(), thread.GetID(), thread_state); SignalIfAllThreadsStopped(); } // Done handling. return; } // Check if debugger should stop at this signal or just ignore it // and resume the inferior. if (m_signals_to_ignore.find(signo) != m_signals_to_ignore.end()) { ResumeThread(thread, thread.GetState(), signo); return; } // This thread is stopped. LLDB_LOG(log, "received signal {0}", Host::GetSignalAsCString(signo)); thread.SetStoppedBySignal(signo, &info); // Send a stop to the debugger after we get all other threads to stop. StopRunningThreads(thread.GetID()); } namespace { struct EmulatorBaton { NativeProcessLinux *m_process; NativeRegisterContext *m_reg_context; // eRegisterKindDWARF -> RegsiterValue std::unordered_map m_register_values; EmulatorBaton(NativeProcessLinux *process, NativeRegisterContext *reg_context) : m_process(process), m_reg_context(reg_context) {} }; } // anonymous namespace static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton, const EmulateInstruction::Context &context, lldb::addr_t addr, void *dst, size_t length) { EmulatorBaton *emulator_baton = static_cast(baton); size_t bytes_read; emulator_baton->m_process->ReadMemory(addr, dst, length, bytes_read); return bytes_read; } static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton, const RegisterInfo *reg_info, RegisterValue ®_value) { EmulatorBaton *emulator_baton = static_cast(baton); auto it = emulator_baton->m_register_values.find( reg_info->kinds[eRegisterKindDWARF]); if (it != emulator_baton->m_register_values.end()) { reg_value = it->second; return true; } // The emulator only fill in the dwarf regsiter numbers (and in some case // the generic register numbers). Get the full register info from the // register context based on the dwarf register numbers. const RegisterInfo *full_reg_info = emulator_baton->m_reg_context->GetRegisterInfo( eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]); Status error = emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value); if (error.Success()) return true; return false; } static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton, const EmulateInstruction::Context &context, const RegisterInfo *reg_info, const RegisterValue ®_value) { EmulatorBaton *emulator_baton = static_cast(baton); emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] = reg_value; return true; } static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton, const EmulateInstruction::Context &context, lldb::addr_t addr, const void *dst, size_t length) { return length; } static lldb::addr_t ReadFlags(NativeRegisterContext *regsiter_context) { const RegisterInfo *flags_info = regsiter_context->GetRegisterInfo( eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); return regsiter_context->ReadRegisterAsUnsigned(flags_info, LLDB_INVALID_ADDRESS); } Status NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadLinux &thread) { Status error; NativeRegisterContextSP register_context_sp = thread.GetRegisterContext(); std::unique_ptr emulator_ap( EmulateInstruction::FindPlugin(m_arch, eInstructionTypePCModifying, nullptr)); if (emulator_ap == nullptr) return Status("Instruction emulator not found!"); EmulatorBaton baton(this, register_context_sp.get()); emulator_ap->SetBaton(&baton); emulator_ap->SetReadMemCallback(&ReadMemoryCallback); emulator_ap->SetReadRegCallback(&ReadRegisterCallback); emulator_ap->SetWriteMemCallback(&WriteMemoryCallback); emulator_ap->SetWriteRegCallback(&WriteRegisterCallback); if (!emulator_ap->ReadInstruction()) return Status("Read instruction failed!"); bool emulation_result = emulator_ap->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC); const RegisterInfo *reg_info_pc = register_context_sp->GetRegisterInfo( eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); const RegisterInfo *reg_info_flags = register_context_sp->GetRegisterInfo( eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); auto pc_it = baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]); auto flags_it = baton.m_register_values.find(reg_info_flags->kinds[eRegisterKindDWARF]); lldb::addr_t next_pc; lldb::addr_t next_flags; if (emulation_result) { assert(pc_it != baton.m_register_values.end() && "Emulation was successfull but PC wasn't updated"); next_pc = pc_it->second.GetAsUInt64(); if (flags_it != baton.m_register_values.end()) next_flags = flags_it->second.GetAsUInt64(); else next_flags = ReadFlags(register_context_sp.get()); } else if (pc_it == baton.m_register_values.end()) { // Emulate instruction failed and it haven't changed PC. Advance PC // with the size of the current opcode because the emulation of all // PC modifying instruction should be successful. The failure most // likely caused by a not supported instruction which don't modify PC. next_pc = register_context_sp->GetPC() + emulator_ap->GetOpcode().GetByteSize(); next_flags = ReadFlags(register_context_sp.get()); } else { // The instruction emulation failed after it modified the PC. It is an // unknown error where we can't continue because the next instruction is // modifying the PC but we don't know how. return Status("Instruction emulation failed unexpectedly."); } if (m_arch.GetMachine() == llvm::Triple::arm) { if (next_flags & 0x20) { // Thumb mode error = SetSoftwareBreakpoint(next_pc, 2); } else { // Arm mode error = SetSoftwareBreakpoint(next_pc, 4); } } else if (m_arch.GetMachine() == llvm::Triple::mips64 || m_arch.GetMachine() == llvm::Triple::mips64el || m_arch.GetMachine() == llvm::Triple::mips || m_arch.GetMachine() == llvm::Triple::mipsel) error = SetSoftwareBreakpoint(next_pc, 4); else { // No size hint is given for the next breakpoint error = SetSoftwareBreakpoint(next_pc, 0); } // If setting the breakpoint fails because next_pc is out of // the address space, ignore it and let the debugee segfault. if (error.GetError() == EIO || error.GetError() == EFAULT) { return Status(); } else if (error.Fail()) return error; m_threads_stepping_with_breakpoint.insert({thread.GetID(), next_pc}); return Status(); } bool NativeProcessLinux::SupportHardwareSingleStepping() const { if (m_arch.GetMachine() == llvm::Triple::arm || m_arch.GetMachine() == llvm::Triple::mips64 || m_arch.GetMachine() == llvm::Triple::mips64el || m_arch.GetMachine() == llvm::Triple::mips || m_arch.GetMachine() == llvm::Triple::mipsel) return false; return true; } Status NativeProcessLinux::Resume(const ResumeActionList &resume_actions) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); LLDB_LOG(log, "pid {0}", GetID()); bool software_single_step = !SupportHardwareSingleStepping(); if (software_single_step) { for (auto thread_sp : m_threads) { assert(thread_sp && "thread list should not contain NULL threads"); const ResumeAction *const action = resume_actions.GetActionForThread(thread_sp->GetID(), true); if (action == nullptr) continue; if (action->state == eStateStepping) { Status error = SetupSoftwareSingleStepping( static_cast(*thread_sp)); if (error.Fail()) return error; } } } for (auto thread_sp : m_threads) { assert(thread_sp && "thread list should not contain NULL threads"); const ResumeAction *const action = resume_actions.GetActionForThread(thread_sp->GetID(), true); if (action == nullptr) { LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(), thread_sp->GetID()); continue; } LLDB_LOG(log, "processing resume action state {0} for pid {1} tid {2}", action->state, GetID(), thread_sp->GetID()); switch (action->state) { case eStateRunning: case eStateStepping: { // Run the thread, possibly feeding it the signal. const int signo = action->signal; ResumeThread(static_cast(*thread_sp), action->state, signo); break; } case eStateSuspended: case eStateStopped: llvm_unreachable("Unexpected state"); default: return Status("NativeProcessLinux::%s (): unexpected state %s specified " "for pid %" PRIu64 ", tid %" PRIu64, __FUNCTION__, StateAsCString(action->state), GetID(), thread_sp->GetID()); } } return Status(); } Status NativeProcessLinux::Halt() { Status error; if (kill(GetID(), SIGSTOP) != 0) error.SetErrorToErrno(); return error; } Status NativeProcessLinux::Detach() { Status error; // Stop monitoring the inferior. m_sigchld_handle.reset(); // Tell ptrace to detach from the process. if (GetID() == LLDB_INVALID_PROCESS_ID) return error; for (auto thread_sp : m_threads) { Status e = Detach(thread_sp->GetID()); if (e.Fail()) error = e; // Save the error, but still attempt to detach from other threads. } m_processor_trace_monitor.clear(); m_pt_proces_trace_id = LLDB_INVALID_UID; return error; } Status NativeProcessLinux::Signal(int signo) { Status error; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); LLDB_LOG(log, "sending signal {0} ({1}) to pid {1}", signo, Host::GetSignalAsCString(signo), GetID()); if (kill(GetID(), signo)) error.SetErrorToErrno(); return error; } Status NativeProcessLinux::Interrupt() { // Pick a running thread (or if none, a not-dead stopped thread) as // the chosen thread that will be the stop-reason thread. Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); NativeThreadProtocolSP running_thread_sp; NativeThreadProtocolSP stopped_thread_sp; LLDB_LOG(log, "selecting running thread for interrupt target"); for (auto thread_sp : m_threads) { // The thread shouldn't be null but lets just cover that here. if (!thread_sp) continue; // If we have a running or stepping thread, we'll call that the // target of the interrupt. const auto thread_state = thread_sp->GetState(); if (thread_state == eStateRunning || thread_state == eStateStepping) { running_thread_sp = thread_sp; break; } else if (!stopped_thread_sp && StateIsStoppedState(thread_state, true)) { // Remember the first non-dead stopped thread. We'll use that as a backup // if there are no running threads. stopped_thread_sp = thread_sp; } } if (!running_thread_sp && !stopped_thread_sp) { Status error("found no running/stepping or live stopped threads as target " "for interrupt"); LLDB_LOG(log, "skipping due to error: {0}", error); return error; } NativeThreadProtocolSP deferred_signal_thread_sp = running_thread_sp ? running_thread_sp : stopped_thread_sp; LLDB_LOG(log, "pid {0} {1} tid {2} chosen for interrupt target", GetID(), running_thread_sp ? "running" : "stopped", deferred_signal_thread_sp->GetID()); StopRunningThreads(deferred_signal_thread_sp->GetID()); return Status(); } Status NativeProcessLinux::Kill() { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); LLDB_LOG(log, "pid {0}", GetID()); Status error; switch (m_state) { case StateType::eStateInvalid: case StateType::eStateExited: case StateType::eStateCrashed: case StateType::eStateDetached: case StateType::eStateUnloaded: // Nothing to do - the process is already dead. LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(), m_state); return error; case StateType::eStateConnected: case StateType::eStateAttaching: case StateType::eStateLaunching: case StateType::eStateStopped: case StateType::eStateRunning: case StateType::eStateStepping: case StateType::eStateSuspended: // We can try to kill a process in these states. break; } if (kill(GetID(), SIGKILL) != 0) { error.SetErrorToErrno(); return error; } return error; } static Status ParseMemoryRegionInfoFromProcMapsLine(llvm::StringRef &maps_line, MemoryRegionInfo &memory_region_info) { memory_region_info.Clear(); StringExtractor line_extractor(maps_line); // Format: {address_start_hex}-{address_end_hex} perms offset dev inode // pathname // perms: rwxp (letter is present if set, '-' if not, final character is // p=private, s=shared). // Parse out the starting address lldb::addr_t start_address = line_extractor.GetHexMaxU64(false, 0); // Parse out hyphen separating start and end address from range. if (!line_extractor.GetBytesLeft() || (line_extractor.GetChar() != '-')) return Status( "malformed /proc/{pid}/maps entry, missing dash between address range"); // Parse out the ending address lldb::addr_t end_address = line_extractor.GetHexMaxU64(false, start_address); // Parse out the space after the address. if (!line_extractor.GetBytesLeft() || (line_extractor.GetChar() != ' ')) return Status( "malformed /proc/{pid}/maps entry, missing space after range"); // Save the range. memory_region_info.GetRange().SetRangeBase(start_address); memory_region_info.GetRange().SetRangeEnd(end_address); // Any memory region in /proc/{pid}/maps is by definition mapped into the // process. memory_region_info.SetMapped(MemoryRegionInfo::OptionalBool::eYes); // Parse out each permission entry. if (line_extractor.GetBytesLeft() < 4) return Status("malformed /proc/{pid}/maps entry, missing some portion of " "permissions"); // Handle read permission. const char read_perm_char = line_extractor.GetChar(); if (read_perm_char == 'r') memory_region_info.SetReadable(MemoryRegionInfo::OptionalBool::eYes); else if (read_perm_char == '-') memory_region_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo); else return Status("unexpected /proc/{pid}/maps read permission char"); // Handle write permission. const char write_perm_char = line_extractor.GetChar(); if (write_perm_char == 'w') memory_region_info.SetWritable(MemoryRegionInfo::OptionalBool::eYes); else if (write_perm_char == '-') memory_region_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo); else return Status("unexpected /proc/{pid}/maps write permission char"); // Handle execute permission. const char exec_perm_char = line_extractor.GetChar(); if (exec_perm_char == 'x') memory_region_info.SetExecutable(MemoryRegionInfo::OptionalBool::eYes); else if (exec_perm_char == '-') memory_region_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo); else return Status("unexpected /proc/{pid}/maps exec permission char"); line_extractor.GetChar(); // Read the private bit line_extractor.SkipSpaces(); // Skip the separator line_extractor.GetHexMaxU64(false, 0); // Read the offset line_extractor.GetHexMaxU64(false, 0); // Read the major device number line_extractor.GetChar(); // Read the device id separator line_extractor.GetHexMaxU64(false, 0); // Read the major device number line_extractor.SkipSpaces(); // Skip the separator line_extractor.GetU64(0, 10); // Read the inode number line_extractor.SkipSpaces(); const char *name = line_extractor.Peek(); if (name) memory_region_info.SetName(name); return Status(); } Status NativeProcessLinux::GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info) { // FIXME review that the final memory region returned extends to the end of // the virtual address space, // with no perms if it is not mapped. // Use an approach that reads memory regions from /proc/{pid}/maps. // Assume proc maps entries are in ascending order. // FIXME assert if we find differently. if (m_supports_mem_region == LazyBool::eLazyBoolNo) { // We're done. return Status("unsupported"); } Status error = PopulateMemoryRegionCache(); if (error.Fail()) { return error; } lldb::addr_t prev_base_address = 0; // FIXME start by finding the last region that is <= target address using // binary search. Data is sorted. // There can be a ton of regions on pthreads apps with lots of threads. for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end(); ++it) { MemoryRegionInfo &proc_entry_info = it->first; // Sanity check assumption that /proc/{pid}/maps entries are ascending. assert((proc_entry_info.GetRange().GetRangeBase() >= prev_base_address) && "descending /proc/pid/maps entries detected, unexpected"); prev_base_address = proc_entry_info.GetRange().GetRangeBase(); UNUSED_IF_ASSERT_DISABLED(prev_base_address); // If the target address comes before this entry, indicate distance to next // region. if (load_addr < proc_entry_info.GetRange().GetRangeBase()) { range_info.GetRange().SetRangeBase(load_addr); range_info.GetRange().SetByteSize( proc_entry_info.GetRange().GetRangeBase() - load_addr); range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo); range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo); range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo); range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo); return error; } else if (proc_entry_info.GetRange().Contains(load_addr)) { // The target address is within the memory region we're processing here. range_info = proc_entry_info; return error; } // The target memory address comes somewhere after the region we just // parsed. } // If we made it here, we didn't find an entry that contained the given // address. Return the // load_addr as start and the amount of bytes betwwen load address and the end // of the memory as // size. range_info.GetRange().SetRangeBase(load_addr); range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo); range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo); range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo); range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo); return error; } Status NativeProcessLinux::PopulateMemoryRegionCache() { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); // If our cache is empty, pull the latest. There should always be at least // one memory region if memory region handling is supported. if (!m_mem_region_cache.empty()) { LLDB_LOG(log, "reusing {0} cached memory region entries", m_mem_region_cache.size()); return Status(); } auto BufferOrError = getProcFile(GetID(), "maps"); if (!BufferOrError) { m_supports_mem_region = LazyBool::eLazyBoolNo; return BufferOrError.getError(); } StringRef Rest = BufferOrError.get()->getBuffer(); while (! Rest.empty()) { StringRef Line; std::tie(Line, Rest) = Rest.split('\n'); MemoryRegionInfo info; const Status parse_error = ParseMemoryRegionInfoFromProcMapsLine(Line, info); if (parse_error.Fail()) { LLDB_LOG(log, "failed to parse proc maps line '{0}': {1}", Line, parse_error); m_supports_mem_region = LazyBool::eLazyBoolNo; return parse_error; } m_mem_region_cache.emplace_back( info, FileSpec(info.GetName().GetCString(), true)); } if (m_mem_region_cache.empty()) { // No entries after attempting to read them. This shouldn't happen if // /proc/{pid}/maps is supported. Assume we don't support map entries // via procfs. m_supports_mem_region = LazyBool::eLazyBoolNo; LLDB_LOG(log, "failed to find any procfs maps entries, assuming no support " "for memory region metadata retrieval"); return Status("not supported"); } LLDB_LOG(log, "read {0} memory region entries from /proc/{1}/maps", m_mem_region_cache.size(), GetID()); // We support memory retrieval, remember that. m_supports_mem_region = LazyBool::eLazyBoolYes; return Status(); } void NativeProcessLinux::DoStopIDBumped(uint32_t newBumpId) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); LLDB_LOG(log, "newBumpId={0}", newBumpId); LLDB_LOG(log, "clearing {0} entries from memory region cache", m_mem_region_cache.size()); m_mem_region_cache.clear(); } Status NativeProcessLinux::AllocateMemory(size_t size, uint32_t permissions, lldb::addr_t &addr) { // FIXME implementing this requires the equivalent of // InferiorCallPOSIX::InferiorCallMmap, which depends on // functional ThreadPlans working with Native*Protocol. #if 1 return Status("not implemented yet"); #else addr = LLDB_INVALID_ADDRESS; unsigned prot = 0; if (permissions & lldb::ePermissionsReadable) prot |= eMmapProtRead; if (permissions & lldb::ePermissionsWritable) prot |= eMmapProtWrite; if (permissions & lldb::ePermissionsExecutable) prot |= eMmapProtExec; // TODO implement this directly in NativeProcessLinux // (and lift to NativeProcessPOSIX if/when that class is // refactored out). if (InferiorCallMmap(this, addr, 0, size, prot, eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { m_addr_to_mmap_size[addr] = size; return Status(); } else { addr = LLDB_INVALID_ADDRESS; return Status("unable to allocate %" PRIu64 " bytes of memory with permissions %s", size, GetPermissionsAsCString(permissions)); } #endif } Status NativeProcessLinux::DeallocateMemory(lldb::addr_t addr) { // FIXME see comments in AllocateMemory - required lower-level // bits not in place yet (ThreadPlans) return Status("not implemented"); } lldb::addr_t NativeProcessLinux::GetSharedLibraryInfoAddress() { // punt on this for now return LLDB_INVALID_ADDRESS; } size_t NativeProcessLinux::UpdateThreads() { // The NativeProcessLinux monitoring threads are always up to date // with respect to thread state and they keep the thread list // populated properly. All this method needs to do is return the // thread count. return m_threads.size(); } bool NativeProcessLinux::GetArchitecture(ArchSpec &arch) const { arch = m_arch; return true; } Status NativeProcessLinux::GetSoftwareBreakpointPCOffset( uint32_t &actual_opcode_size) { // FIXME put this behind a breakpoint protocol class that can be // set per architecture. Need ARM, MIPS support here. static const uint8_t g_i386_opcode[] = {0xCC}; static const uint8_t g_s390x_opcode[] = {0x00, 0x01}; switch (m_arch.GetMachine()) { case llvm::Triple::x86: case llvm::Triple::x86_64: actual_opcode_size = static_cast(sizeof(g_i386_opcode)); return Status(); case llvm::Triple::systemz: actual_opcode_size = static_cast(sizeof(g_s390x_opcode)); return Status(); case llvm::Triple::arm: case llvm::Triple::aarch64: case llvm::Triple::mips64: case llvm::Triple::mips64el: case llvm::Triple::mips: case llvm::Triple::mipsel: // On these architectures the PC don't get updated for breakpoint hits actual_opcode_size = 0; return Status(); default: assert(false && "CPU type not supported!"); return Status("CPU type not supported"); } } Status NativeProcessLinux::SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) { if (hardware) return SetHardwareBreakpoint(addr, size); else return SetSoftwareBreakpoint(addr, size); } Status NativeProcessLinux::RemoveBreakpoint(lldb::addr_t addr, bool hardware) { if (hardware) return RemoveHardwareBreakpoint(addr); else return NativeProcessProtocol::RemoveBreakpoint(addr); } Status NativeProcessLinux::GetSoftwareBreakpointTrapOpcode( size_t trap_opcode_size_hint, size_t &actual_opcode_size, const uint8_t *&trap_opcode_bytes) { // FIXME put this behind a breakpoint protocol class that can be set per // architecture. Need MIPS support here. static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x20, 0xd4}; // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the // linux kernel does otherwise. static const uint8_t g_arm_breakpoint_opcode[] = {0xf0, 0x01, 0xf0, 0xe7}; static const uint8_t g_i386_opcode[] = {0xCC}; static const uint8_t g_mips64_opcode[] = {0x00, 0x00, 0x00, 0x0d}; static const uint8_t g_mips64el_opcode[] = {0x0d, 0x00, 0x00, 0x00}; static const uint8_t g_s390x_opcode[] = {0x00, 0x01}; static const uint8_t g_thumb_breakpoint_opcode[] = {0x01, 0xde}; switch (m_arch.GetMachine()) { case llvm::Triple::aarch64: trap_opcode_bytes = g_aarch64_opcode; actual_opcode_size = sizeof(g_aarch64_opcode); return Status(); case llvm::Triple::arm: switch (trap_opcode_size_hint) { case 2: trap_opcode_bytes = g_thumb_breakpoint_opcode; actual_opcode_size = sizeof(g_thumb_breakpoint_opcode); return Status(); case 4: trap_opcode_bytes = g_arm_breakpoint_opcode; actual_opcode_size = sizeof(g_arm_breakpoint_opcode); return Status(); default: assert(false && "Unrecognised trap opcode size hint!"); return Status("Unrecognised trap opcode size hint!"); } case llvm::Triple::x86: case llvm::Triple::x86_64: trap_opcode_bytes = g_i386_opcode; actual_opcode_size = sizeof(g_i386_opcode); return Status(); case llvm::Triple::mips: case llvm::Triple::mips64: trap_opcode_bytes = g_mips64_opcode; actual_opcode_size = sizeof(g_mips64_opcode); return Status(); case llvm::Triple::mipsel: case llvm::Triple::mips64el: trap_opcode_bytes = g_mips64el_opcode; actual_opcode_size = sizeof(g_mips64el_opcode); return Status(); case llvm::Triple::systemz: trap_opcode_bytes = g_s390x_opcode; actual_opcode_size = sizeof(g_s390x_opcode); return Status(); default: assert(false && "CPU type not supported!"); return Status("CPU type not supported"); } } #if 0 ProcessMessage::CrashReason NativeProcessLinux::GetCrashReasonForSIGSEGV(const siginfo_t *info) { ProcessMessage::CrashReason reason; assert(info->si_signo == SIGSEGV); reason = ProcessMessage::eInvalidCrashReason; switch (info->si_code) { default: assert(false && "unexpected si_code for SIGSEGV"); break; case SI_KERNEL: // Linux will occasionally send spurious SI_KERNEL codes. // (this is poorly documented in sigaction) // One way to get this is via unaligned SIMD loads. reason = ProcessMessage::eInvalidAddress; // for lack of anything better break; case SEGV_MAPERR: reason = ProcessMessage::eInvalidAddress; break; case SEGV_ACCERR: reason = ProcessMessage::ePrivilegedAddress; break; } return reason; } #endif #if 0 ProcessMessage::CrashReason NativeProcessLinux::GetCrashReasonForSIGILL(const siginfo_t *info) { ProcessMessage::CrashReason reason; assert(info->si_signo == SIGILL); reason = ProcessMessage::eInvalidCrashReason; switch (info->si_code) { default: assert(false && "unexpected si_code for SIGILL"); break; case ILL_ILLOPC: reason = ProcessMessage::eIllegalOpcode; break; case ILL_ILLOPN: reason = ProcessMessage::eIllegalOperand; break; case ILL_ILLADR: reason = ProcessMessage::eIllegalAddressingMode; break; case ILL_ILLTRP: reason = ProcessMessage::eIllegalTrap; break; case ILL_PRVOPC: reason = ProcessMessage::ePrivilegedOpcode; break; case ILL_PRVREG: reason = ProcessMessage::ePrivilegedRegister; break; case ILL_COPROC: reason = ProcessMessage::eCoprocessorError; break; case ILL_BADSTK: reason = ProcessMessage::eInternalStackError; break; } return reason; } #endif #if 0 ProcessMessage::CrashReason NativeProcessLinux::GetCrashReasonForSIGFPE(const siginfo_t *info) { ProcessMessage::CrashReason reason; assert(info->si_signo == SIGFPE); reason = ProcessMessage::eInvalidCrashReason; switch (info->si_code) { default: assert(false && "unexpected si_code for SIGFPE"); break; case FPE_INTDIV: reason = ProcessMessage::eIntegerDivideByZero; break; case FPE_INTOVF: reason = ProcessMessage::eIntegerOverflow; break; case FPE_FLTDIV: reason = ProcessMessage::eFloatDivideByZero; break; case FPE_FLTOVF: reason = ProcessMessage::eFloatOverflow; break; case FPE_FLTUND: reason = ProcessMessage::eFloatUnderflow; break; case FPE_FLTRES: reason = ProcessMessage::eFloatInexactResult; break; case FPE_FLTINV: reason = ProcessMessage::eFloatInvalidOperation; break; case FPE_FLTSUB: reason = ProcessMessage::eFloatSubscriptRange; break; } return reason; } #endif #if 0 ProcessMessage::CrashReason NativeProcessLinux::GetCrashReasonForSIGBUS(const siginfo_t *info) { ProcessMessage::CrashReason reason; assert(info->si_signo == SIGBUS); reason = ProcessMessage::eInvalidCrashReason; switch (info->si_code) { default: assert(false && "unexpected si_code for SIGBUS"); break; case BUS_ADRALN: reason = ProcessMessage::eIllegalAlignment; break; case BUS_ADRERR: reason = ProcessMessage::eIllegalAddress; break; case BUS_OBJERR: reason = ProcessMessage::eHardwareError; break; } return reason; } #endif Status NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) { if (ProcessVmReadvSupported()) { // The process_vm_readv path is about 50 times faster than ptrace api. We // want to use // this syscall if it is supported. const ::pid_t pid = GetID(); struct iovec local_iov, remote_iov; local_iov.iov_base = buf; local_iov.iov_len = size; remote_iov.iov_base = reinterpret_cast(addr); remote_iov.iov_len = size; bytes_read = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0); const bool success = bytes_read == size; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); LLDB_LOG(log, "using process_vm_readv to read {0} bytes from inferior " "address {1:x}: {2}", size, addr, success ? "Success" : llvm::sys::StrError(errno)); if (success) return Status(); // else the call failed for some reason, let's retry the read using ptrace // api. } unsigned char *dst = static_cast(buf); size_t remainder; long data; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY)); LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size); for (bytes_read = 0; bytes_read < size; bytes_read += remainder) { Status error = NativeProcessLinux::PtraceWrapper( PTRACE_PEEKDATA, GetID(), (void *)addr, nullptr, 0, &data); if (error.Fail()) return error; remainder = size - bytes_read; remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder; // Copy the data into our buffer memcpy(dst, &data, remainder); LLDB_LOG(log, "[{0:x}]:{1:x}", addr, data); addr += k_ptrace_word_size; dst += k_ptrace_word_size; } return Status(); } Status NativeProcessLinux::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) { Status error = ReadMemory(addr, buf, size, bytes_read); if (error.Fail()) return error; return m_breakpoint_list.RemoveTrapsFromBuffer(addr, buf, size); } Status NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written) { const unsigned char *src = static_cast(buf); size_t remainder; Status error; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY)); LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size); for (bytes_written = 0; bytes_written < size; bytes_written += remainder) { remainder = size - bytes_written; remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder; if (remainder == k_ptrace_word_size) { unsigned long data = 0; memcpy(&data, src, k_ptrace_word_size); LLDB_LOG(log, "[{0:x}]:{1:x}", addr, data); error = NativeProcessLinux::PtraceWrapper(PTRACE_POKEDATA, GetID(), (void *)addr, (void *)data); if (error.Fail()) return error; } else { unsigned char buff[8]; size_t bytes_read; error = ReadMemory(addr, buff, k_ptrace_word_size, bytes_read); if (error.Fail()) return error; memcpy(buff, src, remainder); size_t bytes_written_rec; error = WriteMemory(addr, buff, k_ptrace_word_size, bytes_written_rec); if (error.Fail()) return error; LLDB_LOG(log, "[{0:x}]:{1:x} ({2:x})", addr, *(const unsigned long *)src, *(unsigned long *)buff); } addr += k_ptrace_word_size; src += k_ptrace_word_size; } return error; } Status NativeProcessLinux::GetSignalInfo(lldb::tid_t tid, void *siginfo) { return PtraceWrapper(PTRACE_GETSIGINFO, tid, nullptr, siginfo); } Status NativeProcessLinux::GetEventMessage(lldb::tid_t tid, unsigned long *message) { return PtraceWrapper(PTRACE_GETEVENTMSG, tid, nullptr, message); } Status NativeProcessLinux::Detach(lldb::tid_t tid) { if (tid == LLDB_INVALID_THREAD_ID) return Status(); return PtraceWrapper(PTRACE_DETACH, tid); } bool NativeProcessLinux::HasThreadNoLock(lldb::tid_t thread_id) { for (auto thread_sp : m_threads) { assert(thread_sp && "thread list should not contain NULL threads"); if (thread_sp->GetID() == thread_id) { // We have this thread. return true; } } // We don't have this thread. return false; } bool NativeProcessLinux::StopTrackingThread(lldb::tid_t thread_id) { Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD); LLDB_LOG(log, "tid: {0})", thread_id); bool found = false; for (auto it = m_threads.begin(); it != m_threads.end(); ++it) { if (*it && ((*it)->GetID() == thread_id)) { m_threads.erase(it); found = true; break; } } if (found) StopTracingForThread(thread_id); SignalIfAllThreadsStopped(); return found; } NativeThreadLinuxSP NativeProcessLinux::AddThread(lldb::tid_t thread_id) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id); assert(!HasThreadNoLock(thread_id) && "attempted to add a thread by id that already exists"); // If this is the first thread, save it as the current thread if (m_threads.empty()) SetCurrentThreadID(thread_id); auto thread_sp = std::make_shared(this, thread_id); m_threads.push_back(thread_sp); if (m_pt_proces_trace_id != LLDB_INVALID_UID) { auto traceMonitor = ProcessorTraceMonitor::Create( GetID(), thread_id, m_pt_process_trace_config, true); if (traceMonitor) { m_pt_traced_thread_group.insert(thread_id); m_processor_trace_monitor.insert( std::make_pair(thread_id, std::move(*traceMonitor))); } else { LLDB_LOG(log, "failed to start trace on thread {0}", thread_id); Status error(traceMonitor.takeError()); LLDB_LOG(log, "error {0}", error); } } return thread_sp; } Status NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); Status error; // Find out the size of a breakpoint (might depend on where we are in the // code). NativeRegisterContextSP context_sp = thread.GetRegisterContext(); if (!context_sp) { error.SetErrorString("cannot get a NativeRegisterContext for the thread"); LLDB_LOG(log, "failed: {0}", error); return error; } uint32_t breakpoint_size = 0; error = GetSoftwareBreakpointPCOffset(breakpoint_size); if (error.Fail()) { LLDB_LOG(log, "GetBreakpointSize() failed: {0}", error); return error; } else LLDB_LOG(log, "breakpoint size: {0}", breakpoint_size); // First try probing for a breakpoint at a software breakpoint location: PC - // breakpoint size. const lldb::addr_t initial_pc_addr = context_sp->GetPCfromBreakpointLocation(); lldb::addr_t breakpoint_addr = initial_pc_addr; if (breakpoint_size > 0) { // Do not allow breakpoint probe to wrap around. if (breakpoint_addr >= breakpoint_size) breakpoint_addr -= breakpoint_size; } // Check if we stopped because of a breakpoint. NativeBreakpointSP breakpoint_sp; error = m_breakpoint_list.GetBreakpoint(breakpoint_addr, breakpoint_sp); if (!error.Success() || !breakpoint_sp) { // We didn't find one at a software probe location. Nothing to do. LLDB_LOG(log, "pid {0} no lldb breakpoint found at current pc with " "adjustment: {1}", GetID(), breakpoint_addr); return Status(); } // If the breakpoint is not a software breakpoint, nothing to do. if (!breakpoint_sp->IsSoftwareBreakpoint()) { LLDB_LOG( log, "pid {0} breakpoint found at {1:x}, not software, nothing to adjust", GetID(), breakpoint_addr); return Status(); } // // We have a software breakpoint and need to adjust the PC. // // Sanity check. if (breakpoint_size == 0) { // Nothing to do! How did we get here? LLDB_LOG(log, "pid {0} breakpoint found at {1:x}, it is software, but the " "size is zero, nothing to do (unexpected)", GetID(), breakpoint_addr); return Status(); } // Change the program counter. LLDB_LOG(log, "pid {0} tid {1}: changing PC from {2:x} to {3:x}", GetID(), thread.GetID(), initial_pc_addr, breakpoint_addr); error = context_sp->SetPC(breakpoint_addr); if (error.Fail()) { LLDB_LOG(log, "pid {0} tid {1}: failed to set PC: {2}", GetID(), thread.GetID(), error); return error; } return error; } Status NativeProcessLinux::GetLoadedModuleFileSpec(const char *module_path, FileSpec &file_spec) { Status error = PopulateMemoryRegionCache(); if (error.Fail()) return error; FileSpec module_file_spec(module_path, true); file_spec.Clear(); for (const auto &it : m_mem_region_cache) { if (it.second.GetFilename() == module_file_spec.GetFilename()) { file_spec = it.second; return Status(); } } return Status("Module file (%s) not found in /proc/%" PRIu64 "/maps file!", module_file_spec.GetFilename().AsCString(), GetID()); } Status NativeProcessLinux::GetFileLoadAddress(const llvm::StringRef &file_name, lldb::addr_t &load_addr) { load_addr = LLDB_INVALID_ADDRESS; Status error = PopulateMemoryRegionCache(); if (error.Fail()) return error; FileSpec file(file_name, false); for (const auto &it : m_mem_region_cache) { if (it.second == file) { load_addr = it.first.GetRange().GetRangeBase(); return Status(); } } return Status("No load address found for specified file."); } NativeThreadLinuxSP NativeProcessLinux::GetThreadByID(lldb::tid_t tid) { return std::static_pointer_cast( NativeProcessProtocol::GetThreadByID(tid)); } Status NativeProcessLinux::ResumeThread(NativeThreadLinux &thread, lldb::StateType state, int signo) { Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD); LLDB_LOG(log, "tid: {0}", thread.GetID()); // Before we do the resume below, first check if we have a pending // stop notification that is currently waiting for // all threads to stop. This is potentially a buggy situation since // we're ostensibly waiting for threads to stop before we send out the // pending notification, and here we are resuming one before we send // out the pending stop notification. if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID) { LLDB_LOG(log, "about to resume tid {0} per explicit request but we have a " "pending stop notification (tid {1}) that is actively " "waiting for this thread to stop. Valid sequence of events?", thread.GetID(), m_pending_notification_tid); } // Request a resume. We expect this to be synchronous and the system // to reflect it is running after this completes. switch (state) { case eStateRunning: { const auto resume_result = thread.Resume(signo); if (resume_result.Success()) SetState(eStateRunning, true); return resume_result; } case eStateStepping: { const auto step_result = thread.SingleStep(signo); if (step_result.Success()) SetState(eStateRunning, true); return step_result; } default: LLDB_LOG(log, "Unhandled state {0}.", state); llvm_unreachable("Unhandled state for resume"); } } //===----------------------------------------------------------------------===// void NativeProcessLinux::StopRunningThreads(const lldb::tid_t triggering_tid) { Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD); LLDB_LOG(log, "about to process event: (triggering_tid: {0})", triggering_tid); m_pending_notification_tid = triggering_tid; // Request a stop for all the thread stops that need to be stopped // and are not already known to be stopped. for (const auto &thread_sp : m_threads) { if (StateIsRunningState(thread_sp->GetState())) static_pointer_cast(thread_sp)->RequestStop(); } SignalIfAllThreadsStopped(); LLDB_LOG(log, "event processing done"); } void NativeProcessLinux::SignalIfAllThreadsStopped() { if (m_pending_notification_tid == LLDB_INVALID_THREAD_ID) return; // No pending notification. Nothing to do. for (const auto &thread_sp : m_threads) { if (StateIsRunningState(thread_sp->GetState())) return; // Some threads are still running. Don't signal yet. } // We have a pending notification and all threads have stopped. Log *log( GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_BREAKPOINTS)); // Clear any temporary breakpoints we used to implement software single // stepping. for (const auto &thread_info : m_threads_stepping_with_breakpoint) { Status error = RemoveBreakpoint(thread_info.second); if (error.Fail()) LLDB_LOG(log, "pid = {0} remove stepping breakpoint: {1}", thread_info.first, error); } m_threads_stepping_with_breakpoint.clear(); // Notify the delegate about the stop SetCurrentThreadID(m_pending_notification_tid); SetState(StateType::eStateStopped, true); m_pending_notification_tid = LLDB_INVALID_THREAD_ID; } void NativeProcessLinux::ThreadWasCreated(NativeThreadLinux &thread) { Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD); LLDB_LOG(log, "tid: {0}", thread.GetID()); if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID && StateIsRunningState(thread.GetState())) { // We will need to wait for this new thread to stop as well before firing // the // notification. thread.RequestStop(); } } void NativeProcessLinux::SigchldHandler() { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); // Process all pending waitpid notifications. while (true) { int status = -1; - ::pid_t wait_pid = waitpid(-1, &status, __WALL | __WNOTHREAD | WNOHANG); + ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, -1, &status, + __WALL | __WNOTHREAD | WNOHANG); if (wait_pid == 0) break; // We are done. if (wait_pid == -1) { - if (errno == EINTR) - continue; - Status error(errno, eErrorTypePOSIX); LLDB_LOG(log, "waitpid (-1, &status, _) failed: {0}", error); break; } WaitStatus wait_status = WaitStatus::Decode(status); bool exited = wait_status.type == WaitStatus::Exit || (wait_status.type == WaitStatus::Signal && wait_pid == static_cast<::pid_t>(GetID())); LLDB_LOG( log, "waitpid (-1, &status, _) => pid = {0}, status = {1}, exited = {2}", wait_pid, wait_status, exited); MonitorCallback(wait_pid, exited, wait_status); } } // Wrapper for ptrace to catch errors and log calls. // Note that ptrace sets errno on error because -1 can be a valid result (i.e. // for PTRACE_PEEK*) Status NativeProcessLinux::PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size, long *result) { Status error; long int ret; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); PtraceDisplayBytes(req, data, data_size); errno = 0; if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET) ret = ptrace(static_cast<__ptrace_request>(req), static_cast<::pid_t>(pid), *(unsigned int *)addr, data); else ret = ptrace(static_cast<__ptrace_request>(req), static_cast<::pid_t>(pid), addr, data); if (ret == -1) error.SetErrorToErrno(); if (result) *result = ret; LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3}, {4})={5:x}", req, pid, addr, data, data_size, ret); PtraceDisplayBytes(req, data, data_size); if (error.Fail()) LLDB_LOG(log, "ptrace() failed: {0}", error); return error; } llvm::Expected NativeProcessLinux::LookupProcessorTraceInstance(lldb::user_id_t traceid, lldb::tid_t thread) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); if (thread == LLDB_INVALID_THREAD_ID && traceid == m_pt_proces_trace_id) { LLDB_LOG(log, "thread not specified: {0}", traceid); return Status("tracing not active thread not specified").ToError(); } for (auto& iter : m_processor_trace_monitor) { if (traceid == iter.second->GetTraceID() && (thread == iter.first || thread == LLDB_INVALID_THREAD_ID)) return *(iter.second); } LLDB_LOG(log, "traceid not being traced: {0}", traceid); return Status("tracing not active for this thread").ToError(); } Status NativeProcessLinux::GetMetaData(lldb::user_id_t traceid, lldb::tid_t thread, llvm::MutableArrayRef &buffer, size_t offset) { TraceOptions trace_options; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); Status error; LLDB_LOG(log, "traceid {0}", traceid); auto perf_monitor = LookupProcessorTraceInstance(traceid, thread); if (!perf_monitor) { LLDB_LOG(log, "traceid not being traced: {0}", traceid); buffer = buffer.slice(buffer.size()); error = perf_monitor.takeError(); return error; } return (*perf_monitor).ReadPerfTraceData(buffer, offset); } Status NativeProcessLinux::GetData(lldb::user_id_t traceid, lldb::tid_t thread, llvm::MutableArrayRef &buffer, size_t offset) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); Status error; LLDB_LOG(log, "traceid {0}", traceid); auto perf_monitor = LookupProcessorTraceInstance(traceid, thread); if (!perf_monitor) { LLDB_LOG(log, "traceid not being traced: {0}", traceid); buffer = buffer.slice(buffer.size()); error = perf_monitor.takeError(); return error; } return (*perf_monitor).ReadPerfTraceAux(buffer, offset); } Status NativeProcessLinux::GetTraceConfig(lldb::user_id_t traceid, TraceOptions &config) { Status error; if (config.getThreadID() == LLDB_INVALID_THREAD_ID && m_pt_proces_trace_id == traceid) { if (m_pt_proces_trace_id == LLDB_INVALID_UID) { error.SetErrorString("tracing not active for this process"); return error; } config = m_pt_process_trace_config; } else { auto perf_monitor = LookupProcessorTraceInstance(traceid, config.getThreadID()); if (!perf_monitor) { error = perf_monitor.takeError(); return error; } error = (*perf_monitor).GetTraceConfig(config); } return error; } lldb::user_id_t NativeProcessLinux::StartTraceGroup(const TraceOptions &config, Status &error) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); if (config.getType() != TraceType::eTraceTypeProcessorTrace) return LLDB_INVALID_UID; if (m_pt_proces_trace_id != LLDB_INVALID_UID) { error.SetErrorString("tracing already active on this process"); return m_pt_proces_trace_id; } for (const auto &thread_sp : m_threads) { if (auto traceInstance = ProcessorTraceMonitor::Create( GetID(), thread_sp->GetID(), config, true)) { m_pt_traced_thread_group.insert(thread_sp->GetID()); m_processor_trace_monitor.insert( std::make_pair(thread_sp->GetID(), std::move(*traceInstance))); } } m_pt_process_trace_config = config; error = ProcessorTraceMonitor::GetCPUType(m_pt_process_trace_config); // Trace on Complete process will have traceid of 0 m_pt_proces_trace_id = 0; LLDB_LOG(log, "Process Trace ID {0}", m_pt_proces_trace_id); return m_pt_proces_trace_id; } lldb::user_id_t NativeProcessLinux::StartTrace(const TraceOptions &config, Status &error) { if (config.getType() != TraceType::eTraceTypeProcessorTrace) return NativeProcessProtocol::StartTrace(config, error); Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); lldb::tid_t threadid = config.getThreadID(); if (threadid == LLDB_INVALID_THREAD_ID) return StartTraceGroup(config, error); auto thread_sp = GetThreadByID(threadid); if (!thread_sp) { // Thread not tracked by lldb so don't trace. error.SetErrorString("invalid thread id"); return LLDB_INVALID_UID; } const auto &iter = m_processor_trace_monitor.find(threadid); if (iter != m_processor_trace_monitor.end()) { LLDB_LOG(log, "Thread already being traced"); error.SetErrorString("tracing already active on this thread"); return LLDB_INVALID_UID; } auto traceMonitor = ProcessorTraceMonitor::Create(GetID(), threadid, config, false); if (!traceMonitor) { error = traceMonitor.takeError(); LLDB_LOG(log, "error {0}", error); return LLDB_INVALID_UID; } lldb::user_id_t ret_trace_id = (*traceMonitor)->GetTraceID(); m_processor_trace_monitor.insert( std::make_pair(threadid, std::move(*traceMonitor))); return ret_trace_id; } Status NativeProcessLinux::StopTracingForThread(lldb::tid_t thread) { Status error; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); LLDB_LOG(log, "Thread {0}", thread); const auto& iter = m_processor_trace_monitor.find(thread); if (iter == m_processor_trace_monitor.end()) { error.SetErrorString("tracing not active for this thread"); return error; } if (iter->second->GetTraceID() == m_pt_proces_trace_id) { // traceid maps to the whole process so we have to erase it from the // thread group. LLDB_LOG(log, "traceid maps to process"); m_pt_traced_thread_group.erase(thread); } m_processor_trace_monitor.erase(iter); return error; } Status NativeProcessLinux::StopTrace(lldb::user_id_t traceid, lldb::tid_t thread) { Status error; TraceOptions trace_options; trace_options.setThreadID(thread); error = NativeProcessLinux::GetTraceConfig(traceid, trace_options); if (error.Fail()) return error; switch (trace_options.getType()) { case lldb::TraceType::eTraceTypeProcessorTrace: if (traceid == m_pt_proces_trace_id && thread == LLDB_INVALID_THREAD_ID) StopProcessorTracingOnProcess(); else error = StopProcessorTracingOnThread(traceid, thread); break; default: error.SetErrorString("trace not supported"); break; } return error; } void NativeProcessLinux::StopProcessorTracingOnProcess() { for (auto thread_id_iter : m_pt_traced_thread_group) m_processor_trace_monitor.erase(thread_id_iter); m_pt_traced_thread_group.clear(); m_pt_proces_trace_id = LLDB_INVALID_UID; } Status NativeProcessLinux::StopProcessorTracingOnThread(lldb::user_id_t traceid, lldb::tid_t thread) { Status error; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); if (thread == LLDB_INVALID_THREAD_ID) { for (auto& iter : m_processor_trace_monitor) { if (iter.second->GetTraceID() == traceid) { // Stopping a trace instance for an individual thread // hence there will only be one traceid that can match. m_processor_trace_monitor.erase(iter.first); return error; } LLDB_LOG(log, "Trace ID {0}", iter.second->GetTraceID()); } LLDB_LOG(log, "Invalid TraceID"); error.SetErrorString("invalid trace id"); return error; } // thread is specified so we can use find function on the map. const auto& iter = m_processor_trace_monitor.find(thread); if (iter == m_processor_trace_monitor.end()) { // thread not found in our map. LLDB_LOG(log, "thread not being traced"); error.SetErrorString("tracing not active for this thread"); return error; } if (iter->second->GetTraceID() != traceid) { // traceid did not match so it has to be invalid. LLDB_LOG(log, "Invalid TraceID"); error.SetErrorString("invalid trace id"); return error; } LLDB_LOG(log, "UID - {0} , Thread -{1}", traceid, thread); if (traceid == m_pt_proces_trace_id) { // traceid maps to the whole process so we have to erase it from the // thread group. LLDB_LOG(log, "traceid maps to process"); m_pt_traced_thread_group.erase(thread); } m_processor_trace_monitor.erase(iter); return error; } Index: vendor/lldb/dist/source/Plugins/Process/Linux/NativeProcessLinux.h =================================================================== --- vendor/lldb/dist/source/Plugins/Process/Linux/NativeProcessLinux.h (revision 320966) +++ vendor/lldb/dist/source/Plugins/Process/Linux/NativeProcessLinux.h (revision 320967) @@ -1,290 +1,289 @@ //===-- NativeProcessLinux.h ---------------------------------- -*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef liblldb_NativeProcessLinux_H_ #define liblldb_NativeProcessLinux_H_ // C++ Includes #include // Other libraries and framework includes #include "lldb/Core/ArchSpec.h" #include "lldb/Host/Debug.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/linux/Support.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Utility/FileSpec.h" #include "lldb/lldb-types.h" #include "NativeThreadLinux.h" #include "ProcessorTrace.h" #include "lldb/Host/common/NativeProcessProtocol.h" namespace lldb_private { class Status; class Scalar; namespace process_linux { /// @class NativeProcessLinux /// @brief Manages communication with the inferior (debugee) process. /// /// Upon construction, this class prepares and launches an inferior process for /// debugging. /// /// Changes in the inferior process state are broadcasted. class NativeProcessLinux : public NativeProcessProtocol { - friend Status NativeProcessProtocol::Launch( - ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &process_sp); +public: + class Factory : public NativeProcessProtocol::Factory { + public: + llvm::Expected + Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, + MainLoop &mainloop) const override; - friend Status NativeProcessProtocol::Attach( - lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &process_sp); + llvm::Expected + Attach(lldb::pid_t pid, NativeDelegate &native_delegate, + MainLoop &mainloop) const override; + }; -public: // --------------------------------------------------------------------- // NativeProcessProtocol Interface // --------------------------------------------------------------------- Status Resume(const ResumeActionList &resume_actions) override; Status Halt() override; Status Detach() override; Status Signal(int signo) override; Status Interrupt() override; Status Kill() override; Status GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info) override; Status ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) override; Status ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) override; Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written) override; Status AllocateMemory(size_t size, uint32_t permissions, lldb::addr_t &addr) override; Status DeallocateMemory(lldb::addr_t addr) override; lldb::addr_t GetSharedLibraryInfoAddress() override; size_t UpdateThreads() override; bool GetArchitecture(ArchSpec &arch) const override; Status SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) override; Status RemoveBreakpoint(lldb::addr_t addr, bool hardware = false) override; void DoStopIDBumped(uint32_t newBumpId) override; Status GetLoadedModuleFileSpec(const char *module_path, FileSpec &file_spec) override; Status GetFileLoadAddress(const llvm::StringRef &file_name, lldb::addr_t &load_addr) override; NativeThreadLinuxSP GetThreadByID(lldb::tid_t id); llvm::ErrorOr> GetAuxvData() const override { return getProcFile(GetID(), "auxv"); } lldb::user_id_t StartTrace(const TraceOptions &config, Status &error) override; Status StopTrace(lldb::user_id_t traceid, lldb::tid_t thread) override; Status GetData(lldb::user_id_t traceid, lldb::tid_t thread, llvm::MutableArrayRef &buffer, size_t offset = 0) override; Status GetMetaData(lldb::user_id_t traceid, lldb::tid_t thread, llvm::MutableArrayRef &buffer, size_t offset = 0) override; Status GetTraceConfig(lldb::user_id_t traceid, TraceOptions &config) override; // --------------------------------------------------------------------- // Interface used by NativeRegisterContext-derived classes. // --------------------------------------------------------------------- static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr = nullptr, void *data = nullptr, size_t data_size = 0, long *result = nullptr); bool SupportHardwareSingleStepping() const; protected: // --------------------------------------------------------------------- // NativeProcessProtocol protected interface // --------------------------------------------------------------------- Status GetSoftwareBreakpointTrapOpcode(size_t trap_opcode_size_hint, size_t &actual_opcode_size, const uint8_t *&trap_opcode_bytes) override; private: MainLoop::SignalHandleUP m_sigchld_handle; ArchSpec m_arch; - LazyBool m_supports_mem_region; + LazyBool m_supports_mem_region = eLazyBoolCalculate; std::vector> m_mem_region_cache; - lldb::tid_t m_pending_notification_tid; + lldb::tid_t m_pending_notification_tid = LLDB_INVALID_THREAD_ID; // List of thread ids stepping with a breakpoint with the address of // the relevan breakpoint std::map m_threads_stepping_with_breakpoint; // --------------------------------------------------------------------- // Private Instance Methods // --------------------------------------------------------------------- - NativeProcessLinux(); + NativeProcessLinux(::pid_t pid, int terminal_fd, NativeDelegate &delegate, + const ArchSpec &arch, MainLoop &mainloop); - Status LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info); + // Returns a list of process threads that we have attached to. + static llvm::Expected> Attach(::pid_t pid); - /// Attaches to an existing process. Forms the - /// implementation of Process::DoAttach - void AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, Status &error); - - ::pid_t Attach(lldb::pid_t pid, Status &error); - static Status SetDefaultPtraceOpts(const lldb::pid_t); - static void *MonitorThread(void *baton); + void InitializeThreads(llvm::ArrayRef<::pid_t> tids); void MonitorCallback(lldb::pid_t pid, bool exited, WaitStatus status); void WaitForNewThread(::pid_t tid); void MonitorSIGTRAP(const siginfo_t &info, NativeThreadLinux &thread); void MonitorTrace(NativeThreadLinux &thread); void MonitorBreakpoint(NativeThreadLinux &thread); void MonitorWatchpoint(NativeThreadLinux &thread, uint32_t wp_index); void MonitorSignal(const siginfo_t &info, NativeThreadLinux &thread, bool exited); Status SetupSoftwareSingleStepping(NativeThreadLinux &thread); #if 0 static ::ProcessMessage::CrashReason GetCrashReasonForSIGSEGV(const siginfo_t *info); static ::ProcessMessage::CrashReason GetCrashReasonForSIGILL(const siginfo_t *info); static ::ProcessMessage::CrashReason GetCrashReasonForSIGFPE(const siginfo_t *info); static ::ProcessMessage::CrashReason GetCrashReasonForSIGBUS(const siginfo_t *info); #endif bool HasThreadNoLock(lldb::tid_t thread_id); bool StopTrackingThread(lldb::tid_t thread_id); NativeThreadLinuxSP AddThread(lldb::tid_t thread_id); Status GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size); Status FixupBreakpointPCAsNeeded(NativeThreadLinux &thread); /// Writes a siginfo_t structure corresponding to the given thread ID to the /// memory region pointed to by @p siginfo. Status GetSignalInfo(lldb::tid_t tid, void *siginfo); /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG) /// corresponding to the given thread ID to the memory pointed to by @p /// message. Status GetEventMessage(lldb::tid_t tid, unsigned long *message); void NotifyThreadDeath(lldb::tid_t tid); Status Detach(lldb::tid_t tid); // This method is requests a stop on all threads which are still running. It // sets up a // deferred delegate notification, which will fire once threads report as // stopped. The // triggerring_tid will be set as the current thread (main stop reason). void StopRunningThreads(lldb::tid_t triggering_tid); // Notify the delegate if all threads have stopped. void SignalIfAllThreadsStopped(); // Resume the given thread, optionally passing it the given signal. The type // of resume // operation (continue, single-step) depends on the state parameter. Status ResumeThread(NativeThreadLinux &thread, lldb::StateType state, int signo); void ThreadWasCreated(NativeThreadLinux &thread); void SigchldHandler(); Status PopulateMemoryRegionCache(); lldb::user_id_t StartTraceGroup(const TraceOptions &config, Status &error); // This function is intended to be used to stop tracing // on a thread that exited. Status StopTracingForThread(lldb::tid_t thread); // The below function as the name suggests, looks up a ProcessorTrace // instance from the m_processor_trace_monitor map. In the case of // process tracing where the traceid passed would map to the complete // process, it is mandatory to provide a threadid to obtain a trace // instance (since ProcessorTrace is tied to a thread). In the other // scenario that an individual thread is being traced, just the traceid // is sufficient to obtain the actual ProcessorTrace instance. llvm::Expected LookupProcessorTraceInstance(lldb::user_id_t traceid, lldb::tid_t thread); // Stops tracing on individual threads being traced. Not intended // to be used to stop tracing on complete process. Status StopProcessorTracingOnThread(lldb::user_id_t traceid, lldb::tid_t thread); // Intended to stop tracing on complete process. // Should not be used for stopping trace on // individual threads. void StopProcessorTracingOnProcess(); llvm::DenseMap m_processor_trace_monitor; // Set for tracking threads being traced under // same process user id. llvm::DenseSet m_pt_traced_thread_group; - lldb::user_id_t m_pt_proces_trace_id; + lldb::user_id_t m_pt_proces_trace_id = LLDB_INVALID_UID; TraceOptions m_pt_process_trace_config; }; } // namespace process_linux } // namespace lldb_private #endif // #ifndef liblldb_NativeProcessLinux_H_ Index: vendor/lldb/dist/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp (revision 320967) @@ -1,999 +1,999 @@ //===-- NativeRegisterContextLinux_arm64.cpp --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #if defined(__arm64__) || defined(__aarch64__) #include "NativeRegisterContextLinux_arm.h" #include "NativeRegisterContextLinux_arm64.h" // C Includes // C++ Includes // Other libraries and framework includes #include "lldb/Core/RegisterValue.h" #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" #include "Plugins/Process/Linux/NativeProcessLinux.h" #include "Plugins/Process/Linux/Procfs.h" #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" // System includes - They have to be included after framework includes because // they define some // macros which collide with variable names in other modules #include // NT_PRSTATUS and NT_FPREGSET definition #include // user_hwdebug_state definition #include #define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize()) using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_linux; // ARM64 general purpose registers. static const uint32_t g_gpr_regnums_arm64[] = { gpr_x0_arm64, gpr_x1_arm64, gpr_x2_arm64, gpr_x3_arm64, gpr_x4_arm64, gpr_x5_arm64, gpr_x6_arm64, gpr_x7_arm64, gpr_x8_arm64, gpr_x9_arm64, gpr_x10_arm64, gpr_x11_arm64, gpr_x12_arm64, gpr_x13_arm64, gpr_x14_arm64, gpr_x15_arm64, gpr_x16_arm64, gpr_x17_arm64, gpr_x18_arm64, gpr_x19_arm64, gpr_x20_arm64, gpr_x21_arm64, gpr_x22_arm64, gpr_x23_arm64, gpr_x24_arm64, gpr_x25_arm64, gpr_x26_arm64, gpr_x27_arm64, gpr_x28_arm64, gpr_fp_arm64, gpr_lr_arm64, gpr_sp_arm64, gpr_pc_arm64, gpr_cpsr_arm64, gpr_w0_arm64, gpr_w1_arm64, gpr_w2_arm64, gpr_w3_arm64, gpr_w4_arm64, gpr_w5_arm64, gpr_w6_arm64, gpr_w7_arm64, gpr_w8_arm64, gpr_w9_arm64, gpr_w10_arm64, gpr_w11_arm64, gpr_w12_arm64, gpr_w13_arm64, gpr_w14_arm64, gpr_w15_arm64, gpr_w16_arm64, gpr_w17_arm64, gpr_w18_arm64, gpr_w19_arm64, gpr_w20_arm64, gpr_w21_arm64, gpr_w22_arm64, gpr_w23_arm64, gpr_w24_arm64, gpr_w25_arm64, gpr_w26_arm64, gpr_w27_arm64, gpr_w28_arm64, LLDB_INVALID_REGNUM // register sets need to end with this flag }; static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) - 1) == k_num_gpr_registers_arm64, "g_gpr_regnums_arm64 has wrong number of register infos"); // ARM64 floating point registers. static const uint32_t g_fpu_regnums_arm64[] = { fpu_v0_arm64, fpu_v1_arm64, fpu_v2_arm64, fpu_v3_arm64, fpu_v4_arm64, fpu_v5_arm64, fpu_v6_arm64, fpu_v7_arm64, fpu_v8_arm64, fpu_v9_arm64, fpu_v10_arm64, fpu_v11_arm64, fpu_v12_arm64, fpu_v13_arm64, fpu_v14_arm64, fpu_v15_arm64, fpu_v16_arm64, fpu_v17_arm64, fpu_v18_arm64, fpu_v19_arm64, fpu_v20_arm64, fpu_v21_arm64, fpu_v22_arm64, fpu_v23_arm64, fpu_v24_arm64, fpu_v25_arm64, fpu_v26_arm64, fpu_v27_arm64, fpu_v28_arm64, fpu_v29_arm64, fpu_v30_arm64, fpu_v31_arm64, fpu_s0_arm64, fpu_s1_arm64, fpu_s2_arm64, fpu_s3_arm64, fpu_s4_arm64, fpu_s5_arm64, fpu_s6_arm64, fpu_s7_arm64, fpu_s8_arm64, fpu_s9_arm64, fpu_s10_arm64, fpu_s11_arm64, fpu_s12_arm64, fpu_s13_arm64, fpu_s14_arm64, fpu_s15_arm64, fpu_s16_arm64, fpu_s17_arm64, fpu_s18_arm64, fpu_s19_arm64, fpu_s20_arm64, fpu_s21_arm64, fpu_s22_arm64, fpu_s23_arm64, fpu_s24_arm64, fpu_s25_arm64, fpu_s26_arm64, fpu_s27_arm64, fpu_s28_arm64, fpu_s29_arm64, fpu_s30_arm64, fpu_s31_arm64, fpu_d0_arm64, fpu_d1_arm64, fpu_d2_arm64, fpu_d3_arm64, fpu_d4_arm64, fpu_d5_arm64, fpu_d6_arm64, fpu_d7_arm64, fpu_d8_arm64, fpu_d9_arm64, fpu_d10_arm64, fpu_d11_arm64, fpu_d12_arm64, fpu_d13_arm64, fpu_d14_arm64, fpu_d15_arm64, fpu_d16_arm64, fpu_d17_arm64, fpu_d18_arm64, fpu_d19_arm64, fpu_d20_arm64, fpu_d21_arm64, fpu_d22_arm64, fpu_d23_arm64, fpu_d24_arm64, fpu_d25_arm64, fpu_d26_arm64, fpu_d27_arm64, fpu_d28_arm64, fpu_d29_arm64, fpu_d30_arm64, fpu_d31_arm64, fpu_fpsr_arm64, fpu_fpcr_arm64, LLDB_INVALID_REGNUM // register sets need to end with this flag }; static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) - 1) == k_num_fpr_registers_arm64, "g_fpu_regnums_arm64 has wrong number of register infos"); namespace { // Number of register sets provided by this context. enum { k_num_register_sets = 2 }; } // Register sets for ARM64. static const RegisterSet g_reg_sets_arm64[k_num_register_sets] = { {"General Purpose Registers", "gpr", k_num_gpr_registers_arm64, g_gpr_regnums_arm64}, {"Floating Point Registers", "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64}}; NativeRegisterContextLinux * NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( const ArchSpec &target_arch, NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx) { switch (target_arch.GetMachine()) { case llvm::Triple::arm: return new NativeRegisterContextLinux_arm(target_arch, native_thread, concrete_frame_idx); case llvm::Triple::aarch64: return new NativeRegisterContextLinux_arm64(target_arch, native_thread, concrete_frame_idx); default: llvm_unreachable("have no register context for architecture"); } } NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64( const ArchSpec &target_arch, NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx) : NativeRegisterContextLinux(native_thread, concrete_frame_idx, new RegisterInfoPOSIX_arm64(target_arch)) { switch (target_arch.GetMachine()) { case llvm::Triple::aarch64: m_reg_info.num_registers = k_num_registers_arm64; m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64; m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64; m_reg_info.last_gpr = k_last_gpr_arm64; m_reg_info.first_fpr = k_first_fpr_arm64; m_reg_info.last_fpr = k_last_fpr_arm64; m_reg_info.first_fpr_v = fpu_v0_arm64; m_reg_info.last_fpr_v = fpu_v31_arm64; m_reg_info.gpr_flags = gpr_cpsr_arm64; break; default: llvm_unreachable("Unhandled target architecture."); break; } ::memset(&m_fpr, 0, sizeof(m_fpr)); ::memset(&m_gpr_arm64, 0, sizeof(m_gpr_arm64)); ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); ::memset(&m_hbr_regs, 0, sizeof(m_hbr_regs)); // 16 is just a maximum value, query hardware for actual watchpoint count m_max_hwp_supported = 16; m_max_hbp_supported = 16; m_refresh_hwdebug_info = true; } uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount() const { return k_num_register_sets; } const RegisterSet * NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index) const { if (set_index < k_num_register_sets) return &g_reg_sets_arm64[set_index]; return nullptr; } uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount() const { uint32_t count = 0; for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) count += g_reg_sets_arm64[set_index].num_registers; return count; } Status NativeRegisterContextLinux_arm64::ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) { Status error; if (!reg_info) { error.SetErrorString("reg_info NULL"); return error; } const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; if (IsFPR(reg)) { error = ReadFPR(); if (error.Fail()) return error; } else { uint32_t full_reg = reg; bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); if (is_subreg) { // Read the full aligned 64-bit register. full_reg = reg_info->invalidate_regs[0]; } error = ReadRegisterRaw(full_reg, reg_value); if (error.Success()) { // If our read was not aligned (for ah,bh,ch,dh), shift our returned value // one byte to the right. if (is_subreg && (reg_info->byte_offset & 0x1)) reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); // If our return byte size was greater than the return value reg size, // then // use the type specified by reg_info rather than the uint64_t default if (reg_value.GetByteSize() > reg_info->byte_size) reg_value.SetType(reg_info); } return error; } // Get pointer to m_fpr variable and set the data from it. uint32_t fpr_offset = CalculateFprOffset(reg_info); assert(fpr_offset < sizeof m_fpr); uint8_t *src = (uint8_t *)&m_fpr + fpr_offset; reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, eByteOrderLittle, error); return error; } Status NativeRegisterContextLinux_arm64::WriteRegister( const RegisterInfo *reg_info, const RegisterValue ®_value) { if (!reg_info) return Status("reg_info NULL"); const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; if (reg_index == LLDB_INVALID_REGNUM) return Status("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : ""); if (IsGPR(reg_index)) return WriteRegisterRaw(reg_index, reg_value); if (IsFPR(reg_index)) { // Get pointer to m_fpr variable and set the data to it. uint32_t fpr_offset = CalculateFprOffset(reg_info); assert(fpr_offset < sizeof m_fpr); uint8_t *dst = (uint8_t *)&m_fpr + fpr_offset; switch (reg_info->byte_size) { case 2: *(uint16_t *)dst = reg_value.GetAsUInt16(); break; case 4: *(uint32_t *)dst = reg_value.GetAsUInt32(); break; case 8: *(uint64_t *)dst = reg_value.GetAsUInt64(); break; default: assert(false && "Unhandled data size."); return Status("unhandled register data size %" PRIu32, reg_info->byte_size); } Status error = WriteFPR(); if (error.Fail()) return error; return Status(); } return Status("failed - register wasn't recognized to be a GPR or an FPR, " "write strategy unknown"); } Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues( lldb::DataBufferSP &data_sp) { Status error; data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); if (!data_sp) return Status("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE); error = ReadGPR(); if (error.Fail()) return error; error = ReadFPR(); if (error.Fail()) return error; uint8_t *dst = data_sp->GetBytes(); if (dst == nullptr) { error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", REG_CONTEXT_SIZE); return error; } ::memcpy(dst, &m_gpr_arm64, GetGPRSize()); dst += GetGPRSize(); ::memcpy(dst, &m_fpr, sizeof(m_fpr)); return error; } Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues( const lldb::DataBufferSP &data_sp) { Status error; if (!data_sp) { error.SetErrorStringWithFormat( "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__); return error; } if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { error.SetErrorStringWithFormat( "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched " "data size, expected %" PRIu64 ", actual %" PRIu64, __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); return error; } uint8_t *src = data_sp->GetBytes(); if (src == nullptr) { error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s " "DataBuffer::GetBytes() returned a null " "pointer", __FUNCTION__); return error; } ::memcpy(&m_gpr_arm64, src, GetRegisterInfoInterface().GetGPRSize()); error = WriteGPR(); if (error.Fail()) return error; src += GetRegisterInfoInterface().GetGPRSize(); ::memcpy(&m_fpr, src, sizeof(m_fpr)); error = WriteFPR(); if (error.Fail()) return error; return error; } bool NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const { return reg <= m_reg_info.last_gpr; // GPR's come first. } bool NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const { return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); } uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareBreakpoints() { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); if (log) log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); Status error; // Read hardware breakpoint and watchpoint information. error = ReadHardwareDebugInfo(); if (error.Fail()) return 0; return m_max_hbp_supported; } uint32_t NativeRegisterContextLinux_arm64::SetHardwareBreakpoint(lldb::addr_t addr, size_t size) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); LLDB_LOG(log, "addr: {0:x}, size: {1:x}", addr, size); // Read hardware breakpoint and watchpoint information. Status error = ReadHardwareDebugInfo(); if (error.Fail()) return LLDB_INVALID_INDEX32; uint32_t control_value = 0, bp_index = 0; // Check if size has a valid hardware breakpoint length. if (size != 4) return LLDB_INVALID_INDEX32; // Invalid size for a AArch64 hardware // breakpoint // Check 4-byte alignment for hardware breakpoint target address. if (addr & 0x03) return LLDB_INVALID_INDEX32; // Invalid address, should be 4-byte aligned. // Setup control value control_value = 0; control_value |= ((1 << size) - 1) << 5; control_value |= (2 << 1) | 1; // Iterate over stored breakpoints and find a free bp_index bp_index = LLDB_INVALID_INDEX32; for (uint32_t i = 0; i < m_max_hbp_supported; i++) { if ((m_hbr_regs[i].control & 1) == 0) { bp_index = i; // Mark last free slot } else if (m_hbr_regs[i].address == addr) { return LLDB_INVALID_INDEX32; // We do not support duplicate breakpoints. } } if (bp_index == LLDB_INVALID_INDEX32) return LLDB_INVALID_INDEX32; // Update breakpoint in local cache m_hbr_regs[bp_index].real_addr = addr; m_hbr_regs[bp_index].address = addr; m_hbr_regs[bp_index].control = control_value; // PTRACE call to set corresponding hardware breakpoint register. error = WriteHardwareDebugRegs(eDREGTypeBREAK); if (error.Fail()) { m_hbr_regs[bp_index].address = 0; m_hbr_regs[bp_index].control &= ~1; return LLDB_INVALID_INDEX32; } return bp_index; } bool NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint( uint32_t hw_idx) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); LLDB_LOG(log, "hw_idx: {0}", hw_idx); // Read hardware breakpoint and watchpoint information. Status error = ReadHardwareDebugInfo(); if (error.Fail()) return false; if (hw_idx >= m_max_hbp_supported) return false; // Create a backup we can revert to in case of failure. lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address; uint32_t tempControl = m_hbr_regs[hw_idx].control; m_hbr_regs[hw_idx].control &= ~1; m_hbr_regs[hw_idx].address = 0; // PTRACE call to clear corresponding hardware breakpoint register. error = WriteHardwareDebugRegs(eDREGTypeBREAK); if (error.Fail()) { m_hbr_regs[hw_idx].control = tempControl; m_hbr_regs[hw_idx].address = tempAddr; return false; } return true; } Status NativeRegisterContextLinux_arm64::GetHardwareBreakHitIndex( uint32_t &bp_index, lldb::addr_t trap_addr) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); if (log) log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); lldb::addr_t break_addr; for (bp_index = 0; bp_index < m_max_hbp_supported; ++bp_index) { break_addr = m_hbr_regs[bp_index].address; if ((m_hbr_regs[bp_index].control & 0x1) && (trap_addr == break_addr)) { m_hbr_regs[bp_index].hit_addr = trap_addr; return Status(); } } bp_index = LLDB_INVALID_INDEX32; return Status(); } Status NativeRegisterContextLinux_arm64::ClearAllHardwareBreakpoints() { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); if (log) log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); Status error; // Read hardware breakpoint and watchpoint information. error = ReadHardwareDebugInfo(); if (error.Fail()) return error; lldb::addr_t tempAddr = 0; uint32_t tempControl = 0; for (uint32_t i = 0; i < m_max_hbp_supported; i++) { if (m_hbr_regs[i].control & 0x01) { // Create a backup we can revert to in case of failure. tempAddr = m_hbr_regs[i].address; tempControl = m_hbr_regs[i].control; // Clear watchpoints in local cache m_hbr_regs[i].control &= ~1; m_hbr_regs[i].address = 0; // Ptrace call to update hardware debug registers error = WriteHardwareDebugRegs(eDREGTypeBREAK); if (error.Fail()) { m_hbr_regs[i].control = tempControl; m_hbr_regs[i].address = tempAddr; return error; } } } return Status(); } uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints() { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); // Read hardware breakpoint and watchpoint information. Status error = ReadHardwareDebugInfo(); if (error.Fail()) return 0; LLDB_LOG(log, "{0}", m_max_hwp_supported); return m_max_hwp_supported; } uint32_t NativeRegisterContextLinux_arm64::SetHardwareWatchpoint( lldb::addr_t addr, size_t size, uint32_t watch_flags) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size, watch_flags); // Read hardware breakpoint and watchpoint information. Status error = ReadHardwareDebugInfo(); if (error.Fail()) return LLDB_INVALID_INDEX32; uint32_t control_value = 0, wp_index = 0; lldb::addr_t real_addr = addr; // Check if we are setting watchpoint other than read/write/access // Also update watchpoint flag to match AArch64 write-read bit configuration. switch (watch_flags) { case 1: watch_flags = 2; break; case 2: watch_flags = 1; break; case 3: break; default: return LLDB_INVALID_INDEX32; } // Check if size has a valid hardware watchpoint length. if (size != 1 && size != 2 && size != 4 && size != 8) return LLDB_INVALID_INDEX32; // Check 8-byte alignment for hardware watchpoint target address. // Below is a hack to recalculate address and size in order to // make sure we can watch non 8-byte alligned addresses as well. if (addr & 0x07) { uint8_t watch_mask = (addr & 0x07) + size; if (watch_mask > 0x08) return LLDB_INVALID_INDEX32; else if (watch_mask <= 0x02) size = 2; else if (watch_mask <= 0x04) size = 4; else size = 8; addr = addr & (~0x07); } // Setup control value control_value = watch_flags << 3; control_value |= ((1 << size) - 1) << 5; control_value |= (2 << 1) | 1; // Iterate over stored watchpoints and find a free wp_index wp_index = LLDB_INVALID_INDEX32; for (uint32_t i = 0; i < m_max_hwp_supported; i++) { if ((m_hwp_regs[i].control & 1) == 0) { wp_index = i; // Mark last free slot } else if (m_hwp_regs[i].address == addr) { return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints. } } if (wp_index == LLDB_INVALID_INDEX32) return LLDB_INVALID_INDEX32; // Update watchpoint in local cache m_hwp_regs[wp_index].real_addr = real_addr; m_hwp_regs[wp_index].address = addr; m_hwp_regs[wp_index].control = control_value; // PTRACE call to set corresponding watchpoint register. error = WriteHardwareDebugRegs(eDREGTypeWATCH); if (error.Fail()) { m_hwp_regs[wp_index].address = 0; m_hwp_regs[wp_index].control &= ~1; return LLDB_INVALID_INDEX32; } return wp_index; } bool NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint( uint32_t wp_index) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); LLDB_LOG(log, "wp_index: {0}", wp_index); // Read hardware breakpoint and watchpoint information. Status error = ReadHardwareDebugInfo(); if (error.Fail()) return false; if (wp_index >= m_max_hwp_supported) return false; // Create a backup we can revert to in case of failure. lldb::addr_t tempAddr = m_hwp_regs[wp_index].address; uint32_t tempControl = m_hwp_regs[wp_index].control; // Update watchpoint in local cache m_hwp_regs[wp_index].control &= ~1; m_hwp_regs[wp_index].address = 0; // Ptrace call to update hardware debug registers error = WriteHardwareDebugRegs(eDREGTypeWATCH); if (error.Fail()) { m_hwp_regs[wp_index].control = tempControl; m_hwp_regs[wp_index].address = tempAddr; return false; } return true; } Status NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints() { // Read hardware breakpoint and watchpoint information. Status error = ReadHardwareDebugInfo(); if (error.Fail()) return error; lldb::addr_t tempAddr = 0; - uint32_t tempControl = 0, tempRefCount = 0; + uint32_t tempControl = 0; for (uint32_t i = 0; i < m_max_hwp_supported; i++) { if (m_hwp_regs[i].control & 0x01) { // Create a backup we can revert to in case of failure. tempAddr = m_hwp_regs[i].address; tempControl = m_hwp_regs[i].control; // Clear watchpoints in local cache m_hwp_regs[i].control &= ~1; m_hwp_regs[i].address = 0; // Ptrace call to update hardware debug registers error = WriteHardwareDebugRegs(eDREGTypeWATCH); if (error.Fail()) { m_hwp_regs[i].control = tempControl; m_hwp_regs[i].address = tempAddr; return error; } } } return Status(); } uint32_t NativeRegisterContextLinux_arm64::GetWatchpointSize(uint32_t wp_index) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); LLDB_LOG(log, "wp_index: {0}", wp_index); switch ((m_hwp_regs[wp_index].control >> 5) & 0xff) { case 0x01: return 1; case 0x03: return 2; case 0x0f: return 4; case 0xff: return 8; default: return 0; } } bool NativeRegisterContextLinux_arm64::WatchpointIsEnabled(uint32_t wp_index) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); LLDB_LOG(log, "wp_index: {0}", wp_index); if ((m_hwp_regs[wp_index].control & 0x1) == 0x1) return true; else return false; } Status NativeRegisterContextLinux_arm64::GetWatchpointHitIndex( uint32_t &wp_index, lldb::addr_t trap_addr) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr); uint32_t watch_size; lldb::addr_t watch_addr; for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) { watch_size = GetWatchpointSize(wp_index); watch_addr = m_hwp_regs[wp_index].address; if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr && trap_addr < watch_addr + watch_size) { m_hwp_regs[wp_index].hit_addr = trap_addr; return Status(); } } wp_index = LLDB_INVALID_INDEX32; return Status(); } lldb::addr_t NativeRegisterContextLinux_arm64::GetWatchpointAddress(uint32_t wp_index) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); LLDB_LOG(log, "wp_index: {0}", wp_index); if (wp_index >= m_max_hwp_supported) return LLDB_INVALID_ADDRESS; if (WatchpointIsEnabled(wp_index)) return m_hwp_regs[wp_index].real_addr; else return LLDB_INVALID_ADDRESS; } lldb::addr_t NativeRegisterContextLinux_arm64::GetWatchpointHitAddress(uint32_t wp_index) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); LLDB_LOG(log, "wp_index: {0}", wp_index); if (wp_index >= m_max_hwp_supported) return LLDB_INVALID_ADDRESS; if (WatchpointIsEnabled(wp_index)) return m_hwp_regs[wp_index].hit_addr; else return LLDB_INVALID_ADDRESS; } Status NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() { if (!m_refresh_hwdebug_info) { return Status(); } ::pid_t tid = m_thread.GetID(); int regset = NT_ARM_HW_WATCH; struct iovec ioVec; struct user_hwdebug_state dreg_state; Status error; ioVec.iov_base = &dreg_state; ioVec.iov_len = sizeof(dreg_state); error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, &ioVec, ioVec.iov_len); if (error.Fail()) return error; m_max_hwp_supported = dreg_state.dbg_info & 0xff; regset = NT_ARM_HW_BREAK; error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, &ioVec, ioVec.iov_len); if (error.Fail()) return error; m_max_hbp_supported = dreg_state.dbg_info & 0xff; m_refresh_hwdebug_info = false; return error; } Status NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(int hwbType) { struct iovec ioVec; struct user_hwdebug_state dreg_state; Status error; memset(&dreg_state, 0, sizeof(dreg_state)); ioVec.iov_base = &dreg_state; if (hwbType == eDREGTypeWATCH) { hwbType = NT_ARM_HW_WATCH; ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) + (sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported); for (uint32_t i = 0; i < m_max_hwp_supported; i++) { dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address; dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control; } } else { hwbType = NT_ARM_HW_BREAK; ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) + (sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported); for (uint32_t i = 0; i < m_max_hbp_supported; i++) { dreg_state.dbg_regs[i].addr = m_hbr_regs[i].address; dreg_state.dbg_regs[i].ctrl = m_hbr_regs[i].control; } } return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), &hwbType, &ioVec, ioVec.iov_len); } Status NativeRegisterContextLinux_arm64::DoReadRegisterValue( uint32_t offset, const char *reg_name, uint32_t size, RegisterValue &value) { Status error; if (offset > sizeof(struct user_pt_regs)) { - uintptr_t offset = offset - sizeof(struct user_pt_regs); + offset -= sizeof(struct user_pt_regs); if (offset > sizeof(struct user_fpsimd_state)) { error.SetErrorString("invalid offset value"); return error; } elf_fpregset_t regs; int regset = NT_FPREGSET; struct iovec ioVec; ioVec.iov_base = ®s; ioVec.iov_len = sizeof regs; error = NativeProcessLinux::PtraceWrapper( PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, sizeof regs); if (error.Success()) { ArchSpec arch; if (m_thread.GetProcess()->GetArchitecture(arch)) value.SetBytes((void *)(((unsigned char *)(®s)) + offset), 16, arch.GetByteOrder()); else error.SetErrorString("failed to get architecture"); } } else { elf_gregset_t regs; int regset = NT_PRSTATUS; struct iovec ioVec; ioVec.iov_base = ®s; ioVec.iov_len = sizeof regs; error = NativeProcessLinux::PtraceWrapper( PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, sizeof regs); if (error.Success()) { ArchSpec arch; if (m_thread.GetProcess()->GetArchitecture(arch)) value.SetBytes((void *)(((unsigned char *)(regs)) + offset), 8, arch.GetByteOrder()); else error.SetErrorString("failed to get architecture"); } } return error; } Status NativeRegisterContextLinux_arm64::DoWriteRegisterValue( uint32_t offset, const char *reg_name, const RegisterValue &value) { Status error; ::pid_t tid = m_thread.GetID(); if (offset > sizeof(struct user_pt_regs)) { - uintptr_t offset = offset - sizeof(struct user_pt_regs); + offset -= sizeof(struct user_pt_regs); if (offset > sizeof(struct user_fpsimd_state)) { error.SetErrorString("invalid offset value"); return error; } elf_fpregset_t regs; int regset = NT_FPREGSET; struct iovec ioVec; ioVec.iov_base = ®s; ioVec.iov_len = sizeof regs; error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, &ioVec, sizeof regs); if (error.Success()) { ::memcpy((void *)(((unsigned char *)(®s)) + offset), value.GetBytes(), 16); error = NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, tid, ®set, &ioVec, sizeof regs); } } else { elf_gregset_t regs; int regset = NT_PRSTATUS; struct iovec ioVec; ioVec.iov_base = ®s; ioVec.iov_len = sizeof regs; error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, &ioVec, sizeof regs); if (error.Success()) { ::memcpy((void *)(((unsigned char *)(®s)) + offset), value.GetBytes(), 8); error = NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, tid, ®set, &ioVec, sizeof regs); } } return error; } Status NativeRegisterContextLinux_arm64::DoReadGPR(void *buf, size_t buf_size) { int regset = NT_PRSTATUS; struct iovec ioVec; Status error; ioVec.iov_base = buf; ioVec.iov_len = buf_size; return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, buf_size); } Status NativeRegisterContextLinux_arm64::DoWriteGPR(void *buf, size_t buf_size) { int regset = NT_PRSTATUS; struct iovec ioVec; Status error; ioVec.iov_base = buf; ioVec.iov_len = buf_size; return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), ®set, &ioVec, buf_size); } Status NativeRegisterContextLinux_arm64::DoReadFPR(void *buf, size_t buf_size) { int regset = NT_FPREGSET; struct iovec ioVec; Status error; ioVec.iov_base = buf; ioVec.iov_len = buf_size; return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, buf_size); } Status NativeRegisterContextLinux_arm64::DoWriteFPR(void *buf, size_t buf_size) { int regset = NT_FPREGSET; struct iovec ioVec; Status error; ioVec.iov_base = buf; ioVec.iov_len = buf_size; return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), ®set, &ioVec, buf_size); } uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset( const RegisterInfo *reg_info) const { return reg_info->byte_offset - GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset; } #endif // defined (__arm64__) || defined (__aarch64__) Index: vendor/lldb/dist/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp (revision 320967) @@ -1,1222 +1,1207 @@ //===-- NativeRegisterContextLinux_x86_64.cpp ---------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #if defined(__i386__) || defined(__x86_64__) #include "NativeRegisterContextLinux_x86_64.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/HostInfo.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" #include "Plugins/Process/Utility/RegisterContextLinux_i386.h" #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" #include using namespace lldb_private; using namespace lldb_private::process_linux; // ---------------------------------------------------------------------------- // Private namespace. // ---------------------------------------------------------------------------- namespace { // x86 32-bit general purpose registers. const uint32_t g_gpr_regnums_i386[] = { lldb_eax_i386, lldb_ebx_i386, lldb_ecx_i386, lldb_edx_i386, lldb_edi_i386, lldb_esi_i386, lldb_ebp_i386, lldb_esp_i386, lldb_eip_i386, lldb_eflags_i386, lldb_cs_i386, lldb_fs_i386, lldb_gs_i386, lldb_ss_i386, lldb_ds_i386, lldb_es_i386, lldb_ax_i386, lldb_bx_i386, lldb_cx_i386, lldb_dx_i386, lldb_di_i386, lldb_si_i386, lldb_bp_i386, lldb_sp_i386, lldb_ah_i386, lldb_bh_i386, lldb_ch_i386, lldb_dh_i386, lldb_al_i386, lldb_bl_i386, lldb_cl_i386, lldb_dl_i386, LLDB_INVALID_REGNUM // register sets need to end with this flag }; static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) - 1 == k_num_gpr_registers_i386, "g_gpr_regnums_i386 has wrong number of register infos"); // x86 32-bit floating point registers. const uint32_t g_fpu_regnums_i386[] = { lldb_fctrl_i386, lldb_fstat_i386, lldb_ftag_i386, lldb_fop_i386, lldb_fiseg_i386, lldb_fioff_i386, lldb_foseg_i386, lldb_fooff_i386, lldb_mxcsr_i386, lldb_mxcsrmask_i386, lldb_st0_i386, lldb_st1_i386, lldb_st2_i386, lldb_st3_i386, lldb_st4_i386, lldb_st5_i386, lldb_st6_i386, lldb_st7_i386, lldb_mm0_i386, lldb_mm1_i386, lldb_mm2_i386, lldb_mm3_i386, lldb_mm4_i386, lldb_mm5_i386, lldb_mm6_i386, lldb_mm7_i386, lldb_xmm0_i386, lldb_xmm1_i386, lldb_xmm2_i386, lldb_xmm3_i386, lldb_xmm4_i386, lldb_xmm5_i386, lldb_xmm6_i386, lldb_xmm7_i386, LLDB_INVALID_REGNUM // register sets need to end with this flag }; static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) - 1 == k_num_fpr_registers_i386, "g_fpu_regnums_i386 has wrong number of register infos"); // x86 32-bit AVX registers. const uint32_t g_avx_regnums_i386[] = { lldb_ymm0_i386, lldb_ymm1_i386, lldb_ymm2_i386, lldb_ymm3_i386, lldb_ymm4_i386, lldb_ymm5_i386, lldb_ymm6_i386, lldb_ymm7_i386, LLDB_INVALID_REGNUM // register sets need to end with this flag }; static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) - 1 == k_num_avx_registers_i386, " g_avx_regnums_i386 has wrong number of register infos"); // x64 32-bit MPX registers. static const uint32_t g_mpx_regnums_i386[] = { lldb_bnd0_i386, lldb_bnd1_i386, lldb_bnd2_i386, lldb_bnd3_i386, lldb_bndcfgu_i386, lldb_bndstatus_i386, LLDB_INVALID_REGNUM // register sets need to end with this flag }; static_assert((sizeof(g_mpx_regnums_i386) / sizeof(g_mpx_regnums_i386[0])) - 1 == k_num_mpx_registers_i386, "g_mpx_regnums_x86_64 has wrong number of register infos"); // x86 64-bit general purpose registers. static const uint32_t g_gpr_regnums_x86_64[] = { lldb_rax_x86_64, lldb_rbx_x86_64, lldb_rcx_x86_64, lldb_rdx_x86_64, lldb_rdi_x86_64, lldb_rsi_x86_64, lldb_rbp_x86_64, lldb_rsp_x86_64, lldb_r8_x86_64, lldb_r9_x86_64, lldb_r10_x86_64, lldb_r11_x86_64, lldb_r12_x86_64, lldb_r13_x86_64, lldb_r14_x86_64, lldb_r15_x86_64, lldb_rip_x86_64, lldb_rflags_x86_64, lldb_cs_x86_64, lldb_fs_x86_64, lldb_gs_x86_64, lldb_ss_x86_64, lldb_ds_x86_64, lldb_es_x86_64, lldb_eax_x86_64, lldb_ebx_x86_64, lldb_ecx_x86_64, lldb_edx_x86_64, lldb_edi_x86_64, lldb_esi_x86_64, lldb_ebp_x86_64, lldb_esp_x86_64, lldb_r8d_x86_64, // Low 32 bits or r8 lldb_r9d_x86_64, // Low 32 bits or r9 lldb_r10d_x86_64, // Low 32 bits or r10 lldb_r11d_x86_64, // Low 32 bits or r11 lldb_r12d_x86_64, // Low 32 bits or r12 lldb_r13d_x86_64, // Low 32 bits or r13 lldb_r14d_x86_64, // Low 32 bits or r14 lldb_r15d_x86_64, // Low 32 bits or r15 lldb_ax_x86_64, lldb_bx_x86_64, lldb_cx_x86_64, lldb_dx_x86_64, lldb_di_x86_64, lldb_si_x86_64, lldb_bp_x86_64, lldb_sp_x86_64, lldb_r8w_x86_64, // Low 16 bits or r8 lldb_r9w_x86_64, // Low 16 bits or r9 lldb_r10w_x86_64, // Low 16 bits or r10 lldb_r11w_x86_64, // Low 16 bits or r11 lldb_r12w_x86_64, // Low 16 bits or r12 lldb_r13w_x86_64, // Low 16 bits or r13 lldb_r14w_x86_64, // Low 16 bits or r14 lldb_r15w_x86_64, // Low 16 bits or r15 lldb_ah_x86_64, lldb_bh_x86_64, lldb_ch_x86_64, lldb_dh_x86_64, lldb_al_x86_64, lldb_bl_x86_64, lldb_cl_x86_64, lldb_dl_x86_64, lldb_dil_x86_64, lldb_sil_x86_64, lldb_bpl_x86_64, lldb_spl_x86_64, lldb_r8l_x86_64, // Low 8 bits or r8 lldb_r9l_x86_64, // Low 8 bits or r9 lldb_r10l_x86_64, // Low 8 bits or r10 lldb_r11l_x86_64, // Low 8 bits or r11 lldb_r12l_x86_64, // Low 8 bits or r12 lldb_r13l_x86_64, // Low 8 bits or r13 lldb_r14l_x86_64, // Low 8 bits or r14 lldb_r15l_x86_64, // Low 8 bits or r15 LLDB_INVALID_REGNUM // register sets need to end with this flag }; static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) - 1 == k_num_gpr_registers_x86_64, "g_gpr_regnums_x86_64 has wrong number of register infos"); // x86 64-bit floating point registers. static const uint32_t g_fpu_regnums_x86_64[] = { lldb_fctrl_x86_64, lldb_fstat_x86_64, lldb_ftag_x86_64, lldb_fop_x86_64, lldb_fiseg_x86_64, lldb_fioff_x86_64, lldb_foseg_x86_64, lldb_fooff_x86_64, lldb_mxcsr_x86_64, lldb_mxcsrmask_x86_64, lldb_st0_x86_64, lldb_st1_x86_64, lldb_st2_x86_64, lldb_st3_x86_64, lldb_st4_x86_64, lldb_st5_x86_64, lldb_st6_x86_64, lldb_st7_x86_64, lldb_mm0_x86_64, lldb_mm1_x86_64, lldb_mm2_x86_64, lldb_mm3_x86_64, lldb_mm4_x86_64, lldb_mm5_x86_64, lldb_mm6_x86_64, lldb_mm7_x86_64, lldb_xmm0_x86_64, lldb_xmm1_x86_64, lldb_xmm2_x86_64, lldb_xmm3_x86_64, lldb_xmm4_x86_64, lldb_xmm5_x86_64, lldb_xmm6_x86_64, lldb_xmm7_x86_64, lldb_xmm8_x86_64, lldb_xmm9_x86_64, lldb_xmm10_x86_64, lldb_xmm11_x86_64, lldb_xmm12_x86_64, lldb_xmm13_x86_64, lldb_xmm14_x86_64, lldb_xmm15_x86_64, LLDB_INVALID_REGNUM // register sets need to end with this flag }; static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) - 1 == k_num_fpr_registers_x86_64, "g_fpu_regnums_x86_64 has wrong number of register infos"); // x86 64-bit AVX registers. static const uint32_t g_avx_regnums_x86_64[] = { lldb_ymm0_x86_64, lldb_ymm1_x86_64, lldb_ymm2_x86_64, lldb_ymm3_x86_64, lldb_ymm4_x86_64, lldb_ymm5_x86_64, lldb_ymm6_x86_64, lldb_ymm7_x86_64, lldb_ymm8_x86_64, lldb_ymm9_x86_64, lldb_ymm10_x86_64, lldb_ymm11_x86_64, lldb_ymm12_x86_64, lldb_ymm13_x86_64, lldb_ymm14_x86_64, lldb_ymm15_x86_64, LLDB_INVALID_REGNUM // register sets need to end with this flag }; static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) - 1 == k_num_avx_registers_x86_64, "g_avx_regnums_x86_64 has wrong number of register infos"); // x86 64-bit MPX registers. static const uint32_t g_mpx_regnums_x86_64[] = { lldb_bnd0_x86_64, lldb_bnd1_x86_64, lldb_bnd2_x86_64, lldb_bnd3_x86_64, lldb_bndcfgu_x86_64, lldb_bndstatus_x86_64, LLDB_INVALID_REGNUM // register sets need to end with this flag }; static_assert((sizeof(g_mpx_regnums_x86_64) / sizeof(g_mpx_regnums_x86_64[0])) - 1 == k_num_mpx_registers_x86_64, "g_mpx_regnums_x86_64 has wrong number of register infos"); // Number of register sets provided by this context. enum { k_num_extended_register_sets = 2, k_num_register_sets = 4 }; // Register sets for x86 32-bit. static const RegisterSet g_reg_sets_i386[k_num_register_sets] = { {"General Purpose Registers", "gpr", k_num_gpr_registers_i386, g_gpr_regnums_i386}, {"Floating Point Registers", "fpu", k_num_fpr_registers_i386, g_fpu_regnums_i386}, {"Advanced Vector Extensions", "avx", k_num_avx_registers_i386, g_avx_regnums_i386}, { "Memory Protection Extensions", "mpx", k_num_mpx_registers_i386, g_mpx_regnums_i386}}; // Register sets for x86 64-bit. static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = { {"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64, g_gpr_regnums_x86_64}, {"Floating Point Registers", "fpu", k_num_fpr_registers_x86_64, g_fpu_regnums_x86_64}, {"Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64, g_avx_regnums_x86_64}, { "Memory Protection Extensions", "mpx", k_num_mpx_registers_x86_64, g_mpx_regnums_x86_64}}; } #define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize() + sizeof(FPR)) // ---------------------------------------------------------------------------- // Required ptrace defines. // ---------------------------------------------------------------------------- // Support ptrace extensions even when compiled without required kernel support #ifndef NT_X86_XSTATE #define NT_X86_XSTATE 0x202 #endif #ifndef NT_PRXFPREG #define NT_PRXFPREG 0x46e62b7f #endif // On x86_64 NT_PRFPREG is used to access the FXSAVE area. On i386, we need to // use NT_PRXFPREG. static inline unsigned int fxsr_regset(const ArchSpec &arch) { return arch.GetAddressByteSize() == 8 ? NT_PRFPREG : NT_PRXFPREG; } // ---------------------------------------------------------------------------- // Required MPX define. // ---------------------------------------------------------------------------- // Support MPX extensions also if compiled with compiler without MPX support. #ifndef bit_MPX #define bit_MPX 0x4000 #endif // ---------------------------------------------------------------------------- // XCR0 extended register sets masks. // ---------------------------------------------------------------------------- #define mask_XSTATE_AVX (1ULL << 2) #define mask_XSTATE_BNDREGS (1ULL << 3) #define mask_XSTATE_BNDCFG (1ULL << 4) #define mask_XSTATE_MPX (mask_XSTATE_BNDREGS | mask_XSTATE_BNDCFG) NativeRegisterContextLinux * NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( const ArchSpec &target_arch, NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx) { return new NativeRegisterContextLinux_x86_64(target_arch, native_thread, concrete_frame_idx); } // ---------------------------------------------------------------------------- // NativeRegisterContextLinux_x86_64 members. // ---------------------------------------------------------------------------- static RegisterInfoInterface * CreateRegisterInfoInterface(const ArchSpec &target_arch) { if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) { // 32-bit hosts run with a RegisterContextLinux_i386 context. return new RegisterContextLinux_i386(target_arch); } else { assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && "Register setting path assumes this is a 64-bit host"); // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the // x86_64 register context. return new RegisterContextLinux_x86_64(target_arch); } } NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64( const ArchSpec &target_arch, NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx) : NativeRegisterContextLinux(native_thread, concrete_frame_idx, CreateRegisterInfoInterface(target_arch)), m_xstate_type(XStateType::Invalid), m_fpr(), m_iovec(), m_ymm_set(), m_mpx_set(), m_reg_info(), m_gpr_x86_64() { // Set up data about ranges of valid registers. switch (target_arch.GetMachine()) { case llvm::Triple::x86: m_reg_info.num_registers = k_num_registers_i386; m_reg_info.num_gpr_registers = k_num_gpr_registers_i386; m_reg_info.num_fpr_registers = k_num_fpr_registers_i386; m_reg_info.num_avx_registers = k_num_avx_registers_i386; m_reg_info.num_mpx_registers = k_num_mpx_registers_i386; m_reg_info.last_gpr = k_last_gpr_i386; m_reg_info.first_fpr = k_first_fpr_i386; m_reg_info.last_fpr = k_last_fpr_i386; m_reg_info.first_st = lldb_st0_i386; m_reg_info.last_st = lldb_st7_i386; m_reg_info.first_mm = lldb_mm0_i386; m_reg_info.last_mm = lldb_mm7_i386; m_reg_info.first_xmm = lldb_xmm0_i386; m_reg_info.last_xmm = lldb_xmm7_i386; m_reg_info.first_ymm = lldb_ymm0_i386; m_reg_info.last_ymm = lldb_ymm7_i386; m_reg_info.first_mpxr = lldb_bnd0_i386; m_reg_info.last_mpxr = lldb_bnd3_i386; m_reg_info.first_mpxc = lldb_bndcfgu_i386; m_reg_info.last_mpxc = lldb_bndstatus_i386; m_reg_info.first_dr = lldb_dr0_i386; m_reg_info.gpr_flags = lldb_eflags_i386; break; case llvm::Triple::x86_64: m_reg_info.num_registers = k_num_registers_x86_64; m_reg_info.num_gpr_registers = k_num_gpr_registers_x86_64; m_reg_info.num_fpr_registers = k_num_fpr_registers_x86_64; m_reg_info.num_avx_registers = k_num_avx_registers_x86_64; m_reg_info.num_mpx_registers = k_num_mpx_registers_x86_64; m_reg_info.last_gpr = k_last_gpr_x86_64; m_reg_info.first_fpr = k_first_fpr_x86_64; m_reg_info.last_fpr = k_last_fpr_x86_64; m_reg_info.first_st = lldb_st0_x86_64; m_reg_info.last_st = lldb_st7_x86_64; m_reg_info.first_mm = lldb_mm0_x86_64; m_reg_info.last_mm = lldb_mm7_x86_64; m_reg_info.first_xmm = lldb_xmm0_x86_64; m_reg_info.last_xmm = lldb_xmm15_x86_64; m_reg_info.first_ymm = lldb_ymm0_x86_64; m_reg_info.last_ymm = lldb_ymm15_x86_64; m_reg_info.first_mpxr = lldb_bnd0_x86_64; m_reg_info.last_mpxr = lldb_bnd3_x86_64; m_reg_info.first_mpxc = lldb_bndcfgu_x86_64; m_reg_info.last_mpxc = lldb_bndstatus_x86_64; m_reg_info.first_dr = lldb_dr0_x86_64; m_reg_info.gpr_flags = lldb_rflags_x86_64; break; default: assert(false && "Unhandled target architecture."); break; } // Initialize m_iovec to point to the buffer and buffer size // using the conventions of Berkeley style UIO structures, as required // by PTRACE extensions. m_iovec.iov_base = &m_fpr.xstate.xsave; m_iovec.iov_len = sizeof(m_fpr.xstate.xsave); // Clear out the FPR state. ::memset(&m_fpr, 0, sizeof(FPR)); // Store byte offset of fctrl (i.e. first register of FPR) const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl"); m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset; } // CONSIDER after local and llgs debugging are merged, register set support can // be moved into a base x86-64 class with IsRegisterSetAvailable made virtual. uint32_t NativeRegisterContextLinux_x86_64::GetRegisterSetCount() const { uint32_t sets = 0; for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { if (IsRegisterSetAvailable(set_index)) ++sets; } return sets; } uint32_t NativeRegisterContextLinux_x86_64::GetUserRegisterCount() const { uint32_t count = 0; for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { const RegisterSet *set = GetRegisterSet(set_index); if (set) count += set->num_registers; } return count; } const RegisterSet * NativeRegisterContextLinux_x86_64::GetRegisterSet(uint32_t set_index) const { if (!IsRegisterSetAvailable(set_index)) return nullptr; switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { case llvm::Triple::x86: return &g_reg_sets_i386[set_index]; case llvm::Triple::x86_64: return &g_reg_sets_x86_64[set_index]; default: assert(false && "Unhandled target architecture."); return nullptr; } return nullptr; } Status NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) { Status error; if (!reg_info) { error.SetErrorString("reg_info NULL"); return error; } const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; if (reg == LLDB_INVALID_REGNUM) { // This is likely an internal register for lldb use only and should not be // directly queried. error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb " "register, cannot read directly", reg_info->name); return error; } if (IsFPR(reg) || IsAVX(reg) || IsMPX(reg)) { error = ReadFPR(); if (error.Fail()) return error; } else { uint32_t full_reg = reg; bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); if (is_subreg) { // Read the full aligned 64-bit register. full_reg = reg_info->invalidate_regs[0]; } error = ReadRegisterRaw(full_reg, reg_value); if (error.Success()) { // If our read was not aligned (for ah,bh,ch,dh), shift our returned value // one byte to the right. if (is_subreg && (reg_info->byte_offset & 0x1)) reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); // If our return byte size was greater than the return value reg size, // then // use the type specified by reg_info rather than the uint64_t default if (reg_value.GetByteSize() > reg_info->byte_size) reg_value.SetType(reg_info); } return error; } if (reg_info->encoding == lldb::eEncodingVector) { lldb::ByteOrder byte_order = GetByteOrder(); if (byte_order != lldb::eByteOrderInvalid) { if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st) reg_value.SetBytes( m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, reg_info->byte_size, byte_order); if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm) reg_value.SetBytes( m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, reg_info->byte_size, byte_order); if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm) reg_value.SetBytes( m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, reg_info->byte_size, byte_order); if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) { // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes if (CopyXSTATEtoYMM(reg, byte_order)) reg_value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, reg_info->byte_size, byte_order); else { error.SetErrorString("failed to copy ymm register value"); return error; } } if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) { if (CopyXSTATEtoMPX(reg)) reg_value.SetBytes(m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, reg_info->byte_size, byte_order); else { error.SetErrorString("failed to copy mpx register value"); return error; } } if (reg >= m_reg_info.first_mpxc && reg <= m_reg_info.last_mpxc) { if (CopyXSTATEtoMPX(reg)) reg_value.SetBytes(m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, reg_info->byte_size, byte_order); else { error.SetErrorString("failed to copy mpx register value"); return error; } } if (reg_value.GetType() != RegisterValue::eTypeBytes) error.SetErrorString( "write failed - type was expected to be RegisterValue::eTypeBytes"); return error; } error.SetErrorString("byte order is invalid"); return error; } // Get pointer to m_fpr.xstate.fxsave variable and set the data from it. // Byte offsets of all registers are calculated wrt 'UserArea' structure. // However, ReadFPR() reads fpu registers {using ptrace(PTRACE_GETFPREGS,..)} // and stores them in 'm_fpr' (of type FPR structure). To extract values of // fpu // registers, m_fpr should be read at byte offsets calculated wrt to FPR // structure. // Since, FPR structure is also one of the member of UserArea structure. // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - // byte_offset(fctrl wrt UserArea) assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr)); uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea; switch (reg_info->byte_size) { case 1: reg_value.SetUInt8(*(uint8_t *)src); break; case 2: reg_value.SetUInt16(*(uint16_t *)src); break; case 4: reg_value.SetUInt32(*(uint32_t *)src); break; case 8: reg_value.SetUInt64(*(uint64_t *)src); break; default: assert(false && "Unhandled data size."); error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32, reg_info->byte_size); break; } return error; } Status NativeRegisterContextLinux_x86_64::WriteRegister( const RegisterInfo *reg_info, const RegisterValue ®_value) { assert(reg_info && "reg_info is null"); const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; if (reg_index == LLDB_INVALID_REGNUM) return Status("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : ""); if (IsGPR(reg_index)) return WriteRegisterRaw(reg_index, reg_value); if (IsFPR(reg_index) || IsAVX(reg_index) || IsMPX(reg_index)) { if (reg_info->encoding == lldb::eEncodingVector) { if (reg_index >= m_reg_info.first_st && reg_index <= m_reg_info.last_st) ::memcpy( m_fpr.xstate.fxsave.stmm[reg_index - m_reg_info.first_st].bytes, reg_value.GetBytes(), reg_value.GetByteSize()); if (reg_index >= m_reg_info.first_mm && reg_index <= m_reg_info.last_mm) ::memcpy( m_fpr.xstate.fxsave.stmm[reg_index - m_reg_info.first_mm].bytes, reg_value.GetBytes(), reg_value.GetByteSize()); if (reg_index >= m_reg_info.first_xmm && reg_index <= m_reg_info.last_xmm) ::memcpy( m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes, reg_value.GetBytes(), reg_value.GetByteSize()); if (reg_index >= m_reg_info.first_ymm && reg_index <= m_reg_info.last_ymm) { // Store ymm register content, and split into the register halves in // xmm.bytes and ymmh.bytes ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes, reg_value.GetBytes(), reg_value.GetByteSize()); if (!CopyYMMtoXSTATE(reg_index, GetByteOrder())) return Status("CopyYMMtoXSTATE() failed"); } if (reg_index >= m_reg_info.first_mpxr && reg_index <= m_reg_info.last_mpxr) { ::memcpy(m_mpx_set.mpxr[reg_index - m_reg_info.first_mpxr].bytes, reg_value.GetBytes(), reg_value.GetByteSize()); if (!CopyMPXtoXSTATE(reg_index)) return Status("CopyMPXtoXSTATE() failed"); } if (reg_index >= m_reg_info.first_mpxc && reg_index <= m_reg_info.last_mpxc) { ::memcpy(m_mpx_set.mpxc[reg_index - m_reg_info.first_mpxc].bytes, reg_value.GetBytes(), reg_value.GetByteSize()); if (!CopyMPXtoXSTATE(reg_index)) return Status("CopyMPXtoXSTATE() failed"); } } else { // Get pointer to m_fpr.xstate.fxsave variable and set the data to it. // Byte offsets of all registers are calculated wrt 'UserArea' structure. // However, WriteFPR() takes m_fpr (of type FPR structure) and writes only // fpu // registers using ptrace(PTRACE_SETFPREGS,..) API. Hence fpu registers // should // be written in m_fpr at byte offsets calculated wrt FPR structure. // Since, FPR structure is also one of the member of UserArea structure. // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - // byte_offset(fctrl wrt UserArea) assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr)); uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea; switch (reg_info->byte_size) { case 1: *(uint8_t *)dst = reg_value.GetAsUInt8(); break; case 2: *(uint16_t *)dst = reg_value.GetAsUInt16(); break; case 4: *(uint32_t *)dst = reg_value.GetAsUInt32(); break; case 8: *(uint64_t *)dst = reg_value.GetAsUInt64(); break; default: assert(false && "Unhandled data size."); return Status("unhandled register data size %" PRIu32, reg_info->byte_size); } } Status error = WriteFPR(); if (error.Fail()) return error; if (IsAVX(reg_index)) { if (!CopyYMMtoXSTATE(reg_index, GetByteOrder())) return Status("CopyYMMtoXSTATE() failed"); } if (IsMPX(reg_index)) { if (!CopyMPXtoXSTATE(reg_index)) return Status("CopyMPXtoXSTATE() failed"); } return Status(); } return Status("failed - register wasn't recognized to be a GPR or an FPR, " "write strategy unknown"); } Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues( lldb::DataBufferSP &data_sp) { Status error; data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); - if (!data_sp) { - error.SetErrorStringWithFormat( - "failed to allocate DataBufferHeap instance of size %" PRIu64, - REG_CONTEXT_SIZE); - return error; - } - error = ReadGPR(); if (error.Fail()) return error; error = ReadFPR(); if (error.Fail()) return error; uint8_t *dst = data_sp->GetBytes(); - if (dst == nullptr) { - error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 - " returned a null pointer", - REG_CONTEXT_SIZE); - return error; - } - ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize()); dst += GetRegisterInfoInterface().GetGPRSize(); if (m_xstate_type == XStateType::FXSAVE) ::memcpy(dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave)); else if (m_xstate_type == XStateType::XSAVE) { lldb::ByteOrder byte_order = GetByteOrder(); if (IsCPUFeatureAvailable(RegSet::avx)) { // Assemble the YMM register content from the register halves. for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm; ++reg) { if (!CopyXSTATEtoYMM(reg, byte_order)) { error.SetErrorStringWithFormat( "NativeRegisterContextLinux_x86_64::%s " "CopyXSTATEtoYMM() failed for reg num " "%" PRIu32, __FUNCTION__, reg); return error; } } } if (IsCPUFeatureAvailable(RegSet::mpx)) { for (uint32_t reg = m_reg_info.first_mpxr; reg <= m_reg_info.last_mpxc; ++reg) { if (!CopyXSTATEtoMPX(reg)) { error.SetErrorStringWithFormat( "NativeRegisterContextLinux_x86_64::%s " "CopyXSTATEtoMPX() failed for reg num " "%" PRIu32, __FUNCTION__, reg); return error; } } } // Copy the extended register state including the assembled ymm registers. ::memcpy(dst, &m_fpr, sizeof(m_fpr)); } else { assert(false && "how do we save the floating point registers?"); error.SetErrorString("unsure how to save the floating point registers"); } /** The following code is specific to Linux x86 based architectures, * where the register orig_eax (32 bit)/orig_rax (64 bit) is set to * -1 to solve the bug 23659, such a setting prevents the automatic * decrement of the instruction pointer which was causing the SIGILL * exception. * **/ RegisterValue value((uint64_t)-1); const RegisterInfo *reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_eax"); if (reg_info == nullptr) reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_rax"); if (reg_info != nullptr) return DoWriteRegisterValue(reg_info->byte_offset, reg_info->name, value); return error; } Status NativeRegisterContextLinux_x86_64::WriteAllRegisterValues( const lldb::DataBufferSP &data_sp) { Status error; if (!data_sp) { error.SetErrorStringWithFormat( "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", __FUNCTION__); return error; } if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched " - "data size, expected %" PRIu64 ", actual %" PRIu64, - __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); + error.SetErrorStringWithFormatv( + "data_sp contained mismatched data size, expected {0}, actual {1}", + REG_CONTEXT_SIZE, data_sp->GetByteSize()); return error; } uint8_t *src = data_sp->GetBytes(); if (src == nullptr) { error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s " "DataBuffer::GetBytes() returned a null " "pointer", __FUNCTION__); return error; } ::memcpy(&m_gpr_x86_64, src, GetRegisterInfoInterface().GetGPRSize()); error = WriteGPR(); if (error.Fail()) return error; src += GetRegisterInfoInterface().GetGPRSize(); if (m_xstate_type == XStateType::FXSAVE) ::memcpy(&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave)); else if (m_xstate_type == XStateType::XSAVE) ::memcpy(&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave)); error = WriteFPR(); if (error.Fail()) return error; if (m_xstate_type == XStateType::XSAVE) { lldb::ByteOrder byte_order = GetByteOrder(); if (IsCPUFeatureAvailable(RegSet::avx)) { // Parse the YMM register content from the register halves. for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm; ++reg) { if (!CopyYMMtoXSTATE(reg, byte_order)) { error.SetErrorStringWithFormat( "NativeRegisterContextLinux_x86_64::%s " "CopyYMMtoXSTATE() failed for reg num " "%" PRIu32, __FUNCTION__, reg); return error; } } } if (IsCPUFeatureAvailable(RegSet::mpx)) { for (uint32_t reg = m_reg_info.first_mpxr; reg <= m_reg_info.last_mpxc; ++reg) { if (!CopyMPXtoXSTATE(reg)) { error.SetErrorStringWithFormat( "NativeRegisterContextLinux_x86_64::%s " "CopyMPXtoXSTATE() failed for reg num " "%" PRIu32, __FUNCTION__, reg); return error; } } } } return error; } bool NativeRegisterContextLinux_x86_64::IsCPUFeatureAvailable( RegSet feature_code) const { if (m_xstate_type == XStateType::Invalid) { if (const_cast(this)->ReadFPR().Fail()) return false; } switch (feature_code) { case RegSet::gpr: case RegSet::fpu: return true; case RegSet::avx: // Check if CPU has AVX and if there is kernel support, by // reading in the XCR0 area of XSAVE. if ((m_fpr.xstate.xsave.i387.xcr0 & mask_XSTATE_AVX) == mask_XSTATE_AVX) return true; break; case RegSet::mpx: // Check if CPU has MPX and if there is kernel support, by // reading in the XCR0 area of XSAVE. if ((m_fpr.xstate.xsave.i387.xcr0 & mask_XSTATE_MPX) == mask_XSTATE_MPX) return true; break; } return false; } bool NativeRegisterContextLinux_x86_64::IsRegisterSetAvailable( uint32_t set_index) const { uint32_t num_sets = k_num_register_sets - k_num_extended_register_sets; switch (static_cast(set_index)) { case RegSet::gpr: case RegSet::fpu: return (set_index < num_sets); case RegSet::avx: return IsCPUFeatureAvailable(RegSet::avx); case RegSet::mpx: return IsCPUFeatureAvailable(RegSet::mpx); } return false; } bool NativeRegisterContextLinux_x86_64::IsGPR(uint32_t reg_index) const { // GPRs come first. return reg_index <= m_reg_info.last_gpr; } bool NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index) const { return (m_reg_info.first_fpr <= reg_index && reg_index <= m_reg_info.last_fpr); } Status NativeRegisterContextLinux_x86_64::WriteFPR() { switch (m_xstate_type) { case XStateType::FXSAVE: return WriteRegisterSet( &m_iovec, sizeof(m_fpr.xstate.xsave), fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture())); case XStateType::XSAVE: return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); default: return Status("Unrecognized FPR type."); } } bool NativeRegisterContextLinux_x86_64::IsAVX(uint32_t reg_index) const { if (!IsCPUFeatureAvailable(RegSet::avx)) return false; return (m_reg_info.first_ymm <= reg_index && reg_index <= m_reg_info.last_ymm); } bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM( uint32_t reg_index, lldb::ByteOrder byte_order) { if (!IsAVX(reg_index)) return false; if (byte_order == lldb::eByteOrderLittle) { ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes, m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes, sizeof(XMMReg)); ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes + sizeof(XMMReg), m_fpr.xstate.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, sizeof(YMMHReg)); return true; } if (byte_order == lldb::eByteOrderBig) { ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes + sizeof(XMMReg), m_fpr.xstate.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes, sizeof(XMMReg)); ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes, m_fpr.xstate.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, sizeof(YMMHReg)); return true; } return false; // unsupported or invalid byte order } bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE( uint32_t reg, lldb::ByteOrder byte_order) { if (!IsAVX(reg)) return false; if (byte_order == lldb::eByteOrderLittle) { ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(XMMReg)); ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), sizeof(YMMHReg)); return true; } if (byte_order == lldb::eByteOrderBig) { ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), sizeof(XMMReg)); ::memcpy(m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(YMMHReg)); return true; } return false; // unsupported or invalid byte order } void *NativeRegisterContextLinux_x86_64::GetFPRBuffer() { switch (m_xstate_type) { case XStateType::FXSAVE: return &m_fpr.xstate.fxsave; case XStateType::XSAVE: return &m_iovec; default: return nullptr; } } size_t NativeRegisterContextLinux_x86_64::GetFPRSize() { switch (m_xstate_type) { case XStateType::FXSAVE: return sizeof(m_fpr.xstate.fxsave); case XStateType::XSAVE: return sizeof(m_iovec); default: return 0; } } Status NativeRegisterContextLinux_x86_64::ReadFPR() { Status error; // Probe XSAVE and if it is not supported fall back to FXSAVE. if (m_xstate_type != XStateType::FXSAVE) { error = ReadRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); if (!error.Fail()) { m_xstate_type = XStateType::XSAVE; return error; } } error = ReadRegisterSet( &m_iovec, sizeof(m_fpr.xstate.xsave), fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture())); if (!error.Fail()) { m_xstate_type = XStateType::FXSAVE; return error; } return Status("Unrecognized FPR type."); } bool NativeRegisterContextLinux_x86_64::IsMPX(uint32_t reg_index) const { if (!IsCPUFeatureAvailable(RegSet::mpx)) return false; return (m_reg_info.first_mpxr <= reg_index && reg_index <= m_reg_info.last_mpxc); } bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoMPX(uint32_t reg) { if (!IsMPX(reg)) return false; if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) { ::memcpy(m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, m_fpr.xstate.xsave.mpxr[reg - m_reg_info.first_mpxr].bytes, sizeof(MPXReg)); } else { ::memcpy(m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, m_fpr.xstate.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes, sizeof(MPXCsr)); } return true; } bool NativeRegisterContextLinux_x86_64::CopyMPXtoXSTATE(uint32_t reg) { if (!IsMPX(reg)) return false; if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) { ::memcpy(m_fpr.xstate.xsave.mpxr[reg - m_reg_info.first_mpxr].bytes, m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, sizeof(MPXReg)); } else { ::memcpy(m_fpr.xstate.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes, m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, sizeof(MPXCsr)); } return true; } Status NativeRegisterContextLinux_x86_64::IsWatchpointHit(uint32_t wp_index, bool &is_hit) { if (wp_index >= NumSupportedHardwareWatchpoints()) return Status("Watchpoint index out of range"); RegisterValue reg_value; Status error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value); if (error.Fail()) { is_hit = false; return error; } uint64_t status_bits = reg_value.GetAsUInt64(); is_hit = status_bits & (1 << wp_index); return error; } Status NativeRegisterContextLinux_x86_64::GetWatchpointHitIndex( uint32_t &wp_index, lldb::addr_t trap_addr) { uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) { bool is_hit; Status error = IsWatchpointHit(wp_index, is_hit); if (error.Fail()) { wp_index = LLDB_INVALID_INDEX32; return error; } else if (is_hit) { return error; } } wp_index = LLDB_INVALID_INDEX32; return Status(); } Status NativeRegisterContextLinux_x86_64::IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) { if (wp_index >= NumSupportedHardwareWatchpoints()) return Status("Watchpoint index out of range"); RegisterValue reg_value; Status error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value); if (error.Fail()) { is_vacant = false; return error; } uint64_t control_bits = reg_value.GetAsUInt64(); is_vacant = !(control_bits & (1 << (2 * wp_index))); return error; } Status NativeRegisterContextLinux_x86_64::SetHardwareWatchpointWithIndex( lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) { if (wp_index >= NumSupportedHardwareWatchpoints()) return Status("Watchpoint index out of range"); // Read only watchpoints aren't supported on x86_64. Fall back to read/write // waitchpoints instead. // TODO: Add logic to detect when a write happens and ignore that watchpoint // hit. if (watch_flags == 0x2) watch_flags = 0x3; if (watch_flags != 0x1 && watch_flags != 0x3) return Status("Invalid read/write bits for watchpoint"); if (size != 1 && size != 2 && size != 4 && size != 8) return Status("Invalid size for watchpoint"); bool is_vacant; Status error = IsWatchpointVacant(wp_index, is_vacant); if (error.Fail()) return error; if (!is_vacant) return Status("Watchpoint index not vacant"); RegisterValue reg_value; error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value); if (error.Fail()) return error; // for watchpoints 0, 1, 2, or 3, respectively, // set bits 1, 3, 5, or 7 uint64_t enable_bit = 1 << (2 * wp_index); // set bits 16-17, 20-21, 24-25, or 28-29 // with 0b01 for write, and 0b11 for read/write uint64_t rw_bits = watch_flags << (16 + 4 * wp_index); // set bits 18-19, 22-23, 26-27, or 30-31 // with 0b00, 0b01, 0b10, or 0b11 // for 1, 2, 8 (if supported), or 4 bytes, respectively uint64_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index); uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index)); uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; control_bits |= enable_bit | rw_bits | size_bits; error = WriteRegisterRaw(m_reg_info.first_dr + wp_index, RegisterValue(addr)); if (error.Fail()) return error; error = WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits)); if (error.Fail()) return error; error.Clear(); return error; } bool NativeRegisterContextLinux_x86_64::ClearHardwareWatchpoint( uint32_t wp_index) { if (wp_index >= NumSupportedHardwareWatchpoints()) return false; RegisterValue reg_value; // for watchpoints 0, 1, 2, or 3, respectively, // clear bits 0, 1, 2, or 3 of the debug status register (DR6) Status error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value); if (error.Fail()) return false; uint64_t bit_mask = 1 << wp_index; uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask; error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits)); if (error.Fail()) return false; // for watchpoints 0, 1, 2, or 3, respectively, // clear bits {0-1,16-19}, {2-3,20-23}, {4-5,24-27}, or {6-7,28-31} // of the debug control register (DR7) error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value); if (error.Fail()) return false; bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index)); uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits)) .Success(); } Status NativeRegisterContextLinux_x86_64::ClearAllHardwareWatchpoints() { RegisterValue reg_value; // clear bits {0-4} of the debug status register (DR6) Status error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value); if (error.Fail()) return error; uint64_t bit_mask = 0xF; uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask; error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits)); if (error.Fail()) return error; // clear bits {0-7,16-31} of the debug control register (DR7) error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value); if (error.Fail()) return error; bit_mask = 0xFF | (0xFFFF << 16); uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits)); } uint32_t NativeRegisterContextLinux_x86_64::SetHardwareWatchpoint( lldb::addr_t addr, size_t size, uint32_t watch_flags) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index) { bool is_vacant; Status error = IsWatchpointVacant(wp_index, is_vacant); if (is_vacant) { error = SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index); if (error.Success()) return wp_index; } if (error.Fail() && log) { log->Printf("NativeRegisterContextLinux_x86_64::%s Error: %s", __FUNCTION__, error.AsCString()); } } return LLDB_INVALID_INDEX32; } lldb::addr_t NativeRegisterContextLinux_x86_64::GetWatchpointAddress(uint32_t wp_index) { if (wp_index >= NumSupportedHardwareWatchpoints()) return LLDB_INVALID_ADDRESS; RegisterValue reg_value; if (ReadRegisterRaw(m_reg_info.first_dr + wp_index, reg_value).Fail()) return LLDB_INVALID_ADDRESS; return reg_value.GetAsUInt64(); } uint32_t NativeRegisterContextLinux_x86_64::NumSupportedHardwareWatchpoints() { // Available debug address registers: dr0, dr1, dr2, dr3 return 4; } #endif // defined(__i386__) || defined(__x86_64__) Index: vendor/lldb/dist/source/Plugins/Process/Linux/ProcessorTrace.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/Process/Linux/ProcessorTrace.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/Process/Linux/ProcessorTrace.cpp (revision 320967) @@ -1,400 +1,395 @@ //===-- ProcessorTrace.cpp ------------------------------------ -*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include #include #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" #include "llvm/Support/MathExtras.h" #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #include "ProcessorTrace.h" #include "lldb/Host/linux/Support.h" #include using namespace lldb; using namespace lldb_private; using namespace process_linux; using namespace llvm; lldb::user_id_t ProcessorTraceMonitor::m_trace_num = 1; Status ProcessorTraceMonitor::GetTraceConfig(TraceOptions &config) const { #ifndef PERF_ATTR_SIZE_VER5 llvm_unreachable("perf event not supported"); #else Status error; config.setType(lldb::TraceType::eTraceTypeProcessorTrace); config.setMetaDataBufferSize(m_mmap_meta->data_size); config.setTraceBufferSize(m_mmap_meta->aux_size); error = GetCPUType(config); return error; #endif } Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid, const TraceOptions &config) { - Status error; - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - LLDB_LOG(log, "{0}", config.getThreadID()); - #ifndef PERF_ATTR_SIZE_VER5 llvm_unreachable("perf event not supported"); #else + Status error; + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); LLDB_LOG(log, "called thread id {0}", tid); uint64_t page_size = getpagesize(); uint64_t bufsize = config.getTraceBufferSize(); uint64_t metabufsize = config.getMetaDataBufferSize(); uint64_t numpages = static_cast( llvm::PowerOf2Floor((bufsize + page_size - 1) / page_size)); - numpages = std::max(1ul, numpages); + numpages = std::max(1, numpages); bufsize = page_size * numpages; numpages = static_cast( llvm::PowerOf2Floor((metabufsize + page_size - 1) / page_size)); - numpages = std::max(0ul, numpages); metabufsize = page_size * numpages; perf_event_attr attr; memset(&attr, 0, sizeof(attr)); attr.size = sizeof(attr); attr.exclude_kernel = 1; attr.sample_type = PERF_SAMPLE_TIME; attr.sample_id_all = 1; attr.exclude_hv = 1; attr.exclude_idle = 1; attr.mmap = 1; int intel_pt_type = 0; auto ret = llvm::MemoryBuffer::getFileAsStream( "/sys/bus/event_source/devices/intel_pt/type"); if (!ret) { LLDB_LOG(log, "failed to open Config file"); return ret.getError(); } StringRef rest = ret.get()->getBuffer(); if (rest.empty() || rest.trim().getAsInteger(10, intel_pt_type)) { LLDB_LOG(log, "failed to read Config file"); error.SetErrorString("invalid file"); return error; } rest.trim().getAsInteger(10, intel_pt_type); LLDB_LOG(log, "intel pt type {0}", intel_pt_type); attr.type = intel_pt_type; LLDB_LOG(log, "meta buffer size {0}", metabufsize); LLDB_LOG(log, "buffer size {0} ", bufsize); if (error.Fail()) { LLDB_LOG(log, "Status in custom config"); return error; } errno = 0; auto fd = syscall(SYS_perf_event_open, &attr, static_cast<::tid_t>(tid), -1, -1, 0); if (fd == -1) { LLDB_LOG(log, "syscall error {0}", errno); error.SetErrorString("perf event syscall Failed"); return error; } - m_fd = std::move(std::unique_ptr(new int(fd), file_close())); + m_fd = std::unique_ptr(new int(fd), file_close()); errno = 0; auto base = mmap(NULL, (metabufsize + page_size), PROT_WRITE, MAP_SHARED, fd, 0); if (base == MAP_FAILED) { LLDB_LOG(log, "mmap base error {0}", errno); error.SetErrorString("Meta buffer allocation failed"); return error; } - m_mmap_meta = std::move(std::unique_ptr( + m_mmap_meta = std::unique_ptr( reinterpret_cast(base), - munmap_delete(metabufsize + page_size))); + munmap_delete(metabufsize + page_size)); m_mmap_meta->aux_offset = m_mmap_meta->data_offset + m_mmap_meta->data_size; m_mmap_meta->aux_size = bufsize; errno = 0; auto mmap_aux = mmap(NULL, bufsize, PROT_READ, MAP_SHARED, fd, static_cast(m_mmap_meta->aux_offset)); if (mmap_aux == MAP_FAILED) { LLDB_LOG(log, "second mmap done {0}", errno); error.SetErrorString("Trace buffer allocation failed"); return error; } - m_mmap_aux = std::move(std::unique_ptr( - reinterpret_cast(mmap_aux), munmap_delete(bufsize))); -#endif + m_mmap_aux = std::unique_ptr( + reinterpret_cast(mmap_aux), munmap_delete(bufsize)); return error; +#endif } llvm::MutableArrayRef ProcessorTraceMonitor::GetDataBuffer() { #ifndef PERF_ATTR_SIZE_VER5 llvm_unreachable("perf event not supported"); #else return MutableArrayRef( (reinterpret_cast(m_mmap_meta.get()) + m_mmap_meta->data_offset), m_mmap_meta->data_size); #endif } llvm::MutableArrayRef ProcessorTraceMonitor::GetAuxBuffer() { #ifndef PERF_ATTR_SIZE_VER5 llvm_unreachable("perf event not supported"); #else return MutableArrayRef(m_mmap_aux.get(), m_mmap_meta->aux_size); #endif } Status ProcessorTraceMonitor::GetCPUType(TraceOptions &config) { Status error; uint64_t cpu_family = -1; uint64_t model = -1; uint64_t stepping = -1; std::string vendor_id; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); auto BufferOrError = getProcFile("cpuinfo"); if (!BufferOrError) return BufferOrError.getError(); LLDB_LOG(log, "GetCPUType Function"); StringRef Rest = BufferOrError.get()->getBuffer(); while (!Rest.empty()) { StringRef Line; std::tie(Line, Rest) = Rest.split('\n'); SmallVector columns; Line.split(columns, StringRef(":"), -1, false); if (columns.size() < 2) continue; // continue searching columns[1] = columns[1].trim(" "); if (columns[0].contains("cpu family") && columns[1].getAsInteger(10, cpu_family)) continue; else if (columns[0].contains("model") && columns[1].getAsInteger(10, model)) continue; else if (columns[0].contains("stepping") && columns[1].getAsInteger(10, stepping)) continue; else if (columns[0].contains("vendor_id")) { vendor_id = columns[1].str(); if (!vendor_id.empty()) continue; } LLDB_LOG(log, "{0}:{1}:{2}:{3}", cpu_family, model, stepping, vendor_id); if ((cpu_family != static_cast(-1)) && (model != static_cast(-1)) && (stepping != static_cast(-1)) && (!vendor_id.empty())) { auto params_dict = std::make_shared(); params_dict->AddIntegerItem("cpu_family", cpu_family); params_dict->AddIntegerItem("cpu_model", model); params_dict->AddIntegerItem("cpu_stepping", stepping); params_dict->AddStringItem("cpu_vendor", vendor_id); llvm::StringRef intel_custom_params_key("intel-pt"); auto intel_custom_params = std::make_shared(); intel_custom_params->AddItem( intel_custom_params_key, StructuredData::ObjectSP(std::move(params_dict))); config.setTraceParams(intel_custom_params); return error; // we are done } } error.SetErrorString("cpu info not found"); return error; } llvm::Expected ProcessorTraceMonitor::Create(lldb::pid_t pid, lldb::tid_t tid, const TraceOptions &config, bool useProcessSettings) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); Status error; if (tid == LLDB_INVALID_THREAD_ID) { error.SetErrorString("thread not specified"); - return std::move(error.ToError()); + return error.ToError(); } ProcessorTraceMonitorUP pt_monitor_up(new ProcessorTraceMonitor); error = pt_monitor_up->StartTrace(pid, tid, config); if (error.Fail()) - return std::move(error.ToError()); + return error.ToError(); pt_monitor_up->SetThreadID(tid); if (useProcessSettings) { pt_monitor_up->SetTraceID(0); } else { pt_monitor_up->SetTraceID(m_trace_num++); LLDB_LOG(log, "Trace ID {0}", m_trace_num); } return std::move(pt_monitor_up); } Status ProcessorTraceMonitor::ReadPerfTraceAux(llvm::MutableArrayRef &buffer, size_t offset) { - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - Status error; - #ifndef PERF_ATTR_SIZE_VER5 llvm_unreachable("perf event not supported"); #else + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); + Status error; uint64_t head = m_mmap_meta->aux_head; LLDB_LOG(log, "Aux size -{0} , Head - {1}", m_mmap_meta->aux_size, head); /** * When configured as ring buffer, the aux buffer keeps wrapping around * the buffer and its not possible to detect how many times the buffer * wrapped. Initially the buffer is filled with zeros,as shown below * so in order to get complete buffer we first copy firstpartsize, followed * by any left over part from beginning to aux_head * * aux_offset [d,d,d,d,d,d,d,d,0,0,0,0,0,0,0,0,0,0,0] aux_size * aux_head->||<- firstpartsize ->| * * */ ReadCyclicBuffer(buffer, GetAuxBuffer(), static_cast(head), offset); LLDB_LOG(log, "ReadCyclic BUffer Done"); return error; #endif } Status ProcessorTraceMonitor::ReadPerfTraceData(llvm::MutableArrayRef &buffer, size_t offset) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - uint64_t bytes_remaining = buffer.size(); - Status error; #ifndef PERF_ATTR_SIZE_VER5 llvm_unreachable("perf event not supported"); #else + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); + uint64_t bytes_remaining = buffer.size(); + Status error; uint64_t head = m_mmap_meta->data_head; /* * The data buffer and aux buffer have different implementations * with respect to their definition of head pointer. In the case * of Aux data buffer the head always wraps around the aux buffer * and we don't need to care about it, whereas the data_head keeps * increasing and needs to be wrapped by modulus operator */ LLDB_LOG(log, "bytes_remaining - {0}", bytes_remaining); auto data_buffer = GetDataBuffer(); if (head > data_buffer.size()) { head = head % data_buffer.size(); LLDB_LOG(log, "Data size -{0} Head - {1}", m_mmap_meta->data_size, head); ReadCyclicBuffer(buffer, data_buffer, static_cast(head), offset); bytes_remaining -= buffer.size(); } else { LLDB_LOG(log, "Head - {0}", head); if (offset >= head) { LLDB_LOG(log, "Invalid Offset "); error.SetErrorString("invalid offset"); buffer = buffer.slice(buffer.size()); return error; } auto data = data_buffer.slice(offset, (head - offset)); auto remaining = std::copy(data.begin(), data.end(), buffer.begin()); bytes_remaining -= (remaining - buffer.begin()); } buffer = buffer.drop_back(bytes_remaining); return error; #endif } void ProcessorTraceMonitor::ReadCyclicBuffer( llvm::MutableArrayRef &dst, llvm::MutableArrayRef src, size_t src_cyc_index, size_t offset) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); if (dst.empty() || src.empty()) { dst = dst.drop_back(dst.size()); return; } if (dst.data() == nullptr || src.data() == nullptr) { dst = dst.drop_back(dst.size()); return; } if (src_cyc_index > src.size()) { dst = dst.drop_back(dst.size()); return; } if (offset >= src.size()) { LLDB_LOG(log, "Too Big offset "); dst = dst.drop_back(dst.size()); return; } llvm::SmallVector, 2> parts = { src.slice(src_cyc_index), src.take_front(src_cyc_index)}; if (offset > parts[0].size()) { parts[1] = parts[1].slice(offset - parts[0].size()); parts[0] = parts[0].drop_back(parts[0].size()); } else if (offset == parts[0].size()) { parts[0] = parts[0].drop_back(parts[0].size()); } else { parts[0] = parts[0].slice(offset); } auto next = dst.begin(); auto bytes_left = dst.size(); for (auto part : parts) { size_t chunk_size = std::min(part.size(), bytes_left); next = std::copy_n(part.begin(), chunk_size, next); bytes_left -= chunk_size; } dst = dst.drop_back(bytes_left); } Index: vendor/lldb/dist/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp (revision 320967) @@ -1,1037 +1,938 @@ //===-- NativeProcessNetBSD.cpp ------------------------------- -*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "NativeProcessNetBSD.h" // C Includes // C++ Includes // Other libraries and framework includes #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #include "lldb/Core/State.h" #include "lldb/Host/HostProcess.h" #include "lldb/Host/common/NativeBreakpoint.h" #include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Host/posix/ProcessLauncherPosixFork.h" #include "lldb/Target/Process.h" +#include "llvm/Support/Errno.h" // System includes - They have to be included after framework includes because // they define some // macros which collide with variable names in other modules // clang-format off #include #include #include #include #include #include #include // clang-format on using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_netbsd; using namespace llvm; // Simple helper function to ensure flags are enabled on the given file // descriptor. static Status EnsureFDFlags(int fd, int flags) { Status error; int status = fcntl(fd, F_GETFL); if (status == -1) { error.SetErrorToErrno(); return error; } if (fcntl(fd, F_SETFL, status | flags) == -1) { error.SetErrorToErrno(); return error; } return error; } // ----------------------------------------------------------------------------- // Public Static Methods // ----------------------------------------------------------------------------- -Status NativeProcessProtocol::Launch( - ProcessLaunchInfo &launch_info, - NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop, - NativeProcessProtocolSP &native_process_sp) { +llvm::Expected +NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info, + NativeDelegate &native_delegate, + MainLoop &mainloop) const { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - Status error; + Status status; + ::pid_t pid = ProcessLauncherPosixFork() + .LaunchProcess(launch_info, status) + .GetProcessId(); + LLDB_LOG(log, "pid = {0:x}", pid); + if (status.Fail()) { + LLDB_LOG(log, "failed to launch process: {0}", status); + return status.ToError(); + } - // Verify the working directory is valid if one was specified. - FileSpec working_dir{launch_info.GetWorkingDirectory()}; - if (working_dir && (!working_dir.ResolvePath() || - !llvm::sys::fs::is_directory(working_dir.GetPath()))) { - error.SetErrorStringWithFormat("No such file or directory: %s", - working_dir.GetCString()); - return error; + // Wait for the child process to trap on its call to execve. + int wstatus; + ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0); + assert(wpid == pid); + (void)wpid; + if (!WIFSTOPPED(wstatus)) { + LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}", + WaitStatus::Decode(wstatus)); + return llvm::make_error("Could not sync with inferior process", + llvm::inconvertibleErrorCode()); } + LLDB_LOG(log, "inferior started, now in stopped state"); - // Create the NativeProcessNetBSD in launch mode. - native_process_sp.reset(new NativeProcessNetBSD()); + ArchSpec arch; + if ((status = ResolveProcessArchitecture(pid, arch)).Fail()) + return status.ToError(); - if (!native_process_sp->RegisterNativeDelegate(native_delegate)) { - native_process_sp.reset(); - error.SetErrorStringWithFormat("failed to register the native delegate"); - return error; - } + // Set the architecture to the exe architecture. + LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid, + arch.GetArchitectureName()); - error = std::static_pointer_cast(native_process_sp) - ->LaunchInferior(mainloop, launch_info); + std::shared_ptr process_sp(new NativeProcessNetBSD( + pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate, + arch, mainloop)); - if (error.Fail()) { - native_process_sp.reset(); - LLDB_LOG(log, "failed to launch process: {0}", error); - return error; + status = process_sp->ReinitializeThreads(); + if (status.Fail()) + return status.ToError(); + + for (const auto &thread_sp : process_sp->m_threads) { + static_pointer_cast(thread_sp)->SetStoppedBySignal( + SIGSTOP); } + process_sp->SetState(StateType::eStateStopped); - launch_info.SetProcessID(native_process_sp->GetID()); - - return error; + return process_sp; } -Status NativeProcessProtocol::Attach( +llvm::Expected NativeProcessNetBSD::Factory::Attach( lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) { + MainLoop &mainloop) const { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); LLDB_LOG(log, "pid = {0:x}", pid); // Retrieve the architecture for the running process. - ArchSpec process_arch; - Status error = ResolveProcessArchitecture(pid, process_arch); - if (!error.Success()) - return error; + ArchSpec arch; + Status status = ResolveProcessArchitecture(pid, arch); + if (!status.Success()) + return status.ToError(); - std::shared_ptr native_process_netbsd_sp( - new NativeProcessNetBSD()); + std::shared_ptr process_sp( + new NativeProcessNetBSD(pid, -1, native_delegate, arch, mainloop)); - if (!native_process_netbsd_sp->RegisterNativeDelegate(native_delegate)) { - error.SetErrorStringWithFormat("failed to register the native delegate"); - return error; - } + status = process_sp->Attach(); + if (!status.Success()) + return status.ToError(); - native_process_netbsd_sp->AttachToInferior(mainloop, pid, error); - if (!error.Success()) - return error; - - native_process_sp = native_process_netbsd_sp; - return error; + return process_sp; } // ----------------------------------------------------------------------------- // Public Instance Methods // ----------------------------------------------------------------------------- -NativeProcessNetBSD::NativeProcessNetBSD() - : NativeProcessProtocol(LLDB_INVALID_PROCESS_ID), m_arch(), - m_supports_mem_region(eLazyBoolCalculate), m_mem_region_cache() {} +NativeProcessNetBSD::NativeProcessNetBSD(::pid_t pid, int terminal_fd, + NativeDelegate &delegate, + const ArchSpec &arch, + MainLoop &mainloop) + : NativeProcessProtocol(pid, terminal_fd, delegate), m_arch(arch) { + if (m_terminal_fd != -1) { + Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); + assert(status.Success()); + } + Status status; + m_sigchld_handle = mainloop.RegisterSignal( + SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status); + assert(m_sigchld_handle && status.Success()); +} + // Handles all waitpid events from the inferior process. void NativeProcessNetBSD::MonitorCallback(lldb::pid_t pid, int signal) { switch (signal) { case SIGTRAP: return MonitorSIGTRAP(pid); case SIGSTOP: return MonitorSIGSTOP(pid); default: return MonitorSignal(pid, signal); } } void NativeProcessNetBSD::MonitorExited(lldb::pid_t pid, WaitStatus status) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); LLDB_LOG(log, "got exit signal({0}) , pid = {1}", status, pid); /* Stop Tracking All Threads attached to Process */ m_threads.clear(); SetExitStatus(status, true); // Notify delegate that our process has exited. SetState(StateType::eStateExited, true); } void NativeProcessNetBSD::MonitorSIGSTOP(lldb::pid_t pid) { ptrace_siginfo_t info; const auto siginfo_err = PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info)); // Get details on the signal raised. if (siginfo_err.Success()) { // Handle SIGSTOP from LLGS (LLDB GDB Server) if (info.psi_siginfo.si_code == SI_USER && info.psi_siginfo.si_pid == ::getpid()) { /* Stop Tracking All Threads attached to Process */ for (const auto &thread_sp : m_threads) { static_pointer_cast(thread_sp)->SetStoppedBySignal( SIGSTOP, &info.psi_siginfo); } } } } void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); ptrace_siginfo_t info; const auto siginfo_err = PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info)); // Get details on the signal raised. if (siginfo_err.Fail()) { return; } switch (info.psi_siginfo.si_code) { case TRAP_BRKPT: for (const auto &thread_sp : m_threads) { static_pointer_cast(thread_sp) ->SetStoppedByBreakpoint(); FixupBreakpointPCAsNeeded( *static_pointer_cast(thread_sp)); } SetState(StateType::eStateStopped, true); break; case TRAP_TRACE: for (const auto &thread_sp : m_threads) { static_pointer_cast(thread_sp)->SetStoppedByTrace(); } SetState(StateType::eStateStopped, true); break; case TRAP_EXEC: { Status error = ReinitializeThreads(); if (error.Fail()) { SetState(StateType::eStateInvalid); return; } // Let our delegate know we have just exec'd. NotifyDidExec(); for (const auto &thread_sp : m_threads) { static_pointer_cast(thread_sp)->SetStoppedByExec(); } SetState(StateType::eStateStopped, true); } break; case TRAP_DBREG: { // If a watchpoint was hit, report it uint32_t wp_index; Status error = static_pointer_cast(m_threads[info.psi_lwpid]) ->GetRegisterContext() ->GetWatchpointHitIndex(wp_index, (uintptr_t)info.psi_siginfo.si_addr); if (error.Fail()) LLDB_LOG(log, "received error while checking for watchpoint hits, pid = " "{0}, LWP = {1}, error = {2}", GetID(), info.psi_lwpid, error); if (wp_index != LLDB_INVALID_INDEX32) { for (const auto &thread_sp : m_threads) { static_pointer_cast(thread_sp) ->SetStoppedByWatchpoint(wp_index); } SetState(StateType::eStateStopped, true); break; } // If a breakpoint was hit, report it uint32_t bp_index; error = static_pointer_cast(m_threads[info.psi_lwpid]) ->GetRegisterContext() ->GetHardwareBreakHitIndex(bp_index, (uintptr_t)info.psi_siginfo.si_addr); if (error.Fail()) LLDB_LOG(log, "received error while checking for hardware " "breakpoint hits, pid = {0}, LWP = {1}, error = {2}", GetID(), info.psi_lwpid, error); if (bp_index != LLDB_INVALID_INDEX32) { for (const auto &thread_sp : m_threads) { static_pointer_cast(thread_sp) ->SetStoppedByBreakpoint(); } SetState(StateType::eStateStopped, true); break; } } break; } } void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) { ptrace_siginfo_t info; const auto siginfo_err = PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info)); for (const auto &thread_sp : m_threads) { static_pointer_cast(thread_sp)->SetStoppedBySignal( info.psi_siginfo.si_signo, &info.psi_siginfo); } SetState(StateType::eStateStopped, true); } Status NativeProcessNetBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data, int *result) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); Status error; int ret; errno = 0; ret = ptrace(req, static_cast<::pid_t>(pid), addr, data); if (ret == -1) error.SetErrorToErrno(); if (result) *result = ret; LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3})={4:x}", req, pid, addr, data, ret); if (error.Fail()) LLDB_LOG(log, "ptrace() failed: {0}", error); return error; } Status NativeProcessNetBSD::GetSoftwareBreakpointPCOffset( uint32_t &actual_opcode_size) { // FIXME put this behind a breakpoint protocol class that can be // set per architecture. Need ARM, MIPS support here. static const uint8_t g_i386_opcode[] = {0xCC}; switch (m_arch.GetMachine()) { case llvm::Triple::x86_64: actual_opcode_size = static_cast(sizeof(g_i386_opcode)); return Status(); default: assert(false && "CPU type not supported!"); return Status("CPU type not supported"); } } Status NativeProcessNetBSD::FixupBreakpointPCAsNeeded(NativeThreadNetBSD &thread) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); Status error; // Find out the size of a breakpoint (might depend on where we are in the // code). NativeRegisterContextSP context_sp = thread.GetRegisterContext(); if (!context_sp) { error.SetErrorString("cannot get a NativeRegisterContext for the thread"); LLDB_LOG(log, "failed: {0}", error); return error; } uint32_t breakpoint_size = 0; error = GetSoftwareBreakpointPCOffset(breakpoint_size); if (error.Fail()) { LLDB_LOG(log, "GetBreakpointSize() failed: {0}", error); return error; } else LLDB_LOG(log, "breakpoint size: {0}", breakpoint_size); // First try probing for a breakpoint at a software breakpoint location: PC // - breakpoint size. const lldb::addr_t initial_pc_addr = context_sp->GetPCfromBreakpointLocation(); lldb::addr_t breakpoint_addr = initial_pc_addr; if (breakpoint_size > 0) { // Do not allow breakpoint probe to wrap around. if (breakpoint_addr >= breakpoint_size) breakpoint_addr -= breakpoint_size; } // Check if we stopped because of a breakpoint. NativeBreakpointSP breakpoint_sp; error = m_breakpoint_list.GetBreakpoint(breakpoint_addr, breakpoint_sp); if (!error.Success() || !breakpoint_sp) { // We didn't find one at a software probe location. Nothing to do. LLDB_LOG(log, "pid {0} no lldb breakpoint found at current pc with " "adjustment: {1}", GetID(), breakpoint_addr); return Status(); } // If the breakpoint is not a software breakpoint, nothing to do. if (!breakpoint_sp->IsSoftwareBreakpoint()) { LLDB_LOG( log, "pid {0} breakpoint found at {1:x}, not software, nothing to adjust", GetID(), breakpoint_addr); return Status(); } // // We have a software breakpoint and need to adjust the PC. // // Sanity check. if (breakpoint_size == 0) { // Nothing to do! How did we get here? LLDB_LOG(log, "pid {0} breakpoint found at {1:x}, it is software, but the " "size is zero, nothing to do (unexpected)", GetID(), breakpoint_addr); return Status(); } // // We have a software breakpoint and need to adjust the PC. // // Sanity check. if (breakpoint_size == 0) { // Nothing to do! How did we get here? LLDB_LOG(log, "pid {0} breakpoint found at {1:x}, it is software, but the " "size is zero, nothing to do (unexpected)", GetID(), breakpoint_addr); return Status(); } // Change the program counter. LLDB_LOG(log, "pid {0} tid {1}: changing PC from {2:x} to {3:x}", GetID(), thread.GetID(), initial_pc_addr, breakpoint_addr); error = context_sp->SetPC(breakpoint_addr); if (error.Fail()) { LLDB_LOG(log, "pid {0} tid {1}: failed to set PC: {2}", GetID(), thread.GetID(), error); return error; } return error; } Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); LLDB_LOG(log, "pid {0}", GetID()); const auto &thread_sp = m_threads[0]; const ResumeAction *const action = resume_actions.GetActionForThread(thread_sp->GetID(), true); if (action == nullptr) { LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(), thread_sp->GetID()); return Status(); } Status error; switch (action->state) { case eStateRunning: { // Run the thread, possibly feeding it the signal. error = NativeProcessNetBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1, action->signal); if (!error.Success()) return error; for (const auto &thread_sp : m_threads) { static_pointer_cast(thread_sp)->SetRunning(); } SetState(eStateRunning, true); break; } case eStateStepping: // Run the thread, possibly feeding it the signal. error = NativeProcessNetBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1, action->signal); if (!error.Success()) return error; for (const auto &thread_sp : m_threads) { static_pointer_cast(thread_sp)->SetStepping(); } SetState(eStateStepping, true); break; case eStateSuspended: case eStateStopped: llvm_unreachable("Unexpected state"); default: return Status("NativeProcessNetBSD::%s (): unexpected state %s specified " "for pid %" PRIu64 ", tid %" PRIu64, __FUNCTION__, StateAsCString(action->state), GetID(), thread_sp->GetID()); } return Status(); } Status NativeProcessNetBSD::Halt() { Status error; if (kill(GetID(), SIGSTOP) != 0) error.SetErrorToErrno(); return error; } Status NativeProcessNetBSD::Detach() { Status error; // Stop monitoring the inferior. m_sigchld_handle.reset(); // Tell ptrace to detach from the process. if (GetID() == LLDB_INVALID_PROCESS_ID) return error; return PtraceWrapper(PT_DETACH, GetID()); } Status NativeProcessNetBSD::Signal(int signo) { Status error; if (kill(GetID(), signo)) error.SetErrorToErrno(); return error; } Status NativeProcessNetBSD::Kill() { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); LLDB_LOG(log, "pid {0}", GetID()); Status error; switch (m_state) { case StateType::eStateInvalid: case StateType::eStateExited: case StateType::eStateCrashed: case StateType::eStateDetached: case StateType::eStateUnloaded: // Nothing to do - the process is already dead. LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(), StateAsCString(m_state)); return error; case StateType::eStateConnected: case StateType::eStateAttaching: case StateType::eStateLaunching: case StateType::eStateStopped: case StateType::eStateRunning: case StateType::eStateStepping: case StateType::eStateSuspended: // We can try to kill a process in these states. break; } if (kill(GetID(), SIGKILL) != 0) { error.SetErrorToErrno(); return error; } return error; } Status NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info) { if (m_supports_mem_region == LazyBool::eLazyBoolNo) { // We're done. return Status("unsupported"); } Status error = PopulateMemoryRegionCache(); if (error.Fail()) { return error; } lldb::addr_t prev_base_address = 0; // FIXME start by finding the last region that is <= target address using // binary search. Data is sorted. // There can be a ton of regions on pthreads apps with lots of threads. for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end(); ++it) { MemoryRegionInfo &proc_entry_info = it->first; // Sanity check assumption that memory map entries are ascending. assert((proc_entry_info.GetRange().GetRangeBase() >= prev_base_address) && "descending memory map entries detected, unexpected"); prev_base_address = proc_entry_info.GetRange().GetRangeBase(); UNUSED_IF_ASSERT_DISABLED(prev_base_address); // If the target address comes before this entry, indicate distance to // next region. if (load_addr < proc_entry_info.GetRange().GetRangeBase()) { range_info.GetRange().SetRangeBase(load_addr); range_info.GetRange().SetByteSize( proc_entry_info.GetRange().GetRangeBase() - load_addr); range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo); range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo); range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo); range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo); return error; } else if (proc_entry_info.GetRange().Contains(load_addr)) { // The target address is within the memory region we're processing here. range_info = proc_entry_info; return error; } // The target memory address comes somewhere after the region we just // parsed. } // If we made it here, we didn't find an entry that contained the given // address. Return the // load_addr as start and the amount of bytes betwwen load address and the // end of the memory as size. range_info.GetRange().SetRangeBase(load_addr); range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo); range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo); range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo); range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo); return error; } Status NativeProcessNetBSD::PopulateMemoryRegionCache() { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); // If our cache is empty, pull the latest. There should always be at least // one memory region if memory region handling is supported. if (!m_mem_region_cache.empty()) { LLDB_LOG(log, "reusing {0} cached memory region entries", m_mem_region_cache.size()); return Status(); } struct kinfo_vmentry *vm; size_t count, i; vm = kinfo_getvmmap(GetID(), &count); if (vm == NULL) { m_supports_mem_region = LazyBool::eLazyBoolNo; Status error; error.SetErrorString("not supported"); return error; } for (i = 0; i < count; i++) { MemoryRegionInfo info; info.Clear(); info.GetRange().SetRangeBase(vm[i].kve_start); info.GetRange().SetRangeEnd(vm[i].kve_end); info.SetMapped(MemoryRegionInfo::OptionalBool::eYes); if (vm[i].kve_protection & VM_PROT_READ) info.SetReadable(MemoryRegionInfo::OptionalBool::eYes); else info.SetReadable(MemoryRegionInfo::OptionalBool::eNo); if (vm[i].kve_protection & VM_PROT_WRITE) info.SetWritable(MemoryRegionInfo::OptionalBool::eYes); else info.SetWritable(MemoryRegionInfo::OptionalBool::eNo); if (vm[i].kve_protection & VM_PROT_EXECUTE) info.SetExecutable(MemoryRegionInfo::OptionalBool::eYes); else info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo); if (vm[i].kve_path[0]) info.SetName(vm[i].kve_path); m_mem_region_cache.emplace_back( info, FileSpec(info.GetName().GetCString(), true)); } free(vm); if (m_mem_region_cache.empty()) { // No entries after attempting to read them. This shouldn't happen. // Assume we don't support map entries. LLDB_LOG(log, "failed to find any vmmap entries, assuming no support " "for memory region metadata retrieval"); m_supports_mem_region = LazyBool::eLazyBoolNo; Status error; error.SetErrorString("not supported"); return error; } LLDB_LOG(log, "read {0} memory region entries from process {1}", m_mem_region_cache.size(), GetID()); // We support memory retrieval, remember that. m_supports_mem_region = LazyBool::eLazyBoolYes; return Status(); } Status NativeProcessNetBSD::AllocateMemory(size_t size, uint32_t permissions, lldb::addr_t &addr) { return Status("Unimplemented"); } Status NativeProcessNetBSD::DeallocateMemory(lldb::addr_t addr) { return Status("Unimplemented"); } lldb::addr_t NativeProcessNetBSD::GetSharedLibraryInfoAddress() { // punt on this for now return LLDB_INVALID_ADDRESS; } size_t NativeProcessNetBSD::UpdateThreads() { return m_threads.size(); } bool NativeProcessNetBSD::GetArchitecture(ArchSpec &arch) const { arch = m_arch; return true; } Status NativeProcessNetBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) { if (hardware) return Status("NativeProcessNetBSD does not support hardware breakpoints"); else return SetSoftwareBreakpoint(addr, size); } Status NativeProcessNetBSD::GetSoftwareBreakpointTrapOpcode( size_t trap_opcode_size_hint, size_t &actual_opcode_size, const uint8_t *&trap_opcode_bytes) { static const uint8_t g_i386_opcode[] = {0xCC}; switch (m_arch.GetMachine()) { case llvm::Triple::x86: case llvm::Triple::x86_64: trap_opcode_bytes = g_i386_opcode; actual_opcode_size = sizeof(g_i386_opcode); return Status(); default: assert(false && "CPU type not supported!"); return Status("CPU type not supported"); } } Status NativeProcessNetBSD::GetLoadedModuleFileSpec(const char *module_path, FileSpec &file_spec) { return Status("Unimplemented"); } Status NativeProcessNetBSD::GetFileLoadAddress(const llvm::StringRef &file_name, lldb::addr_t &load_addr) { load_addr = LLDB_INVALID_ADDRESS; return Status(); } -Status NativeProcessNetBSD::LaunchInferior(MainLoop &mainloop, - ProcessLaunchInfo &launch_info) { - Status error; - m_sigchld_handle = mainloop.RegisterSignal( - SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); - if (!m_sigchld_handle) - return error; - - SetState(eStateLaunching); - - ::pid_t pid = ProcessLauncherPosixFork() - .LaunchProcess(launch_info, error) - .GetProcessId(); - if (error.Fail()) - return error; - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - - // Wait for the child process to trap on its call to execve. - ::pid_t wpid; - int status; - if ((wpid = waitpid(pid, &status, 0)) < 0) { - error.SetErrorToErrno(); - LLDB_LOG(log, "waitpid for inferior failed with %s", error); - - // Mark the inferior as invalid. - // FIXME this could really use a new state - eStateLaunchFailure. For - // now, using eStateInvalid. - SetState(StateType::eStateInvalid); - - return error; - } - assert(WIFSTOPPED(status) && (wpid == static_cast<::pid_t>(pid)) && - "Could not sync with inferior process."); - - LLDB_LOG(log, "inferior started, now in stopped state"); - - // Release the master terminal descriptor and pass it off to the - // NativeProcessNetBSD instance. Similarly stash the inferior pid. - m_terminal_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); - m_pid = pid; - launch_info.SetProcessID(pid); - - if (m_terminal_fd != -1) { - error = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); - if (error.Fail()) { - LLDB_LOG(log, - "inferior EnsureFDFlags failed for ensuring terminal " - "O_NONBLOCK setting: {0}", - error); - - // Mark the inferior as invalid. - // FIXME this could really use a new state - eStateLaunchFailure. For - // now, using eStateInvalid. - SetState(StateType::eStateInvalid); - - return error; - } - } - - LLDB_LOG(log, "adding pid = {0}", pid); - - ResolveProcessArchitecture(m_pid, m_arch); - - error = ReinitializeThreads(); - if (error.Fail()) { - SetState(StateType::eStateInvalid); - return error; - } - - for (const auto &thread_sp : m_threads) { - static_pointer_cast(thread_sp)->SetStoppedBySignal( - SIGSTOP); - } - - /* Set process stopped */ - SetState(StateType::eStateStopped); - - if (error.Fail()) - LLDB_LOG(log, "inferior launching failed {0}", error); - return error; -} - -void NativeProcessNetBSD::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, - Status &error) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - LLDB_LOG(log, "pid = {0:x}", pid); - - m_sigchld_handle = mainloop.RegisterSignal( - SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); - if (!m_sigchld_handle) - return; - - error = ResolveProcessArchitecture(pid, m_arch); - if (!error.Success()) - return; - - // Set the architecture to the exe architecture. - LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid, - m_arch.GetArchitectureName()); - - m_pid = pid; - SetState(eStateAttaching); - - Attach(pid, error); -} - void NativeProcessNetBSD::SigchldHandler() { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); // Process all pending waitpid notifications. int status; - ::pid_t wait_pid = waitpid(GetID(), &status, WALLSIG | WNOHANG); + ::pid_t wait_pid = + llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WALLSIG | WNOHANG); if (wait_pid == 0) return; // We are done. if (wait_pid == -1) { - if (errno == EINTR) - return; - Status error(errno, eErrorTypePOSIX); LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error); } WaitStatus wait_status = WaitStatus::Decode(status); bool exited = wait_status.type == WaitStatus::Exit || (wait_status.type == WaitStatus::Signal && wait_pid == static_cast<::pid_t>(GetID())); LLDB_LOG(log, "waitpid ({0}, &status, _) => pid = {1}, status = {2}, exited = {3}", GetID(), wait_pid, status, exited); if (exited) MonitorExited(wait_pid, wait_status); else { assert(wait_status.type == WaitStatus::Stop); MonitorCallback(wait_pid, wait_status.status); } } bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) { for (auto thread_sp : m_threads) { assert(thread_sp && "thread list should not contain NULL threads"); if (thread_sp->GetID() == thread_id) { // We have this thread. return true; } } // We don't have this thread. return false; } NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id); assert(!HasThreadNoLock(thread_id) && "attempted to add a thread by id that already exists"); // If this is the first thread, save it as the current thread if (m_threads.empty()) SetCurrentThreadID(thread_id); auto thread_sp = std::make_shared(this, thread_id); m_threads.push_back(thread_sp); return thread_sp; } -::pid_t NativeProcessNetBSD::Attach(lldb::pid_t pid, Status &error) { - if (pid <= 1) { - error.SetErrorToGenericError(); - error.SetErrorString("Attaching to process 1 is not allowed."); - return -1; - } - +Status NativeProcessNetBSD::Attach() { // Attach to the requested process. // An attach will cause the thread to stop with a SIGSTOP. - error = PtraceWrapper(PT_ATTACH, pid); - if (error.Fail()) - return -1; + Status status = PtraceWrapper(PT_ATTACH, m_pid); + if (status.Fail()) + return status; - int status; + int wstatus; // Need to use WALLSIG otherwise we receive an error with errno=ECHLD // At this point we should have a thread stopped if waitpid succeeds. - if ((status = waitpid(pid, NULL, WALLSIG)) < 0) - return -1; + if ((wstatus = waitpid(m_pid, NULL, WALLSIG)) < 0) + return Status(errno, eErrorTypePOSIX); - m_pid = pid; - /* Initialize threads */ - error = ReinitializeThreads(); - if (error.Fail()) { - SetState(StateType::eStateInvalid); - return -1; - } + status = ReinitializeThreads(); + if (status.Fail()) + return status; for (const auto &thread_sp : m_threads) { static_pointer_cast(thread_sp)->SetStoppedBySignal( SIGSTOP); } // Let our process instance know the thread has stopped. SetState(StateType::eStateStopped); - - return pid; + return Status(); } Status NativeProcessNetBSD::ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) { unsigned char *dst = static_cast(buf); struct ptrace_io_desc io; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY)); LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size); bytes_read = 0; io.piod_op = PIOD_READ_D; io.piod_len = size; do { io.piod_offs = (void *)(addr + bytes_read); io.piod_addr = dst + bytes_read; Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io); if (error.Fail()) return error; bytes_read = io.piod_len; io.piod_len = size - bytes_read; } while (bytes_read < size); return Status(); } Status NativeProcessNetBSD::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) { Status error = ReadMemory(addr, buf, size, bytes_read); if (error.Fail()) return error; return m_breakpoint_list.RemoveTrapsFromBuffer(addr, buf, size); } Status NativeProcessNetBSD::WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written) { const unsigned char *src = static_cast(buf); Status error; struct ptrace_io_desc io; Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY)); LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size); bytes_written = 0; io.piod_op = PIOD_WRITE_D; io.piod_len = size; do { io.piod_addr = const_cast(static_cast(src + bytes_written)); io.piod_offs = (void *)(addr + bytes_written); Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io); if (error.Fail()) return error; bytes_written = io.piod_len; io.piod_len = size - bytes_written; } while (bytes_written < size); return error; } llvm::ErrorOr> NativeProcessNetBSD::GetAuxvData() const { /* * ELF_AUX_ENTRIES is currently restricted to kernel * ( r. 1.155 specifies 15) * * ptrace(2) returns the whole AUXV including extra fiels after AT_NULL this * information isn't needed. */ size_t auxv_size = 100 * sizeof(AuxInfo); ErrorOr> buf = llvm::MemoryBuffer::getNewMemBuffer(auxv_size); struct ptrace_io_desc io; io.piod_op = PIOD_READ_AUXV; io.piod_offs = 0; io.piod_addr = const_cast(static_cast(buf.get()->getBufferStart())); io.piod_len = auxv_size; Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io); if (error.Fail()) return std::error_code(error.GetError(), std::generic_category()); if (io.piod_len < 1) return std::error_code(ECANCELED, std::generic_category()); return buf; } Status NativeProcessNetBSD::ReinitializeThreads() { // Clear old threads m_threads.clear(); // Initialize new thread struct ptrace_lwpinfo info = {}; Status error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info)); if (error.Fail()) { return error; } // Reinitialize from scratch threads and register them in process while (info.pl_lwpid != 0) { NativeThreadNetBSDSP thread_sp = AddThread(info.pl_lwpid); error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info)); if (error.Fail()) { return error; } } return error; } Index: vendor/lldb/dist/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h =================================================================== --- vendor/lldb/dist/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h (revision 320966) +++ vendor/lldb/dist/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h (revision 320967) @@ -1,144 +1,144 @@ //===-- NativeProcessNetBSD.h --------------------------------- -*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef liblldb_NativeProcessNetBSD_H_ #define liblldb_NativeProcessNetBSD_H_ // C++ Includes // Other libraries and framework includes #include "lldb/Core/ArchSpec.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Utility/FileSpec.h" #include "NativeThreadNetBSD.h" #include "lldb/Host/common/NativeProcessProtocol.h" namespace lldb_private { namespace process_netbsd { /// @class NativeProcessNetBSD /// @brief Manages communication with the inferior (debugee) process. /// /// Upon construction, this class prepares and launches an inferior process for /// debugging. /// /// Changes in the inferior process state are broadcasted. class NativeProcessNetBSD : public NativeProcessProtocol { - friend Status NativeProcessProtocol::Launch( - ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &process_sp); +public: + class Factory : public NativeProcessProtocol::Factory { + public: + llvm::Expected + Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, + MainLoop &mainloop) const override; - friend Status NativeProcessProtocol::Attach( - lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, - MainLoop &mainloop, NativeProcessProtocolSP &process_sp); + llvm::Expected + Attach(lldb::pid_t pid, NativeDelegate &native_delegate, + MainLoop &mainloop) const override; + }; -public: // --------------------------------------------------------------------- // NativeProcessProtocol Interface // --------------------------------------------------------------------- Status Resume(const ResumeActionList &resume_actions) override; Status Halt() override; Status Detach() override; Status Signal(int signo) override; Status Kill() override; Status GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info) override; Status ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) override; Status ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) override; Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written) override; Status AllocateMemory(size_t size, uint32_t permissions, lldb::addr_t &addr) override; Status DeallocateMemory(lldb::addr_t addr) override; lldb::addr_t GetSharedLibraryInfoAddress() override; size_t UpdateThreads() override; bool GetArchitecture(ArchSpec &arch) const override; Status SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) override; Status GetLoadedModuleFileSpec(const char *module_path, FileSpec &file_spec) override; Status GetFileLoadAddress(const llvm::StringRef &file_name, lldb::addr_t &load_addr) override; llvm::ErrorOr> GetAuxvData() const override; // --------------------------------------------------------------------- // Interface used by NativeRegisterContext-derived classes. // --------------------------------------------------------------------- static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr = nullptr, int data = 0, int *result = nullptr); protected: // --------------------------------------------------------------------- // NativeProcessProtocol protected interface // --------------------------------------------------------------------- Status GetSoftwareBreakpointTrapOpcode(size_t trap_opcode_size_hint, size_t &actual_opcode_size, const uint8_t *&trap_opcode_bytes) override; private: MainLoop::SignalHandleUP m_sigchld_handle; ArchSpec m_arch; - LazyBool m_supports_mem_region; + LazyBool m_supports_mem_region = eLazyBoolCalculate; std::vector> m_mem_region_cache; // --------------------------------------------------------------------- // Private Instance Methods // --------------------------------------------------------------------- - NativeProcessNetBSD(); + NativeProcessNetBSD(::pid_t pid, int terminal_fd, NativeDelegate &delegate, + const ArchSpec &arch, MainLoop &mainloop); bool HasThreadNoLock(lldb::tid_t thread_id); NativeThreadNetBSDSP AddThread(lldb::tid_t thread_id); - Status LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info); - void AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, Status &error); - void MonitorCallback(lldb::pid_t pid, int signal); void MonitorExited(lldb::pid_t pid, WaitStatus status); void MonitorSIGSTOP(lldb::pid_t pid); void MonitorSIGTRAP(lldb::pid_t pid); void MonitorSignal(lldb::pid_t pid, int signal); Status GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size); Status FixupBreakpointPCAsNeeded(NativeThreadNetBSD &thread); Status PopulateMemoryRegionCache(); void SigchldHandler(); - ::pid_t Attach(lldb::pid_t pid, Status &error); - + Status Attach(); Status ReinitializeThreads(); }; } // namespace process_netbsd } // namespace lldb_private #endif // #ifndef liblldb_NativeProcessNetBSD_H_ Index: vendor/lldb/dist/source/Plugins/Process/gdb-remote/CMakeLists.txt =================================================================== --- vendor/lldb/dist/source/Plugins/Process/gdb-remote/CMakeLists.txt (revision 320966) +++ vendor/lldb/dist/source/Plugins/Process/gdb-remote/CMakeLists.txt (revision 320967) @@ -1,43 +1,35 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin") include_directories(${LIBXML2_INCLUDE_DIR}) endif() set(LLDB_PLUGINS lldbPluginProcessUtility lldbPluginPlatformMacOSX ) -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Android") - list(APPEND LLDB_PLUGINS lldbPluginProcessLinux) -endif() - -if(CMAKE_SYSTEM_NAME MATCHES "NetBSD") - list(APPEND LLDB_PLUGINS lldbPluginProcessNetBSD) -endif() - add_lldb_library(lldbPluginProcessGDBRemote PLUGIN GDBRemoteClientBase.cpp GDBRemoteCommunication.cpp GDBRemoteCommunicationClient.cpp GDBRemoteCommunicationServer.cpp GDBRemoteCommunicationServerCommon.cpp GDBRemoteCommunicationServerLLGS.cpp GDBRemoteCommunicationServerPlatform.cpp GDBRemoteRegisterContext.cpp ProcessGDBRemote.cpp ProcessGDBRemoteLog.cpp ThreadGDBRemote.cpp LINK_LIBS lldbBreakpoint lldbCore lldbDataFormatters lldbHost lldbInterpreter lldbSymbol lldbTarget lldbUtility ${LLDB_PLUGINS} LINK_COMPONENTS Support ) Index: vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp (revision 320967) @@ -1,3876 +1,3894 @@ //===-- GDBRemoteCommunicationClient.cpp ------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "GDBRemoteCommunicationClient.h" // C Includes #include #include // C++ Includes #include #include // Other libraries and framework includes #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/State.h" #include "lldb/Host/HostInfo.h" #include "lldb/Interpreter/Args.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/JSON.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" // Project includes #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" #include "Utility/StringExtractorGDBRemote.h" #include "lldb/Host/Config.h" #include "llvm/ADT/StringSwitch.h" #if defined(HAVE_LIBCOMPRESSION) #include #endif using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; using namespace std::chrono; //---------------------------------------------------------------------- // GDBRemoteCommunicationClient constructor //---------------------------------------------------------------------- GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() : GDBRemoteClientBase("gdb-remote.client", "gdb-remote.client.rx_packet"), m_supports_not_sending_acks(eLazyBoolCalculate), m_supports_thread_suffix(eLazyBoolCalculate), m_supports_threads_in_stop_reply(eLazyBoolCalculate), m_supports_vCont_all(eLazyBoolCalculate), m_supports_vCont_any(eLazyBoolCalculate), m_supports_vCont_c(eLazyBoolCalculate), m_supports_vCont_C(eLazyBoolCalculate), m_supports_vCont_s(eLazyBoolCalculate), m_supports_vCont_S(eLazyBoolCalculate), m_qHostInfo_is_valid(eLazyBoolCalculate), m_curr_pid_is_valid(eLazyBoolCalculate), m_qProcessInfo_is_valid(eLazyBoolCalculate), m_qGDBServerVersion_is_valid(eLazyBoolCalculate), m_supports_alloc_dealloc_memory(eLazyBoolCalculate), m_supports_memory_region_info(eLazyBoolCalculate), m_supports_watchpoint_support_info(eLazyBoolCalculate), m_supports_detach_stay_stopped(eLazyBoolCalculate), m_watchpoints_trigger_after_instruction(eLazyBoolCalculate), m_attach_or_wait_reply(eLazyBoolCalculate), m_prepare_for_reg_writing_reply(eLazyBoolCalculate), m_supports_p(eLazyBoolCalculate), m_supports_x(eLazyBoolCalculate), m_avoid_g_packets(eLazyBoolCalculate), m_supports_QSaveRegisterState(eLazyBoolCalculate), m_supports_qXfer_auxv_read(eLazyBoolCalculate), m_supports_qXfer_libraries_read(eLazyBoolCalculate), m_supports_qXfer_libraries_svr4_read(eLazyBoolCalculate), m_supports_qXfer_features_read(eLazyBoolCalculate), m_supports_augmented_libraries_svr4_read(eLazyBoolCalculate), m_supports_jThreadExtendedInfo(eLazyBoolCalculate), m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate), m_supports_jGetSharedCacheInfo(eLazyBoolCalculate), m_supports_QPassSignals(eLazyBoolCalculate), + m_supports_error_string_reply(eLazyBoolCalculate), m_supports_qProcessInfoPID(true), m_supports_qfProcessInfo(true), m_supports_qUserName(true), m_supports_qGroupName(true), m_supports_qThreadStopInfo(true), m_supports_z0(true), m_supports_z1(true), m_supports_z2(true), m_supports_z3(true), m_supports_z4(true), m_supports_QEnvironment(true), m_supports_QEnvironmentHexEncoded(true), m_supports_qSymbol(true), m_qSymbol_requests_done(false), m_supports_qModuleInfo(true), m_supports_jThreadsInfo(true), m_supports_jModulesInfo(true), m_curr_pid(LLDB_INVALID_PROCESS_ID), m_curr_tid(LLDB_INVALID_THREAD_ID), m_curr_tid_run(LLDB_INVALID_THREAD_ID), m_num_supported_hardware_watchpoints(0), m_host_arch(), m_process_arch(), m_os_version_major(UINT32_MAX), m_os_version_minor(UINT32_MAX), m_os_version_update(UINT32_MAX), m_os_build(), m_os_kernel(), m_hostname(), m_gdb_server_name(), m_gdb_server_version(UINT32_MAX), m_default_packet_timeout(0), m_max_packet_size(0), m_qSupported_response(), m_supported_async_json_packets_is_valid(false), m_supported_async_json_packets_sp() {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient() { if (IsConnected()) Disconnect(); } bool GDBRemoteCommunicationClient::HandshakeWithServer(Status *error_ptr) { ResetDiscoverableSettings(false); // Start the read thread after we send the handshake ack since if we // fail to send the handshake ack, there is no reason to continue... if (SendAck()) { // Wait for any responses that might have been queued up in the remote // GDB server and flush them all StringExtractorGDBRemote response; PacketResult packet_result = PacketResult::Success; while (packet_result == PacketResult::Success) packet_result = ReadPacket(response, milliseconds(10), false); // The return value from QueryNoAckModeSupported() is true if the packet // was sent and _any_ response (including UNIMPLEMENTED) was received), // or false if no response was received. This quickly tells us if we have // a live connection to a remote GDB server... if (QueryNoAckModeSupported()) { return true; } else { if (error_ptr) error_ptr->SetErrorString("failed to get reply to handshake packet"); } } else { if (error_ptr) error_ptr->SetErrorString("failed to send the handshake ack"); } return false; } bool GDBRemoteCommunicationClient::GetEchoSupported() { if (m_supports_qEcho == eLazyBoolCalculate) { GetRemoteQSupported(); } return m_supports_qEcho == eLazyBoolYes; } bool GDBRemoteCommunicationClient::GetQPassSignalsSupported() { if (m_supports_QPassSignals == eLazyBoolCalculate) { GetRemoteQSupported(); } return m_supports_QPassSignals == eLazyBoolYes; } bool GDBRemoteCommunicationClient::GetAugmentedLibrariesSVR4ReadSupported() { if (m_supports_augmented_libraries_svr4_read == eLazyBoolCalculate) { GetRemoteQSupported(); } return m_supports_augmented_libraries_svr4_read == eLazyBoolYes; } bool GDBRemoteCommunicationClient::GetQXferLibrariesSVR4ReadSupported() { if (m_supports_qXfer_libraries_svr4_read == eLazyBoolCalculate) { GetRemoteQSupported(); } return m_supports_qXfer_libraries_svr4_read == eLazyBoolYes; } bool GDBRemoteCommunicationClient::GetQXferLibrariesReadSupported() { if (m_supports_qXfer_libraries_read == eLazyBoolCalculate) { GetRemoteQSupported(); } return m_supports_qXfer_libraries_read == eLazyBoolYes; } bool GDBRemoteCommunicationClient::GetQXferAuxvReadSupported() { if (m_supports_qXfer_auxv_read == eLazyBoolCalculate) { GetRemoteQSupported(); } return m_supports_qXfer_auxv_read == eLazyBoolYes; } bool GDBRemoteCommunicationClient::GetQXferFeaturesReadSupported() { if (m_supports_qXfer_features_read == eLazyBoolCalculate) { GetRemoteQSupported(); } return m_supports_qXfer_features_read == eLazyBoolYes; } uint64_t GDBRemoteCommunicationClient::GetRemoteMaxPacketSize() { if (m_max_packet_size == 0) { GetRemoteQSupported(); } return m_max_packet_size; } bool GDBRemoteCommunicationClient::QueryNoAckModeSupported() { if (m_supports_not_sending_acks == eLazyBoolCalculate) { m_send_acks = true; m_supports_not_sending_acks = eLazyBoolNo; // This is the first real packet that we'll send in a debug session and it // may take a little // longer than normal to receive a reply. Wait at least 6 seconds for a // reply to this packet. ScopedTimeout timeout(*this, std::max(GetPacketTimeout(), seconds(6))); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false) == PacketResult::Success) { if (response.IsOKResponse()) { m_send_acks = false; m_supports_not_sending_acks = eLazyBoolYes; } return true; } } return false; } void GDBRemoteCommunicationClient::GetListThreadsInStopReplySupported() { if (m_supports_threads_in_stop_reply == eLazyBoolCalculate) { m_supports_threads_in_stop_reply = eLazyBoolNo; StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response, false) == PacketResult::Success) { if (response.IsOKResponse()) m_supports_threads_in_stop_reply = eLazyBoolYes; } } } bool GDBRemoteCommunicationClient::GetVAttachOrWaitSupported() { if (m_attach_or_wait_reply == eLazyBoolCalculate) { m_attach_or_wait_reply = eLazyBoolNo; StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response, false) == PacketResult::Success) { if (response.IsOKResponse()) m_attach_or_wait_reply = eLazyBoolYes; } } if (m_attach_or_wait_reply == eLazyBoolYes) return true; else return false; } bool GDBRemoteCommunicationClient::GetSyncThreadStateSupported() { if (m_prepare_for_reg_writing_reply == eLazyBoolCalculate) { m_prepare_for_reg_writing_reply = eLazyBoolNo; StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response, false) == PacketResult::Success) { if (response.IsOKResponse()) m_prepare_for_reg_writing_reply = eLazyBoolYes; } } if (m_prepare_for_reg_writing_reply == eLazyBoolYes) return true; else return false; } void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) { if (did_exec == false) { // Hard reset everything, this is when we first connect to a GDB server m_supports_not_sending_acks = eLazyBoolCalculate; m_supports_thread_suffix = eLazyBoolCalculate; m_supports_threads_in_stop_reply = eLazyBoolCalculate; m_supports_vCont_c = eLazyBoolCalculate; m_supports_vCont_C = eLazyBoolCalculate; m_supports_vCont_s = eLazyBoolCalculate; m_supports_vCont_S = eLazyBoolCalculate; m_supports_p = eLazyBoolCalculate; m_supports_x = eLazyBoolCalculate; m_supports_QSaveRegisterState = eLazyBoolCalculate; m_qHostInfo_is_valid = eLazyBoolCalculate; m_curr_pid_is_valid = eLazyBoolCalculate; m_qGDBServerVersion_is_valid = eLazyBoolCalculate; m_supports_alloc_dealloc_memory = eLazyBoolCalculate; m_supports_memory_region_info = eLazyBoolCalculate; m_prepare_for_reg_writing_reply = eLazyBoolCalculate; m_attach_or_wait_reply = eLazyBoolCalculate; m_avoid_g_packets = eLazyBoolCalculate; m_supports_qXfer_auxv_read = eLazyBoolCalculate; m_supports_qXfer_libraries_read = eLazyBoolCalculate; m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate; m_supports_qXfer_features_read = eLazyBoolCalculate; m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate; m_supports_qProcessInfoPID = true; m_supports_qfProcessInfo = true; m_supports_qUserName = true; m_supports_qGroupName = true; m_supports_qThreadStopInfo = true; m_supports_z0 = true; m_supports_z1 = true; m_supports_z2 = true; m_supports_z3 = true; m_supports_z4 = true; m_supports_QEnvironment = true; m_supports_QEnvironmentHexEncoded = true; m_supports_qSymbol = true; m_qSymbol_requests_done = false; m_supports_qModuleInfo = true; m_host_arch.Clear(); m_os_version_major = UINT32_MAX; m_os_version_minor = UINT32_MAX; m_os_version_update = UINT32_MAX; m_os_build.clear(); m_os_kernel.clear(); m_hostname.clear(); m_gdb_server_name.clear(); m_gdb_server_version = UINT32_MAX; m_default_packet_timeout = seconds(0); m_max_packet_size = 0; m_qSupported_response.clear(); m_supported_async_json_packets_is_valid = false; m_supported_async_json_packets_sp.reset(); m_supports_jModulesInfo = true; } // These flags should be reset when we first connect to a GDB server // and when our inferior process execs m_qProcessInfo_is_valid = eLazyBoolCalculate; m_process_arch.Clear(); } void GDBRemoteCommunicationClient::GetRemoteQSupported() { // Clear out any capabilities we expect to see in the qSupported response m_supports_qXfer_auxv_read = eLazyBoolNo; m_supports_qXfer_libraries_read = eLazyBoolNo; m_supports_qXfer_libraries_svr4_read = eLazyBoolNo; m_supports_augmented_libraries_svr4_read = eLazyBoolNo; m_supports_qXfer_features_read = eLazyBoolNo; m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if // not, we assume no limit // build the qSupported packet std::vector features = {"xmlRegisters=i386,arm,mips"}; StreamString packet; packet.PutCString("qSupported"); for (uint32_t i = 0; i < features.size(); ++i) { packet.PutCString(i == 0 ? ":" : ";"); packet.PutCString(features[i]); } StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet.GetString(), response, /*send_async=*/false) == PacketResult::Success) { const char *response_cstr = response.GetStringRef().c_str(); // Hang on to the qSupported packet, so that platforms can do custom // configuration of the transport before attaching/launching the // process. m_qSupported_response = response_cstr; if (::strstr(response_cstr, "qXfer:auxv:read+")) m_supports_qXfer_auxv_read = eLazyBoolYes; if (::strstr(response_cstr, "qXfer:libraries-svr4:read+")) m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; if (::strstr(response_cstr, "augmented-libraries-svr4-read")) { m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; // implied m_supports_augmented_libraries_svr4_read = eLazyBoolYes; } if (::strstr(response_cstr, "qXfer:libraries:read+")) m_supports_qXfer_libraries_read = eLazyBoolYes; if (::strstr(response_cstr, "qXfer:features:read+")) m_supports_qXfer_features_read = eLazyBoolYes; // Look for a list of compressions in the features list e.g. // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-deflate,lzma const char *features_list = ::strstr(response_cstr, "qXfer:features:"); if (features_list) { const char *compressions = ::strstr(features_list, "SupportedCompressions="); if (compressions) { std::vector supported_compressions; compressions += sizeof("SupportedCompressions=") - 1; const char *end_of_compressions = strchr(compressions, ';'); if (end_of_compressions == NULL) { end_of_compressions = strchr(compressions, '\0'); } const char *current_compression = compressions; while (current_compression < end_of_compressions) { const char *next_compression_name = strchr(current_compression, ','); const char *end_of_this_word = next_compression_name; if (next_compression_name == NULL || end_of_compressions < next_compression_name) { end_of_this_word = end_of_compressions; } if (end_of_this_word) { if (end_of_this_word == current_compression) { current_compression++; } else { std::string this_compression( current_compression, end_of_this_word - current_compression); supported_compressions.push_back(this_compression); current_compression = end_of_this_word + 1; } } else { supported_compressions.push_back(current_compression); current_compression = end_of_compressions; } } if (supported_compressions.size() > 0) { MaybeEnableCompression(supported_compressions); } } } if (::strstr(response_cstr, "qEcho")) m_supports_qEcho = eLazyBoolYes; else m_supports_qEcho = eLazyBoolNo; if (::strstr(response_cstr, "QPassSignals+")) m_supports_QPassSignals = eLazyBoolYes; else m_supports_QPassSignals = eLazyBoolNo; const char *packet_size_str = ::strstr(response_cstr, "PacketSize="); if (packet_size_str) { StringExtractorGDBRemote packet_response(packet_size_str + strlen("PacketSize=")); m_max_packet_size = packet_response.GetHexMaxU64(/*little_endian=*/false, UINT64_MAX); if (m_max_packet_size == 0) { m_max_packet_size = UINT64_MAX; // Must have been a garbled response Log *log( ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (log) log->Printf("Garbled PacketSize spec in qSupported response"); } } } } bool GDBRemoteCommunicationClient::GetThreadSuffixSupported() { if (m_supports_thread_suffix == eLazyBoolCalculate) { StringExtractorGDBRemote response; m_supports_thread_suffix = eLazyBoolNo; if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response, false) == PacketResult::Success) { if (response.IsOKResponse()) m_supports_thread_suffix = eLazyBoolYes; } } return m_supports_thread_suffix; } bool GDBRemoteCommunicationClient::GetVContSupported(char flavor) { if (m_supports_vCont_c == eLazyBoolCalculate) { StringExtractorGDBRemote response; m_supports_vCont_any = eLazyBoolNo; m_supports_vCont_all = eLazyBoolNo; m_supports_vCont_c = eLazyBoolNo; m_supports_vCont_C = eLazyBoolNo; m_supports_vCont_s = eLazyBoolNo; m_supports_vCont_S = eLazyBoolNo; if (SendPacketAndWaitForResponse("vCont?", response, false) == PacketResult::Success) { const char *response_cstr = response.GetStringRef().c_str(); if (::strstr(response_cstr, ";c")) m_supports_vCont_c = eLazyBoolYes; if (::strstr(response_cstr, ";C")) m_supports_vCont_C = eLazyBoolYes; if (::strstr(response_cstr, ";s")) m_supports_vCont_s = eLazyBoolYes; if (::strstr(response_cstr, ";S")) m_supports_vCont_S = eLazyBoolYes; if (m_supports_vCont_c == eLazyBoolYes && m_supports_vCont_C == eLazyBoolYes && m_supports_vCont_s == eLazyBoolYes && m_supports_vCont_S == eLazyBoolYes) { m_supports_vCont_all = eLazyBoolYes; } if (m_supports_vCont_c == eLazyBoolYes || m_supports_vCont_C == eLazyBoolYes || m_supports_vCont_s == eLazyBoolYes || m_supports_vCont_S == eLazyBoolYes) { m_supports_vCont_any = eLazyBoolYes; } } } switch (flavor) { case 'a': return m_supports_vCont_any; case 'A': return m_supports_vCont_all; case 'c': return m_supports_vCont_c; case 'C': return m_supports_vCont_C; case 's': return m_supports_vCont_s; case 'S': return m_supports_vCont_S; default: break; } return false; } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse( lldb::tid_t tid, StreamString &&payload, StringExtractorGDBRemote &response, bool send_async) { Lock lock(*this, send_async); if (!lock) { if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet( GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)) log->Printf("GDBRemoteCommunicationClient::%s: Didn't get sequence mutex " "for %s packet.", __FUNCTION__, payload.GetData()); return PacketResult::ErrorNoSequenceLock; } if (GetThreadSuffixSupported()) payload.Printf(";thread:%4.4" PRIx64 ";", tid); else { if (!SetCurrentThread(tid)) return PacketResult::ErrorSendFailed; } return SendPacketAndWaitForResponseNoLock(payload.GetString(), response); } // Check if the target supports 'p' packet. It sends out a 'p' // packet and checks the response. A normal packet will tell us // that support is available. // // Takes a valid thread ID because p needs to apply to a thread. bool GDBRemoteCommunicationClient::GetpPacketSupported(lldb::tid_t tid) { if (m_supports_p == eLazyBoolCalculate) { m_supports_p = eLazyBoolNo; StreamString payload; payload.PutCString("p0"); StringExtractorGDBRemote response; if (SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) == PacketResult::Success && response.IsNormalResponse()) { m_supports_p = eLazyBoolYes; } } return m_supports_p; } StructuredData::ObjectSP GDBRemoteCommunicationClient::GetThreadsInfo() { // Get information on all threads at one using the "jThreadsInfo" packet StructuredData::ObjectSP object_sp; if (m_supports_jThreadsInfo) { StringExtractorGDBRemote response; response.SetResponseValidatorToJSON(); if (SendPacketAndWaitForResponse("jThreadsInfo", response, false) == PacketResult::Success) { if (response.IsUnsupportedResponse()) { m_supports_jThreadsInfo = false; } else if (!response.Empty()) { object_sp = StructuredData::ParseJSON(response.GetStringRef()); } } } return object_sp; } bool GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported() { if (m_supports_jThreadExtendedInfo == eLazyBoolCalculate) { StringExtractorGDBRemote response; m_supports_jThreadExtendedInfo = eLazyBoolNo; if (SendPacketAndWaitForResponse("jThreadExtendedInfo:", response, false) == PacketResult::Success) { if (response.IsOKResponse()) { m_supports_jThreadExtendedInfo = eLazyBoolYes; } } } return m_supports_jThreadExtendedInfo; } +void GDBRemoteCommunicationClient::EnableErrorStringInPacket() { + if (m_supports_error_string_reply == eLazyBoolCalculate) { + StringExtractorGDBRemote response; + // We try to enable error strings in remote packets + // but if we fail, we just work in the older way. + m_supports_error_string_reply = eLazyBoolNo; + if (SendPacketAndWaitForResponse("QEnableErrorStrings", response, false) == + PacketResult::Success) { + if (response.IsOKResponse()) { + m_supports_error_string_reply = eLazyBoolYes; + } + } + } +} + bool GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported() { if (m_supports_jLoadedDynamicLibrariesInfos == eLazyBoolCalculate) { StringExtractorGDBRemote response; m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolNo; if (SendPacketAndWaitForResponse("jGetLoadedDynamicLibrariesInfos:", response, false) == PacketResult::Success) { if (response.IsOKResponse()) { m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolYes; } } } return m_supports_jLoadedDynamicLibrariesInfos; } bool GDBRemoteCommunicationClient::GetSharedCacheInfoSupported() { if (m_supports_jGetSharedCacheInfo == eLazyBoolCalculate) { StringExtractorGDBRemote response; m_supports_jGetSharedCacheInfo = eLazyBoolNo; if (SendPacketAndWaitForResponse("jGetSharedCacheInfo:", response, false) == PacketResult::Success) { if (response.IsOKResponse()) { m_supports_jGetSharedCacheInfo = eLazyBoolYes; } } } return m_supports_jGetSharedCacheInfo; } bool GDBRemoteCommunicationClient::GetxPacketSupported() { if (m_supports_x == eLazyBoolCalculate) { StringExtractorGDBRemote response; m_supports_x = eLazyBoolNo; char packet[256]; snprintf(packet, sizeof(packet), "x0,0"); if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success) { if (response.IsOKResponse()) m_supports_x = eLazyBoolYes; } } return m_supports_x; } GDBRemoteCommunicationClient::PacketResult GDBRemoteCommunicationClient::SendPacketsAndConcatenateResponses( const char *payload_prefix, std::string &response_string) { Lock lock(*this, false); if (!lock) { Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); if (log) log->Printf("error: failed to get packet sequence mutex, not sending " "packets with prefix '%s'", payload_prefix); return PacketResult::ErrorNoSequenceLock; } response_string = ""; std::string payload_prefix_str(payload_prefix); unsigned int response_size = 0x1000; if (response_size > GetRemoteMaxPacketSize()) { // May send qSupported packet response_size = GetRemoteMaxPacketSize(); } for (unsigned int offset = 0; true; offset += response_size) { StringExtractorGDBRemote this_response; // Construct payload char sizeDescriptor[128]; snprintf(sizeDescriptor, sizeof(sizeDescriptor), "%x,%x", offset, response_size); PacketResult result = SendPacketAndWaitForResponseNoLock( payload_prefix_str + sizeDescriptor, this_response); if (result != PacketResult::Success) return result; const std::string &this_string = this_response.GetStringRef(); // Check for m or l as first character; l seems to mean this is the last // chunk char first_char = *this_string.c_str(); if (first_char != 'm' && first_char != 'l') { return PacketResult::ErrorReplyInvalid; } // Concatenate the result so far (skipping 'm' or 'l') response_string.append(this_string, 1, std::string::npos); if (first_char == 'l') // We're done return PacketResult::Success; } } lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) { if (allow_lazy && m_curr_pid_is_valid == eLazyBoolYes) return m_curr_pid; // First try to retrieve the pid via the qProcessInfo request. GetCurrentProcessInfo(allow_lazy); if (m_curr_pid_is_valid == eLazyBoolYes) { // We really got it. return m_curr_pid; } else { // If we don't get a response for qProcessInfo, check if $qC gives us a // result. // $qC only returns a real process id on older debugserver and lldb-platform // stubs. // The gdb remote protocol documents $qC as returning the thread id, which // newer // debugserver and lldb-gdbserver stubs return correctly. StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse("qC", response, false) == PacketResult::Success) { if (response.GetChar() == 'Q') { if (response.GetChar() == 'C') { m_curr_pid = response.GetHexMaxU32(false, LLDB_INVALID_PROCESS_ID); if (m_curr_pid != LLDB_INVALID_PROCESS_ID) { m_curr_pid_is_valid = eLazyBoolYes; return m_curr_pid; } } } } // If we don't get a response for $qC, check if $qfThreadID gives us a // result. if (m_curr_pid == LLDB_INVALID_PROCESS_ID) { std::vector thread_ids; bool sequence_mutex_unavailable; size_t size; size = GetCurrentThreadIDs(thread_ids, sequence_mutex_unavailable); if (size && sequence_mutex_unavailable == false) { m_curr_pid = thread_ids.front(); m_curr_pid_is_valid = eLazyBoolYes; return m_curr_pid; } } } return LLDB_INVALID_PROCESS_ID; } bool GDBRemoteCommunicationClient::GetLaunchSuccess(std::string &error_str) { error_str.clear(); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse("qLaunchSuccess", response, false) == PacketResult::Success) { if (response.IsOKResponse()) return true; if (response.GetChar() == 'E') { // A string the describes what failed when launching... error_str = response.GetStringRef().substr(1); } else { error_str.assign("unknown error occurred launching process"); } } else { error_str.assign("timed out waiting for app to launch"); } return false; } int GDBRemoteCommunicationClient::SendArgumentsPacket( const ProcessLaunchInfo &launch_info) { // Since we don't get the send argv0 separate from the executable path, we // need to // make sure to use the actual executable path found in the launch_info... std::vector argv; FileSpec exe_file = launch_info.GetExecutableFile(); std::string exe_path; const char *arg = NULL; const Args &launch_args = launch_info.GetArguments(); if (exe_file) exe_path = exe_file.GetPath(false); else { arg = launch_args.GetArgumentAtIndex(0); if (arg) exe_path = arg; } if (!exe_path.empty()) { argv.push_back(exe_path.c_str()); for (uint32_t i = 1; (arg = launch_args.GetArgumentAtIndex(i)) != NULL; ++i) { if (arg) argv.push_back(arg); } } if (!argv.empty()) { StreamString packet; packet.PutChar('A'); for (size_t i = 0, n = argv.size(); i < n; ++i) { arg = argv[i]; const int arg_len = strlen(arg); if (i > 0) packet.PutChar(','); packet.Printf("%i,%i,", arg_len * 2, (int)i); packet.PutBytesAsRawHex8(arg, arg_len); } StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == PacketResult::Success) { if (response.IsOKResponse()) return 0; uint8_t error = response.GetError(); if (error) return error; } } return -1; } int GDBRemoteCommunicationClient::SendEnvironmentPacket( char const *name_equal_value) { if (name_equal_value && name_equal_value[0]) { StreamString packet; bool send_hex_encoding = false; for (const char *p = name_equal_value; *p != '\0' && send_hex_encoding == false; ++p) { if (isprint(*p)) { switch (*p) { case '$': case '#': case '*': case '}': send_hex_encoding = true; break; default: break; } } else { // We have non printable characters, lets hex encode this... send_hex_encoding = true; } } StringExtractorGDBRemote response; if (send_hex_encoding) { if (m_supports_QEnvironmentHexEncoded) { packet.PutCString("QEnvironmentHexEncoded:"); packet.PutBytesAsRawHex8(name_equal_value, strlen(name_equal_value)); if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == PacketResult::Success) { if (response.IsOKResponse()) return 0; uint8_t error = response.GetError(); if (error) return error; if (response.IsUnsupportedResponse()) m_supports_QEnvironmentHexEncoded = false; } } } else if (m_supports_QEnvironment) { packet.Printf("QEnvironment:%s", name_equal_value); if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == PacketResult::Success) { if (response.IsOKResponse()) return 0; uint8_t error = response.GetError(); if (error) return error; if (response.IsUnsupportedResponse()) m_supports_QEnvironment = false; } } } return -1; } int GDBRemoteCommunicationClient::SendLaunchArchPacket(char const *arch) { if (arch && arch[0]) { StreamString packet; packet.Printf("QLaunchArch:%s", arch); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == PacketResult::Success) { if (response.IsOKResponse()) return 0; uint8_t error = response.GetError(); if (error) return error; } } return -1; } int GDBRemoteCommunicationClient::SendLaunchEventDataPacket( char const *data, bool *was_supported) { if (data && *data != '\0') { StreamString packet; packet.Printf("QSetProcessEvent:%s", data); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == PacketResult::Success) { if (response.IsOKResponse()) { if (was_supported) *was_supported = true; return 0; } else if (response.IsUnsupportedResponse()) { if (was_supported) *was_supported = false; return -1; } else { uint8_t error = response.GetError(); if (was_supported) *was_supported = true; if (error) return error; } } } return -1; } bool GDBRemoteCommunicationClient::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update) { if (GetHostInfo()) { if (m_os_version_major != UINT32_MAX) { major = m_os_version_major; minor = m_os_version_minor; update = m_os_version_update; return true; } } return false; } bool GDBRemoteCommunicationClient::GetOSBuildString(std::string &s) { if (GetHostInfo()) { if (!m_os_build.empty()) { s = m_os_build; return true; } } s.clear(); return false; } bool GDBRemoteCommunicationClient::GetOSKernelDescription(std::string &s) { if (GetHostInfo()) { if (!m_os_kernel.empty()) { s = m_os_kernel; return true; } } s.clear(); return false; } bool GDBRemoteCommunicationClient::GetHostname(std::string &s) { if (GetHostInfo()) { if (!m_hostname.empty()) { s = m_hostname; return true; } } s.clear(); return false; } ArchSpec GDBRemoteCommunicationClient::GetSystemArchitecture() { if (GetHostInfo()) return m_host_arch; return ArchSpec(); } const lldb_private::ArchSpec & GDBRemoteCommunicationClient::GetProcessArchitecture() { if (m_qProcessInfo_is_valid == eLazyBoolCalculate) GetCurrentProcessInfo(); return m_process_arch; } bool GDBRemoteCommunicationClient::GetGDBServerVersion() { if (m_qGDBServerVersion_is_valid == eLazyBoolCalculate) { m_gdb_server_name.clear(); m_gdb_server_version = 0; m_qGDBServerVersion_is_valid = eLazyBoolNo; StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse("qGDBServerVersion", response, false) == PacketResult::Success) { if (response.IsNormalResponse()) { llvm::StringRef name, value; bool success = false; while (response.GetNameColonValue(name, value)) { if (name.equals("name")) { success = true; m_gdb_server_name = value; } else if (name.equals("version")) { llvm::StringRef major, minor; std::tie(major, minor) = value.split('.'); if (!major.getAsInteger(0, m_gdb_server_version)) success = true; } } if (success) m_qGDBServerVersion_is_valid = eLazyBoolYes; } } } return m_qGDBServerVersion_is_valid == eLazyBoolYes; } void GDBRemoteCommunicationClient::MaybeEnableCompression( std::vector supported_compressions) { CompressionType avail_type = CompressionType::None; std::string avail_name; #if defined(HAVE_LIBCOMPRESSION) // libcompression is weak linked so test if compression_decode_buffer() is // available if (compression_decode_buffer != NULL && avail_type == CompressionType::None) { for (auto compression : supported_compressions) { if (compression == "lzfse") { avail_type = CompressionType::LZFSE; avail_name = compression; break; } } } #endif #if defined(HAVE_LIBCOMPRESSION) // libcompression is weak linked so test if compression_decode_buffer() is // available if (compression_decode_buffer != NULL && avail_type == CompressionType::None) { for (auto compression : supported_compressions) { if (compression == "zlib-deflate") { avail_type = CompressionType::ZlibDeflate; avail_name = compression; break; } } } #endif #if defined(HAVE_LIBZ) if (avail_type == CompressionType::None) { for (auto compression : supported_compressions) { if (compression == "zlib-deflate") { avail_type = CompressionType::ZlibDeflate; avail_name = compression; break; } } } #endif #if defined(HAVE_LIBCOMPRESSION) // libcompression is weak linked so test if compression_decode_buffer() is // available if (compression_decode_buffer != NULL && avail_type == CompressionType::None) { for (auto compression : supported_compressions) { if (compression == "lz4") { avail_type = CompressionType::LZ4; avail_name = compression; break; } } } #endif #if defined(HAVE_LIBCOMPRESSION) // libcompression is weak linked so test if compression_decode_buffer() is // available if (compression_decode_buffer != NULL && avail_type == CompressionType::None) { for (auto compression : supported_compressions) { if (compression == "lzma") { avail_type = CompressionType::LZMA; avail_name = compression; break; } } } #endif if (avail_type != CompressionType::None) { StringExtractorGDBRemote response; std::string packet = "QEnableCompression:type:" + avail_name + ";"; if (SendPacketAndWaitForResponse(packet, response, false) != PacketResult::Success) return; if (response.IsOKResponse()) { m_compression_type = avail_type; } } } const char *GDBRemoteCommunicationClient::GetGDBServerProgramName() { if (GetGDBServerVersion()) { if (!m_gdb_server_name.empty()) return m_gdb_server_name.c_str(); } return NULL; } uint32_t GDBRemoteCommunicationClient::GetGDBServerProgramVersion() { if (GetGDBServerVersion()) return m_gdb_server_version; return 0; } bool GDBRemoteCommunicationClient::GetDefaultThreadId(lldb::tid_t &tid) { StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse("qC", response, false) != PacketResult::Success) return false; if (!response.IsNormalResponse()) return false; if (response.GetChar() == 'Q' && response.GetChar() == 'C') tid = response.GetHexMaxU32(true, -1); return true; } bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS)); if (force || m_qHostInfo_is_valid == eLazyBoolCalculate) { m_qHostInfo_is_valid = eLazyBoolNo; StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse("qHostInfo", response, false) == PacketResult::Success) { if (response.IsNormalResponse()) { llvm::StringRef name; llvm::StringRef value; uint32_t cpu = LLDB_INVALID_CPUTYPE; uint32_t sub = 0; std::string arch_name; std::string os_name; std::string vendor_name; std::string triple; std::string distribution_id; uint32_t pointer_byte_size = 0; ByteOrder byte_order = eByteOrderInvalid; uint32_t num_keys_decoded = 0; while (response.GetNameColonValue(name, value)) { if (name.equals("cputype")) { // exception type in big endian hex if (!value.getAsInteger(0, cpu)) ++num_keys_decoded; } else if (name.equals("cpusubtype")) { // exception count in big endian hex if (!value.getAsInteger(0, sub)) ++num_keys_decoded; } else if (name.equals("arch")) { arch_name = value; ++num_keys_decoded; } else if (name.equals("triple")) { StringExtractor extractor(value); extractor.GetHexByteString(triple); ++num_keys_decoded; } else if (name.equals("distribution_id")) { StringExtractor extractor(value); extractor.GetHexByteString(distribution_id); ++num_keys_decoded; } else if (name.equals("os_build")) { StringExtractor extractor(value); extractor.GetHexByteString(m_os_build); ++num_keys_decoded; } else if (name.equals("hostname")) { StringExtractor extractor(value); extractor.GetHexByteString(m_hostname); ++num_keys_decoded; } else if (name.equals("os_kernel")) { StringExtractor extractor(value); extractor.GetHexByteString(m_os_kernel); ++num_keys_decoded; } else if (name.equals("ostype")) { os_name = value; ++num_keys_decoded; } else if (name.equals("vendor")) { vendor_name = value; ++num_keys_decoded; } else if (name.equals("endian")) { byte_order = llvm::StringSwitch(value) .Case("little", eByteOrderLittle) .Case("big", eByteOrderBig) .Case("pdp", eByteOrderPDP) .Default(eByteOrderInvalid); if (byte_order != eByteOrderInvalid) ++num_keys_decoded; } else if (name.equals("ptrsize")) { if (!value.getAsInteger(0, pointer_byte_size)) ++num_keys_decoded; } else if (name.equals("os_version") || name.equals( "version")) // Older debugserver binaries used the // "version" key instead of // "os_version"... { Args::StringToVersion(value, m_os_version_major, m_os_version_minor, m_os_version_update); if (m_os_version_major != UINT32_MAX) ++num_keys_decoded; } else if (name.equals("watchpoint_exceptions_received")) { m_watchpoints_trigger_after_instruction = llvm::StringSwitch(value) .Case("before", eLazyBoolNo) .Case("after", eLazyBoolYes) .Default(eLazyBoolCalculate); if (m_watchpoints_trigger_after_instruction != eLazyBoolCalculate) ++num_keys_decoded; } else if (name.equals("default_packet_timeout")) { uint32_t timeout_seconds; if (!value.getAsInteger(0, timeout_seconds)) { m_default_packet_timeout = seconds(timeout_seconds); SetPacketTimeout(m_default_packet_timeout); ++num_keys_decoded; } } } if (num_keys_decoded > 0) m_qHostInfo_is_valid = eLazyBoolYes; if (triple.empty()) { if (arch_name.empty()) { if (cpu != LLDB_INVALID_CPUTYPE) { m_host_arch.SetArchitecture(eArchTypeMachO, cpu, sub); if (pointer_byte_size) { assert(pointer_byte_size == m_host_arch.GetAddressByteSize()); } if (byte_order != eByteOrderInvalid) { assert(byte_order == m_host_arch.GetByteOrder()); } if (!vendor_name.empty()) m_host_arch.GetTriple().setVendorName( llvm::StringRef(vendor_name)); if (!os_name.empty()) m_host_arch.GetTriple().setOSName(llvm::StringRef(os_name)); } } else { std::string triple; triple += arch_name; if (!vendor_name.empty() || !os_name.empty()) { triple += '-'; if (vendor_name.empty()) triple += "unknown"; else triple += vendor_name; triple += '-'; if (os_name.empty()) triple += "unknown"; else triple += os_name; } m_host_arch.SetTriple(triple.c_str()); llvm::Triple &host_triple = m_host_arch.GetTriple(); if (host_triple.getVendor() == llvm::Triple::Apple && host_triple.getOS() == llvm::Triple::Darwin) { switch (m_host_arch.GetMachine()) { case llvm::Triple::aarch64: case llvm::Triple::arm: case llvm::Triple::thumb: host_triple.setOS(llvm::Triple::IOS); break; default: host_triple.setOS(llvm::Triple::MacOSX); break; } } if (pointer_byte_size) { assert(pointer_byte_size == m_host_arch.GetAddressByteSize()); } if (byte_order != eByteOrderInvalid) { assert(byte_order == m_host_arch.GetByteOrder()); } } } else { m_host_arch.SetTriple(triple.c_str()); if (pointer_byte_size) { assert(pointer_byte_size == m_host_arch.GetAddressByteSize()); } if (byte_order != eByteOrderInvalid) { assert(byte_order == m_host_arch.GetByteOrder()); } if (log) log->Printf("GDBRemoteCommunicationClient::%s parsed host " "architecture as %s, triple as %s from triple text %s", __FUNCTION__, m_host_arch.GetArchitectureName() ? m_host_arch.GetArchitectureName() : "", m_host_arch.GetTriple().getTriple().c_str(), triple.c_str()); } if (!distribution_id.empty()) m_host_arch.SetDistributionId(distribution_id.c_str()); } } } return m_qHostInfo_is_valid == eLazyBoolYes; } int GDBRemoteCommunicationClient::SendAttach( lldb::pid_t pid, StringExtractorGDBRemote &response) { if (pid != LLDB_INVALID_PROCESS_ID) { char packet[64]; const int packet_len = ::snprintf(packet, sizeof(packet), "vAttach;%" PRIx64, pid); UNUSED_IF_ASSERT_DISABLED(packet_len); assert(packet_len < (int)sizeof(packet)); if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success) { if (response.IsErrorResponse()) return response.GetError(); return 0; } } return -1; } int GDBRemoteCommunicationClient::SendStdinNotification(const char *data, size_t data_len) { StreamString packet; packet.PutCString("I"); packet.PutBytesAsRawHex8(data, data_len); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == PacketResult::Success) { return 0; } return response.GetError(); } const lldb_private::ArchSpec & GDBRemoteCommunicationClient::GetHostArchitecture() { if (m_qHostInfo_is_valid == eLazyBoolCalculate) GetHostInfo(); return m_host_arch; } seconds GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout() { if (m_qHostInfo_is_valid == eLazyBoolCalculate) GetHostInfo(); return m_default_packet_timeout; } addr_t GDBRemoteCommunicationClient::AllocateMemory(size_t size, uint32_t permissions) { if (m_supports_alloc_dealloc_memory != eLazyBoolNo) { m_supports_alloc_dealloc_memory = eLazyBoolYes; char packet[64]; const int packet_len = ::snprintf( packet, sizeof(packet), "_M%" PRIx64 ",%s%s%s", (uint64_t)size, permissions & lldb::ePermissionsReadable ? "r" : "", permissions & lldb::ePermissionsWritable ? "w" : "", permissions & lldb::ePermissionsExecutable ? "x" : ""); assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success) { if (response.IsUnsupportedResponse()) m_supports_alloc_dealloc_memory = eLazyBoolNo; else if (!response.IsErrorResponse()) return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); } else { m_supports_alloc_dealloc_memory = eLazyBoolNo; } } return LLDB_INVALID_ADDRESS; } bool GDBRemoteCommunicationClient::DeallocateMemory(addr_t addr) { if (m_supports_alloc_dealloc_memory != eLazyBoolNo) { m_supports_alloc_dealloc_memory = eLazyBoolYes; char packet[64]; const int packet_len = ::snprintf(packet, sizeof(packet), "_m%" PRIx64, (uint64_t)addr); assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success) { if (response.IsUnsupportedResponse()) m_supports_alloc_dealloc_memory = eLazyBoolNo; else if (response.IsOKResponse()) return true; } else { m_supports_alloc_dealloc_memory = eLazyBoolNo; } } return false; } Status GDBRemoteCommunicationClient::Detach(bool keep_stopped) { Status error; if (keep_stopped) { if (m_supports_detach_stay_stopped == eLazyBoolCalculate) { char packet[64]; const int packet_len = ::snprintf(packet, sizeof(packet), "qSupportsDetachAndStayStopped:"); assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success && response.IsOKResponse()) { m_supports_detach_stay_stopped = eLazyBoolYes; } else { m_supports_detach_stay_stopped = eLazyBoolNo; } } if (m_supports_detach_stay_stopped == eLazyBoolNo) { error.SetErrorString("Stays stopped not supported by this target."); return error; } else { StringExtractorGDBRemote response; PacketResult packet_result = SendPacketAndWaitForResponse("D1", response, false); if (packet_result != PacketResult::Success) error.SetErrorString("Sending extended disconnect packet failed."); } } else { StringExtractorGDBRemote response; PacketResult packet_result = SendPacketAndWaitForResponse("D", response, false); if (packet_result != PacketResult::Success) error.SetErrorString("Sending disconnect packet failed."); } return error; } Status GDBRemoteCommunicationClient::GetMemoryRegionInfo( lldb::addr_t addr, lldb_private::MemoryRegionInfo ®ion_info) { Status error; region_info.Clear(); if (m_supports_memory_region_info != eLazyBoolNo) { m_supports_memory_region_info = eLazyBoolYes; char packet[64]; const int packet_len = ::snprintf( packet, sizeof(packet), "qMemoryRegionInfo:%" PRIx64, (uint64_t)addr); assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success) { llvm::StringRef name; llvm::StringRef value; addr_t addr_value = LLDB_INVALID_ADDRESS; bool success = true; bool saw_permissions = false; while (success && response.GetNameColonValue(name, value)) { if (name.equals("start")) { if (!value.getAsInteger(16, addr_value)) region_info.GetRange().SetRangeBase(addr_value); } else if (name.equals("size")) { if (!value.getAsInteger(16, addr_value)) region_info.GetRange().SetByteSize(addr_value); } else if (name.equals("permissions") && region_info.GetRange().IsValid()) { saw_permissions = true; if (region_info.GetRange().Contains(addr)) { if (value.find('r') != llvm::StringRef::npos) region_info.SetReadable(MemoryRegionInfo::eYes); else region_info.SetReadable(MemoryRegionInfo::eNo); if (value.find('w') != llvm::StringRef::npos) region_info.SetWritable(MemoryRegionInfo::eYes); else region_info.SetWritable(MemoryRegionInfo::eNo); if (value.find('x') != llvm::StringRef::npos) region_info.SetExecutable(MemoryRegionInfo::eYes); else region_info.SetExecutable(MemoryRegionInfo::eNo); region_info.SetMapped(MemoryRegionInfo::eYes); } else { // The reported region does not contain this address -- we're // looking at an unmapped page region_info.SetReadable(MemoryRegionInfo::eNo); region_info.SetWritable(MemoryRegionInfo::eNo); region_info.SetExecutable(MemoryRegionInfo::eNo); region_info.SetMapped(MemoryRegionInfo::eNo); } } else if (name.equals("name")) { StringExtractorGDBRemote name_extractor(value); std::string name; name_extractor.GetHexByteString(name); region_info.SetName(name.c_str()); } else if (name.equals("error")) { StringExtractorGDBRemote error_extractor(value); std::string error_string; // Now convert the HEX bytes into a string value error_extractor.GetHexByteString(error_string); error.SetErrorString(error_string.c_str()); } } if (region_info.GetRange().IsValid()) { // We got a valid address range back but no permissions -- which means // this is an unmapped page if (!saw_permissions) { region_info.SetReadable(MemoryRegionInfo::eNo); region_info.SetWritable(MemoryRegionInfo::eNo); region_info.SetExecutable(MemoryRegionInfo::eNo); region_info.SetMapped(MemoryRegionInfo::eNo); } } else { // We got an invalid address range back error.SetErrorString("Server returned invalid range"); } } else { m_supports_memory_region_info = eLazyBoolNo; } } if (m_supports_memory_region_info == eLazyBoolNo) { error.SetErrorString("qMemoryRegionInfo is not supported"); } if (error.Fail()) region_info.Clear(); return error; } Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo(uint32_t &num) { Status error; if (m_supports_watchpoint_support_info == eLazyBoolYes) { num = m_num_supported_hardware_watchpoints; return error; } // Set num to 0 first. num = 0; if (m_supports_watchpoint_support_info != eLazyBoolNo) { char packet[64]; const int packet_len = ::snprintf(packet, sizeof(packet), "qWatchpointSupportInfo:"); assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success) { m_supports_watchpoint_support_info = eLazyBoolYes; llvm::StringRef name; llvm::StringRef value; while (response.GetNameColonValue(name, value)) { if (name.equals("num")) { value.getAsInteger(0, m_num_supported_hardware_watchpoints); num = m_num_supported_hardware_watchpoints; } } } else { m_supports_watchpoint_support_info = eLazyBoolNo; } } if (m_supports_watchpoint_support_info == eLazyBoolNo) { error.SetErrorString("qWatchpointSupportInfo is not supported"); } return error; } lldb_private::Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo( uint32_t &num, bool &after, const ArchSpec &arch) { Status error(GetWatchpointSupportInfo(num)); if (error.Success()) error = GetWatchpointsTriggerAfterInstruction(after, arch); return error; } lldb_private::Status GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction( bool &after, const ArchSpec &arch) { Status error; llvm::Triple::ArchType atype = arch.GetMachine(); // we assume watchpoints will happen after running the relevant opcode // and we only want to override this behavior if we have explicitly // received a qHostInfo telling us otherwise if (m_qHostInfo_is_valid != eLazyBoolYes) { // On targets like MIPS, watchpoint exceptions are always generated // before the instruction is executed. The connected target may not // support qHostInfo or qWatchpointSupportInfo packets. if (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel || atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el) after = false; else after = true; } else { // For MIPS, set m_watchpoints_trigger_after_instruction to eLazyBoolNo // if it is not calculated before. if (m_watchpoints_trigger_after_instruction == eLazyBoolCalculate && (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel || atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el)) m_watchpoints_trigger_after_instruction = eLazyBoolNo; after = (m_watchpoints_trigger_after_instruction != eLazyBoolNo); } return error; } int GDBRemoteCommunicationClient::SetSTDIN(const FileSpec &file_spec) { if (file_spec) { std::string path{file_spec.GetPath(false)}; StreamString packet; packet.PutCString("QSetSTDIN:"); packet.PutCStringAsRawHex8(path.c_str()); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == PacketResult::Success) { if (response.IsOKResponse()) return 0; uint8_t error = response.GetError(); if (error) return error; } } return -1; } int GDBRemoteCommunicationClient::SetSTDOUT(const FileSpec &file_spec) { if (file_spec) { std::string path{file_spec.GetPath(false)}; StreamString packet; packet.PutCString("QSetSTDOUT:"); packet.PutCStringAsRawHex8(path.c_str()); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == PacketResult::Success) { if (response.IsOKResponse()) return 0; uint8_t error = response.GetError(); if (error) return error; } } return -1; } int GDBRemoteCommunicationClient::SetSTDERR(const FileSpec &file_spec) { if (file_spec) { std::string path{file_spec.GetPath(false)}; StreamString packet; packet.PutCString("QSetSTDERR:"); packet.PutCStringAsRawHex8(path.c_str()); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == PacketResult::Success) { if (response.IsOKResponse()) return 0; uint8_t error = response.GetError(); if (error) return error; } } return -1; } bool GDBRemoteCommunicationClient::GetWorkingDir(FileSpec &working_dir) { StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse("qGetWorkingDir", response, false) == PacketResult::Success) { if (response.IsUnsupportedResponse()) return false; if (response.IsErrorResponse()) return false; std::string cwd; response.GetHexByteString(cwd); working_dir.SetFile(cwd, false, GetHostArchitecture().GetTriple()); return !cwd.empty(); } return false; } int GDBRemoteCommunicationClient::SetWorkingDir(const FileSpec &working_dir) { if (working_dir) { std::string path{working_dir.GetPath(false)}; StreamString packet; packet.PutCString("QSetWorkingDir:"); packet.PutCStringAsRawHex8(path.c_str()); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == PacketResult::Success) { if (response.IsOKResponse()) return 0; uint8_t error = response.GetError(); if (error) return error; } } return -1; } int GDBRemoteCommunicationClient::SetDisableASLR(bool enable) { char packet[32]; const int packet_len = ::snprintf(packet, sizeof(packet), "QSetDisableASLR:%i", enable ? 1 : 0); assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success) { if (response.IsOKResponse()) return 0; uint8_t error = response.GetError(); if (error) return error; } return -1; } int GDBRemoteCommunicationClient::SetDetachOnError(bool enable) { char packet[32]; const int packet_len = ::snprintf(packet, sizeof(packet), "QSetDetachOnError:%i", enable ? 1 : 0); assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success) { if (response.IsOKResponse()) return 0; uint8_t error = response.GetError(); if (error) return error; } return -1; } bool GDBRemoteCommunicationClient::DecodeProcessInfoResponse( StringExtractorGDBRemote &response, ProcessInstanceInfo &process_info) { if (response.IsNormalResponse()) { llvm::StringRef name; llvm::StringRef value; StringExtractor extractor; uint32_t cpu = LLDB_INVALID_CPUTYPE; uint32_t sub = 0; std::string vendor; std::string os_type; while (response.GetNameColonValue(name, value)) { if (name.equals("pid")) { lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; value.getAsInteger(0, pid); process_info.SetProcessID(pid); } else if (name.equals("ppid")) { lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; value.getAsInteger(0, pid); process_info.SetParentProcessID(pid); } else if (name.equals("uid")) { uint32_t uid = UINT32_MAX; value.getAsInteger(0, uid); process_info.SetUserID(uid); } else if (name.equals("euid")) { uint32_t uid = UINT32_MAX; value.getAsInteger(0, uid); process_info.SetEffectiveGroupID(uid); } else if (name.equals("gid")) { uint32_t gid = UINT32_MAX; value.getAsInteger(0, gid); process_info.SetGroupID(gid); } else if (name.equals("egid")) { uint32_t gid = UINT32_MAX; value.getAsInteger(0, gid); process_info.SetEffectiveGroupID(gid); } else if (name.equals("triple")) { StringExtractor extractor(value); std::string triple; extractor.GetHexByteString(triple); process_info.GetArchitecture().SetTriple(triple.c_str()); } else if (name.equals("name")) { StringExtractor extractor(value); // The process name from ASCII hex bytes since we can't // control the characters in a process name std::string name; extractor.GetHexByteString(name); process_info.GetExecutableFile().SetFile(name, false); } else if (name.equals("cputype")) { value.getAsInteger(0, cpu); } else if (name.equals("cpusubtype")) { value.getAsInteger(0, sub); } else if (name.equals("vendor")) { vendor = value; } else if (name.equals("ostype")) { os_type = value; } } if (cpu != LLDB_INVALID_CPUTYPE && !vendor.empty() && !os_type.empty()) { if (vendor == "apple") { process_info.GetArchitecture().SetArchitecture(eArchTypeMachO, cpu, sub); process_info.GetArchitecture().GetTriple().setVendorName( llvm::StringRef(vendor)); process_info.GetArchitecture().GetTriple().setOSName( llvm::StringRef(os_type)); } } if (process_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) return true; } return false; } bool GDBRemoteCommunicationClient::GetProcessInfo( lldb::pid_t pid, ProcessInstanceInfo &process_info) { process_info.Clear(); if (m_supports_qProcessInfoPID) { char packet[32]; const int packet_len = ::snprintf(packet, sizeof(packet), "qProcessInfoPID:%" PRIu64, pid); assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success) { return DecodeProcessInfoResponse(response, process_info); } else { m_supports_qProcessInfoPID = false; return false; } } return false; } bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); if (allow_lazy) { if (m_qProcessInfo_is_valid == eLazyBoolYes) return true; if (m_qProcessInfo_is_valid == eLazyBoolNo) return false; } GetHostInfo(); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse("qProcessInfo", response, false) == PacketResult::Success) { if (response.IsNormalResponse()) { llvm::StringRef name; llvm::StringRef value; uint32_t cpu = LLDB_INVALID_CPUTYPE; uint32_t sub = 0; std::string arch_name; std::string os_name; std::string vendor_name; std::string triple; std::string elf_abi; uint32_t pointer_byte_size = 0; StringExtractor extractor; ByteOrder byte_order = eByteOrderInvalid; uint32_t num_keys_decoded = 0; lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; while (response.GetNameColonValue(name, value)) { if (name.equals("cputype")) { if (!value.getAsInteger(16, cpu)) ++num_keys_decoded; } else if (name.equals("cpusubtype")) { if (!value.getAsInteger(16, sub)) ++num_keys_decoded; } else if (name.equals("triple")) { StringExtractor extractor(value); extractor.GetHexByteString(triple); ++num_keys_decoded; } else if (name.equals("ostype")) { os_name = value; ++num_keys_decoded; } else if (name.equals("vendor")) { vendor_name = value; ++num_keys_decoded; } else if (name.equals("endian")) { byte_order = llvm::StringSwitch(value) .Case("little", eByteOrderLittle) .Case("big", eByteOrderBig) .Case("pdp", eByteOrderPDP) .Default(eByteOrderInvalid); if (byte_order != eByteOrderInvalid) ++num_keys_decoded; } else if (name.equals("ptrsize")) { if (!value.getAsInteger(16, pointer_byte_size)) ++num_keys_decoded; } else if (name.equals("pid")) { if (!value.getAsInteger(16, pid)) ++num_keys_decoded; } else if (name.equals("elf_abi")) { elf_abi = value; ++num_keys_decoded; } } if (num_keys_decoded > 0) m_qProcessInfo_is_valid = eLazyBoolYes; if (pid != LLDB_INVALID_PROCESS_ID) { m_curr_pid_is_valid = eLazyBoolYes; m_curr_pid = pid; } // Set the ArchSpec from the triple if we have it. if (!triple.empty()) { m_process_arch.SetTriple(triple.c_str()); m_process_arch.SetFlags(elf_abi); if (pointer_byte_size) { assert(pointer_byte_size == m_process_arch.GetAddressByteSize()); } } else if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() && !vendor_name.empty()) { llvm::Triple triple(llvm::Twine("-") + vendor_name + "-" + os_name); assert(triple.getObjectFormat() != llvm::Triple::UnknownObjectFormat); assert(triple.getObjectFormat() != llvm::Triple::Wasm); switch (triple.getObjectFormat()) { case llvm::Triple::MachO: m_process_arch.SetArchitecture(eArchTypeMachO, cpu, sub); break; case llvm::Triple::ELF: m_process_arch.SetArchitecture(eArchTypeELF, cpu, sub); break; case llvm::Triple::COFF: m_process_arch.SetArchitecture(eArchTypeCOFF, cpu, sub); break; case llvm::Triple::Wasm: if (log) log->Printf("error: not supported target architecture"); return false; case llvm::Triple::UnknownObjectFormat: if (log) log->Printf("error: failed to determine target architecture"); return false; } if (pointer_byte_size) { assert(pointer_byte_size == m_process_arch.GetAddressByteSize()); } if (byte_order != eByteOrderInvalid) { assert(byte_order == m_process_arch.GetByteOrder()); } m_process_arch.GetTriple().setVendorName(llvm::StringRef(vendor_name)); m_process_arch.GetTriple().setOSName(llvm::StringRef(os_name)); m_host_arch.GetTriple().setVendorName(llvm::StringRef(vendor_name)); m_host_arch.GetTriple().setOSName(llvm::StringRef(os_name)); } return true; } } else { m_qProcessInfo_is_valid = eLazyBoolNo; } return false; } uint32_t GDBRemoteCommunicationClient::FindProcesses( const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) { process_infos.Clear(); if (m_supports_qfProcessInfo) { StreamString packet; packet.PutCString("qfProcessInfo"); if (!match_info.MatchAllProcesses()) { packet.PutChar(':'); const char *name = match_info.GetProcessInfo().GetName(); bool has_name_match = false; if (name && name[0]) { has_name_match = true; NameMatch name_match_type = match_info.GetNameMatchType(); switch (name_match_type) { case NameMatch::Ignore: has_name_match = false; break; case NameMatch::Equals: packet.PutCString("name_match:equals;"); break; case NameMatch::Contains: packet.PutCString("name_match:contains;"); break; case NameMatch::StartsWith: packet.PutCString("name_match:starts_with;"); break; case NameMatch::EndsWith: packet.PutCString("name_match:ends_with;"); break; case NameMatch::RegularExpression: packet.PutCString("name_match:regex;"); break; } if (has_name_match) { packet.PutCString("name:"); packet.PutBytesAsRawHex8(name, ::strlen(name)); packet.PutChar(';'); } } if (match_info.GetProcessInfo().ProcessIDIsValid()) packet.Printf("pid:%" PRIu64 ";", match_info.GetProcessInfo().GetProcessID()); if (match_info.GetProcessInfo().ParentProcessIDIsValid()) packet.Printf("parent_pid:%" PRIu64 ";", match_info.GetProcessInfo().GetParentProcessID()); if (match_info.GetProcessInfo().UserIDIsValid()) packet.Printf("uid:%u;", match_info.GetProcessInfo().GetUserID()); if (match_info.GetProcessInfo().GroupIDIsValid()) packet.Printf("gid:%u;", match_info.GetProcessInfo().GetGroupID()); if (match_info.GetProcessInfo().EffectiveUserIDIsValid()) packet.Printf("euid:%u;", match_info.GetProcessInfo().GetEffectiveUserID()); if (match_info.GetProcessInfo().EffectiveGroupIDIsValid()) packet.Printf("egid:%u;", match_info.GetProcessInfo().GetEffectiveGroupID()); if (match_info.GetProcessInfo().EffectiveGroupIDIsValid()) packet.Printf("all_users:%u;", match_info.GetMatchAllUsers() ? 1 : 0); if (match_info.GetProcessInfo().GetArchitecture().IsValid()) { const ArchSpec &match_arch = match_info.GetProcessInfo().GetArchitecture(); const llvm::Triple &triple = match_arch.GetTriple(); packet.PutCString("triple:"); packet.PutCString(triple.getTriple()); packet.PutChar(';'); } } StringExtractorGDBRemote response; // Increase timeout as the first qfProcessInfo packet takes a long time // on Android. The value of 1min was arrived at empirically. ScopedTimeout timeout(*this, minutes(1)); if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == PacketResult::Success) { do { ProcessInstanceInfo process_info; if (!DecodeProcessInfoResponse(response, process_info)) break; process_infos.Append(process_info); response.GetStringRef().clear(); response.SetFilePos(0); } while (SendPacketAndWaitForResponse("qsProcessInfo", response, false) == PacketResult::Success); } else { m_supports_qfProcessInfo = false; return 0; } } return process_infos.GetSize(); } bool GDBRemoteCommunicationClient::GetUserName(uint32_t uid, std::string &name) { if (m_supports_qUserName) { char packet[32]; const int packet_len = ::snprintf(packet, sizeof(packet), "qUserName:%i", uid); assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success) { if (response.IsNormalResponse()) { // Make sure we parsed the right number of characters. The response is // the hex encoded user name and should make up the entire packet. // If there are any non-hex ASCII bytes, the length won't match below.. if (response.GetHexByteString(name) * 2 == response.GetStringRef().size()) return true; } } else { m_supports_qUserName = false; return false; } } return false; } bool GDBRemoteCommunicationClient::GetGroupName(uint32_t gid, std::string &name) { if (m_supports_qGroupName) { char packet[32]; const int packet_len = ::snprintf(packet, sizeof(packet), "qGroupName:%i", gid); assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success) { if (response.IsNormalResponse()) { // Make sure we parsed the right number of characters. The response is // the hex encoded group name and should make up the entire packet. // If there are any non-hex ASCII bytes, the length won't match below.. if (response.GetHexByteString(name) * 2 == response.GetStringRef().size()) return true; } } else { m_supports_qGroupName = false; return false; } } return false; } bool GDBRemoteCommunicationClient::SetNonStopMode(const bool enable) { // Form non-stop packet request char packet[32]; const int packet_len = ::snprintf(packet, sizeof(packet), "QNonStop:%1d", (int)enable); assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; // Send to target if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success) if (response.IsOKResponse()) return true; // Failed or not supported return false; } static void MakeSpeedTestPacket(StreamString &packet, uint32_t send_size, uint32_t recv_size) { packet.Clear(); packet.Printf("qSpeedTest:response_size:%i;data:", recv_size); uint32_t bytes_left = send_size; while (bytes_left > 0) { if (bytes_left >= 26) { packet.PutCString("abcdefghijklmnopqrstuvwxyz"); bytes_left -= 26; } else { packet.Printf("%*.*s;", bytes_left, bytes_left, "abcdefghijklmnopqrstuvwxyz"); bytes_left = 0; } } } duration calculate_standard_deviation(const std::vector> &v) { using Dur = duration; Dur sum = std::accumulate(std::begin(v), std::end(v), Dur()); Dur mean = sum / v.size(); float accum = 0; for (auto d : v) { float delta = (d - mean).count(); accum += delta * delta; }; return Dur(sqrtf(accum / (v.size() - 1))); } void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets, uint32_t max_send, uint32_t max_recv, uint64_t recv_amount, bool json, Stream &strm) { uint32_t i; if (SendSpeedTestPacket(0, 0)) { StreamString packet; if (json) strm.Printf("{ \"packet_speeds\" : {\n \"num_packets\" : %u,\n " "\"results\" : [", num_packets); else strm.Printf("Testing sending %u packets of various sizes:\n", num_packets); strm.Flush(); uint32_t result_idx = 0; uint32_t send_size; std::vector> packet_times; for (send_size = 0; send_size <= max_send; send_size ? send_size *= 2 : send_size = 4) { for (uint32_t recv_size = 0; recv_size <= max_recv; recv_size ? recv_size *= 2 : recv_size = 4) { MakeSpeedTestPacket(packet, send_size, recv_size); packet_times.clear(); // Test how long it takes to send 'num_packets' packets const auto start_time = steady_clock::now(); for (i = 0; i < num_packets; ++i) { const auto packet_start_time = steady_clock::now(); StringExtractorGDBRemote response; SendPacketAndWaitForResponse(packet.GetString(), response, false); const auto packet_end_time = steady_clock::now(); packet_times.push_back(packet_end_time - packet_start_time); } const auto end_time = steady_clock::now(); const auto total_time = end_time - start_time; float packets_per_second = ((float)num_packets) / duration(total_time).count(); auto average_per_packet = total_time / num_packets; const duration standard_deviation = calculate_standard_deviation(packet_times); if (json) { strm.Format("{0}\n {{\"send_size\" : {1,6}, \"recv_size\" : " "{2,6}, \"total_time_nsec\" : {3,12:ns-}, " "\"standard_deviation_nsec\" : {4,9:ns-f0}}", result_idx > 0 ? "," : "", send_size, recv_size, total_time, standard_deviation); ++result_idx; } else { strm.Format("qSpeedTest(send={0,7}, recv={1,7}) in {2:s+f9} for " "{3,9:f2} packets/s ({4,10:ms+f6} per packet) with " "standard deviation of {5,10:ms+f6}\n", send_size, recv_size, duration(total_time), packets_per_second, duration(average_per_packet), standard_deviation); } strm.Flush(); } } const float k_recv_amount_mb = (float)recv_amount / (1024.0f * 1024.0f); if (json) strm.Printf("\n ]\n },\n \"download_speed\" : {\n \"byte_size\" " ": %" PRIu64 ",\n \"results\" : [", recv_amount); else strm.Printf("Testing receiving %2.1fMB of data using varying receive " "packet sizes:\n", k_recv_amount_mb); strm.Flush(); send_size = 0; result_idx = 0; for (uint32_t recv_size = 32; recv_size <= max_recv; recv_size *= 2) { MakeSpeedTestPacket(packet, send_size, recv_size); // If we have a receive size, test how long it takes to receive 4MB of // data if (recv_size > 0) { const auto start_time = steady_clock::now(); uint32_t bytes_read = 0; uint32_t packet_count = 0; while (bytes_read < recv_amount) { StringExtractorGDBRemote response; SendPacketAndWaitForResponse(packet.GetString(), response, false); bytes_read += recv_size; ++packet_count; } const auto end_time = steady_clock::now(); const auto total_time = end_time - start_time; float mb_second = ((float)recv_amount) / duration(total_time).count() / (1024.0 * 1024.0); float packets_per_second = ((float)packet_count) / duration(total_time).count(); const auto average_per_packet = total_time / packet_count; if (json) { strm.Format("{0}\n {{\"send_size\" : {1,6}, \"recv_size\" : " "{2,6}, \"total_time_nsec\" : {3,12:ns-}}", result_idx > 0 ? "," : "", send_size, recv_size, total_time); ++result_idx; } else { strm.Format("qSpeedTest(send={0,7}, recv={1,7}) {2,6} packets needed " "to receive {3:f1}MB in {4:s+f9} for {5} MB/sec for " "{6,9:f2} packets/sec ({7,10:ms+f6} per packet)\n", send_size, recv_size, packet_count, k_recv_amount_mb, duration(total_time), mb_second, packets_per_second, duration(average_per_packet)); } strm.Flush(); } } if (json) strm.Printf("\n ]\n }\n}\n"); else strm.EOL(); } } bool GDBRemoteCommunicationClient::SendSpeedTestPacket(uint32_t send_size, uint32_t recv_size) { StreamString packet; packet.Printf("qSpeedTest:response_size:%i;data:", recv_size); uint32_t bytes_left = send_size; while (bytes_left > 0) { if (bytes_left >= 26) { packet.PutCString("abcdefghijklmnopqrstuvwxyz"); bytes_left -= 26; } else { packet.Printf("%*.*s;", bytes_left, bytes_left, "abcdefghijklmnopqrstuvwxyz"); bytes_left = 0; } } StringExtractorGDBRemote response; return SendPacketAndWaitForResponse(packet.GetString(), response, false) == PacketResult::Success; } bool GDBRemoteCommunicationClient::LaunchGDBServer( const char *remote_accept_hostname, lldb::pid_t &pid, uint16_t &port, std::string &socket_name) { pid = LLDB_INVALID_PROCESS_ID; port = 0; socket_name.clear(); StringExtractorGDBRemote response; StreamString stream; stream.PutCString("qLaunchGDBServer;"); std::string hostname; if (remote_accept_hostname && remote_accept_hostname[0]) hostname = remote_accept_hostname; else { if (HostInfo::GetHostname(hostname)) { // Make the GDB server we launch only accept connections from this host stream.Printf("host:%s;", hostname.c_str()); } else { // Make the GDB server we launch accept connections from any host since we // can't figure out the hostname stream.Printf("host:*;"); } } // give the process a few seconds to startup ScopedTimeout timeout(*this, seconds(10)); if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { llvm::StringRef name; llvm::StringRef value; while (response.GetNameColonValue(name, value)) { if (name.equals("port")) value.getAsInteger(0, port); else if (name.equals("pid")) value.getAsInteger(0, pid); else if (name.compare("socket_name") == 0) { StringExtractor extractor(value); extractor.GetHexByteString(socket_name); } } return true; } return false; } size_t GDBRemoteCommunicationClient::QueryGDBServer( std::vector> &connection_urls) { connection_urls.clear(); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse("qQueryGDBServer", response, false) != PacketResult::Success) return 0; StructuredData::ObjectSP data = StructuredData::ParseJSON(response.GetStringRef()); if (!data) return 0; StructuredData::Array *array = data->GetAsArray(); if (!array) return 0; for (size_t i = 0, count = array->GetSize(); i < count; ++i) { StructuredData::Dictionary *element = nullptr; if (!array->GetItemAtIndexAsDictionary(i, element)) continue; uint16_t port = 0; if (StructuredData::ObjectSP port_osp = element->GetValueForKey(llvm::StringRef("port"))) port = port_osp->GetIntegerValue(0); std::string socket_name; if (StructuredData::ObjectSP socket_name_osp = element->GetValueForKey(llvm::StringRef("socket_name"))) socket_name = socket_name_osp->GetStringValue(); if (port != 0 || !socket_name.empty()) connection_urls.emplace_back(port, socket_name); } return connection_urls.size(); } bool GDBRemoteCommunicationClient::KillSpawnedProcess(lldb::pid_t pid) { StreamString stream; stream.Printf("qKillSpawnedProcess:%" PRId64, pid); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { if (response.IsOKResponse()) return true; } return false; } bool GDBRemoteCommunicationClient::SetCurrentThread(uint64_t tid) { if (m_curr_tid == tid) return true; char packet[32]; int packet_len; if (tid == UINT64_MAX) packet_len = ::snprintf(packet, sizeof(packet), "Hg-1"); else packet_len = ::snprintf(packet, sizeof(packet), "Hg%" PRIx64, tid); assert(packet_len + 1 < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success) { if (response.IsOKResponse()) { m_curr_tid = tid; return true; } /* * Connected bare-iron target (like YAMON gdb-stub) may not have support for * Hg packet. * The reply from '?' packet could be as simple as 'S05'. There is no packet * which can * give us pid and/or tid. Assume pid=tid=1 in such cases. */ if (response.IsUnsupportedResponse() && IsConnected()) { m_curr_tid = 1; return true; } } return false; } bool GDBRemoteCommunicationClient::SetCurrentThreadForRun(uint64_t tid) { if (m_curr_tid_run == tid) return true; char packet[32]; int packet_len; if (tid == UINT64_MAX) packet_len = ::snprintf(packet, sizeof(packet), "Hc-1"); else packet_len = ::snprintf(packet, sizeof(packet), "Hc%" PRIx64, tid); assert(packet_len + 1 < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success) { if (response.IsOKResponse()) { m_curr_tid_run = tid; return true; } /* * Connected bare-iron target (like YAMON gdb-stub) may not have support for * Hc packet. * The reply from '?' packet could be as simple as 'S05'. There is no packet * which can * give us pid and/or tid. Assume pid=tid=1 in such cases. */ if (response.IsUnsupportedResponse() && IsConnected()) { m_curr_tid_run = 1; return true; } } return false; } bool GDBRemoteCommunicationClient::GetStopReply( StringExtractorGDBRemote &response) { if (SendPacketAndWaitForResponse("?", response, false) == PacketResult::Success) return response.IsNormalResponse(); return false; } bool GDBRemoteCommunicationClient::GetThreadStopInfo( lldb::tid_t tid, StringExtractorGDBRemote &response) { if (m_supports_qThreadStopInfo) { char packet[256]; int packet_len = ::snprintf(packet, sizeof(packet), "qThreadStopInfo%" PRIx64, tid); assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success) { if (response.IsUnsupportedResponse()) m_supports_qThreadStopInfo = false; else if (response.IsNormalResponse()) return true; else return false; } else { m_supports_qThreadStopInfo = false; } } return false; } uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket( GDBStoppointType type, bool insert, addr_t addr, uint32_t length) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); if (log) log->Printf("GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64, __FUNCTION__, insert ? "add" : "remove", addr); // Check if the stub is known not to support this breakpoint type if (!SupportsGDBStoppointPacket(type)) return UINT8_MAX; // Construct the breakpoint packet char packet[64]; const int packet_len = ::snprintf(packet, sizeof(packet), "%c%i,%" PRIx64 ",%x", insert ? 'Z' : 'z', type, addr, length); // Check we haven't overwritten the end of the packet buffer assert(packet_len + 1 < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; // Make sure the response is either "OK", "EXX" where XX are two hex digits, // or "" (unsupported) response.SetResponseValidatorToOKErrorNotSupported(); // Try to send the breakpoint packet, and check that it was correctly sent if (SendPacketAndWaitForResponse(packet, response, true) == PacketResult::Success) { // Receive and OK packet when the breakpoint successfully placed if (response.IsOKResponse()) return 0; // Status while setting breakpoint, send back specific error if (response.IsErrorResponse()) return response.GetError(); // Empty packet informs us that breakpoint is not supported if (response.IsUnsupportedResponse()) { // Disable this breakpoint type since it is unsupported switch (type) { case eBreakpointSoftware: m_supports_z0 = false; break; case eBreakpointHardware: m_supports_z1 = false; break; case eWatchpointWrite: m_supports_z2 = false; break; case eWatchpointRead: m_supports_z3 = false; break; case eWatchpointReadWrite: m_supports_z4 = false; break; case eStoppointInvalid: return UINT8_MAX; } } } // Signal generic failure return UINT8_MAX; } size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs( std::vector &thread_ids, bool &sequence_mutex_unavailable) { thread_ids.clear(); Lock lock(*this, false); if (lock) { sequence_mutex_unavailable = false; StringExtractorGDBRemote response; PacketResult packet_result; for (packet_result = SendPacketAndWaitForResponseNoLock("qfThreadInfo", response); packet_result == PacketResult::Success && response.IsNormalResponse(); packet_result = SendPacketAndWaitForResponseNoLock("qsThreadInfo", response)) { char ch = response.GetChar(); if (ch == 'l') break; if (ch == 'm') { do { tid_t tid = response.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID); if (tid != LLDB_INVALID_THREAD_ID) { thread_ids.push_back(tid); } ch = response.GetChar(); // Skip the command separator } while (ch == ','); // Make sure we got a comma separator } } /* * Connected bare-iron target (like YAMON gdb-stub) may not have support for * qProcessInfo, qC and qfThreadInfo packets. The reply from '?' packet * could * be as simple as 'S05'. There is no packet which can give us pid and/or * tid. * Assume pid=tid=1 in such cases. */ if (response.IsUnsupportedResponse() && thread_ids.size() == 0 && IsConnected()) { thread_ids.push_back(1); } } else { #if !defined(LLDB_CONFIGURATION_DEBUG) Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); if (log) log->Printf("error: failed to get packet sequence mutex, not sending " "packet 'qfThreadInfo'"); #endif sequence_mutex_unavailable = true; } return thread_ids.size(); } lldb::addr_t GDBRemoteCommunicationClient::GetShlibInfoAddr() { StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse("qShlibInfoAddr", response, false) != PacketResult::Success || !response.IsNormalResponse()) return LLDB_INVALID_ADDRESS; return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); } lldb_private::Status GDBRemoteCommunicationClient::RunShellCommand( const char *command, // Shouldn't be NULL const FileSpec & working_dir, // Pass empty FileSpec to use the current working directory int *status_ptr, // Pass NULL if you don't want the process exit status int *signo_ptr, // Pass NULL if you don't want the signal that caused the // process to exit std::string *command_output, // Pass NULL if you don't want the command output uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish { lldb_private::StreamString stream; stream.PutCString("qPlatform_shell:"); stream.PutBytesAsRawHex8(command, strlen(command)); stream.PutChar(','); stream.PutHex32(timeout_sec); if (working_dir) { std::string path{working_dir.GetPath(false)}; stream.PutChar(','); stream.PutCStringAsRawHex8(path.c_str()); } StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { if (response.GetChar() != 'F') return Status("malformed reply"); if (response.GetChar() != ',') return Status("malformed reply"); uint32_t exitcode = response.GetHexMaxU32(false, UINT32_MAX); if (exitcode == UINT32_MAX) return Status("unable to run remote process"); else if (status_ptr) *status_ptr = exitcode; if (response.GetChar() != ',') return Status("malformed reply"); uint32_t signo = response.GetHexMaxU32(false, UINT32_MAX); if (signo_ptr) *signo_ptr = signo; if (response.GetChar() != ',') return Status("malformed reply"); std::string output; response.GetEscapedBinaryData(output); if (command_output) command_output->assign(output); return Status(); } return Status("unable to send packet"); } Status GDBRemoteCommunicationClient::MakeDirectory(const FileSpec &file_spec, uint32_t file_permissions) { std::string path{file_spec.GetPath(false)}; lldb_private::StreamString stream; stream.PutCString("qPlatform_mkdir:"); stream.PutHex32(file_permissions); stream.PutChar(','); stream.PutCStringAsRawHex8(path.c_str()); llvm::StringRef packet = stream.GetString(); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet, response, false) != PacketResult::Success) return Status("failed to send '%s' packet", packet.str().c_str()); if (response.GetChar() != 'F') return Status("invalid response to '%s' packet", packet.str().c_str()); return Status(response.GetU32(UINT32_MAX), eErrorTypePOSIX); } Status GDBRemoteCommunicationClient::SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions) { std::string path{file_spec.GetPath(false)}; lldb_private::StreamString stream; stream.PutCString("qPlatform_chmod:"); stream.PutHex32(file_permissions); stream.PutChar(','); stream.PutCStringAsRawHex8(path.c_str()); llvm::StringRef packet = stream.GetString(); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet, response, false) != PacketResult::Success) return Status("failed to send '%s' packet", stream.GetData()); if (response.GetChar() != 'F') return Status("invalid response to '%s' packet", stream.GetData()); return Status(response.GetU32(UINT32_MAX), eErrorTypePOSIX); } static uint64_t ParseHostIOPacketResponse(StringExtractorGDBRemote &response, uint64_t fail_result, Status &error) { response.SetFilePos(0); if (response.GetChar() != 'F') return fail_result; int32_t result = response.GetS32(-2); if (result == -2) return fail_result; if (response.GetChar() == ',') { int result_errno = response.GetS32(-2); if (result_errno != -2) error.SetError(result_errno, eErrorTypePOSIX); else error.SetError(-1, eErrorTypeGeneric); } else error.Clear(); return result; } lldb::user_id_t GDBRemoteCommunicationClient::OpenFile(const lldb_private::FileSpec &file_spec, uint32_t flags, mode_t mode, Status &error) { std::string path(file_spec.GetPath(false)); lldb_private::StreamString stream; stream.PutCString("vFile:open:"); if (path.empty()) return UINT64_MAX; stream.PutCStringAsRawHex8(path.c_str()); stream.PutChar(','); stream.PutHex32(flags); stream.PutChar(','); stream.PutHex32(mode); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { return ParseHostIOPacketResponse(response, UINT64_MAX, error); } return UINT64_MAX; } bool GDBRemoteCommunicationClient::CloseFile(lldb::user_id_t fd, Status &error) { lldb_private::StreamString stream; stream.Printf("vFile:close:%i", (int)fd); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { return ParseHostIOPacketResponse(response, -1, error) == 0; } return false; } // Extension of host I/O packets to get the file size. lldb::user_id_t GDBRemoteCommunicationClient::GetFileSize( const lldb_private::FileSpec &file_spec) { std::string path(file_spec.GetPath(false)); lldb_private::StreamString stream; stream.PutCString("vFile:size:"); stream.PutCStringAsRawHex8(path.c_str()); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { if (response.GetChar() != 'F') return UINT64_MAX; uint32_t retcode = response.GetHexMaxU64(false, UINT64_MAX); return retcode; } return UINT64_MAX; } Status GDBRemoteCommunicationClient::GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions) { std::string path{file_spec.GetPath(false)}; Status error; lldb_private::StreamString stream; stream.PutCString("vFile:mode:"); stream.PutCStringAsRawHex8(path.c_str()); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { if (response.GetChar() != 'F') { error.SetErrorStringWithFormat("invalid response to '%s' packet", stream.GetData()); } else { const uint32_t mode = response.GetS32(-1); if (static_cast(mode) == -1) { if (response.GetChar() == ',') { int response_errno = response.GetS32(-1); if (response_errno > 0) error.SetError(response_errno, lldb::eErrorTypePOSIX); else error.SetErrorToGenericError(); } else error.SetErrorToGenericError(); } else { file_permissions = mode & (S_IRWXU | S_IRWXG | S_IRWXO); } } } else { error.SetErrorStringWithFormat("failed to send '%s' packet", stream.GetData()); } return error; } uint64_t GDBRemoteCommunicationClient::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst, uint64_t dst_len, Status &error) { lldb_private::StreamString stream; stream.Printf("vFile:pread:%i,%" PRId64 ",%" PRId64, (int)fd, dst_len, offset); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { if (response.GetChar() != 'F') return 0; uint32_t retcode = response.GetHexMaxU32(false, UINT32_MAX); if (retcode == UINT32_MAX) return retcode; const char next = (response.Peek() ? *response.Peek() : 0); if (next == ',') return 0; if (next == ';') { response.GetChar(); // skip the semicolon std::string buffer; if (response.GetEscapedBinaryData(buffer)) { const uint64_t data_to_write = std::min(dst_len, buffer.size()); if (data_to_write > 0) memcpy(dst, &buffer[0], data_to_write); return data_to_write; } } } return 0; } uint64_t GDBRemoteCommunicationClient::WriteFile(lldb::user_id_t fd, uint64_t offset, const void *src, uint64_t src_len, Status &error) { lldb_private::StreamGDBRemote stream; stream.Printf("vFile:pwrite:%i,%" PRId64 ",", (int)fd, offset); stream.PutEscapedBytes(src, src_len); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { if (response.GetChar() != 'F') { error.SetErrorStringWithFormat("write file failed"); return 0; } uint64_t bytes_written = response.GetU64(UINT64_MAX); if (bytes_written == UINT64_MAX) { error.SetErrorToGenericError(); if (response.GetChar() == ',') { int response_errno = response.GetS32(-1); if (response_errno > 0) error.SetError(response_errno, lldb::eErrorTypePOSIX); } return 0; } return bytes_written; } else { error.SetErrorString("failed to send vFile:pwrite packet"); } return 0; } Status GDBRemoteCommunicationClient::CreateSymlink(const FileSpec &src, const FileSpec &dst) { std::string src_path{src.GetPath(false)}, dst_path{dst.GetPath(false)}; Status error; lldb_private::StreamGDBRemote stream; stream.PutCString("vFile:symlink:"); // the unix symlink() command reverses its parameters where the dst if first, // so we follow suit here stream.PutCStringAsRawHex8(dst_path.c_str()); stream.PutChar(','); stream.PutCStringAsRawHex8(src_path.c_str()); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { if (response.GetChar() == 'F') { uint32_t result = response.GetU32(UINT32_MAX); if (result != 0) { error.SetErrorToGenericError(); if (response.GetChar() == ',') { int response_errno = response.GetS32(-1); if (response_errno > 0) error.SetError(response_errno, lldb::eErrorTypePOSIX); } } } else { // Should have returned with 'F[,]' error.SetErrorStringWithFormat("symlink failed"); } } else { error.SetErrorString("failed to send vFile:symlink packet"); } return error; } Status GDBRemoteCommunicationClient::Unlink(const FileSpec &file_spec) { std::string path{file_spec.GetPath(false)}; Status error; lldb_private::StreamGDBRemote stream; stream.PutCString("vFile:unlink:"); // the unix symlink() command reverses its parameters where the dst if first, // so we follow suit here stream.PutCStringAsRawHex8(path.c_str()); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { if (response.GetChar() == 'F') { uint32_t result = response.GetU32(UINT32_MAX); if (result != 0) { error.SetErrorToGenericError(); if (response.GetChar() == ',') { int response_errno = response.GetS32(-1); if (response_errno > 0) error.SetError(response_errno, lldb::eErrorTypePOSIX); } } } else { // Should have returned with 'F[,]' error.SetErrorStringWithFormat("unlink failed"); } } else { error.SetErrorString("failed to send vFile:unlink packet"); } return error; } // Extension of host I/O packets to get whether a file exists. bool GDBRemoteCommunicationClient::GetFileExists( const lldb_private::FileSpec &file_spec) { std::string path(file_spec.GetPath(false)); lldb_private::StreamString stream; stream.PutCString("vFile:exists:"); stream.PutCStringAsRawHex8(path.c_str()); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { if (response.GetChar() != 'F') return false; if (response.GetChar() != ',') return false; bool retcode = (response.GetChar() != '0'); return retcode; } return false; } bool GDBRemoteCommunicationClient::CalculateMD5( const lldb_private::FileSpec &file_spec, uint64_t &high, uint64_t &low) { std::string path(file_spec.GetPath(false)); lldb_private::StreamString stream; stream.PutCString("vFile:MD5:"); stream.PutCStringAsRawHex8(path.c_str()); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == PacketResult::Success) { if (response.GetChar() != 'F') return false; if (response.GetChar() != ',') return false; if (response.Peek() && *response.Peek() == 'x') return false; low = response.GetHexMaxU64(false, UINT64_MAX); high = response.GetHexMaxU64(false, UINT64_MAX); return true; } return false; } bool GDBRemoteCommunicationClient::AvoidGPackets(ProcessGDBRemote *process) { // Some targets have issues with g/G packets and we need to avoid using them if (m_avoid_g_packets == eLazyBoolCalculate) { if (process) { m_avoid_g_packets = eLazyBoolNo; const ArchSpec &arch = process->GetTarget().GetArchitecture(); if (arch.IsValid() && arch.GetTriple().getVendor() == llvm::Triple::Apple && arch.GetTriple().getOS() == llvm::Triple::IOS && arch.GetTriple().getArch() == llvm::Triple::aarch64) { m_avoid_g_packets = eLazyBoolYes; uint32_t gdb_server_version = GetGDBServerProgramVersion(); if (gdb_server_version != 0) { const char *gdb_server_name = GetGDBServerProgramName(); if (gdb_server_name && strcmp(gdb_server_name, "debugserver") == 0) { if (gdb_server_version >= 310) m_avoid_g_packets = eLazyBoolNo; } } } } } return m_avoid_g_packets == eLazyBoolYes; } DataBufferSP GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid, uint32_t reg) { StreamString payload; payload.Printf("p%x", reg); StringExtractorGDBRemote response; if (SendThreadSpecificPacketAndWaitForResponse( tid, std::move(payload), response, false) != PacketResult::Success || !response.IsNormalResponse()) return nullptr; DataBufferSP buffer_sp( new DataBufferHeap(response.GetStringRef().size() / 2, 0)); response.GetHexBytes(buffer_sp->GetData(), '\xcc'); return buffer_sp; } DataBufferSP GDBRemoteCommunicationClient::ReadAllRegisters(lldb::tid_t tid) { StreamString payload; payload.PutChar('g'); StringExtractorGDBRemote response; if (SendThreadSpecificPacketAndWaitForResponse( tid, std::move(payload), response, false) != PacketResult::Success || !response.IsNormalResponse()) return nullptr; DataBufferSP buffer_sp( new DataBufferHeap(response.GetStringRef().size() / 2, 0)); response.GetHexBytes(buffer_sp->GetData(), '\xcc'); return buffer_sp; } bool GDBRemoteCommunicationClient::WriteRegister(lldb::tid_t tid, uint32_t reg_num, llvm::ArrayRef data) { StreamString payload; payload.Printf("P%x=", reg_num); payload.PutBytesAsRawHex8(data.data(), data.size(), endian::InlHostByteOrder(), endian::InlHostByteOrder()); StringExtractorGDBRemote response; return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) == PacketResult::Success && response.IsOKResponse(); } bool GDBRemoteCommunicationClient::WriteAllRegisters( lldb::tid_t tid, llvm::ArrayRef data) { StreamString payload; payload.PutChar('G'); payload.PutBytesAsRawHex8(data.data(), data.size(), endian::InlHostByteOrder(), endian::InlHostByteOrder()); StringExtractorGDBRemote response; return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) == PacketResult::Success && response.IsOKResponse(); } bool GDBRemoteCommunicationClient::SaveRegisterState(lldb::tid_t tid, uint32_t &save_id) { save_id = 0; // Set to invalid save ID if (m_supports_QSaveRegisterState == eLazyBoolNo) return false; m_supports_QSaveRegisterState = eLazyBoolYes; StreamString payload; payload.PutCString("QSaveRegisterState"); StringExtractorGDBRemote response; if (SendThreadSpecificPacketAndWaitForResponse( tid, std::move(payload), response, false) != PacketResult::Success) return false; if (response.IsUnsupportedResponse()) m_supports_QSaveRegisterState = eLazyBoolNo; const uint32_t response_save_id = response.GetU32(0); if (response_save_id == 0) return false; save_id = response_save_id; return true; } bool GDBRemoteCommunicationClient::RestoreRegisterState(lldb::tid_t tid, uint32_t save_id) { // We use the "m_supports_QSaveRegisterState" variable here because the // QSaveRegisterState and QRestoreRegisterState packets must both be supported // in // order to be useful if (m_supports_QSaveRegisterState == eLazyBoolNo) return false; StreamString payload; payload.Printf("QRestoreRegisterState:%u", save_id); StringExtractorGDBRemote response; if (SendThreadSpecificPacketAndWaitForResponse( tid, std::move(payload), response, false) != PacketResult::Success) return false; if (response.IsOKResponse()) return true; if (response.IsUnsupportedResponse()) m_supports_QSaveRegisterState = eLazyBoolNo; return false; } bool GDBRemoteCommunicationClient::SyncThreadState(lldb::tid_t tid) { if (!GetSyncThreadStateSupported()) return false; StreamString packet; StringExtractorGDBRemote response; packet.Printf("QSyncThreadState:%4.4" PRIx64 ";", tid); return SendPacketAndWaitForResponse(packet.GetString(), response, false) == GDBRemoteCommunication::PacketResult::Success && response.IsOKResponse(); } lldb::user_id_t GDBRemoteCommunicationClient::SendStartTracePacket(const TraceOptions &options, Status &error) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); lldb::user_id_t ret_uid = LLDB_INVALID_UID; StreamGDBRemote escaped_packet; escaped_packet.PutCString("jTraceStart:"); StructuredData::Dictionary json_packet; json_packet.AddIntegerItem("type", options.getType()); json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize()); json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize()); if (options.getThreadID() != LLDB_INVALID_THREAD_ID) json_packet.AddIntegerItem("threadid", options.getThreadID()); StructuredData::DictionarySP custom_params = options.getTraceParams(); if (custom_params) json_packet.AddItem("params", custom_params); StreamString json_string; json_packet.Dump(json_string, false); escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize()); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, true) == GDBRemoteCommunication::PacketResult::Success) { if (!response.IsNormalResponse()) { - error.SetError(response.GetError(), eErrorTypeGeneric); - LLDB_LOG(log, "Target does not support Tracing"); + error = response.GetStatus(); + LLDB_LOG(log, "Target does not support Tracing , error {0}", error); } else { ret_uid = response.GetHexMaxU64(false, LLDB_INVALID_UID); } } else { LLDB_LOG(log, "failed to send packet"); error.SetErrorStringWithFormat("failed to send packet: '%s'", escaped_packet.GetData()); } return ret_uid; } Status GDBRemoteCommunicationClient::SendStopTracePacket(lldb::user_id_t uid, lldb::tid_t thread_id) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); StringExtractorGDBRemote response; Status error; StructuredData::Dictionary json_packet; StreamGDBRemote escaped_packet; StreamString json_string; escaped_packet.PutCString("jTraceStop:"); json_packet.AddIntegerItem("traceid", uid); if (thread_id != LLDB_INVALID_THREAD_ID) json_packet.AddIntegerItem("threadid", thread_id); json_packet.Dump(json_string, false); escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize()); if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, true) == GDBRemoteCommunication::PacketResult::Success) { if (!response.IsOKResponse()) { - error.SetError(response.GetError(), eErrorTypeGeneric); + error = response.GetStatus(); LLDB_LOG(log, "stop tracing failed"); } } else { LLDB_LOG(log, "failed to send packet"); error.SetErrorStringWithFormat( "failed to send packet: '%s' with error '%d'", escaped_packet.GetData(), response.GetError()); } return error; } Status GDBRemoteCommunicationClient::SendGetDataPacket( lldb::user_id_t uid, lldb::tid_t thread_id, llvm::MutableArrayRef &buffer, size_t offset) { + StreamGDBRemote escaped_packet; escaped_packet.PutCString("jTraceBufferRead:"); return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset); } Status GDBRemoteCommunicationClient::SendGetMetaDataPacket( lldb::user_id_t uid, lldb::tid_t thread_id, llvm::MutableArrayRef &buffer, size_t offset) { + StreamGDBRemote escaped_packet; escaped_packet.PutCString("jTraceMetaRead:"); return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset); } Status GDBRemoteCommunicationClient::SendGetTraceConfigPacket(lldb::user_id_t uid, TraceOptions &options) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); StringExtractorGDBRemote response; Status error; StreamString json_string; StreamGDBRemote escaped_packet; escaped_packet.PutCString("jTraceConfigRead:"); StructuredData::Dictionary json_packet; json_packet.AddIntegerItem("traceid", uid); if (options.getThreadID() != LLDB_INVALID_THREAD_ID) json_packet.AddIntegerItem("threadid", options.getThreadID()); json_packet.Dump(json_string, false); escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize()); if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, true) == GDBRemoteCommunication::PacketResult::Success) { if (response.IsNormalResponse()) { uint64_t type = std::numeric_limits::max(); uint64_t buffersize = std::numeric_limits::max(); uint64_t metabuffersize = std::numeric_limits::max(); auto json_object = StructuredData::ParseJSON(response.Peek()); if (!json_object || json_object->GetType() != lldb::eStructuredDataTypeDictionary) { error.SetErrorString("Invalid Configuration obtained"); return error; } auto json_dict = json_object->GetAsDictionary(); json_dict->GetValueForKeyAsInteger("metabuffersize", metabuffersize); options.setMetaDataBufferSize(metabuffersize); json_dict->GetValueForKeyAsInteger("buffersize", buffersize); options.setTraceBufferSize(buffersize); json_dict->GetValueForKeyAsInteger("type", type); options.setType(static_cast(type)); StructuredData::ObjectSP custom_params_sp = json_dict->GetValueForKey("params"); if (custom_params_sp) { if (custom_params_sp->GetType() != lldb::eStructuredDataTypeDictionary) { error.SetErrorString("Invalid Configuration obtained"); return error; } else options.setTraceParams( static_pointer_cast( custom_params_sp)); } } else { - error.SetError(response.GetError(), eErrorTypeGeneric); + error = response.GetStatus(); } } else { LLDB_LOG(log, "failed to send packet"); error.SetErrorStringWithFormat("failed to send packet: '%s'", escaped_packet.GetData()); } return error; } Status GDBRemoteCommunicationClient::SendGetTraceDataPacket( StreamGDBRemote &packet, lldb::user_id_t uid, lldb::tid_t thread_id, llvm::MutableArrayRef &buffer, size_t offset) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); Status error; StructuredData::Dictionary json_packet; json_packet.AddIntegerItem("traceid", uid); json_packet.AddIntegerItem("offset", offset); json_packet.AddIntegerItem("buffersize", buffer.size()); if (thread_id != LLDB_INVALID_THREAD_ID) json_packet.AddIntegerItem("threadid", thread_id); StreamString json_string; json_packet.Dump(json_string, false); packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize()); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet.GetString(), response, true) == GDBRemoteCommunication::PacketResult::Success) { if (response.IsNormalResponse()) { size_t filled_size = response.GetHexBytesAvail(buffer); buffer = llvm::MutableArrayRef(buffer.data(), filled_size); } else { - error.SetError(response.GetError(), eErrorTypeGeneric); + error = response.GetStatus(); buffer = buffer.slice(buffer.size()); } } else { LLDB_LOG(log, "failed to send packet"); error.SetErrorStringWithFormat("failed to send packet: '%s'", packet.GetData()); buffer = buffer.slice(buffer.size()); } return error; } bool GDBRemoteCommunicationClient::GetModuleInfo( const FileSpec &module_file_spec, const lldb_private::ArchSpec &arch_spec, ModuleSpec &module_spec) { if (!m_supports_qModuleInfo) return false; std::string module_path = module_file_spec.GetPath(false); if (module_path.empty()) return false; StreamString packet; packet.PutCString("qModuleInfo:"); packet.PutCStringAsRawHex8(module_path.c_str()); packet.PutCString(";"); const auto &triple = arch_spec.GetTriple().getTriple(); packet.PutCStringAsRawHex8(triple.c_str()); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(packet.GetString(), response, false) != PacketResult::Success) return false; if (response.IsErrorResponse()) return false; if (response.IsUnsupportedResponse()) { m_supports_qModuleInfo = false; return false; } llvm::StringRef name; llvm::StringRef value; module_spec.Clear(); module_spec.GetFileSpec() = module_file_spec; while (response.GetNameColonValue(name, value)) { if (name == "uuid" || name == "md5") { StringExtractor extractor(value); std::string uuid; extractor.GetHexByteString(uuid); module_spec.GetUUID().SetFromCString(uuid.c_str(), uuid.size() / 2); } else if (name == "triple") { StringExtractor extractor(value); std::string triple; extractor.GetHexByteString(triple); module_spec.GetArchitecture().SetTriple(triple.c_str()); } else if (name == "file_offset") { uint64_t ival = 0; if (!value.getAsInteger(16, ival)) module_spec.SetObjectOffset(ival); } else if (name == "file_size") { uint64_t ival = 0; if (!value.getAsInteger(16, ival)) module_spec.SetObjectSize(ival); } else if (name == "file_path") { StringExtractor extractor(value); std::string path; extractor.GetHexByteString(path); module_spec.GetFileSpec() = FileSpec(path, false, arch_spec.GetTriple()); } } return true; } static llvm::Optional ParseModuleSpec(StructuredData::Dictionary *dict) { ModuleSpec result; if (!dict) return llvm::None; llvm::StringRef string; uint64_t integer; if (!dict->GetValueForKeyAsString("uuid", string)) return llvm::None; result.GetUUID().SetFromStringRef(string, string.size()); if (!dict->GetValueForKeyAsInteger("file_offset", integer)) return llvm::None; result.SetObjectOffset(integer); if (!dict->GetValueForKeyAsInteger("file_size", integer)) return llvm::None; result.SetObjectSize(integer); if (!dict->GetValueForKeyAsString("triple", string)) return llvm::None; result.GetArchitecture().SetTriple(string); if (!dict->GetValueForKeyAsString("file_path", string)) return llvm::None; result.GetFileSpec() = FileSpec(string, false, result.GetArchitecture().GetTriple()); return result; } llvm::Optional> GDBRemoteCommunicationClient::GetModulesInfo( llvm::ArrayRef module_file_specs, const llvm::Triple &triple) { if (!m_supports_jModulesInfo) return llvm::None; JSONArray::SP module_array_sp = std::make_shared(); for (const FileSpec &module_file_spec : module_file_specs) { JSONObject::SP module_sp = std::make_shared(); module_array_sp->AppendObject(module_sp); module_sp->SetObject( "file", std::make_shared(module_file_spec.GetPath(false))); module_sp->SetObject("triple", std::make_shared(triple.getTriple())); } StreamString unescaped_payload; unescaped_payload.PutCString("jModulesInfo:"); module_array_sp->Write(unescaped_payload); StreamGDBRemote payload; payload.PutEscapedBytes(unescaped_payload.GetString().data(), unescaped_payload.GetSize()); // Increase the timeout for jModulesInfo since this packet can take longer. ScopedTimeout timeout(*this, std::chrono::seconds(10)); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(payload.GetString(), response, false) != PacketResult::Success || response.IsErrorResponse()) return llvm::None; if (response.IsUnsupportedResponse()) { m_supports_jModulesInfo = false; return llvm::None; } StructuredData::ObjectSP response_object_sp = StructuredData::ParseJSON(response.GetStringRef()); if (!response_object_sp) return llvm::None; StructuredData::Array *response_array = response_object_sp->GetAsArray(); if (!response_array) return llvm::None; std::vector result; for (size_t i = 0; i < response_array->GetSize(); ++i) { if (llvm::Optional module_spec = ParseModuleSpec( response_array->GetItemAtIndex(i)->GetAsDictionary())) result.push_back(*module_spec); } return result; } // query the target remote for extended information using the qXfer packet // // example: object='features', annex='target.xml', out= // return: 'true' on success // 'false' on failure (err set) bool GDBRemoteCommunicationClient::ReadExtFeature( const lldb_private::ConstString object, const lldb_private::ConstString annex, std::string &out, lldb_private::Status &err) { std::stringstream output; StringExtractorGDBRemote chunk; uint64_t size = GetRemoteMaxPacketSize(); if (size == 0) size = 0x1000; size = size - 1; // Leave space for the 'm' or 'l' character in the response int offset = 0; bool active = true; // loop until all data has been read while (active) { // send query extended feature packet std::stringstream packet; packet << "qXfer:" << object.AsCString("") << ":read:" << annex.AsCString("") << ":" << std::hex << offset << "," << std::hex << size; GDBRemoteCommunication::PacketResult res = SendPacketAndWaitForResponse(packet.str(), chunk, false); if (res != GDBRemoteCommunication::PacketResult::Success) { err.SetErrorString("Error sending $qXfer packet"); return false; } const std::string &str = chunk.GetStringRef(); if (str.length() == 0) { // should have some data in chunk err.SetErrorString("Empty response from $qXfer packet"); return false; } // check packet code switch (str[0]) { // last chunk case ('l'): active = false; LLVM_FALLTHROUGH; // more chunks case ('m'): if (str.length() > 1) output << &str[1]; offset += size; break; // unknown chunk default: err.SetErrorString("Invalid continuation code from $qXfer packet"); return false; } } out = output.str(); err.Success(); return true; } // Notify the target that gdb is prepared to serve symbol lookup requests. // packet: "qSymbol::" // reply: // OK The target does not need to look up any (more) symbols. // qSymbol: The target requests the value of symbol sym_name (hex // encoded). // LLDB may provide the value by sending another qSymbol // packet // in the form of"qSymbol::". // // Three examples: // // lldb sends: qSymbol:: // lldb receives: OK // Remote gdb stub does not need to know the addresses of any symbols, lldb // does not // need to ask again in this session. // // lldb sends: qSymbol:: // lldb receives: qSymbol:64697370617463685f71756575655f6f666673657473 // lldb sends: qSymbol::64697370617463685f71756575655f6f666673657473 // lldb receives: OK // Remote gdb stub asks for address of 'dispatch_queue_offsets'. lldb does // not know // the address at this time. lldb needs to send qSymbol:: again when it has // more // solibs loaded. // // lldb sends: qSymbol:: // lldb receives: qSymbol:64697370617463685f71756575655f6f666673657473 // lldb sends: qSymbol:2bc97554:64697370617463685f71756575655f6f666673657473 // lldb receives: OK // Remote gdb stub asks for address of 'dispatch_queue_offsets'. lldb says // that it // is at address 0x2bc97554. Remote gdb stub sends 'OK' indicating that it // does not // need any more symbols. lldb does not need to ask again in this session. void GDBRemoteCommunicationClient::ServeSymbolLookups( lldb_private::Process *process) { // Set to true once we've resolved a symbol to an address for the remote stub. // If we get an 'OK' response after this, the remote stub doesn't need any // more // symbols and we can stop asking. bool symbol_response_provided = false; // Is this the initial qSymbol:: packet? bool first_qsymbol_query = true; if (m_supports_qSymbol && m_qSymbol_requests_done == false) { Lock lock(*this, false); if (lock) { StreamString packet; packet.PutCString("qSymbol::"); StringExtractorGDBRemote response; while (SendPacketAndWaitForResponseNoLock(packet.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) { if (symbol_response_provided || first_qsymbol_query) { m_qSymbol_requests_done = true; } // We are done serving symbols requests return; } first_qsymbol_query = false; if (response.IsUnsupportedResponse()) { // qSymbol is not supported by the current GDB server we are connected // to m_supports_qSymbol = false; return; } else { llvm::StringRef response_str(response.GetStringRef()); if (response_str.startswith("qSymbol:")) { response.SetFilePos(strlen("qSymbol:")); std::string symbol_name; if (response.GetHexByteString(symbol_name)) { if (symbol_name.empty()) return; addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; lldb_private::SymbolContextList sc_list; if (process->GetTarget().GetImages().FindSymbolsWithNameAndType( ConstString(symbol_name), eSymbolTypeAny, sc_list)) { const size_t num_scs = sc_list.GetSize(); for (size_t sc_idx = 0; sc_idx < num_scs && symbol_load_addr == LLDB_INVALID_ADDRESS; ++sc_idx) { SymbolContext sc; if (sc_list.GetContextAtIndex(sc_idx, sc)) { if (sc.symbol) { switch (sc.symbol->GetType()) { case eSymbolTypeInvalid: case eSymbolTypeAbsolute: case eSymbolTypeUndefined: case eSymbolTypeSourceFile: case eSymbolTypeHeaderFile: case eSymbolTypeObjectFile: case eSymbolTypeCommonBlock: case eSymbolTypeBlock: case eSymbolTypeLocal: case eSymbolTypeParam: case eSymbolTypeVariable: case eSymbolTypeVariableType: case eSymbolTypeLineEntry: case eSymbolTypeLineHeader: case eSymbolTypeScopeBegin: case eSymbolTypeScopeEnd: case eSymbolTypeAdditional: case eSymbolTypeCompiler: case eSymbolTypeInstrumentation: case eSymbolTypeTrampoline: break; case eSymbolTypeCode: case eSymbolTypeResolver: case eSymbolTypeData: case eSymbolTypeRuntime: case eSymbolTypeException: case eSymbolTypeObjCClass: case eSymbolTypeObjCMetaClass: case eSymbolTypeObjCIVar: case eSymbolTypeReExported: symbol_load_addr = sc.symbol->GetLoadAddress(&process->GetTarget()); break; } } } } } // This is the normal path where our symbol lookup was successful // and we want // to send a packet with the new symbol value and see if another // lookup needs to be // done. // Change "packet" to contain the requested symbol value and name packet.Clear(); packet.PutCString("qSymbol:"); if (symbol_load_addr != LLDB_INVALID_ADDRESS) { packet.Printf("%" PRIx64, symbol_load_addr); symbol_response_provided = true; } else { symbol_response_provided = false; } packet.PutCString(":"); packet.PutBytesAsRawHex8(symbol_name.data(), symbol_name.size()); continue; // go back to the while loop and send "packet" and wait // for another response } } } } // If we make it here, the symbol request packet response wasn't valid or // our symbol lookup failed so we must abort return; } else if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet( GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)) { log->Printf( "GDBRemoteCommunicationClient::%s: Didn't get sequence mutex.", __FUNCTION__); } } } StructuredData::Array * GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() { if (!m_supported_async_json_packets_is_valid) { // Query the server for the array of supported asynchronous JSON // packets. m_supported_async_json_packets_is_valid = true; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); // Poll it now. StringExtractorGDBRemote response; const bool send_async = false; if (SendPacketAndWaitForResponse("qStructuredDataPlugins", response, send_async) == PacketResult::Success) { m_supported_async_json_packets_sp = StructuredData::ParseJSON(response.GetStringRef()); if (m_supported_async_json_packets_sp && !m_supported_async_json_packets_sp->GetAsArray()) { // We were returned something other than a JSON array. This // is invalid. Clear it out. if (log) log->Printf("GDBRemoteCommunicationClient::%s(): " "QSupportedAsyncJSONPackets returned invalid " "result: %s", __FUNCTION__, response.GetStringRef().c_str()); m_supported_async_json_packets_sp.reset(); } } else { if (log) log->Printf("GDBRemoteCommunicationClient::%s(): " "QSupportedAsyncJSONPackets unsupported", __FUNCTION__); } if (log && m_supported_async_json_packets_sp) { StreamString stream; m_supported_async_json_packets_sp->Dump(stream); log->Printf("GDBRemoteCommunicationClient::%s(): supported async " "JSON packets: %s", __FUNCTION__, stream.GetData()); } } return m_supported_async_json_packets_sp ? m_supported_async_json_packets_sp->GetAsArray() : nullptr; } Status GDBRemoteCommunicationClient::SendSignalsToIgnore( llvm::ArrayRef signals) { // Format packet: // QPassSignals:;...; auto range = llvm::make_range(signals.begin(), signals.end()); std::string packet = formatv("QPassSignals:{0:$[;]@(x-2)}", range).str(); StringExtractorGDBRemote response; auto send_status = SendPacketAndWaitForResponse(packet, response, false); if (send_status != GDBRemoteCommunication::PacketResult::Success) return Status("Sending QPassSignals packet failed"); if (response.IsOKResponse()) { return Status(); } else { return Status("Unknown error happened during sending QPassSignals packet."); } } Status GDBRemoteCommunicationClient::ConfigureRemoteStructuredData( const ConstString &type_name, const StructuredData::ObjectSP &config_sp) { Status error; if (type_name.GetLength() == 0) { error.SetErrorString("invalid type_name argument"); return error; } // Build command: Configure{type_name}: serialized config // data. StreamGDBRemote stream; stream.PutCString("QConfigure"); stream.PutCString(type_name.AsCString()); stream.PutChar(':'); if (config_sp) { // Gather the plain-text version of the configuration data. StreamString unescaped_stream; config_sp->Dump(unescaped_stream); unescaped_stream.Flush(); // Add it to the stream in escaped fashion. stream.PutEscapedBytes(unescaped_stream.GetString().data(), unescaped_stream.GetSize()); } stream.Flush(); // Send the packet. const bool send_async = false; StringExtractorGDBRemote response; auto result = SendPacketAndWaitForResponse(stream.GetString(), response, send_async); if (result == PacketResult::Success) { // We failed if the config result comes back other than OK. if (strcmp(response.GetStringRef().c_str(), "OK") == 0) { // Okay! error.Clear(); } else { error.SetErrorStringWithFormat("configuring StructuredData feature " "%s failed with error %s", type_name.AsCString(), response.GetStringRef().c_str()); } } else { // Can we get more data here on the failure? error.SetErrorStringWithFormat("configuring StructuredData feature %s " "failed when sending packet: " "PacketResult=%d", type_name.AsCString(), (int)result); } return error; } void GDBRemoteCommunicationClient::OnRunPacketSent(bool first) { GDBRemoteClientBase::OnRunPacketSent(first); m_curr_tid = LLDB_INVALID_THREAD_ID; } Index: vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h =================================================================== --- vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h (revision 320966) +++ vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h (revision 320967) @@ -1,618 +1,621 @@ //===-- GDBRemoteCommunicationClient.h --------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef liblldb_GDBRemoteCommunicationClient_h_ #define liblldb_GDBRemoteCommunicationClient_h_ #include "GDBRemoteClientBase.h" // C Includes // C++ Includes #include #include #include #include #include // Other libraries and framework includes // Project includes #include "lldb/Core/ArchSpec.h" #include "lldb/Target/Process.h" #include "lldb/Utility/StreamGDBRemote.h" #include "lldb/Utility/StructuredData.h" #include "llvm/ADT/Optional.h" namespace lldb_private { namespace process_gdb_remote { class GDBRemoteCommunicationClient : public GDBRemoteClientBase { public: GDBRemoteCommunicationClient(); ~GDBRemoteCommunicationClient() override; //------------------------------------------------------------------ // After connecting, send the handshake to the server to make sure // we are communicating with it. //------------------------------------------------------------------ bool HandshakeWithServer(Status *error_ptr); // For packets which specify a range of output to be returned, // return all of the output via a series of request packets of the form // 0, // , // *2, // *3, // ... // until a "$l..." packet is received, indicating the end. // (size is in hex; this format is used by a standard gdbserver to // return the given portion of the output specified by ; // for example, "qXfer:libraries-svr4:read::fff,1000" means // "return a chunk of the xml description file for shared // library load addresses, where the chunk starts at offset 0xfff // and continues for 0x1000 bytes"). // Concatenate the resulting server response packets together and // return in response_string. If any packet fails, the return value // indicates that failure and the returned string value is undefined. PacketResult SendPacketsAndConcatenateResponses(const char *send_payload_prefix, std::string &response_string); bool GetThreadSuffixSupported(); // This packet is usually sent first and the boolean return value // indicates if the packet was send and any response was received // even in the response is UNIMPLEMENTED. If the packet failed to // get a response, then false is returned. This quickly tells us // if we were able to connect and communicate with the remote GDB // server bool QueryNoAckModeSupported(); void GetListThreadsInStopReplySupported(); lldb::pid_t GetCurrentProcessID(bool allow_lazy = true); bool GetLaunchSuccess(std::string &error_str); bool LaunchGDBServer(const char *remote_accept_hostname, lldb::pid_t &pid, uint16_t &port, std::string &socket_name); size_t QueryGDBServer( std::vector> &connection_urls); bool KillSpawnedProcess(lldb::pid_t pid); //------------------------------------------------------------------ /// Sends a GDB remote protocol 'A' packet that delivers program /// arguments to the remote server. /// /// @param[in] argv /// A NULL terminated array of const C strings to use as the /// arguments. /// /// @return /// Zero if the response was "OK", a positive value if the /// the response was "Exx" where xx are two hex digits, or /// -1 if the call is unsupported or any other unexpected /// response was received. //------------------------------------------------------------------ int SendArgumentsPacket(const ProcessLaunchInfo &launch_info); //------------------------------------------------------------------ /// Sends a "QEnvironment:NAME=VALUE" packet that will build up the /// environment that will get used when launching an application /// in conjunction with the 'A' packet. This function can be called /// multiple times in a row in order to pass on the desired /// environment that the inferior should be launched with. /// /// @param[in] name_equal_value /// A NULL terminated C string that contains a single environment /// in the format "NAME=VALUE". /// /// @return /// Zero if the response was "OK", a positive value if the /// the response was "Exx" where xx are two hex digits, or /// -1 if the call is unsupported or any other unexpected /// response was received. //------------------------------------------------------------------ int SendEnvironmentPacket(char const *name_equal_value); int SendLaunchArchPacket(const char *arch); int SendLaunchEventDataPacket(const char *data, bool *was_supported = nullptr); //------------------------------------------------------------------ /// Sends a "vAttach:PID" where PID is in hex. /// /// @param[in] pid /// A process ID for the remote gdb server to attach to. /// /// @param[out] response /// The response received from the gdb server. If the return /// value is zero, \a response will contain a stop reply /// packet. /// /// @return /// Zero if the attach was successful, or an error indicating /// an error code. //------------------------------------------------------------------ int SendAttach(lldb::pid_t pid, StringExtractorGDBRemote &response); //------------------------------------------------------------------ /// Sends a GDB remote protocol 'I' packet that delivers stdin /// data to the remote process. /// /// @param[in] data /// A pointer to stdin data. /// /// @param[in] data_len /// The number of bytes available at \a data. /// /// @return /// Zero if the attach was successful, or an error indicating /// an error code. //------------------------------------------------------------------ int SendStdinNotification(const char *data, size_t data_len); //------------------------------------------------------------------ /// Sets the path to use for stdin/out/err for a process /// that will be launched with the 'A' packet. /// /// @param[in] path /// The path to use for stdin/out/err /// /// @return /// Zero if the for success, or an error code for failure. //------------------------------------------------------------------ int SetSTDIN(const FileSpec &file_spec); int SetSTDOUT(const FileSpec &file_spec); int SetSTDERR(const FileSpec &file_spec); //------------------------------------------------------------------ /// Sets the disable ASLR flag to \a enable for a process that will /// be launched with the 'A' packet. /// /// @param[in] enable /// A boolean value indicating whether to disable ASLR or not. /// /// @return /// Zero if the for success, or an error code for failure. //------------------------------------------------------------------ int SetDisableASLR(bool enable); //------------------------------------------------------------------ /// Sets the DetachOnError flag to \a enable for the process controlled by the /// stub. /// /// @param[in] enable /// A boolean value indicating whether to detach on error or not. /// /// @return /// Zero if the for success, or an error code for failure. //------------------------------------------------------------------ int SetDetachOnError(bool enable); //------------------------------------------------------------------ /// Sets the working directory to \a path for a process that will /// be launched with the 'A' packet for non platform based /// connections. If this packet is sent to a GDB server that /// implements the platform, it will change the current working /// directory for the platform process. /// /// @param[in] working_dir /// The path to a directory to use when launching our process /// /// @return /// Zero if the for success, or an error code for failure. //------------------------------------------------------------------ int SetWorkingDir(const FileSpec &working_dir); //------------------------------------------------------------------ /// Gets the current working directory of a remote platform GDB /// server. /// /// @param[out] working_dir /// The current working directory on the remote platform. /// /// @return /// Boolean for success //------------------------------------------------------------------ bool GetWorkingDir(FileSpec &working_dir); lldb::addr_t AllocateMemory(size_t size, uint32_t permissions); bool DeallocateMemory(lldb::addr_t addr); Status Detach(bool keep_stopped); Status GetMemoryRegionInfo(lldb::addr_t addr, MemoryRegionInfo &range_info); Status GetWatchpointSupportInfo(uint32_t &num); Status GetWatchpointSupportInfo(uint32_t &num, bool &after, const ArchSpec &arch); Status GetWatchpointsTriggerAfterInstruction(bool &after, const ArchSpec &arch); const ArchSpec &GetHostArchitecture(); std::chrono::seconds GetHostDefaultPacketTimeout(); const ArchSpec &GetProcessArchitecture(); void GetRemoteQSupported(); bool GetVContSupported(char flavor); bool GetpPacketSupported(lldb::tid_t tid); bool GetxPacketSupported(); bool GetVAttachOrWaitSupported(); bool GetSyncThreadStateSupported(); void ResetDiscoverableSettings(bool did_exec); bool GetHostInfo(bool force = false); bool GetDefaultThreadId(lldb::tid_t &tid); bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update); bool GetOSBuildString(std::string &s); bool GetOSKernelDescription(std::string &s); ArchSpec GetSystemArchitecture(); bool GetHostname(std::string &s); lldb::addr_t GetShlibInfoAddr(); bool GetSupportsThreadSuffix(); bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info); uint32_t FindProcesses(const ProcessInstanceInfoMatch &process_match_info, ProcessInstanceInfoList &process_infos); bool GetUserName(uint32_t uid, std::string &name); bool GetGroupName(uint32_t gid, std::string &name); bool HasFullVContSupport() { return GetVContSupported('A'); } bool HasAnyVContSupport() { return GetVContSupported('a'); } bool GetStopReply(StringExtractorGDBRemote &response); bool GetThreadStopInfo(lldb::tid_t tid, StringExtractorGDBRemote &response); bool SupportsGDBStoppointPacket(GDBStoppointType type) { switch (type) { case eBreakpointSoftware: return m_supports_z0; case eBreakpointHardware: return m_supports_z1; case eWatchpointWrite: return m_supports_z2; case eWatchpointRead: return m_supports_z3; case eWatchpointReadWrite: return m_supports_z4; default: return false; } } uint8_t SendGDBStoppointTypePacket( GDBStoppointType type, // Type of breakpoint or watchpoint bool insert, // Insert or remove? lldb::addr_t addr, // Address of breakpoint or watchpoint uint32_t length); // Byte Size of breakpoint or watchpoint bool SetNonStopMode(const bool enable); void TestPacketSpeed(const uint32_t num_packets, uint32_t max_send, uint32_t max_recv, uint64_t recv_amount, bool json, Stream &strm); // This packet is for testing the speed of the interface only. Both // the client and server need to support it, but this allows us to // measure the packet speed without any other work being done on the // other end and avoids any of that work affecting the packet send // and response times. bool SendSpeedTestPacket(uint32_t send_size, uint32_t recv_size); bool SetCurrentThread(uint64_t tid); bool SetCurrentThreadForRun(uint64_t tid); bool GetQXferAuxvReadSupported(); + void EnableErrorStringInPacket(); + bool GetQXferLibrariesReadSupported(); bool GetQXferLibrariesSVR4ReadSupported(); uint64_t GetRemoteMaxPacketSize(); bool GetEchoSupported(); bool GetQPassSignalsSupported(); bool GetAugmentedLibrariesSVR4ReadSupported(); bool GetQXferFeaturesReadSupported(); LazyBool SupportsAllocDeallocMemory() // const { // Uncomment this to have lldb pretend the debug server doesn't respond to // alloc/dealloc memory packets. // m_supports_alloc_dealloc_memory = lldb_private::eLazyBoolNo; return m_supports_alloc_dealloc_memory; } size_t GetCurrentThreadIDs(std::vector &thread_ids, bool &sequence_mutex_unavailable); lldb::user_id_t OpenFile(const FileSpec &file_spec, uint32_t flags, mode_t mode, Status &error); bool CloseFile(lldb::user_id_t fd, Status &error); lldb::user_id_t GetFileSize(const FileSpec &file_spec); Status GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions); Status SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions); uint64_t ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst, uint64_t dst_len, Status &error); uint64_t WriteFile(lldb::user_id_t fd, uint64_t offset, const void *src, uint64_t src_len, Status &error); Status CreateSymlink(const FileSpec &src, const FileSpec &dst); Status Unlink(const FileSpec &file_spec); Status MakeDirectory(const FileSpec &file_spec, uint32_t mode); bool GetFileExists(const FileSpec &file_spec); Status RunShellCommand( const char *command, // Shouldn't be nullptr const FileSpec &working_dir, // Pass empty FileSpec to use the current // working directory int *status_ptr, // Pass nullptr if you don't want the process exit status int *signo_ptr, // Pass nullptr if you don't want the signal that caused // the process to exit std::string *command_output, // Pass nullptr if you don't want the command output uint32_t timeout_sec); // Timeout in seconds to wait for shell program to // finish bool CalculateMD5(const FileSpec &file_spec, uint64_t &high, uint64_t &low); lldb::DataBufferSP ReadRegister( lldb::tid_t tid, uint32_t reg_num); // Must be the eRegisterKindProcessPlugin register number lldb::DataBufferSP ReadAllRegisters(lldb::tid_t tid); bool WriteRegister(lldb::tid_t tid, uint32_t reg_num, // eRegisterKindProcessPlugin register number llvm::ArrayRef data); bool WriteAllRegisters(lldb::tid_t tid, llvm::ArrayRef data); bool SaveRegisterState(lldb::tid_t tid, uint32_t &save_id); bool RestoreRegisterState(lldb::tid_t tid, uint32_t save_id); bool SyncThreadState(lldb::tid_t tid); const char *GetGDBServerProgramName(); uint32_t GetGDBServerProgramVersion(); bool AvoidGPackets(ProcessGDBRemote *process); StructuredData::ObjectSP GetThreadsInfo(); bool GetThreadExtendedInfoSupported(); bool GetLoadedDynamicLibrariesInfosSupported(); bool GetSharedCacheInfoSupported(); bool GetModuleInfo(const FileSpec &module_file_spec, const ArchSpec &arch_spec, ModuleSpec &module_spec); llvm::Optional> GetModulesInfo(llvm::ArrayRef module_file_specs, const llvm::Triple &triple); bool ReadExtFeature(const lldb_private::ConstString object, const lldb_private::ConstString annex, std::string &out, lldb_private::Status &err); void ServeSymbolLookups(lldb_private::Process *process); // Sends QPassSignals packet to the server with given signals to ignore. Status SendSignalsToIgnore(llvm::ArrayRef signals); //------------------------------------------------------------------ /// Return the feature set supported by the gdb-remote server. /// /// This method returns the remote side's response to the qSupported /// packet. The response is the complete string payload returned /// to the client. /// /// @return /// The string returned by the server to the qSupported query. //------------------------------------------------------------------ const std::string &GetServerSupportedFeatures() const { return m_qSupported_response; } //------------------------------------------------------------------ /// Return the array of async JSON packet types supported by the remote. /// /// This method returns the remote side's array of supported JSON /// packet types as a list of type names. Each of the results are /// expected to have an Enable{type_name} command to enable and configure /// the related feature. Each type_name for an enabled feature will /// possibly send async-style packets that contain a payload of a /// binhex-encoded JSON dictionary. The dictionary will have a /// string field named 'type', that contains the type_name of the /// supported packet type. /// /// There is a Plugin category called structured-data plugins. /// A plugin indicates whether it knows how to handle a type_name. /// If so, it can be used to process the async JSON packet. /// /// @return /// The string returned by the server to the qSupported query. //------------------------------------------------------------------ lldb_private::StructuredData::Array *GetSupportedStructuredDataPlugins(); //------------------------------------------------------------------ /// Configure a StructuredData feature on the remote end. /// /// @see \b Process::ConfigureStructuredData(...) for details. //------------------------------------------------------------------ Status ConfigureRemoteStructuredData(const ConstString &type_name, const StructuredData::ObjectSP &config_sp); lldb::user_id_t SendStartTracePacket(const TraceOptions &options, Status &error); Status SendStopTracePacket(lldb::user_id_t uid, lldb::tid_t thread_id); Status SendGetDataPacket(lldb::user_id_t uid, lldb::tid_t thread_id, llvm::MutableArrayRef &buffer, size_t offset = 0); Status SendGetMetaDataPacket(lldb::user_id_t uid, lldb::tid_t thread_id, llvm::MutableArrayRef &buffer, size_t offset = 0); Status SendGetTraceConfigPacket(lldb::user_id_t uid, TraceOptions &options); protected: LazyBool m_supports_not_sending_acks; LazyBool m_supports_thread_suffix; LazyBool m_supports_threads_in_stop_reply; LazyBool m_supports_vCont_all; LazyBool m_supports_vCont_any; LazyBool m_supports_vCont_c; LazyBool m_supports_vCont_C; LazyBool m_supports_vCont_s; LazyBool m_supports_vCont_S; LazyBool m_qHostInfo_is_valid; LazyBool m_curr_pid_is_valid; LazyBool m_qProcessInfo_is_valid; LazyBool m_qGDBServerVersion_is_valid; LazyBool m_supports_alloc_dealloc_memory; LazyBool m_supports_memory_region_info; LazyBool m_supports_watchpoint_support_info; LazyBool m_supports_detach_stay_stopped; LazyBool m_watchpoints_trigger_after_instruction; LazyBool m_attach_or_wait_reply; LazyBool m_prepare_for_reg_writing_reply; LazyBool m_supports_p; LazyBool m_supports_x; LazyBool m_avoid_g_packets; LazyBool m_supports_QSaveRegisterState; LazyBool m_supports_qXfer_auxv_read; LazyBool m_supports_qXfer_libraries_read; LazyBool m_supports_qXfer_libraries_svr4_read; LazyBool m_supports_qXfer_features_read; LazyBool m_supports_augmented_libraries_svr4_read; LazyBool m_supports_jThreadExtendedInfo; LazyBool m_supports_jLoadedDynamicLibrariesInfos; LazyBool m_supports_jGetSharedCacheInfo; LazyBool m_supports_QPassSignals; + LazyBool m_supports_error_string_reply; bool m_supports_qProcessInfoPID : 1, m_supports_qfProcessInfo : 1, m_supports_qUserName : 1, m_supports_qGroupName : 1, m_supports_qThreadStopInfo : 1, m_supports_z0 : 1, m_supports_z1 : 1, m_supports_z2 : 1, m_supports_z3 : 1, m_supports_z4 : 1, m_supports_QEnvironment : 1, m_supports_QEnvironmentHexEncoded : 1, m_supports_qSymbol : 1, m_qSymbol_requests_done : 1, m_supports_qModuleInfo : 1, m_supports_jThreadsInfo : 1, m_supports_jModulesInfo : 1; lldb::pid_t m_curr_pid; lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all // other operations lldb::tid_t m_curr_tid_run; // Current gdb remote protocol thread index for // continue, step, etc uint32_t m_num_supported_hardware_watchpoints; ArchSpec m_host_arch; ArchSpec m_process_arch; uint32_t m_os_version_major; uint32_t m_os_version_minor; uint32_t m_os_version_update; std::string m_os_build; std::string m_os_kernel; std::string m_hostname; std::string m_gdb_server_name; // from reply to qGDBServerVersion, empty if // qGDBServerVersion is not supported uint32_t m_gdb_server_version; // from reply to qGDBServerVersion, zero if // qGDBServerVersion is not supported std::chrono::seconds m_default_packet_timeout; uint64_t m_max_packet_size; // as returned by qSupported std::string m_qSupported_response; // the complete response to qSupported bool m_supported_async_json_packets_is_valid; lldb_private::StructuredData::ObjectSP m_supported_async_json_packets_sp; bool GetCurrentProcessInfo(bool allow_lazy_pid = true); bool GetGDBServerVersion(); // Given the list of compression types that the remote debug stub can support, // possibly enable compression if we find an encoding we can handle. void MaybeEnableCompression(std::vector supported_compressions); bool DecodeProcessInfoResponse(StringExtractorGDBRemote &response, ProcessInstanceInfo &process_info); void OnRunPacketSent(bool first) override; PacketResult SendThreadSpecificPacketAndWaitForResponse( lldb::tid_t tid, StreamString &&payload, StringExtractorGDBRemote &response, bool send_async); Status SendGetTraceDataPacket(StreamGDBRemote &packet, lldb::user_id_t uid, lldb::tid_t thread_id, llvm::MutableArrayRef &buffer, size_t offset); private: DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationClient); }; } // namespace process_gdb_remote } // namespace lldb_private #endif // liblldb_GDBRemoteCommunicationClient_h_ Index: vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp (revision 320967) @@ -1,120 +1,144 @@ //===-- GDBRemoteCommunicationServer.cpp ------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include #include "lldb/Host/Config.h" #include "GDBRemoteCommunicationServer.h" // C Includes // C++ Includes #include // Project includes #include "ProcessGDBRemoteLog.h" #include "Utility/StringExtractorGDBRemote.h" +#include "lldb/Utility/StreamString.h" using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; GDBRemoteCommunicationServer::GDBRemoteCommunicationServer( const char *comm_name, const char *listener_name) - : GDBRemoteCommunication(comm_name, listener_name), m_exit_now(false) {} + : GDBRemoteCommunication(comm_name, listener_name), m_exit_now(false) { + RegisterPacketHandler( + StringExtractorGDBRemote::eServerPacketType_QEnableErrorStrings, + [this](StringExtractorGDBRemote packet, Status &error, bool &interrupt, + bool &quit) { return this->Handle_QErrorStringEnable(packet); }); +} GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() {} void GDBRemoteCommunicationServer::RegisterPacketHandler( StringExtractorGDBRemote::ServerPacketType packet_type, PacketHandler handler) { m_packet_handlers[packet_type] = std::move(handler); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::GetPacketAndSendResponse( Timeout timeout, Status &error, bool &interrupt, bool &quit) { StringExtractorGDBRemote packet; PacketResult packet_result = WaitForPacketNoLock(packet, timeout, false); if (packet_result == PacketResult::Success) { const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType(); switch (packet_type) { case StringExtractorGDBRemote::eServerPacketType_nack: case StringExtractorGDBRemote::eServerPacketType_ack: break; case StringExtractorGDBRemote::eServerPacketType_invalid: error.SetErrorString("invalid packet"); quit = true; break; case StringExtractorGDBRemote::eServerPacketType_unimplemented: packet_result = SendUnimplementedResponse(packet.GetStringRef().c_str()); break; default: auto handler_it = m_packet_handlers.find(packet_type); if (handler_it == m_packet_handlers.end()) packet_result = SendUnimplementedResponse(packet.GetStringRef().c_str()); else packet_result = handler_it->second(packet, error, interrupt, quit); break; } } else { if (!IsConnected()) { error.SetErrorString("lost connection"); quit = true; } else { error.SetErrorString("timeout"); } } // Check if anything occurred that would force us to want to exit. if (m_exit_now) quit = true; return packet_result; } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::SendUnimplementedResponse(const char *) { // TODO: Log the packet we aren't handling... return SendPacketNoLock(""); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::SendErrorResponse(uint8_t err) { char packet[16]; int packet_len = ::snprintf(packet, sizeof(packet), "E%2.2x", err); assert(packet_len < (int)sizeof(packet)); return SendPacketNoLock(llvm::StringRef(packet, packet_len)); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServer::SendErrorResponse(const Status &error) { + if (m_send_error_strings) { + lldb_private::StreamString packet; + packet.Printf("E%2.2x;", static_cast(error.GetError())); + packet.PutCStringAsRawHex8(error.AsCString()); + return SendPacketNoLock(packet.GetString()); + } else + return SendErrorResponse(error.GetError()); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServer::Handle_QErrorStringEnable( + StringExtractorGDBRemote &packet) { + m_send_error_strings = true; + return SendOKResponse(); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::SendIllFormedResponse( const StringExtractorGDBRemote &failed_packet, const char *message) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); if (log) log->Printf("GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)", __FUNCTION__, failed_packet.GetStringRef().c_str(), message ? message : ""); return SendErrorResponse(0x03); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::SendOKResponse() { return SendPacketNoLock("OK"); } bool GDBRemoteCommunicationServer::HandshakeWithClient() { return GetAck() == PacketResult::Success; } Index: vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h =================================================================== --- vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h (revision 320966) +++ vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h (revision 320967) @@ -1,76 +1,83 @@ //===-- GDBRemoteCommunicationServer.h --------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef liblldb_GDBRemoteCommunicationServer_h_ #define liblldb_GDBRemoteCommunicationServer_h_ // C Includes // C++ Includes #include #include // Other libraries and framework includes // Project includes #include "GDBRemoteCommunication.h" #include "lldb/lldb-private-forward.h" class StringExtractorGDBRemote; namespace lldb_private { namespace process_gdb_remote { class ProcessGDBRemote; class GDBRemoteCommunicationServer : public GDBRemoteCommunication { public: using PortMap = std::map; using PacketHandler = std::function; GDBRemoteCommunicationServer(const char *comm_name, const char *listener_name); ~GDBRemoteCommunicationServer() override; void RegisterPacketHandler(StringExtractorGDBRemote::ServerPacketType packet_type, PacketHandler handler); PacketResult GetPacketAndSendResponse(Timeout timeout, Status &error, bool &interrupt, bool &quit); // After connecting, do a little handshake with the client to make sure // we are at least communicating bool HandshakeWithClient(); protected: std::map m_packet_handlers; bool m_exit_now; // use in asynchronous handling to indicate process should // exit. + bool m_send_error_strings; // If the client enables this then + // we will send error strings as well. + + PacketResult Handle_QErrorStringEnable(StringExtractorGDBRemote &packet); + + PacketResult SendErrorResponse(const Status &error); + PacketResult SendUnimplementedResponse(const char *packet); PacketResult SendErrorResponse(uint8_t error); PacketResult SendIllFormedResponse(const StringExtractorGDBRemote &packet, const char *error_message); PacketResult SendOKResponse(); private: DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationServer); }; } // namespace process_gdb_remote } // namespace lldb_private #endif // liblldb_GDBRemoteCommunicationServer_h_ Index: vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp (revision 320967) @@ -1,1301 +1,1296 @@ //===-- GDBRemoteCommunicationServerCommon.cpp ------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "GDBRemoteCommunicationServerCommon.h" #include // C Includes #ifdef __APPLE__ #include #endif // C++ Includes #include #include // Other libraries and framework includes #include "lldb/Core/ModuleSpec.h" #include "lldb/Host/Config.h" #include "lldb/Host/File.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Interpreter/Args.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Utility/Endian.h" #include "lldb/Utility/JSON.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamGDBRemote.h" #include "lldb/Utility/StreamString.h" #include "llvm/ADT/Triple.h" // Project includes #include "ProcessGDBRemoteLog.h" #include "Utility/StringExtractorGDBRemote.h" #ifdef __ANDROID__ #include "lldb/Host/android/HostInfoAndroid.h" #endif #include "llvm/ADT/StringSwitch.h" using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; #ifdef __ANDROID__ const static uint32_t g_default_packet_timeout_sec = 20; // seconds #else const static uint32_t g_default_packet_timeout_sec = 0; // not specified #endif //---------------------------------------------------------------------- // GDBRemoteCommunicationServerCommon constructor //---------------------------------------------------------------------- GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon( const char *comm_name, const char *listener_name) : GDBRemoteCommunicationServer(comm_name, listener_name), m_process_launch_info(), m_process_launch_error(), m_proc_infos(), m_proc_infos_index(0), m_thread_suffix_supported(false), m_list_threads_in_stop_reply(false) { RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_A, &GDBRemoteCommunicationServerCommon::Handle_A); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_QEnvironment, &GDBRemoteCommunicationServerCommon::Handle_QEnvironment); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_QEnvironmentHexEncoded, &GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qfProcessInfo, &GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qGroupName, &GDBRemoteCommunicationServerCommon::Handle_qGroupName); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qHostInfo, &GDBRemoteCommunicationServerCommon::Handle_qHostInfo); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_QLaunchArch, &GDBRemoteCommunicationServerCommon::Handle_QLaunchArch); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess, &GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_QListThreadsInStopReply, &GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qEcho, &GDBRemoteCommunicationServerCommon::Handle_qEcho); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qModuleInfo, &GDBRemoteCommunicationServerCommon::Handle_qModuleInfo); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_jModulesInfo, &GDBRemoteCommunicationServerCommon::Handle_jModulesInfo); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod, &GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir, &GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qPlatform_shell, &GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID, &GDBRemoteCommunicationServerCommon::Handle_qProcessInfoPID); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_QSetDetachOnError, &GDBRemoteCommunicationServerCommon::Handle_QSetDetachOnError); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_QSetSTDERR, &GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_QSetSTDIN, &GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT, &GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qSpeedTest, &GDBRemoteCommunicationServerCommon::Handle_qSpeedTest); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qsProcessInfo, &GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode, &GDBRemoteCommunicationServerCommon::Handle_QStartNoAckMode); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qSupported, &GDBRemoteCommunicationServerCommon::Handle_qSupported); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_QThreadSuffixSupported, &GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qUserName, &GDBRemoteCommunicationServerCommon::Handle_qUserName); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_vFile_close, &GDBRemoteCommunicationServerCommon::Handle_vFile_Close); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_vFile_exists, &GDBRemoteCommunicationServerCommon::Handle_vFile_Exists); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_vFile_md5, &GDBRemoteCommunicationServerCommon::Handle_vFile_MD5); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_vFile_mode, &GDBRemoteCommunicationServerCommon::Handle_vFile_Mode); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_vFile_open, &GDBRemoteCommunicationServerCommon::Handle_vFile_Open); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_vFile_pread, &GDBRemoteCommunicationServerCommon::Handle_vFile_pRead); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_vFile_pwrite, &GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_vFile_size, &GDBRemoteCommunicationServerCommon::Handle_vFile_Size); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_vFile_stat, &GDBRemoteCommunicationServerCommon::Handle_vFile_Stat); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_vFile_symlink, &GDBRemoteCommunicationServerCommon::Handle_vFile_symlink); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_vFile_unlink, &GDBRemoteCommunicationServerCommon::Handle_vFile_unlink); } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- GDBRemoteCommunicationServerCommon::~GDBRemoteCommunicationServerCommon() {} GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qHostInfo( StringExtractorGDBRemote &packet) { StreamString response; // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00 ArchSpec host_arch(HostInfo::GetArchitecture()); const llvm::Triple &host_triple = host_arch.GetTriple(); response.PutCString("triple:"); response.PutCStringAsRawHex8(host_triple.getTriple().c_str()); response.Printf(";ptrsize:%u;", host_arch.GetAddressByteSize()); const char *distribution_id = host_arch.GetDistributionId().AsCString(); if (distribution_id) { response.PutCString("distribution_id:"); response.PutCStringAsRawHex8(distribution_id); response.PutCString(";"); } #if defined(__APPLE__) // For parity with debugserver, we'll include the vendor key. response.PutCString("vendor:apple;"); // Send out MachO info. uint32_t cpu = host_arch.GetMachOCPUType(); uint32_t sub = host_arch.GetMachOCPUSubType(); if (cpu != LLDB_INVALID_CPUTYPE) response.Printf("cputype:%u;", cpu); if (sub != LLDB_INVALID_CPUTYPE) response.Printf("cpusubtype:%u;", sub); if (cpu == ArchSpec::kCore_arm_any) { // Indicate the OS type. #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1 response.PutCString("ostype:tvos;"); #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 response.PutCString("ostype:watchos;"); #else response.PutCString("ostype:ios;"); #endif // On arm, we use "synchronous" watchpoints which means the exception is // delivered before the instruction executes. response.PutCString("watchpoint_exceptions_received:before;"); } else { response.PutCString("ostype:macosx;"); response.Printf("watchpoint_exceptions_received:after;"); } #else if (host_arch.GetMachine() == llvm::Triple::aarch64 || host_arch.GetMachine() == llvm::Triple::aarch64_be || host_arch.GetMachine() == llvm::Triple::arm || host_arch.GetMachine() == llvm::Triple::armeb || host_arch.GetMachine() == llvm::Triple::mips64 || host_arch.GetMachine() == llvm::Triple::mips64el || host_arch.GetMachine() == llvm::Triple::mips || host_arch.GetMachine() == llvm::Triple::mipsel) response.Printf("watchpoint_exceptions_received:before;"); else response.Printf("watchpoint_exceptions_received:after;"); #endif switch (endian::InlHostByteOrder()) { case eByteOrderBig: response.PutCString("endian:big;"); break; case eByteOrderLittle: response.PutCString("endian:little;"); break; case eByteOrderPDP: response.PutCString("endian:pdp;"); break; default: response.PutCString("endian:unknown;"); break; } uint32_t major = UINT32_MAX; uint32_t minor = UINT32_MAX; uint32_t update = UINT32_MAX; if (HostInfo::GetOSVersion(major, minor, update)) { if (major != UINT32_MAX) { response.Printf("os_version:%u", major); if (minor != UINT32_MAX) { response.Printf(".%u", minor); if (update != UINT32_MAX) response.Printf(".%u", update); } response.PutChar(';'); } } std::string s; if (HostInfo::GetOSBuildString(s)) { response.PutCString("os_build:"); response.PutCStringAsRawHex8(s.c_str()); response.PutChar(';'); } if (HostInfo::GetOSKernelDescription(s)) { response.PutCString("os_kernel:"); response.PutCStringAsRawHex8(s.c_str()); response.PutChar(';'); } #if defined(__APPLE__) #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) // For iOS devices, we are connected through a USB Mux so we never pretend // to actually have a hostname as far as the remote lldb that is connecting // to this lldb-platform is concerned response.PutCString("hostname:"); response.PutCStringAsRawHex8("127.0.0.1"); response.PutChar(';'); #else // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) if (HostInfo::GetHostname(s)) { response.PutCString("hostname:"); response.PutCStringAsRawHex8(s.c_str()); response.PutChar(';'); } #endif // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) #else // #if defined(__APPLE__) if (HostInfo::GetHostname(s)) { response.PutCString("hostname:"); response.PutCStringAsRawHex8(s.c_str()); response.PutChar(';'); } #endif // #if defined(__APPLE__) if (g_default_packet_timeout_sec > 0) response.Printf("default_packet_timeout:%u;", g_default_packet_timeout_sec); return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qProcessInfoPID( StringExtractorGDBRemote &packet) { // Packet format: "qProcessInfoPID:%i" where %i is the pid packet.SetFilePos(::strlen("qProcessInfoPID:")); lldb::pid_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID); if (pid != LLDB_INVALID_PROCESS_ID) { ProcessInstanceInfo proc_info; if (Host::GetProcessInfo(pid, proc_info)) { StreamString response; CreateProcessInfoResponse(proc_info, response); return SendPacketNoLock(response.GetString()); } } return SendErrorResponse(1); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo( StringExtractorGDBRemote &packet) { m_proc_infos_index = 0; m_proc_infos.Clear(); ProcessInstanceInfoMatch match_info; packet.SetFilePos(::strlen("qfProcessInfo")); if (packet.GetChar() == ':') { llvm::StringRef key; llvm::StringRef value; while (packet.GetNameColonValue(key, value)) { bool success = true; if (key.equals("name")) { StringExtractor extractor(value); std::string file; extractor.GetHexByteString(file); match_info.GetProcessInfo().GetExecutableFile().SetFile(file, false); } else if (key.equals("name_match")) { NameMatch name_match = llvm::StringSwitch(value) .Case("equals", NameMatch::Equals) .Case("starts_with", NameMatch::StartsWith) .Case("ends_with", NameMatch::EndsWith) .Case("contains", NameMatch::Contains) .Case("regex", NameMatch::RegularExpression) .Default(NameMatch::Ignore); match_info.SetNameMatchType(name_match); if (name_match == NameMatch::Ignore) return SendErrorResponse(2); } else if (key.equals("pid")) { lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; if (value.getAsInteger(0, pid)) return SendErrorResponse(2); match_info.GetProcessInfo().SetProcessID(pid); } else if (key.equals("parent_pid")) { lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; if (value.getAsInteger(0, pid)) return SendErrorResponse(2); match_info.GetProcessInfo().SetParentProcessID(pid); } else if (key.equals("uid")) { uint32_t uid = UINT32_MAX; if (value.getAsInteger(0, uid)) return SendErrorResponse(2); match_info.GetProcessInfo().SetUserID(uid); } else if (key.equals("gid")) { uint32_t gid = UINT32_MAX; if (value.getAsInteger(0, gid)) return SendErrorResponse(2); match_info.GetProcessInfo().SetGroupID(gid); } else if (key.equals("euid")) { uint32_t uid = UINT32_MAX; if (value.getAsInteger(0, uid)) return SendErrorResponse(2); match_info.GetProcessInfo().SetEffectiveUserID(uid); } else if (key.equals("egid")) { uint32_t gid = UINT32_MAX; if (value.getAsInteger(0, gid)) return SendErrorResponse(2); match_info.GetProcessInfo().SetEffectiveGroupID(gid); } else if (key.equals("all_users")) { match_info.SetMatchAllUsers( Args::StringToBoolean(value, false, &success)); } else if (key.equals("triple")) { match_info.GetProcessInfo().GetArchitecture().SetTriple( value.str().c_str(), NULL); } else { success = false; } if (!success) return SendErrorResponse(2); } } if (Host::FindProcesses(match_info, m_proc_infos)) { // We found something, return the first item by calling the get // subsequent process info packet handler... return Handle_qsProcessInfo(packet); } return SendErrorResponse(3); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo( StringExtractorGDBRemote &packet) { if (m_proc_infos_index < m_proc_infos.GetSize()) { StreamString response; CreateProcessInfoResponse( m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response); ++m_proc_infos_index; return SendPacketNoLock(response.GetString()); } return SendErrorResponse(4); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qUserName( StringExtractorGDBRemote &packet) { #if !defined(LLDB_DISABLE_POSIX) Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) log->Printf("GDBRemoteCommunicationServerCommon::%s begin", __FUNCTION__); // Packet format: "qUserName:%i" where %i is the uid packet.SetFilePos(::strlen("qUserName:")); uint32_t uid = packet.GetU32(UINT32_MAX); if (uid != UINT32_MAX) { std::string name; if (HostInfo::LookupUserName(uid, name)) { StreamString response; response.PutCStringAsRawHex8(name.c_str()); return SendPacketNoLock(response.GetString()); } } if (log) log->Printf("GDBRemoteCommunicationServerCommon::%s end", __FUNCTION__); #endif return SendErrorResponse(5); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qGroupName( StringExtractorGDBRemote &packet) { #if !defined(LLDB_DISABLE_POSIX) // Packet format: "qGroupName:%i" where %i is the gid packet.SetFilePos(::strlen("qGroupName:")); uint32_t gid = packet.GetU32(UINT32_MAX); if (gid != UINT32_MAX) { std::string name; if (HostInfo::LookupGroupName(gid, name)) { StreamString response; response.PutCStringAsRawHex8(name.c_str()); return SendPacketNoLock(response.GetString()); } } #endif return SendErrorResponse(6); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qSpeedTest( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("qSpeedTest:")); llvm::StringRef key; llvm::StringRef value; bool success = packet.GetNameColonValue(key, value); if (success && key.equals("response_size")) { uint32_t response_size = 0; if (!value.getAsInteger(0, response_size)) { if (response_size == 0) return SendOKResponse(); StreamString response; uint32_t bytes_left = response_size; response.PutCString("data:"); while (bytes_left > 0) { if (bytes_left >= 26) { response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); bytes_left -= 26; } else { response.Printf("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); bytes_left = 0; } } return SendPacketNoLock(response.GetString()); } } return SendErrorResponse(7); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_vFile_Open( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("vFile:open:")); std::string path; packet.GetHexByteStringTerminatedBy(path, ','); if (!path.empty()) { if (packet.GetChar() == ',') { uint32_t flags = File::ConvertOpenOptionsForPOSIXOpen(packet.GetHexMaxU32(false, 0)); if (packet.GetChar() == ',') { mode_t mode = packet.GetHexMaxU32(false, 0600); Status error; const FileSpec path_spec{path, true}; int fd = ::open(path_spec.GetCString(), flags, mode); const int save_errno = fd == -1 ? errno : 0; StreamString response; response.PutChar('F'); response.Printf("%i", fd); if (save_errno) response.Printf(",%i", save_errno); return SendPacketNoLock(response.GetString()); } } } return SendErrorResponse(18); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_vFile_Close( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("vFile:close:")); int fd = packet.GetS32(-1); Status error; int err = -1; int save_errno = 0; if (fd >= 0) { err = close(fd); save_errno = err == -1 ? errno : 0; } else { save_errno = EINVAL; } StreamString response; response.PutChar('F'); response.Printf("%i", err); if (save_errno) response.Printf(",%i", save_errno); return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_vFile_pRead( StringExtractorGDBRemote &packet) { #ifdef _WIN32 // Not implemented on Windows return SendUnimplementedResponse( "GDBRemoteCommunicationServerCommon::Handle_vFile_pRead() unimplemented"); #else StreamGDBRemote response; packet.SetFilePos(::strlen("vFile:pread:")); int fd = packet.GetS32(-1); if (packet.GetChar() == ',') { uint64_t count = packet.GetU64(UINT64_MAX); if (packet.GetChar() == ',') { uint64_t offset = packet.GetU64(UINT32_MAX); if (count == UINT64_MAX) { response.Printf("F-1:%i", EINVAL); return SendPacketNoLock(response.GetString()); } std::string buffer(count, 0); const ssize_t bytes_read = ::pread(fd, &buffer[0], buffer.size(), offset); const int save_errno = bytes_read == -1 ? errno : 0; response.PutChar('F'); response.Printf("%zi", bytes_read); if (save_errno) response.Printf(",%i", save_errno); else { response.PutChar(';'); response.PutEscapedBytes(&buffer[0], bytes_read); } return SendPacketNoLock(response.GetString()); } } return SendErrorResponse(21); #endif } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite( StringExtractorGDBRemote &packet) { #ifdef _WIN32 return SendUnimplementedResponse("GDBRemoteCommunicationServerCommon::Handle_" "vFile_pWrite() unimplemented"); #else packet.SetFilePos(::strlen("vFile:pwrite:")); StreamGDBRemote response; response.PutChar('F'); int fd = packet.GetU32(UINT32_MAX); if (packet.GetChar() == ',') { off_t offset = packet.GetU64(UINT32_MAX); if (packet.GetChar() == ',') { std::string buffer; if (packet.GetEscapedBinaryData(buffer)) { const ssize_t bytes_written = ::pwrite(fd, buffer.data(), buffer.size(), offset); const int save_errno = bytes_written == -1 ? errno : 0; response.Printf("%zi", bytes_written); if (save_errno) response.Printf(",%i", save_errno); } else { response.Printf("-1,%i", EINVAL); } return SendPacketNoLock(response.GetString()); } } return SendErrorResponse(27); #endif } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_vFile_Size( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("vFile:size:")); std::string path; packet.GetHexByteString(path); if (!path.empty()) { uint64_t Size; if (llvm::sys::fs::file_size(path, Size)) return SendErrorResponse(5); StreamString response; response.PutChar('F'); response.PutHex64(Size); if (Size == UINT64_MAX) { response.PutChar(','); response.PutHex64(Size); // TODO: replace with Host::GetSyswideErrorCode() } return SendPacketNoLock(response.GetString()); } return SendErrorResponse(22); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_vFile_Mode( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("vFile:mode:")); std::string path; packet.GetHexByteString(path); if (!path.empty()) { Status error; const uint32_t mode = File::GetPermissions(FileSpec{path, true}, error); StreamString response; response.Printf("F%u", mode); if (mode == 0 || error.Fail()) response.Printf(",%i", (int)error.GetError()); return SendPacketNoLock(response.GetString()); } return SendErrorResponse(23); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_vFile_Exists( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("vFile:exists:")); std::string path; packet.GetHexByteString(path); if (!path.empty()) { bool retcode = llvm::sys::fs::exists(path); StreamString response; response.PutChar('F'); response.PutChar(','); if (retcode) response.PutChar('1'); else response.PutChar('0'); return SendPacketNoLock(response.GetString()); } return SendErrorResponse(24); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_vFile_symlink( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("vFile:symlink:")); std::string dst, src; packet.GetHexByteStringTerminatedBy(dst, ','); packet.GetChar(); // Skip ',' char packet.GetHexByteString(src); Status error = FileSystem::Symlink(FileSpec{src, true}, FileSpec{dst, false}); StreamString response; response.Printf("F%u,%u", error.GetError(), error.GetError()); return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_vFile_unlink( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("vFile:unlink:")); std::string path; packet.GetHexByteString(path); Status error(llvm::sys::fs::remove(path)); StreamString response; response.Printf("F%u,%u", error.GetError(), error.GetError()); return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("qPlatform_shell:")); std::string path; std::string working_dir; packet.GetHexByteStringTerminatedBy(path, ','); if (!path.empty()) { if (packet.GetChar() == ',') { // FIXME: add timeout to qPlatform_shell packet // uint32_t timeout = packet.GetHexMaxU32(false, 32); uint32_t timeout = 10; if (packet.GetChar() == ',') packet.GetHexByteString(working_dir); int status, signo; std::string output; Status err = Host::RunShellCommand(path.c_str(), FileSpec{working_dir, true}, &status, &signo, &output, timeout); StreamGDBRemote response; if (err.Fail()) { response.PutCString("F,"); response.PutHex32(UINT32_MAX); } else { response.PutCString("F,"); response.PutHex32(status); response.PutChar(','); response.PutHex32(signo); response.PutChar(','); response.PutEscapedBytes(output.c_str(), output.size()); } return SendPacketNoLock(response.GetString()); } } return SendErrorResponse(24); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_vFile_Stat( StringExtractorGDBRemote &packet) { return SendUnimplementedResponse( "GDBRemoteCommunicationServerCommon::Handle_vFile_Stat() unimplemented"); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_vFile_MD5( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("vFile:MD5:")); std::string path; packet.GetHexByteString(path); if (!path.empty()) { StreamGDBRemote response; auto Result = llvm::sys::fs::md5_contents(path); if (!Result) { response.PutCString("F,"); response.PutCString("x"); } else { response.PutCString("F,"); response.PutHex64(Result->low()); response.PutHex64(Result->high()); } return SendPacketNoLock(response.GetString()); } return SendErrorResponse(25); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("qPlatform_mkdir:")); mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX); if (packet.GetChar() == ',') { std::string path; packet.GetHexByteString(path); Status error(llvm::sys::fs::create_directory(path, mode)); StreamGDBRemote response; response.Printf("F%u", error.GetError()); return SendPacketNoLock(response.GetString()); } return SendErrorResponse(20); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("qPlatform_chmod:")); auto perms = static_cast(packet.GetHexMaxU32(false, UINT32_MAX)); if (packet.GetChar() == ',') { std::string path; packet.GetHexByteString(path); Status error(llvm::sys::fs::setPermissions(path, perms)); StreamGDBRemote response; response.Printf("F%u", error.GetError()); return SendPacketNoLock(response.GetString()); } return SendErrorResponse(19); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qSupported( StringExtractorGDBRemote &packet) { StreamGDBRemote response; // Features common to lldb-platform and llgs. uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet // size--debugger can always use less response.Printf("PacketSize=%x", max_packet_size); response.PutCString(";QStartNoAckMode+"); response.PutCString(";QThreadSuffixSupported+"); response.PutCString(";QListThreadsInStopReply+"); response.PutCString(";qEcho+"); #if defined(__linux__) || defined(__NetBSD__) response.PutCString(";QPassSignals+"); response.PutCString(";qXfer:auxv:read+"); #endif return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported( StringExtractorGDBRemote &packet) { m_thread_suffix_supported = true; return SendOKResponse(); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply( StringExtractorGDBRemote &packet) { m_list_threads_in_stop_reply = true; return SendOKResponse(); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_QSetDetachOnError( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("QSetDetachOnError:")); if (packet.GetU32(0)) m_process_launch_info.GetFlags().Set(eLaunchFlagDetachOnError); else m_process_launch_info.GetFlags().Clear(eLaunchFlagDetachOnError); return SendOKResponse(); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_QStartNoAckMode( StringExtractorGDBRemote &packet) { // Send response first before changing m_send_acks to we ack this packet PacketResult packet_result = SendOKResponse(); m_send_acks = false; return packet_result; } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("QSetSTDIN:")); FileAction file_action; std::string path; packet.GetHexByteString(path); const bool read = true; const bool write = false; if (file_action.Open(STDIN_FILENO, FileSpec{path, false}, read, write)) { m_process_launch_info.AppendFileAction(file_action); return SendOKResponse(); } return SendErrorResponse(15); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("QSetSTDOUT:")); FileAction file_action; std::string path; packet.GetHexByteString(path); const bool read = false; const bool write = true; if (file_action.Open(STDOUT_FILENO, FileSpec{path, false}, read, write)) { m_process_launch_info.AppendFileAction(file_action); return SendOKResponse(); } return SendErrorResponse(16); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("QSetSTDERR:")); FileAction file_action; std::string path; packet.GetHexByteString(path); const bool read = false; const bool write = true; if (file_action.Open(STDERR_FILENO, FileSpec{path, false}, read, write)) { m_process_launch_info.AppendFileAction(file_action); return SendOKResponse(); } return SendErrorResponse(17); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess( StringExtractorGDBRemote &packet) { if (m_process_launch_error.Success()) return SendOKResponse(); StreamString response; response.PutChar('E'); response.PutCString(m_process_launch_error.AsCString("")); return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_QEnvironment( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("QEnvironment:")); const uint32_t bytes_left = packet.GetBytesLeft(); if (bytes_left > 0) { m_process_launch_info.GetEnvironmentEntries().AppendArgument( llvm::StringRef::withNullAsEmpty(packet.Peek())); return SendOKResponse(); } return SendErrorResponse(12); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("QEnvironmentHexEncoded:")); const uint32_t bytes_left = packet.GetBytesLeft(); if (bytes_left > 0) { std::string str; packet.GetHexByteString(str); m_process_launch_info.GetEnvironmentEntries().AppendArgument(str); return SendOKResponse(); } return SendErrorResponse(12); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_QLaunchArch( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("QLaunchArch:")); const uint32_t bytes_left = packet.GetBytesLeft(); if (bytes_left > 0) { const char *arch_triple = packet.Peek(); ArchSpec arch_spec(arch_triple, NULL); m_process_launch_info.SetArchitecture(arch_spec); return SendOKResponse(); } return SendErrorResponse(13); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) { // The 'A' packet is the most over designed packet ever here with // redundant argument indexes, redundant argument lengths and needed hex // encoded argument string values. Really all that is needed is a comma // separated hex encoded argument value list, but we will stay true to the // documented version of the 'A' packet here... Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); int actual_arg_index = 0; packet.SetFilePos(1); // Skip the 'A' bool success = true; while (success && packet.GetBytesLeft() > 0) { // Decode the decimal argument string length. This length is the // number of hex nibbles in the argument string value. const uint32_t arg_len = packet.GetU32(UINT32_MAX); if (arg_len == UINT32_MAX) success = false; else { // Make sure the argument hex string length is followed by a comma if (packet.GetChar() != ',') success = false; else { // Decode the argument index. We ignore this really because // who would really send down the arguments in a random order??? const uint32_t arg_idx = packet.GetU32(UINT32_MAX); if (arg_idx == UINT32_MAX) success = false; else { // Make sure the argument index is followed by a comma if (packet.GetChar() != ',') success = false; else { // Decode the argument string value from hex bytes // back into a UTF8 string and make sure the length // matches the one supplied in the packet std::string arg; if (packet.GetHexByteStringFixedLength(arg, arg_len) != (arg_len / 2)) success = false; else { // If there are any bytes left if (packet.GetBytesLeft()) { if (packet.GetChar() != ',') success = false; } if (success) { if (arg_idx == 0) m_process_launch_info.GetExecutableFile().SetFile(arg, false); m_process_launch_info.GetArguments().AppendArgument(arg); if (log) log->Printf("LLGSPacketHandler::%s added arg %d: \"%s\"", __FUNCTION__, actual_arg_index, arg.c_str()); ++actual_arg_index; } } } } } } } if (success) { m_process_launch_error = LaunchProcess(); - if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) { + if (m_process_launch_error.Success()) return SendOKResponse(); - } else { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("LLGSPacketHandler::%s failed to launch exe: %s", - __FUNCTION__, m_process_launch_error.AsCString()); - } + LLDB_LOG(log, "failed to launch exe: {0}", m_process_launch_error); } return SendErrorResponse(8); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qEcho( StringExtractorGDBRemote &packet) { // Just echo back the exact same packet for qEcho... return SendPacketNoLock(packet.GetStringRef()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qModuleInfo( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("qModuleInfo:")); std::string module_path; packet.GetHexByteStringTerminatedBy(module_path, ';'); if (module_path.empty()) return SendErrorResponse(1); if (packet.GetChar() != ';') return SendErrorResponse(2); std::string triple; packet.GetHexByteString(triple); ModuleSpec matched_module_spec = GetModuleInfo(module_path, triple); if (!matched_module_spec.GetFileSpec()) return SendErrorResponse(3); const auto file_offset = matched_module_spec.GetObjectOffset(); const auto file_size = matched_module_spec.GetObjectSize(); const auto uuid_str = matched_module_spec.GetUUID().GetAsString(""); StreamGDBRemote response; if (uuid_str.empty()) { auto Result = llvm::sys::fs::md5_contents(matched_module_spec.GetFileSpec().GetPath()); if (!Result) return SendErrorResponse(5); response.PutCString("md5:"); response.PutCStringAsRawHex8(Result->digest().c_str()); } else { response.PutCString("uuid:"); response.PutCStringAsRawHex8(uuid_str.c_str()); } response.PutChar(';'); const auto &module_arch = matched_module_spec.GetArchitecture(); response.PutCString("triple:"); response.PutCStringAsRawHex8(module_arch.GetTriple().getTriple().c_str()); response.PutChar(';'); response.PutCString("file_path:"); response.PutCStringAsRawHex8(matched_module_spec.GetFileSpec().GetCString()); response.PutChar(';'); response.PutCString("file_offset:"); response.PutHex64(file_offset); response.PutChar(';'); response.PutCString("file_size:"); response.PutHex64(file_size); response.PutChar(';'); return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_jModulesInfo( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("jModulesInfo:")); StructuredData::ObjectSP object_sp = StructuredData::ParseJSON(packet.Peek()); if (!object_sp) return SendErrorResponse(1); StructuredData::Array *packet_array = object_sp->GetAsArray(); if (!packet_array) return SendErrorResponse(2); JSONArray::SP response_array_sp = std::make_shared(); for (size_t i = 0; i < packet_array->GetSize(); ++i) { StructuredData::Dictionary *query = packet_array->GetItemAtIndex(i)->GetAsDictionary(); if (!query) continue; llvm::StringRef file, triple; if (!query->GetValueForKeyAsString("file", file) || !query->GetValueForKeyAsString("triple", triple)) continue; ModuleSpec matched_module_spec = GetModuleInfo(file, triple); if (!matched_module_spec.GetFileSpec()) continue; const auto file_offset = matched_module_spec.GetObjectOffset(); const auto file_size = matched_module_spec.GetObjectSize(); const auto uuid_str = matched_module_spec.GetUUID().GetAsString(""); if (uuid_str.empty()) continue; JSONObject::SP response = std::make_shared(); response_array_sp->AppendObject(response); response->SetObject("uuid", std::make_shared(uuid_str)); response->SetObject( "triple", std::make_shared( matched_module_spec.GetArchitecture().GetTriple().getTriple())); response->SetObject("file_path", std::make_shared( matched_module_spec.GetFileSpec().GetPath())); response->SetObject("file_offset", std::make_shared(file_offset)); response->SetObject("file_size", std::make_shared(file_size)); } StreamString response; response_array_sp->Write(response); StreamGDBRemote escaped_response; escaped_response.PutEscapedBytes(response.GetString().data(), response.GetSize()); return SendPacketNoLock(escaped_response.GetString()); } void GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse( const ProcessInstanceInfo &proc_info, StreamString &response) { response.Printf( "pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;", proc_info.GetProcessID(), proc_info.GetParentProcessID(), proc_info.GetUserID(), proc_info.GetGroupID(), proc_info.GetEffectiveUserID(), proc_info.GetEffectiveGroupID()); response.PutCString("name:"); response.PutCStringAsRawHex8(proc_info.GetExecutableFile().GetCString()); response.PutChar(';'); const ArchSpec &proc_arch = proc_info.GetArchitecture(); if (proc_arch.IsValid()) { const llvm::Triple &proc_triple = proc_arch.GetTriple(); response.PutCString("triple:"); response.PutCStringAsRawHex8(proc_triple.getTriple().c_str()); response.PutChar(';'); } } void GDBRemoteCommunicationServerCommon:: CreateProcessInfoResponse_DebugServerStyle( const ProcessInstanceInfo &proc_info, StreamString &response) { response.Printf("pid:%" PRIx64 ";parent-pid:%" PRIx64 ";real-uid:%x;real-gid:%x;effective-uid:%x;effective-gid:%x;", proc_info.GetProcessID(), proc_info.GetParentProcessID(), proc_info.GetUserID(), proc_info.GetGroupID(), proc_info.GetEffectiveUserID(), proc_info.GetEffectiveGroupID()); const ArchSpec &proc_arch = proc_info.GetArchitecture(); if (proc_arch.IsValid()) { const llvm::Triple &proc_triple = proc_arch.GetTriple(); #if defined(__APPLE__) // We'll send cputype/cpusubtype. const uint32_t cpu_type = proc_arch.GetMachOCPUType(); if (cpu_type != 0) response.Printf("cputype:%" PRIx32 ";", cpu_type); const uint32_t cpu_subtype = proc_arch.GetMachOCPUSubType(); if (cpu_subtype != 0) response.Printf("cpusubtype:%" PRIx32 ";", cpu_subtype); const std::string vendor = proc_triple.getVendorName(); if (!vendor.empty()) response.Printf("vendor:%s;", vendor.c_str()); #else // We'll send the triple. response.PutCString("triple:"); response.PutCStringAsRawHex8(proc_triple.getTriple().c_str()); response.PutChar(';'); #endif std::string ostype = proc_triple.getOSName(); // Adjust so ostype reports ios for Apple/ARM and Apple/ARM64. if (proc_triple.getVendor() == llvm::Triple::Apple) { switch (proc_triple.getArch()) { case llvm::Triple::arm: case llvm::Triple::thumb: case llvm::Triple::aarch64: ostype = "ios"; break; default: // No change. break; } } response.Printf("ostype:%s;", ostype.c_str()); switch (proc_arch.GetByteOrder()) { case lldb::eByteOrderLittle: response.PutCString("endian:little;"); break; case lldb::eByteOrderBig: response.PutCString("endian:big;"); break; case lldb::eByteOrderPDP: response.PutCString("endian:pdp;"); break; default: // Nothing. break; } // In case of MIPS64, pointer size is depend on ELF ABI // For N32 the pointer size is 4 and for N64 it is 8 std::string abi = proc_arch.GetTargetABI(); if (!abi.empty()) response.Printf("elf_abi:%s;", abi.c_str()); response.Printf("ptrsize:%d;", proc_arch.GetAddressByteSize()); } } FileSpec GDBRemoteCommunicationServerCommon::FindModuleFile( const std::string &module_path, const ArchSpec &arch) { #ifdef __ANDROID__ return HostInfoAndroid::ResolveLibraryPath(module_path, arch); #else return FileSpec(module_path, true); #endif } ModuleSpec GDBRemoteCommunicationServerCommon::GetModuleInfo(llvm::StringRef module_path, llvm::StringRef triple) { ArchSpec arch(triple); const FileSpec req_module_path_spec(module_path, true); const FileSpec module_path_spec = FindModuleFile(req_module_path_spec.GetPath(), arch); const ModuleSpec module_spec(module_path_spec, arch); ModuleSpecList module_specs; if (!ObjectFile::GetModuleSpecifications(module_path_spec, 0, 0, module_specs)) return ModuleSpec(); ModuleSpec matched_module_spec; if (!module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) return ModuleSpec(); return matched_module_spec; } Index: vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp (revision 320967) @@ -1,3439 +1,3434 @@ //===-- GDBRemoteCommunicationServerLLGS.cpp --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include #include "lldb/Host/Config.h" #include "GDBRemoteCommunicationServerLLGS.h" #include "lldb/Utility/StreamGDBRemote.h" // C Includes // C++ Includes #include #include #include // Other libraries and framework includes #include "lldb/Core/RegisterValue.h" #include "lldb/Core/State.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Debug.h" #include "lldb/Host/File.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Host/common/NativeThreadProtocol.h" #include "lldb/Interpreter/Args.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/Endian.h" #include "lldb/Utility/JSON.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/UriParser.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/ScopedPrinter.h" // Project includes #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" #include "Utility/StringExtractorGDBRemote.h" using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; using namespace llvm; //---------------------------------------------------------------------- // GDBRemote Errors //---------------------------------------------------------------------- namespace { enum GDBRemoteServerError { // Set to the first unused error number in literal form below eErrorFirst = 29, eErrorNoProcess = eErrorFirst, eErrorResume, eErrorExitStatus }; } //---------------------------------------------------------------------- // GDBRemoteCommunicationServerLLGS constructor //---------------------------------------------------------------------- GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS( - MainLoop &mainloop) + MainLoop &mainloop, const NativeProcessProtocol::Factory &process_factory) : GDBRemoteCommunicationServerCommon("gdb-remote.server", "gdb-remote.server.rx_packet"), - m_mainloop(mainloop), m_current_tid(LLDB_INVALID_THREAD_ID), - m_continue_tid(LLDB_INVALID_THREAD_ID), m_debugged_process_mutex(), - m_debugged_process_sp(), m_stdio_communication("process.stdio"), - m_inferior_prev_state(StateType::eStateInvalid), - m_saved_registers_map(), m_next_saved_registers_id(1), - m_handshake_completed(false) { + m_mainloop(mainloop), m_process_factory(process_factory), + m_stdio_communication("process.stdio") { RegisterPacketHandlers(); } void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_C, &GDBRemoteCommunicationServerLLGS::Handle_C); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_c, &GDBRemoteCommunicationServerLLGS::Handle_c); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_D, &GDBRemoteCommunicationServerLLGS::Handle_D); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_H, &GDBRemoteCommunicationServerLLGS::Handle_H); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_I, &GDBRemoteCommunicationServerLLGS::Handle_I); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_interrupt, &GDBRemoteCommunicationServerLLGS::Handle_interrupt); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_m, &GDBRemoteCommunicationServerLLGS::Handle_memory_read); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_M, &GDBRemoteCommunicationServerLLGS::Handle_M); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_p, &GDBRemoteCommunicationServerLLGS::Handle_p); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_P, &GDBRemoteCommunicationServerLLGS::Handle_P); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC, &GDBRemoteCommunicationServerLLGS::Handle_qC); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qfThreadInfo, &GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qFileLoadAddress, &GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir, &GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfo, &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfoSupported, &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qProcessInfo, &GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qRegisterInfo, &GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_QRestoreRegisterState, &GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_QSaveRegisterState, &GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR, &GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir, &GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qsThreadInfo, &GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qThreadStopInfo, &GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_jThreadsInfo, &GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo, &GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qXfer_auxv_read, &GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_s, &GDBRemoteCommunicationServerLLGS::Handle_s); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_stop_reason, &GDBRemoteCommunicationServerLLGS::Handle_stop_reason); // ? RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_vAttach, &GDBRemoteCommunicationServerLLGS::Handle_vAttach); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_vCont, &GDBRemoteCommunicationServerLLGS::Handle_vCont); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_vCont_actions, &GDBRemoteCommunicationServerLLGS::Handle_vCont_actions); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_x, &GDBRemoteCommunicationServerLLGS::Handle_memory_read); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_Z, &GDBRemoteCommunicationServerLLGS::Handle_Z); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z, &GDBRemoteCommunicationServerLLGS::Handle_z); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_QPassSignals, &GDBRemoteCommunicationServerLLGS::Handle_QPassSignals); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_jTraceStart, &GDBRemoteCommunicationServerLLGS::Handle_jTraceStart); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_jTraceBufferRead, &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_jTraceMetaRead, &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_jTraceStop, &GDBRemoteCommunicationServerLLGS::Handle_jTraceStop); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_jTraceConfigRead, &GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead); RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k, [this](StringExtractorGDBRemote packet, Status &error, bool &interrupt, bool &quit) { quit = true; return this->Handle_k(packet); }); } Status GDBRemoteCommunicationServerLLGS::SetLaunchArguments(const char *const args[], int argc) { if ((argc < 1) || !args || !args[0] || !args[0][0]) return Status("%s: no process command line specified to launch", __FUNCTION__); m_process_launch_info.SetArguments(const_cast(args), true); return Status(); } Status GDBRemoteCommunicationServerLLGS::SetLaunchFlags(unsigned int launch_flags) { m_process_launch_info.GetFlags().Set(launch_flags); return Status(); } Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (!m_process_launch_info.GetArguments().GetArgumentCount()) return Status("%s: no process command line specified to launch", __FUNCTION__); const bool should_forward_stdio = m_process_launch_info.GetFileActionForFD(STDIN_FILENO) == nullptr || m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) == nullptr || m_process_launch_info.GetFileActionForFD(STDERR_FILENO) == nullptr; m_process_launch_info.SetLaunchInSeparateProcessGroup(true); m_process_launch_info.GetFlags().Set(eLaunchFlagDebug); const bool default_to_use_pty = true; m_process_launch_info.FinalizeFileActions(nullptr, default_to_use_pty); - Status error; { std::lock_guard guard(m_debugged_process_mutex); assert(!m_debugged_process_sp && "lldb-server creating debugged " "process but one already exists"); - error = NativeProcessProtocol::Launch(m_process_launch_info, *this, - m_mainloop, m_debugged_process_sp); + auto process_or = + m_process_factory.Launch(m_process_launch_info, *this, m_mainloop); + if (!process_or) { + Status status(process_or.takeError()); + llvm::errs() << llvm::formatv( + "failed to launch executable `{0}`: {1}", + m_process_launch_info.GetArguments().GetArgumentAtIndex(0), status); + return status; + } + m_debugged_process_sp = *process_or; } - if (!error.Success()) { - fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__, - m_process_launch_info.GetArguments().GetArgumentAtIndex(0)); - return error; - } - // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol // as needed. // llgs local-process debugging may specify PTY paths, which will make these // file actions non-null // process launch -i/e/o will also make these file actions non-null // nullptr means that the traffic is expected to flow over gdb-remote protocol if (should_forward_stdio) { // nullptr means it's not redirected to file or pty (in case of LLGS local) // at least one of stdio will be transferred pty<->gdb-remote // we need to give the pty master handle to this object to read and/or write if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " setting up stdout/stderr redirection via $O gdb-remote commands", __FUNCTION__, m_debugged_process_sp->GetID()); // Setup stdout/stderr mapping from inferior to $O auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor(); if (terminal_fd >= 0) { if (log) log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting " "inferior STDIO fd to %d", __FUNCTION__, terminal_fd); - error = SetSTDIOFileDescriptor(terminal_fd); - if (error.Fail()) - return error; + Status status = SetSTDIOFileDescriptor(terminal_fd); + if (status.Fail()) + return status; } else { if (log) log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " "inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd); } } else { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " skipping stdout/stderr redirection via $O: inferior will " "communicate over client-provided file descriptors", __FUNCTION__, m_debugged_process_sp->GetID()); } printf("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments().GetArgumentAtIndex(0), - m_process_launch_info.GetProcessID()); + m_debugged_process_sp->GetID()); - return error; + return Status(); } Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { - Status error; - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64, __FUNCTION__, pid); // Before we try to attach, make sure we aren't already monitoring something // else. if (m_debugged_process_sp && m_debugged_process_sp->GetID() != LLDB_INVALID_PROCESS_ID) return Status("cannot attach to a process %" PRIu64 " when another process with pid %" PRIu64 " is being debugged.", pid, m_debugged_process_sp->GetID()); // Try to attach. - error = NativeProcessProtocol::Attach(pid, *this, m_mainloop, - m_debugged_process_sp); - if (!error.Success()) { - fprintf(stderr, "%s: failed to attach to process %" PRIu64 ": %s", - __FUNCTION__, pid, error.AsCString()); - return error; + auto process_or = m_process_factory.Attach(pid, *this, m_mainloop); + if (!process_or) { + Status status(process_or.takeError()); + llvm::errs() << llvm::formatv("failed to attach to process {0}: {1}", pid, + status); + return status; } + m_debugged_process_sp = *process_or; // Setup stdout/stderr mapping from inferior. auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor(); if (terminal_fd >= 0) { if (log) log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting " "inferior STDIO fd to %d", __FUNCTION__, terminal_fd); - error = SetSTDIOFileDescriptor(terminal_fd); - if (error.Fail()) - return error; + Status status = SetSTDIOFileDescriptor(terminal_fd); + if (status.Fail()) + return status; } else { if (log) log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " "inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd); } printf("Attached to process %" PRIu64 "...\n", pid); - - return error; + return Status(); } void GDBRemoteCommunicationServerLLGS::InitializeDelegate( NativeProcessProtocol *process) { assert(process && "process cannot be NULL"); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) { log->Printf("GDBRemoteCommunicationServerLLGS::%s called with " "NativeProcessProtocol pid %" PRIu64 ", current state: %s", __FUNCTION__, process->GetID(), StateAsCString(process->GetState())); } } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::SendWResponse( NativeProcessProtocol *process) { assert(process && "process cannot be NULL"); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); // send W notification auto wait_status = process->GetExitStatus(); if (!wait_status) { LLDB_LOG(log, "pid = {0}, failed to retrieve process exit status", process->GetID()); StreamGDBRemote response; response.PutChar('E'); response.PutHex8(GDBRemoteServerError::eErrorExitStatus); return SendPacketNoLock(response.GetString()); } LLDB_LOG(log, "pid = {0}, returning exit type {1}", process->GetID(), *wait_status); StreamGDBRemote response; response.Format("{0:g}", *wait_status); return SendPacketNoLock(response.GetString()); } static void AppendHexValue(StreamString &response, const uint8_t *buf, uint32_t buf_size, bool swap) { int64_t i; if (swap) { for (i = buf_size - 1; i >= 0; i--) response.PutHex8(buf[i]); } else { for (i = 0; i < buf_size; i++) response.PutHex8(buf[i]); } } static void WriteRegisterValueInHexFixedWidth( StreamString &response, NativeRegisterContextSP ®_ctx_sp, const RegisterInfo ®_info, const RegisterValue *reg_value_p, lldb::ByteOrder byte_order) { RegisterValue reg_value; if (!reg_value_p) { Status error = reg_ctx_sp->ReadRegister(®_info, reg_value); if (error.Success()) reg_value_p = ®_value; // else log. } if (reg_value_p) { AppendHexValue(response, (const uint8_t *)reg_value_p->GetBytes(), reg_value_p->GetByteSize(), byte_order == lldb::eByteOrderLittle); } else { // Zero-out any unreadable values. if (reg_info.byte_size > 0) { std::basic_string zeros(reg_info.byte_size, '\0'); AppendHexValue(response, zeros.data(), zeros.size(), false); } } } static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); NativeRegisterContextSP reg_ctx_sp = thread.GetRegisterContext(); if (!reg_ctx_sp) return nullptr; JSONObject::SP register_object_sp = std::make_shared(); #ifdef LLDB_JTHREADSINFO_FULL_REGISTER_SET // Expedite all registers in the first register set (i.e. should be GPRs) that // are not contained in other registers. const RegisterSet *reg_set_p = reg_ctx_sp->GetRegisterSet(0); if (!reg_set_p) return nullptr; for (const uint32_t *reg_num_p = reg_set_p->registers; *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) { uint32_t reg_num = *reg_num_p; #else // Expedite only a couple of registers until we figure out why sending // registers is // expensive. static const uint32_t k_expedited_registers[] = { LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM}; for (const uint32_t *generic_reg_p = k_expedited_registers; *generic_reg_p != LLDB_INVALID_REGNUM; ++generic_reg_p) { uint32_t reg_num = reg_ctx_sp->ConvertRegisterKindToRegisterNumber( eRegisterKindGeneric, *generic_reg_p); if (reg_num == LLDB_INVALID_REGNUM) continue; // Target does not support the given register. #endif const RegisterInfo *const reg_info_p = reg_ctx_sp->GetRegisterInfoAtIndex(reg_num); if (reg_info_p == nullptr) { if (log) log->Printf( "%s failed to get register info for register index %" PRIu32, __FUNCTION__, reg_num); continue; } if (reg_info_p->value_regs != nullptr) continue; // Only expedite registers that are not contained in other // registers. RegisterValue reg_value; Status error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value); if (error.Fail()) { if (log) log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s", __FUNCTION__, reg_info_p->name ? reg_info_p->name : "", reg_num, error.AsCString()); continue; } StreamString stream; WriteRegisterValueInHexFixedWidth(stream, reg_ctx_sp, *reg_info_p, ®_value, lldb::eByteOrderBig); register_object_sp->SetObject( llvm::to_string(reg_num), std::make_shared(stream.GetString())); } return register_object_sp; } static const char *GetStopReasonString(StopReason stop_reason) { switch (stop_reason) { case eStopReasonTrace: return "trace"; case eStopReasonBreakpoint: return "breakpoint"; case eStopReasonWatchpoint: return "watchpoint"; case eStopReasonSignal: return "signal"; case eStopReasonException: return "exception"; case eStopReasonExec: return "exec"; case eStopReasonInstrumentation: case eStopReasonInvalid: case eStopReasonPlanComplete: case eStopReasonThreadExiting: case eStopReasonNone: break; // ignored } return nullptr; } static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process, bool abridged) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); JSONArray::SP threads_array_sp = std::make_shared(); // Ensure we can get info on the given thread. uint32_t thread_idx = 0; for (NativeThreadProtocolSP thread_sp; (thread_sp = process.GetThreadAtIndex(thread_idx)) != nullptr; ++thread_idx) { lldb::tid_t tid = thread_sp->GetID(); // Grab the reason this thread stopped. struct ThreadStopInfo tid_stop_info; std::string description; if (!thread_sp->GetStopReason(tid_stop_info, description)) return nullptr; const int signum = tid_stop_info.details.signal.signo; if (log) { log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " got signal signo = %d, reason = %d, exc_type = %" PRIu64, __FUNCTION__, process.GetID(), tid, signum, tid_stop_info.reason, tid_stop_info.details.exception.type); } JSONObject::SP thread_obj_sp = std::make_shared(); threads_array_sp->AppendObject(thread_obj_sp); if (!abridged) { if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp)) thread_obj_sp->SetObject("registers", registers_sp); } thread_obj_sp->SetObject("tid", std::make_shared(tid)); if (signum != 0) thread_obj_sp->SetObject("signal", std::make_shared(signum)); const std::string thread_name = thread_sp->GetName(); if (!thread_name.empty()) thread_obj_sp->SetObject("name", std::make_shared(thread_name)); if (const char *stop_reason_str = GetStopReasonString(tid_stop_info.reason)) thread_obj_sp->SetObject("reason", std::make_shared(stop_reason_str)); if (!description.empty()) thread_obj_sp->SetObject("description", std::make_shared(description)); if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type) { thread_obj_sp->SetObject( "metype", std::make_shared(tid_stop_info.details.exception.type)); JSONArray::SP medata_array_sp = std::make_shared(); for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i) { medata_array_sp->AppendObject(std::make_shared( tid_stop_info.details.exception.data[i])); } thread_obj_sp->SetObject("medata", medata_array_sp); } // TODO: Expedite interesting regions of inferior memory } return threads_array_sp; } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( lldb::tid_t tid) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); // Ensure we have a debugged process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(50); if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s preparing packet for pid %" PRIu64 " tid %" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID(), tid); // Ensure we can get info on the given thread. NativeThreadProtocolSP thread_sp(m_debugged_process_sp->GetThreadByID(tid)); if (!thread_sp) return SendErrorResponse(51); // Grab the reason this thread stopped. struct ThreadStopInfo tid_stop_info; std::string description; if (!thread_sp->GetStopReason(tid_stop_info, description)) return SendErrorResponse(52); // FIXME implement register handling for exec'd inferiors. // if (tid_stop_info.reason == eStopReasonExec) // { // const bool force = true; // InitializeRegisters(force); // } StreamString response; // Output the T packet with the thread response.PutChar('T'); int signum = tid_stop_info.details.signal.signo; if (log) { log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " got signal signo = %d, reason = %d, exc_type = %" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID(), tid, signum, tid_stop_info.reason, tid_stop_info.details.exception.type); } // Print the signal number. response.PutHex8(signum & 0xff); // Include the tid. response.Printf("thread:%" PRIx64 ";", tid); // Include the thread name if there is one. const std::string thread_name = thread_sp->GetName(); if (!thread_name.empty()) { size_t thread_name_len = thread_name.length(); if (::strcspn(thread_name.c_str(), "$#+-;:") == thread_name_len) { response.PutCString("name:"); response.PutCString(thread_name); } else { // The thread name contains special chars, send as hex bytes. response.PutCString("hexname:"); response.PutCStringAsRawHex8(thread_name.c_str()); } response.PutChar(';'); } // 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) { response.PutCString("threads:"); uint32_t thread_index = 0; NativeThreadProtocolSP listed_thread_sp; for (listed_thread_sp = m_debugged_process_sp->GetThreadAtIndex(thread_index); listed_thread_sp; ++thread_index, listed_thread_sp = m_debugged_process_sp->GetThreadAtIndex( thread_index)) { if (thread_index > 0) response.PutChar(','); response.Printf("%" PRIx64, listed_thread_sp->GetID()); } response.PutChar(';'); // 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 (thread_index > 0) { const bool threads_with_valid_stop_info_only = true; JSONArray::SP threads_info_sp = GetJSONThreadsInfo( *m_debugged_process_sp, threads_with_valid_stop_info_only); if (threads_info_sp) { response.PutCString("jstopinfo:"); StreamString unescaped_response; threads_info_sp->Write(unescaped_response); response.PutCStringAsRawHex8(unescaped_response.GetData()); response.PutChar(';'); } else if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to prepare a " "jstopinfo field for pid %" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID()); } uint32_t i = 0; response.PutCString("thread-pcs"); char delimiter = ':'; for (NativeThreadProtocolSP thread_sp; (thread_sp = m_debugged_process_sp->GetThreadAtIndex(i)) != nullptr; ++i) { NativeRegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); if (!reg_ctx_sp) continue; uint32_t reg_to_read = reg_ctx_sp->ConvertRegisterKindToRegisterNumber( eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); const RegisterInfo *const reg_info_p = reg_ctx_sp->GetRegisterInfoAtIndex(reg_to_read); RegisterValue reg_value; Status error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value); if (error.Fail()) { if (log) log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s", __FUNCTION__, reg_info_p->name ? reg_info_p->name : "", reg_to_read, error.AsCString()); continue; } response.PutChar(delimiter); delimiter = ','; WriteRegisterValueInHexFixedWidth(response, reg_ctx_sp, *reg_info_p, ®_value, endian::InlHostByteOrder()); } response.PutChar(';'); } // // Expedite registers. // // Grab the register context. NativeRegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); if (reg_ctx_sp) { // Expedite all registers in the first register set (i.e. should be GPRs) // that are not contained in other registers. const RegisterSet *reg_set_p; if (reg_ctx_sp->GetRegisterSetCount() > 0 && ((reg_set_p = reg_ctx_sp->GetRegisterSet(0)) != nullptr)) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s expediting registers " "from set '%s' (registers set count: %zu)", __FUNCTION__, reg_set_p->name ? reg_set_p->name : "", reg_set_p->num_registers); for (const uint32_t *reg_num_p = reg_set_p->registers; *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) { const RegisterInfo *const reg_info_p = reg_ctx_sp->GetRegisterInfoAtIndex(*reg_num_p); if (reg_info_p == nullptr) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to get " "register info for register set '%s', register index " "%" PRIu32, __FUNCTION__, reg_set_p->name ? reg_set_p->name : "", *reg_num_p); } else if (reg_info_p->value_regs == nullptr) { // Only expediate registers that are not contained in other registers. RegisterValue reg_value; Status error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value); if (error.Success()) { response.Printf("%.02x:", *reg_num_p); WriteRegisterValueInHexFixedWidth(response, reg_ctx_sp, *reg_info_p, ®_value, lldb::eByteOrderBig); response.PutChar(';'); } else { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to read " "register '%s' index %" PRIu32 ": %s", __FUNCTION__, reg_info_p->name ? reg_info_p->name : "", *reg_num_p, error.AsCString()); } } } } } const char *reason_str = GetStopReasonString(tid_stop_info.reason); if (reason_str != nullptr) { response.Printf("reason:%s;", reason_str); } if (!description.empty()) { // Description may contains special chars, send as hex bytes. response.PutCString("description:"); response.PutCStringAsRawHex8(description.c_str()); response.PutChar(';'); } else if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type) { response.PutCString("metype:"); response.PutHex64(tid_stop_info.details.exception.type); response.PutCString(";mecount:"); response.PutHex32(tid_stop_info.details.exception.data_count); response.PutChar(';'); for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i) { response.PutCString("medata:"); response.PutHex64(tid_stop_info.details.exception.data[i]); response.PutChar(';'); } } return SendPacketNoLock(response.GetString()); } void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited( NativeProcessProtocol *process) { assert(process && "process cannot be NULL"); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); PacketResult result = SendStopReasonForState(StateType::eStateExited); if (result != PacketResult::Success) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to send stop " "notification for PID %" PRIu64 ", state: eStateExited", __FUNCTION__, process->GetID()); } // Close the pipe to the inferior terminal i/o if we launched it // and set one up. MaybeCloseInferiorTerminalConnection(); // We are ready to exit the debug monitor. m_exit_now = true; } void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped( NativeProcessProtocol *process) { assert(process && "process cannot be NULL"); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); // Send the stop reason unless this is the stop after the // launch or attach. switch (m_inferior_prev_state) { case eStateLaunching: case eStateAttaching: // Don't send anything per debugserver behavior. break; default: // In all other cases, send the stop reason. PacketResult result = SendStopReasonForState(StateType::eStateStopped); if (result != PacketResult::Success) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to send stop " "notification for PID %" PRIu64 ", state: eStateExited", __FUNCTION__, process->GetID()); } break; } } void GDBRemoteCommunicationServerLLGS::ProcessStateChanged( NativeProcessProtocol *process, lldb::StateType state) { assert(process && "process cannot be NULL"); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) { log->Printf("GDBRemoteCommunicationServerLLGS::%s called with " "NativeProcessProtocol pid %" PRIu64 ", state: %s", __FUNCTION__, process->GetID(), StateAsCString(state)); } switch (state) { case StateType::eStateRunning: StartSTDIOForwarding(); break; case StateType::eStateStopped: // Make sure we get all of the pending stdout/stderr from the inferior // and send it to the lldb host before we send the state change // notification SendProcessOutput(); // Then stop the forwarding, so that any late output (see llvm.org/pr25652) // does not // interfere with our protocol. StopSTDIOForwarding(); HandleInferiorState_Stopped(process); break; case StateType::eStateExited: // Same as above SendProcessOutput(); StopSTDIOForwarding(); HandleInferiorState_Exited(process); break; default: if (log) { log->Printf("GDBRemoteCommunicationServerLLGS::%s didn't handle state " "change for pid %" PRIu64 ", new state: %s", __FUNCTION__, process->GetID(), StateAsCString(state)); } break; } // Remember the previous state reported to us. m_inferior_prev_state = state; } void GDBRemoteCommunicationServerLLGS::DidExec(NativeProcessProtocol *process) { ClearProcessSpecificData(); } void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() { Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_COMM)); if (!m_handshake_completed) { if (!HandshakeWithClient()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s handshake with " "client failed, exiting", __FUNCTION__); m_mainloop.RequestTermination(); return; } m_handshake_completed = true; } bool interrupt = false; bool done = false; Status error; while (true) { const PacketResult result = GetPacketAndSendResponse( std::chrono::microseconds(0), error, interrupt, done); if (result == PacketResult::ErrorReplyTimeout) break; // No more packets in the queue if ((result != PacketResult::Success)) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s processing a packet " "failed: %s", __FUNCTION__, error.AsCString()); m_mainloop.RequestTermination(); break; } } } Status GDBRemoteCommunicationServerLLGS::InitializeConnection( std::unique_ptr &&connection) { IOObjectSP read_object_sp = connection->GetReadObject(); GDBRemoteCommunicationServer::SetConnection(connection.release()); Status error; m_network_handle_up = m_mainloop.RegisterReadObject( read_object_sp, [this](MainLoopBase &) { DataAvailableCallback(); }, error); return error; } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::SendONotification(const char *buffer, uint32_t len) { if ((buffer == nullptr) || (len == 0)) { // Nothing to send. return PacketResult::Success; } StreamString response; response.PutChar('O'); response.PutBytesAsRawHex8(buffer, len); return SendPacketNoLock(response.GetString()); } Status GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor(int fd) { Status error; // Set up the reading/handling of process I/O std::unique_ptr conn_up( new ConnectionFileDescriptor(fd, true)); if (!conn_up) { error.SetErrorString("failed to create ConnectionFileDescriptor"); return error; } m_stdio_communication.SetCloseOnEOF(false); m_stdio_communication.SetConnection(conn_up.release()); if (!m_stdio_communication.IsConnected()) { error.SetErrorString( "failed to set connection for inferior I/O communication"); return error; } return Status(); } void GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding() { // Don't forward if not connected (e.g. when attaching). if (!m_stdio_communication.IsConnected()) return; Status error; lldbassert(!m_stdio_handle_up); m_stdio_handle_up = m_mainloop.RegisterReadObject( m_stdio_communication.GetConnection()->GetReadObject(), [this](MainLoopBase &) { SendProcessOutput(); }, error); if (!m_stdio_handle_up) { // Not much we can do about the failure. Log it and continue without // forwarding. if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)) log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to set up stdio " "forwarding: %s", __FUNCTION__, error.AsCString()); } } void GDBRemoteCommunicationServerLLGS::StopSTDIOForwarding() { m_stdio_handle_up.reset(); } void GDBRemoteCommunicationServerLLGS::SendProcessOutput() { char buffer[1024]; ConnectionStatus status; Status error; while (true) { size_t bytes_read = m_stdio_communication.Read( buffer, sizeof buffer, std::chrono::microseconds(0), status, &error); switch (status) { case eConnectionStatusSuccess: SendONotification(buffer, bytes_read); break; case eConnectionStatusLostConnection: case eConnectionStatusEndOfFile: case eConnectionStatusError: case eConnectionStatusNoConnection: if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)) log->Printf("GDBRemoteCommunicationServerLLGS::%s Stopping stdio " "forwarding as communication returned status %d (error: " "%s)", __FUNCTION__, status, error.AsCString()); m_stdio_handle_up.reset(); return; case eConnectionStatusInterrupted: case eConnectionStatusTimedOut: return; } } } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_jTraceStart( StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); // Fail if we don't have a current process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(68); if (!packet.ConsumeFront("jTraceStart:")) return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet "); TraceOptions options; uint64_t type = std::numeric_limits::max(); uint64_t buffersize = std::numeric_limits::max(); lldb::tid_t tid = LLDB_INVALID_THREAD_ID; uint64_t metabuffersize = std::numeric_limits::max(); auto json_object = StructuredData::ParseJSON(packet.Peek()); if (!json_object || json_object->GetType() != lldb::eStructuredDataTypeDictionary) return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet "); auto json_dict = json_object->GetAsDictionary(); json_dict->GetValueForKeyAsInteger("metabuffersize", metabuffersize); options.setMetaDataBufferSize(metabuffersize); json_dict->GetValueForKeyAsInteger("buffersize", buffersize); options.setTraceBufferSize(buffersize); json_dict->GetValueForKeyAsInteger("type", type); options.setType(static_cast(type)); json_dict->GetValueForKeyAsInteger("threadid", tid); options.setThreadID(tid); StructuredData::ObjectSP custom_params_sp = json_dict->GetValueForKey("params"); if (custom_params_sp && custom_params_sp->GetType() != lldb::eStructuredDataTypeDictionary) return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet "); options.setTraceParams( static_pointer_cast(custom_params_sp)); if (buffersize == std::numeric_limits::max() || type != lldb::TraceType::eTraceTypeProcessorTrace) { LLDB_LOG(log, "Ill formed packet buffersize = {0} type = {1}", buffersize, type); return SendIllFormedResponse(packet, "JTrace:start: Ill formed packet "); } Status error; lldb::user_id_t uid = LLDB_INVALID_UID; uid = m_debugged_process_sp->StartTrace(options, error); LLDB_LOG(log, "uid is {0} , error is {1}", uid, error.GetError()); if (error.Fail()) - return SendErrorResponse(error.GetError()); + return SendErrorResponse(error); StreamGDBRemote response; response.Printf("%" PRIx64, uid); return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_jTraceStop( StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(68); if (!packet.ConsumeFront("jTraceStop:")) return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet "); lldb::user_id_t uid = LLDB_INVALID_UID; lldb::tid_t tid = LLDB_INVALID_THREAD_ID; auto json_object = StructuredData::ParseJSON(packet.Peek()); if (!json_object || json_object->GetType() != lldb::eStructuredDataTypeDictionary) return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet "); auto json_dict = json_object->GetAsDictionary(); if (!json_dict->GetValueForKeyAsInteger("traceid", uid)) return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet "); json_dict->GetValueForKeyAsInteger("threadid", tid); Status error = m_debugged_process_sp->StopTrace(uid, tid); if (error.Fail()) - return SendErrorResponse(error.GetError()); + return SendErrorResponse(error); return SendOKResponse(); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead( StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(68); if (!packet.ConsumeFront("jTraceConfigRead:")) return SendIllFormedResponse(packet, "jTraceConfigRead: Ill formed packet "); lldb::user_id_t uid = LLDB_INVALID_UID; lldb::tid_t threadid = LLDB_INVALID_THREAD_ID; auto json_object = StructuredData::ParseJSON(packet.Peek()); if (!json_object || json_object->GetType() != lldb::eStructuredDataTypeDictionary) return SendIllFormedResponse(packet, "jTraceConfigRead: Ill formed packet "); auto json_dict = json_object->GetAsDictionary(); if (!json_dict->GetValueForKeyAsInteger("traceid", uid)) return SendIllFormedResponse(packet, "jTraceConfigRead: Ill formed packet "); json_dict->GetValueForKeyAsInteger("threadid", threadid); TraceOptions options; StreamGDBRemote response; options.setThreadID(threadid); Status error = m_debugged_process_sp->GetTraceConfig(uid, options); if (error.Fail()) - return SendErrorResponse(error.GetError()); + return SendErrorResponse(error); StreamGDBRemote escaped_response; StructuredData::Dictionary json_packet; json_packet.AddIntegerItem("type", options.getType()); json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize()); json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize()); StructuredData::DictionarySP custom_params = options.getTraceParams(); if (custom_params) json_packet.AddItem("params", custom_params); StreamString json_string; json_packet.Dump(json_string, false); escaped_response.PutEscapedBytes(json_string.GetData(), json_string.GetSize()); return SendPacketNoLock(escaped_response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_jTraceRead( StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(68); enum PacketType { MetaData, BufferData }; PacketType tracetype = MetaData; if (packet.ConsumeFront("jTraceBufferRead:")) tracetype = BufferData; else if (packet.ConsumeFront("jTraceMetaRead:")) tracetype = MetaData; else { return SendIllFormedResponse(packet, "jTrace: Ill formed packet "); } lldb::user_id_t uid = LLDB_INVALID_UID; uint64_t byte_count = std::numeric_limits::max(); lldb::tid_t tid = LLDB_INVALID_THREAD_ID; uint64_t offset = std::numeric_limits::max(); auto json_object = StructuredData::ParseJSON(packet.Peek()); if (!json_object || json_object->GetType() != lldb::eStructuredDataTypeDictionary) return SendIllFormedResponse(packet, "jTrace: Ill formed packet "); auto json_dict = json_object->GetAsDictionary(); if (!json_dict->GetValueForKeyAsInteger("traceid", uid) || !json_dict->GetValueForKeyAsInteger("offset", offset) || !json_dict->GetValueForKeyAsInteger("buffersize", byte_count)) return SendIllFormedResponse(packet, "jTrace: Ill formed packet "); json_dict->GetValueForKeyAsInteger("threadid", tid); // Allocate the response buffer. std::unique_ptr buffer (new (std::nothrow) uint8_t[byte_count]); if (!buffer) return SendErrorResponse(0x78); StreamGDBRemote response; Status error; llvm::MutableArrayRef buf(buffer.get(), byte_count); if (tracetype == BufferData) error = m_debugged_process_sp->GetData(uid, tid, buf, offset); else if (tracetype == MetaData) error = m_debugged_process_sp->GetMetaData(uid, tid, buf, offset); if (error.Fail()) - return SendErrorResponse(error.GetError()); + return SendErrorResponse(error); for (auto i : buf) response.PutHex8(i); StreamGDBRemote escaped_response; escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); return SendPacketNoLock(escaped_response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo( StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(68); lldb::pid_t pid = m_debugged_process_sp->GetID(); if (pid == LLDB_INVALID_PROCESS_ID) return SendErrorResponse(1); ProcessInstanceInfo proc_info; if (!Host::GetProcessInfo(pid, proc_info)) return SendErrorResponse(1); StreamString response; CreateProcessInfoResponse_DebugServerStyle(proc_info, response); return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(68); // Make sure we set the current thread so g and p packets return // the data the gdb will expect. lldb::tid_t tid = m_debugged_process_sp->GetCurrentThreadID(); SetCurrentThreadID(tid); NativeThreadProtocolSP thread_sp = m_debugged_process_sp->GetCurrentThread(); if (!thread_sp) return SendErrorResponse(69); StreamString response; response.Printf("QC%" PRIx64, thread_sp->GetID()); return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); StopSTDIOForwarding(); if (!m_debugged_process_sp) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s No debugged process found.", __FUNCTION__); return PacketResult::Success; } Status error = m_debugged_process_sp->Kill(); if (error.Fail() && log) log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to kill debugged " "process %" PRIu64 ": %s", __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString()); // No OK response for kill packet. // return SendOKResponse (); return PacketResult::Success; } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("QSetDisableASLR:")); if (packet.GetU32(0)) m_process_launch_info.GetFlags().Set(eLaunchFlagDisableASLR); else m_process_launch_info.GetFlags().Clear(eLaunchFlagDisableASLR); return SendOKResponse(); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("QSetWorkingDir:")); std::string path; packet.GetHexByteString(path); m_process_launch_info.SetWorkingDirectory(FileSpec{path, true}); return SendOKResponse(); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir( StringExtractorGDBRemote &packet) { FileSpec working_dir{m_process_launch_info.GetWorkingDirectory()}; if (working_dir) { StreamString response; response.PutCStringAsRawHex8(working_dir.GetCString()); return SendPacketNoLock(response.GetString()); } return SendErrorResponse(14); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); // Ensure we have a native process. if (!m_debugged_process_sp) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process " "shared pointer", __FUNCTION__); return SendErrorResponse(0x36); } // Pull out the signal number. packet.SetFilePos(::strlen("C")); if (packet.GetBytesLeft() < 1) { // Shouldn't be using a C without a signal. return SendIllFormedResponse(packet, "C packet specified without signal."); } const uint32_t signo = packet.GetHexMaxU32(false, std::numeric_limits::max()); if (signo == std::numeric_limits::max()) return SendIllFormedResponse(packet, "failed to parse signal number"); // Handle optional continue address. if (packet.GetBytesLeft() > 0) { // FIXME add continue at address support for $C{signo}[;{continue-address}]. if (*packet.Peek() == ';') return SendUnimplementedResponse(packet.GetStringRef().c_str()); else return SendIllFormedResponse( packet, "unexpected content after $C{signal-number}"); } ResumeActionList resume_actions(StateType::eStateRunning, 0); Status error; // We have two branches: what to do if a continue thread is specified (in // which case we target // sending the signal to that thread), or when we don't have a continue thread // set (in which // case we send a signal to the process). // TODO discuss with Greg Clayton, make sure this makes sense. lldb::tid_t signal_tid = GetContinueThreadID(); if (signal_tid != LLDB_INVALID_THREAD_ID) { // The resume action for the continue thread (or all threads if a continue // thread is not set). ResumeAction action = {GetContinueThreadID(), StateType::eStateRunning, static_cast(signo)}; // Add the action for the continue thread (or all threads when the continue // thread isn't present). resume_actions.Append(action); } else { // Send the signal to the process since we weren't targeting a specific // continue thread with the signal. error = m_debugged_process_sp->Signal(signo); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to send " "signal for process %" PRIu64 ": %s", __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString()); return SendErrorResponse(0x52); } } // Resume the threads. error = m_debugged_process_sp->Resume(resume_actions); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to resume " "threads for process %" PRIu64 ": %s", __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString()); return SendErrorResponse(0x38); } // Don't send an "OK" packet; response is the stopped/exited message. return PacketResult::Success; } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); packet.SetFilePos(packet.GetFilePos() + ::strlen("c")); // For now just support all continue. const bool has_continue_address = (packet.GetBytesLeft() > 0); if (has_continue_address) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s not implemented for " "c{address} variant [%s remains]", __FUNCTION__, packet.Peek()); return SendUnimplementedResponse(packet.GetStringRef().c_str()); } // Ensure we have a native process. if (!m_debugged_process_sp) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process " "shared pointer", __FUNCTION__); return SendErrorResponse(0x36); } // Build the ResumeActionList ResumeActionList actions(StateType::eStateRunning, 0); Status error = m_debugged_process_sp->Resume(actions); if (error.Fail()) { if (log) { log->Printf( "GDBRemoteCommunicationServerLLGS::%s c failed for process %" PRIu64 ": %s", __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString()); } return SendErrorResponse(GDBRemoteServerError::eErrorResume); } if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s continued process %" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID()); // No response required from continue. return PacketResult::Success; } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_vCont_actions( StringExtractorGDBRemote &packet) { StreamString response; response.Printf("vCont;c;C;s;S"); return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_vCont( StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s handling vCont packet", __FUNCTION__); packet.SetFilePos(::strlen("vCont")); if (packet.GetBytesLeft() == 0) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s missing action from " "vCont package", __FUNCTION__); return SendIllFormedResponse(packet, "Missing action from vCont package"); } // Check if this is all continue (no options or ";c"). if (::strcmp(packet.Peek(), ";c") == 0) { // Move past the ';', then do a simple 'c'. packet.SetFilePos(packet.GetFilePos() + 1); return Handle_c(packet); } else if (::strcmp(packet.Peek(), ";s") == 0) { // Move past the ';', then do a simple 's'. packet.SetFilePos(packet.GetFilePos() + 1); return Handle_s(packet); } // Ensure we have a native process. if (!m_debugged_process_sp) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process " "shared pointer", __FUNCTION__); return SendErrorResponse(0x36); } ResumeActionList thread_actions; while (packet.GetBytesLeft() && *packet.Peek() == ';') { // Skip the semi-colon. packet.GetChar(); // Build up the thread action. ResumeAction thread_action; thread_action.tid = LLDB_INVALID_THREAD_ID; thread_action.state = eStateInvalid; thread_action.signal = 0; const char action = packet.GetChar(); switch (action) { case 'C': thread_action.signal = packet.GetHexMaxU32(false, 0); if (thread_action.signal == 0) return SendIllFormedResponse( packet, "Could not parse signal in vCont packet C action"); LLVM_FALLTHROUGH; case 'c': // Continue thread_action.state = eStateRunning; break; case 'S': thread_action.signal = packet.GetHexMaxU32(false, 0); if (thread_action.signal == 0) return SendIllFormedResponse( packet, "Could not parse signal in vCont packet S action"); LLVM_FALLTHROUGH; case 's': // Step thread_action.state = eStateStepping; break; default: return SendIllFormedResponse(packet, "Unsupported vCont action"); break; } // Parse out optional :{thread-id} value. if (packet.GetBytesLeft() && (*packet.Peek() == ':')) { // Consume the separator. packet.GetChar(); thread_action.tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID); if (thread_action.tid == LLDB_INVALID_THREAD_ID) return SendIllFormedResponse( packet, "Could not parse thread number in vCont packet"); } thread_actions.Append(thread_action); } Status error = m_debugged_process_sp->Resume(thread_actions); if (error.Fail()) { if (log) { log->Printf("GDBRemoteCommunicationServerLLGS::%s vCont failed for " "process %" PRIu64 ": %s", __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString()); } return SendErrorResponse(GDBRemoteServerError::eErrorResume); } if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s continued process %" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID()); // No response required from vCont. return PacketResult::Success; } void GDBRemoteCommunicationServerLLGS::SetCurrentThreadID(lldb::tid_t tid) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s setting current thread " "id to %" PRIu64, __FUNCTION__, tid); m_current_tid = tid; if (m_debugged_process_sp) m_debugged_process_sp->SetCurrentThreadID(m_current_tid); } void GDBRemoteCommunicationServerLLGS::SetContinueThreadID(lldb::tid_t tid) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s setting continue thread " "id to %" PRIu64, __FUNCTION__, tid); m_continue_tid = tid; } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_stop_reason( StringExtractorGDBRemote &packet) { // Handle the $? gdbremote command. // If no process, indicate error if (!m_debugged_process_sp) return SendErrorResponse(02); return SendStopReasonForState(m_debugged_process_sp->GetState()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::SendStopReasonForState( lldb::StateType process_state) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); switch (process_state) { case eStateAttaching: case eStateLaunching: case eStateRunning: case eStateStepping: case eStateDetached: // NOTE: gdb protocol doc looks like it should return $OK // when everything is running (i.e. no stopped result). return PacketResult::Success; // Ignore case eStateSuspended: case eStateStopped: case eStateCrashed: { lldb::tid_t tid = m_debugged_process_sp->GetCurrentThreadID(); // Make sure we set the current thread so g and p packets return // the data the gdb will expect. SetCurrentThreadID(tid); return SendStopReplyPacketForThread(tid); } case eStateInvalid: case eStateUnloaded: case eStateExited: return SendWResponse(m_debugged_process_sp.get()); default: if (log) { log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 ", current state reporting not handled: %s", __FUNCTION__, m_debugged_process_sp->GetID(), StateAsCString(process_state)); } break; } return SendErrorResponse(0); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo( StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(68); // Ensure we have a thread. NativeThreadProtocolSP thread_sp(m_debugged_process_sp->GetThreadAtIndex(0)); if (!thread_sp) return SendErrorResponse(69); // Get the register context for the first thread. NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); if (!reg_context_sp) return SendErrorResponse(69); // Parse out the register number from the request. packet.SetFilePos(strlen("qRegisterInfo")); const uint32_t reg_index = packet.GetHexMaxU32(false, std::numeric_limits::max()); if (reg_index == std::numeric_limits::max()) return SendErrorResponse(69); // Return the end of registers response if we've iterated one past the end of // the register set. if (reg_index >= reg_context_sp->GetUserRegisterCount()) return SendErrorResponse(69); const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex(reg_index); if (!reg_info) return SendErrorResponse(69); // Build the reginfos response. StreamGDBRemote response; response.PutCString("name:"); response.PutCString(reg_info->name); response.PutChar(';'); if (reg_info->alt_name && reg_info->alt_name[0]) { response.PutCString("alt-name:"); response.PutCString(reg_info->alt_name); response.PutChar(';'); } response.Printf("bitsize:%" PRIu32 ";offset:%" PRIu32 ";", reg_info->byte_size * 8, reg_info->byte_offset); switch (reg_info->encoding) { case eEncodingUint: response.PutCString("encoding:uint;"); break; case eEncodingSint: response.PutCString("encoding:sint;"); break; case eEncodingIEEE754: response.PutCString("encoding:ieee754;"); break; case eEncodingVector: response.PutCString("encoding:vector;"); break; default: break; } switch (reg_info->format) { case eFormatBinary: response.PutCString("format:binary;"); break; case eFormatDecimal: response.PutCString("format:decimal;"); break; case eFormatHex: response.PutCString("format:hex;"); break; case eFormatFloat: response.PutCString("format:float;"); break; case eFormatVectorOfSInt8: response.PutCString("format:vector-sint8;"); break; case eFormatVectorOfUInt8: response.PutCString("format:vector-uint8;"); break; case eFormatVectorOfSInt16: response.PutCString("format:vector-sint16;"); break; case eFormatVectorOfUInt16: response.PutCString("format:vector-uint16;"); break; case eFormatVectorOfSInt32: response.PutCString("format:vector-sint32;"); break; case eFormatVectorOfUInt32: response.PutCString("format:vector-uint32;"); break; case eFormatVectorOfFloat32: response.PutCString("format:vector-float32;"); break; case eFormatVectorOfUInt64: response.PutCString("format:vector-uint64;"); break; case eFormatVectorOfUInt128: response.PutCString("format:vector-uint128;"); break; default: break; }; const char *const register_set_name = reg_context_sp->GetRegisterSetNameForRegisterAtIndex(reg_index); if (register_set_name) { response.PutCString("set:"); response.PutCString(register_set_name); response.PutChar(';'); } if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) response.Printf("ehframe:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindEHFrame]); if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] != LLDB_INVALID_REGNUM) response.Printf("dwarf:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindDWARF]); switch (reg_info->kinds[RegisterKind::eRegisterKindGeneric]) { case LLDB_REGNUM_GENERIC_PC: response.PutCString("generic:pc;"); break; case LLDB_REGNUM_GENERIC_SP: response.PutCString("generic:sp;"); break; case LLDB_REGNUM_GENERIC_FP: response.PutCString("generic:fp;"); break; case LLDB_REGNUM_GENERIC_RA: response.PutCString("generic:ra;"); break; case LLDB_REGNUM_GENERIC_FLAGS: response.PutCString("generic:flags;"); break; case LLDB_REGNUM_GENERIC_ARG1: response.PutCString("generic:arg1;"); break; case LLDB_REGNUM_GENERIC_ARG2: response.PutCString("generic:arg2;"); break; case LLDB_REGNUM_GENERIC_ARG3: response.PutCString("generic:arg3;"); break; case LLDB_REGNUM_GENERIC_ARG4: response.PutCString("generic:arg4;"); break; case LLDB_REGNUM_GENERIC_ARG5: response.PutCString("generic:arg5;"); break; case LLDB_REGNUM_GENERIC_ARG6: response.PutCString("generic:arg6;"); break; case LLDB_REGNUM_GENERIC_ARG7: response.PutCString("generic:arg7;"); break; case LLDB_REGNUM_GENERIC_ARG8: response.PutCString("generic:arg8;"); break; default: break; } if (reg_info->value_regs && reg_info->value_regs[0] != LLDB_INVALID_REGNUM) { response.PutCString("container-regs:"); int i = 0; for (const uint32_t *reg_num = reg_info->value_regs; *reg_num != LLDB_INVALID_REGNUM; ++reg_num, ++i) { if (i > 0) response.PutChar(','); response.Printf("%" PRIx32, *reg_num); } response.PutChar(';'); } if (reg_info->invalidate_regs && reg_info->invalidate_regs[0]) { response.PutCString("invalidate-regs:"); int i = 0; for (const uint32_t *reg_num = reg_info->invalidate_regs; *reg_num != LLDB_INVALID_REGNUM; ++reg_num, ++i) { if (i > 0) response.PutChar(','); response.Printf("%" PRIx32, *reg_num); } response.PutChar(';'); } if (reg_info->dynamic_size_dwarf_expr_bytes) { const size_t dwarf_opcode_len = reg_info->dynamic_size_dwarf_len; response.PutCString("dynamic_size_dwarf_expr_bytes:"); for (uint32_t i = 0; i < dwarf_opcode_len; ++i) response.PutHex8(reg_info->dynamic_size_dwarf_expr_bytes[i]); response.PutChar(';'); } return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo( StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); // Fail if we don't have a current process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s() no process (%s), " "returning OK", __FUNCTION__, m_debugged_process_sp ? "invalid process id" : "null m_debugged_process_sp"); return SendOKResponse(); } StreamGDBRemote response; response.PutChar('m'); if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s() starting thread iteration", __FUNCTION__); NativeThreadProtocolSP thread_sp; uint32_t thread_index; for (thread_index = 0, thread_sp = m_debugged_process_sp->GetThreadAtIndex(thread_index); thread_sp; ++thread_index, thread_sp = m_debugged_process_sp->GetThreadAtIndex(thread_index)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s() iterated thread %" PRIu32 "(%s, tid=0x%" PRIx64 ")", __FUNCTION__, thread_index, thread_sp ? "is not null" : "null", thread_sp ? thread_sp->GetID() : LLDB_INVALID_THREAD_ID); if (thread_index > 0) response.PutChar(','); response.Printf("%" PRIx64, thread_sp->GetID()); } if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s() finished thread iteration", __FUNCTION__); return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo( StringExtractorGDBRemote &packet) { // FIXME for now we return the full thread list in the initial packet and // always do nothing here. return SendPacketNoLock("l"); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); // Parse out the register number from the request. packet.SetFilePos(strlen("p")); const uint32_t reg_index = packet.GetHexMaxU32(false, std::numeric_limits::max()); if (reg_index == std::numeric_limits::max()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not " "parse register number from request \"%s\"", __FUNCTION__, packet.GetStringRef().c_str()); return SendErrorResponse(0x15); } // Get the thread to use. NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet); if (!thread_sp) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no thread available", __FUNCTION__); return SendErrorResponse(0x15); } // Get the thread's register context. NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); if (!reg_context_sp) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " failed, no register context available for the thread", __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID()); return SendErrorResponse(0x15); } // Return the end of registers response if we've iterated one past the end of // the register set. if (reg_index >= reg_context_sp->GetUserRegisterCount()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " "register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetUserRegisterCount()); return SendErrorResponse(0x15); } const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex(reg_index); if (!reg_info) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " "register %" PRIu32 " returned NULL", __FUNCTION__, reg_index); return SendErrorResponse(0x15); } // Build the reginfos response. StreamGDBRemote response; // Retrieve the value RegisterValue reg_value; Status error = reg_context_sp->ReadRegister(reg_info, reg_value); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, read of " "requested register %" PRIu32 " (%s) failed: %s", __FUNCTION__, reg_index, reg_info->name, error.AsCString()); return SendErrorResponse(0x15); } const uint8_t *const data = reinterpret_cast(reg_value.GetBytes()); if (!data) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to get data " "bytes from requested register %" PRIu32, __FUNCTION__, reg_index); return SendErrorResponse(0x15); } // FIXME flip as needed to get data in big/little endian format for this host. for (uint32_t i = 0; i < reg_value.GetByteSize(); ++i) response.PutHex8(data[i]); return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); // Ensure there is more content. if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Empty P packet"); // Parse out the register number from the request. packet.SetFilePos(strlen("P")); const uint32_t reg_index = packet.GetHexMaxU32(false, std::numeric_limits::max()); if (reg_index == std::numeric_limits::max()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not " "parse register number from request \"%s\"", __FUNCTION__, packet.GetStringRef().c_str()); return SendErrorResponse(0x29); } // Note debugserver would send an E30 here. if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != '=')) return SendIllFormedResponse( packet, "P packet missing '=' char after register number"); // Get process architecture. ArchSpec process_arch; if (!m_debugged_process_sp || !m_debugged_process_sp->GetArchitecture(process_arch)) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to retrieve " "inferior architecture", __FUNCTION__); return SendErrorResponse(0x49); } // Parse out the value. uint8_t reg_bytes[32]; // big enough to support up to 256 bit ymmN register size_t reg_size = packet.GetHexBytesAvail(reg_bytes); // Get the thread to use. NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet); if (!thread_sp) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, no thread " "available (thread index 0)", __FUNCTION__); return SendErrorResponse(0x28); } // Get the thread's register context. NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); if (!reg_context_sp) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " failed, no register context available for the thread", __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID()); return SendErrorResponse(0x15); } const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex(reg_index); if (!reg_info) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " "register %" PRIu32 " returned NULL", __FUNCTION__, reg_index); return SendErrorResponse(0x48); } // Return the end of registers response if we've iterated one past the end of // the register set. if (reg_index >= reg_context_sp->GetUserRegisterCount()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " "register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetUserRegisterCount()); return SendErrorResponse(0x47); } // The dwarf expression are evaluate on host site // which may cause register size to change // Hence the reg_size may not be same as reg_info->bytes_size if ((reg_size != reg_info->byte_size) && !(reg_info->dynamic_size_dwarf_expr_bytes)) { return SendIllFormedResponse(packet, "P packet register size is incorrect"); } // Build the reginfos response. StreamGDBRemote response; RegisterValue reg_value(reg_bytes, reg_size, process_arch.GetByteOrder()); Status error = reg_context_sp->WriteRegister(reg_info, reg_value); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, write of " "requested register %" PRIu32 " (%s) failed: %s", __FUNCTION__, reg_index, reg_info->name, error.AsCString()); return SendErrorResponse(0x32); } return SendOKResponse(); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); // Fail if we don't have a current process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); return SendErrorResponse(0x15); } // Parse out which variant of $H is requested. packet.SetFilePos(strlen("H")); if (packet.GetBytesLeft() < 1) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, H command " "missing {g,c} variant", __FUNCTION__); return SendIllFormedResponse(packet, "H command missing {g,c} variant"); } const char h_variant = packet.GetChar(); switch (h_variant) { case 'g': break; case 'c': break; default: if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, invalid $H variant %c", __FUNCTION__, h_variant); return SendIllFormedResponse(packet, "H variant unsupported, should be c or g"); } // Parse out the thread number. // FIXME return a parse success/fail value. All values are valid here. const lldb::tid_t tid = packet.GetHexMaxU64(false, std::numeric_limits::max()); // Ensure we have the given thread when not specifying -1 (all threads) or 0 // (any thread). if (tid != LLDB_INVALID_THREAD_ID && tid != 0) { NativeThreadProtocolSP thread_sp(m_debugged_process_sp->GetThreadByID(tid)); if (!thread_sp) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64 " not found", __FUNCTION__, tid); return SendErrorResponse(0x15); } } // Now switch the given thread type. switch (h_variant) { case 'g': SetCurrentThreadID(tid); break; case 'c': SetContinueThreadID(tid); break; default: assert(false && "unsupported $H variant - shouldn't get here"); return SendIllFormedResponse(packet, "H variant unsupported, should be c or g"); } return SendOKResponse(); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); // Fail if we don't have a current process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); return SendErrorResponse(0x15); } packet.SetFilePos(::strlen("I")); uint8_t tmp[4096]; for (;;) { size_t read = packet.GetHexBytesAvail(tmp); if (read == 0) { break; } // write directly to stdin *this might block if stdin buffer is full* // TODO: enqueue this block in circular buffer and send window size to // remote host ConnectionStatus status; Status error; m_stdio_communication.Write(tmp, read, status, &error); if (error.Fail()) { return SendErrorResponse(0x15); } } return SendOKResponse(); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_interrupt( StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); // Fail if we don't have a current process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); return SendErrorResponse(0x15); } // Interrupt the process. Status error = m_debugged_process_sp->Interrupt(); if (error.Fail()) { if (log) { log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed for process %" PRIu64 ": %s", __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString()); } return SendErrorResponse(GDBRemoteServerError::eErrorResume); } if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s stopped process %" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID()); // No response required from stop all. return PacketResult::Success; } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_memory_read( StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); return SendErrorResponse(0x15); } // Parse out the memory address. packet.SetFilePos(strlen("m")); if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Too short m packet"); // Read the address. Punting on validation. // FIXME replace with Hex U64 read with no default value that fails on failed // read. const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0); // Validate comma. if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ',')) return SendIllFormedResponse(packet, "Comma sep missing in m packet"); // Get # bytes to read. if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Length missing in m packet"); const uint64_t byte_count = packet.GetHexMaxU64(false, 0); if (byte_count == 0) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s nothing to read: " "zero-length packet", __FUNCTION__); return SendOKResponse(); } // Allocate the response buffer. std::string buf(byte_count, '\0'); if (buf.empty()) return SendErrorResponse(0x78); // Retrieve the process memory. size_t bytes_read = 0; Status error = m_debugged_process_sp->ReadMemoryWithoutTrap( read_addr, &buf[0], byte_count, bytes_read); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " mem 0x%" PRIx64 ": failed to read. Error: %s", __FUNCTION__, m_debugged_process_sp->GetID(), read_addr, error.AsCString()); return SendErrorResponse(0x08); } if (bytes_read == 0) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " mem 0x%" PRIx64 ": read 0 of %" PRIu64 " requested bytes", __FUNCTION__, m_debugged_process_sp->GetID(), read_addr, byte_count); return SendErrorResponse(0x08); } StreamGDBRemote response; packet.SetFilePos(0); char kind = packet.GetChar('?'); if (kind == 'x') response.PutEscapedBytes(buf.data(), byte_count); else { assert(kind == 'm'); for (size_t i = 0; i < bytes_read; ++i) response.PutHex8(buf[i]); } return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); return SendErrorResponse(0x15); } // Parse out the memory address. packet.SetFilePos(strlen("M")); if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Too short M packet"); // Read the address. Punting on validation. // FIXME replace with Hex U64 read with no default value that fails on failed // read. const lldb::addr_t write_addr = packet.GetHexMaxU64(false, 0); // Validate comma. if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ',')) return SendIllFormedResponse(packet, "Comma sep missing in M packet"); // Get # bytes to read. if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Length missing in M packet"); const uint64_t byte_count = packet.GetHexMaxU64(false, 0); if (byte_count == 0) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s nothing to write: " "zero-length packet", __FUNCTION__); return PacketResult::Success; } // Validate colon. if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ':')) return SendIllFormedResponse( packet, "Comma sep missing in M packet after byte length"); // Allocate the conversion buffer. std::vector buf(byte_count, 0); if (buf.empty()) return SendErrorResponse(0x78); // Convert the hex memory write contents to bytes. StreamGDBRemote response; const uint64_t convert_count = packet.GetHexBytes(buf, 0); if (convert_count != byte_count) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " mem 0x%" PRIx64 ": asked to write %" PRIu64 " bytes, but only found %" PRIu64 " to convert.", __FUNCTION__, m_debugged_process_sp->GetID(), write_addr, byte_count, convert_count); return SendIllFormedResponse(packet, "M content byte length specified did " "not match hex-encoded content " "length"); } // Write the process memory. size_t bytes_written = 0; Status error = m_debugged_process_sp->WriteMemory(write_addr, &buf[0], byte_count, bytes_written); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " mem 0x%" PRIx64 ": failed to write. Error: %s", __FUNCTION__, m_debugged_process_sp->GetID(), write_addr, error.AsCString()); return SendErrorResponse(0x09); } if (bytes_written == 0) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " mem 0x%" PRIx64 ": wrote 0 of %" PRIu64 " requested bytes", __FUNCTION__, m_debugged_process_sp->GetID(), write_addr, byte_count); return SendErrorResponse(0x09); } return SendOKResponse(); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported( StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); // Currently only the NativeProcessProtocol knows if it can handle a // qMemoryRegionInfoSupported // request, but we're not guaranteed to be attached to a process. For now // we'll assume the // client only asks this when a process is being debugged. // Ensure we have a process running; otherwise, we can't figure this out // since we won't have a NativeProcessProtocol. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); return SendErrorResponse(0x15); } // Test if we can get any region back when asking for the region around NULL. MemoryRegionInfo region_info; const Status error = m_debugged_process_sp->GetMemoryRegionInfo(0, region_info); if (error.Fail()) { // We don't support memory region info collection for this // NativeProcessProtocol. return SendUnimplementedResponse(""); } return SendOKResponse(); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo( StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); // Ensure we have a process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); return SendErrorResponse(0x15); } // Parse out the memory address. packet.SetFilePos(strlen("qMemoryRegionInfo:")); if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Too short qMemoryRegionInfo: packet"); // Read the address. Punting on validation. const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0); StreamGDBRemote response; // Get the memory region info for the target address. MemoryRegionInfo region_info; const Status error = m_debugged_process_sp->GetMemoryRegionInfo(read_addr, region_info); if (error.Fail()) { // Return the error message. response.PutCString("error:"); response.PutCStringAsRawHex8(error.AsCString()); response.PutChar(';'); } else { // Range start and size. response.Printf("start:%" PRIx64 ";size:%" PRIx64 ";", region_info.GetRange().GetRangeBase(), region_info.GetRange().GetByteSize()); // Permissions. if (region_info.GetReadable() || region_info.GetWritable() || region_info.GetExecutable()) { // Write permissions info. response.PutCString("permissions:"); if (region_info.GetReadable()) response.PutChar('r'); if (region_info.GetWritable()) response.PutChar('w'); if (region_info.GetExecutable()) response.PutChar('x'); response.PutChar(';'); } // Name ConstString name = region_info.GetName(); if (name) { response.PutCString("name:"); response.PutCStringAsRawHex8(name.AsCString()); response.PutChar(';'); } } return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) { // Ensure we have a process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); return SendErrorResponse(0x15); } // Parse out software or hardware breakpoint or watchpoint requested. packet.SetFilePos(strlen("Z")); if (packet.GetBytesLeft() < 1) return SendIllFormedResponse( packet, "Too short Z packet, missing software/hardware specifier"); bool want_breakpoint = true; bool want_hardware = false; uint32_t watch_flags = 0; const GDBStoppointType stoppoint_type = GDBStoppointType(packet.GetS32(eStoppointInvalid)); switch (stoppoint_type) { case eBreakpointSoftware: want_hardware = false; want_breakpoint = true; break; case eBreakpointHardware: want_hardware = true; want_breakpoint = true; break; case eWatchpointWrite: watch_flags = 1; want_hardware = true; want_breakpoint = false; break; case eWatchpointRead: watch_flags = 2; want_hardware = true; want_breakpoint = false; break; case eWatchpointReadWrite: watch_flags = 3; want_hardware = true; want_breakpoint = false; break; case eStoppointInvalid: return SendIllFormedResponse( packet, "Z packet had invalid software/hardware specifier"); } if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') return SendIllFormedResponse( packet, "Malformed Z packet, expecting comma after stoppoint type"); // Parse out the stoppoint address. if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Too short Z packet, missing address"); const lldb::addr_t addr = packet.GetHexMaxU64(false, 0); if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') return SendIllFormedResponse( packet, "Malformed Z packet, expecting comma after address"); // Parse out the stoppoint size (i.e. size hint for opcode size). const uint32_t size = packet.GetHexMaxU32(false, std::numeric_limits::max()); if (size == std::numeric_limits::max()) return SendIllFormedResponse( packet, "Malformed Z packet, failed to parse size argument"); if (want_breakpoint) { // Try to set the breakpoint. const Status error = m_debugged_process_sp->SetBreakpoint(addr, size, want_hardware); if (error.Success()) return SendOKResponse(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " failed to set breakpoint: %s", __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString()); return SendErrorResponse(0x09); } else { // Try to set the watchpoint. const Status error = m_debugged_process_sp->SetWatchpoint( addr, size, watch_flags, want_hardware); if (error.Success()) return SendOKResponse(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " failed to set watchpoint: %s", __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString()); return SendErrorResponse(0x09); } } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) { // Ensure we have a process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); return SendErrorResponse(0x15); } // Parse out software or hardware breakpoint or watchpoint requested. packet.SetFilePos(strlen("z")); if (packet.GetBytesLeft() < 1) return SendIllFormedResponse( packet, "Too short z packet, missing software/hardware specifier"); bool want_breakpoint = true; bool want_hardware = false; const GDBStoppointType stoppoint_type = GDBStoppointType(packet.GetS32(eStoppointInvalid)); switch (stoppoint_type) { case eBreakpointHardware: want_breakpoint = true; want_hardware = true; break; case eBreakpointSoftware: want_breakpoint = true; break; case eWatchpointWrite: want_breakpoint = false; break; case eWatchpointRead: want_breakpoint = false; break; case eWatchpointReadWrite: want_breakpoint = false; break; default: return SendIllFormedResponse( packet, "z packet had invalid software/hardware specifier"); } if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') return SendIllFormedResponse( packet, "Malformed z packet, expecting comma after stoppoint type"); // Parse out the stoppoint address. if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Too short z packet, missing address"); const lldb::addr_t addr = packet.GetHexMaxU64(false, 0); if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') return SendIllFormedResponse( packet, "Malformed z packet, expecting comma after address"); /* // Parse out the stoppoint size (i.e. size hint for opcode size). const uint32_t size = packet.GetHexMaxU32 (false, std::numeric_limits::max ()); if (size == std::numeric_limits::max ()) return SendIllFormedResponse(packet, "Malformed z packet, failed to parse size argument"); */ if (want_breakpoint) { // Try to clear the breakpoint. const Status error = m_debugged_process_sp->RemoveBreakpoint(addr, want_hardware); if (error.Success()) return SendOKResponse(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " failed to remove breakpoint: %s", __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString()); return SendErrorResponse(0x09); } else { // Try to clear the watchpoint. const Status error = m_debugged_process_sp->RemoveWatchpoint(addr); if (error.Success()) return SendOKResponse(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " failed to remove watchpoint: %s", __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString()); return SendErrorResponse(0x09); } } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); // Ensure we have a process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); return SendErrorResponse(0x32); } // We first try to use a continue thread id. If any one or any all set, use // the current thread. // Bail out if we don't have a thread id. lldb::tid_t tid = GetContinueThreadID(); if (tid == 0 || tid == LLDB_INVALID_THREAD_ID) tid = GetCurrentThreadID(); if (tid == LLDB_INVALID_THREAD_ID) return SendErrorResponse(0x33); // Double check that we have such a thread. // TODO investigate: on MacOSX we might need to do an UpdateThreads () here. NativeThreadProtocolSP thread_sp = m_debugged_process_sp->GetThreadByID(tid); if (!thread_sp || thread_sp->GetID() != tid) return SendErrorResponse(0x33); // Create the step action for the given thread. ResumeAction action = {tid, eStateStepping, 0}; // Setup the actions list. ResumeActionList actions; actions.Append(action); // All other threads stop while we're single stepping a thread. actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); Status error = m_debugged_process_sp->Resume(actions); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " Resume() failed with error: %s", __FUNCTION__, m_debugged_process_sp->GetID(), tid, error.AsCString()); return SendErrorResponse(0x49); } // No response here - the stop or exit will come from the resulting action. return PacketResult::Success; } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read( StringExtractorGDBRemote &packet) { // *BSD impls should be able to do this too. #if defined(__linux__) || defined(__NetBSD__) Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); // Parse out the offset. packet.SetFilePos(strlen("qXfer:auxv:read::")); if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "qXfer:auxv:read:: packet missing offset"); const uint64_t auxv_offset = packet.GetHexMaxU64(false, std::numeric_limits::max()); if (auxv_offset == std::numeric_limits::max()) return SendIllFormedResponse(packet, "qXfer:auxv:read:: packet missing offset"); // Parse out comma. if (packet.GetBytesLeft() < 1 || packet.GetChar() != ',') return SendIllFormedResponse( packet, "qXfer:auxv:read:: packet missing comma after offset"); // Parse out the length. const uint64_t auxv_length = packet.GetHexMaxU64(false, std::numeric_limits::max()); if (auxv_length == std::numeric_limits::max()) return SendIllFormedResponse(packet, "qXfer:auxv:read:: packet missing length"); // Grab the auxv data if we need it. if (!m_active_auxv_buffer_up) { // Make sure we have a valid process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); return SendErrorResponse(0x10); } // Grab the auxv data. auto buffer_or_error = m_debugged_process_sp->GetAuxvData(); if (!buffer_or_error) { std::error_code ec = buffer_or_error.getError(); LLDB_LOG(log, "no auxv data retrieved: {0}", ec.message()); return SendErrorResponse(ec.value()); } m_active_auxv_buffer_up = std::move(*buffer_or_error); } StreamGDBRemote response; bool done_with_buffer = false; llvm::StringRef buffer = m_active_auxv_buffer_up->getBuffer(); if (auxv_offset >= buffer.size()) { // We have nothing left to send. Mark the buffer as complete. response.PutChar('l'); done_with_buffer = true; } else { // Figure out how many bytes are available starting at the given offset. buffer = buffer.drop_front(auxv_offset); // Mark the response type according to whether we're reading the remainder // of the auxv data. if (auxv_length >= buffer.size()) { // There will be nothing left to read after this response.PutChar('l'); done_with_buffer = true; } else { // There will still be bytes to read after this request. response.PutChar('m'); buffer = buffer.take_front(auxv_length); } // Now write the data in encoded binary form. response.PutEscapedBytes(buffer.data(), buffer.size()); } if (done_with_buffer) m_active_auxv_buffer_up.reset(); return SendPacketNoLock(response.GetString()); #else return SendUnimplementedResponse("not implemented on this platform"); #endif } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState( StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); // Move past packet name. packet.SetFilePos(strlen("QSaveRegisterState")); // Get the thread to use. NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet); if (!thread_sp) { if (m_thread_suffix_supported) return SendIllFormedResponse( packet, "No thread specified in QSaveRegisterState packet"); else return SendIllFormedResponse(packet, "No thread was is set with the Hg packet"); } // Grab the register context for the thread. NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); if (!reg_context_sp) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " failed, no register context available for the thread", __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID()); return SendErrorResponse(0x15); } // Save registers to a buffer. DataBufferSP register_data_sp; Status error = reg_context_sp->ReadAllRegisterValues(register_data_sp); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " failed to save all register values: %s", __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString()); return SendErrorResponse(0x75); } // Allocate a new save id. const uint32_t save_id = GetNextSavedRegistersID(); assert((m_saved_registers_map.find(save_id) == m_saved_registers_map.end()) && "GetNextRegisterSaveID() returned an existing register save id"); // Save the register data buffer under the save id. { std::lock_guard guard(m_saved_registers_mutex); m_saved_registers_map[save_id] = register_data_sp; } // Write the response. StreamGDBRemote response; response.Printf("%" PRIu32, save_id); return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState( StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); // Parse out save id. packet.SetFilePos(strlen("QRestoreRegisterState:")); if (packet.GetBytesLeft() < 1) return SendIllFormedResponse( packet, "QRestoreRegisterState packet missing register save id"); const uint32_t save_id = packet.GetU32(0); if (save_id == 0) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s QRestoreRegisterState " "packet has malformed save id, expecting decimal uint32_t", __FUNCTION__); return SendErrorResponse(0x76); } // Get the thread to use. NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet); if (!thread_sp) { if (m_thread_suffix_supported) return SendIllFormedResponse( packet, "No thread specified in QRestoreRegisterState packet"); else return SendIllFormedResponse(packet, "No thread was is set with the Hg packet"); } // Grab the register context for the thread. NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext()); if (!reg_context_sp) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " failed, no register context available for the thread", __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID()); return SendErrorResponse(0x15); } // Retrieve register state buffer, then remove from the list. DataBufferSP register_data_sp; { std::lock_guard guard(m_saved_registers_mutex); // Find the register set buffer for the given save id. auto it = m_saved_registers_map.find(save_id); if (it == m_saved_registers_map.end()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " does not have a register set save buffer for id %" PRIu32, __FUNCTION__, m_debugged_process_sp->GetID(), save_id); return SendErrorResponse(0x77); } register_data_sp = it->second; // Remove it from the map. m_saved_registers_map.erase(it); } Status error = reg_context_sp->WriteAllRegisterValues(register_data_sp); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " failed to restore all register values: %s", __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString()); return SendErrorResponse(0x77); } return SendOKResponse(); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_vAttach( StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); // Consume the ';' after vAttach. packet.SetFilePos(strlen("vAttach")); if (!packet.GetBytesLeft() || packet.GetChar() != ';') return SendIllFormedResponse(packet, "vAttach missing expected ';'"); // Grab the PID to which we will attach (assume hex encoding). lldb::pid_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16); if (pid == LLDB_INVALID_PROCESS_ID) return SendIllFormedResponse(packet, "vAttach failed to parse the process id"); // Attempt to attach. if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s attempting to attach to " "pid %" PRIu64, __FUNCTION__, pid); Status error = AttachToProcess(pid); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to attach to " "pid %" PRIu64 ": %s\n", __FUNCTION__, pid, error.AsCString()); return SendErrorResponse(0x01); } // Notify we attached by sending a stop packet. return SendStopReasonForState(m_debugged_process_sp->GetState()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); StopSTDIOForwarding(); // Fail if we don't have a current process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) { if (log) log->Printf( "GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__); return SendErrorResponse(0x15); } lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; // Consume the ';' after D. packet.SetFilePos(1); if (packet.GetBytesLeft()) { if (packet.GetChar() != ';') return SendIllFormedResponse(packet, "D missing expected ';'"); // Grab the PID from which we will detach (assume hex encoding). pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16); if (pid == LLDB_INVALID_PROCESS_ID) return SendIllFormedResponse(packet, "D failed to parse the process id"); } if (pid != LLDB_INVALID_PROCESS_ID && m_debugged_process_sp->GetID() != pid) { return SendIllFormedResponse(packet, "Invalid pid"); } const Status error = m_debugged_process_sp->Detach(); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to detach from " "pid %" PRIu64 ": %s\n", __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString()); return SendErrorResponse(0x01); } return SendOKResponse(); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo( StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); packet.SetFilePos(strlen("qThreadStopInfo")); const lldb::tid_t tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID); if (tid == LLDB_INVALID_THREAD_ID) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not " "parse thread id from request \"%s\"", __FUNCTION__, packet.GetStringRef().c_str()); return SendErrorResponse(0x15); } return SendStopReplyPacketForThread(tid); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo( StringExtractorGDBRemote &) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); // Ensure we have a debugged process. if (!m_debugged_process_sp || (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(50); if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s preparing packet for pid " "%" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID()); StreamString response; const bool threads_with_valid_stop_info_only = false; JSONArray::SP threads_array_sp = GetJSONThreadsInfo( *m_debugged_process_sp, threads_with_valid_stop_info_only); if (!threads_array_sp) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to prepare a " "packet for pid %" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID()); return SendErrorResponse(52); } threads_array_sp->Write(response); StreamGDBRemote escaped_response; escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); return SendPacketNoLock(escaped_response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo( StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. if (!m_debugged_process_sp || m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID) return SendErrorResponse(68); packet.SetFilePos(strlen("qWatchpointSupportInfo")); if (packet.GetBytesLeft() == 0) return SendOKResponse(); if (packet.GetChar() != ':') return SendErrorResponse(67); auto hw_debug_cap = m_debugged_process_sp->GetHardwareDebugSupportInfo(); StreamGDBRemote response; if (hw_debug_cap == llvm::None) response.Printf("num:0;"); else response.Printf("num:%d;", hw_debug_cap->second); return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress( StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. if (!m_debugged_process_sp || m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID) return SendErrorResponse(67); packet.SetFilePos(strlen("qFileLoadAddress:")); if (packet.GetBytesLeft() == 0) return SendErrorResponse(68); std::string file_name; packet.GetHexByteString(file_name); lldb::addr_t file_load_address = LLDB_INVALID_ADDRESS; Status error = m_debugged_process_sp->GetFileLoadAddress(file_name, file_load_address); if (error.Fail()) return SendErrorResponse(69); if (file_load_address == LLDB_INVALID_ADDRESS) return SendErrorResponse(1); // File not loaded StreamGDBRemote response; response.PutHex64(file_load_address); return SendPacketNoLock(response.GetString()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_QPassSignals( StringExtractorGDBRemote &packet) { std::vector signals; packet.SetFilePos(strlen("QPassSignals:")); // Read sequence of hex signal numbers divided by a semicolon and // optionally spaces. while (packet.GetBytesLeft() > 0) { int signal = packet.GetS32(-1, 16); if (signal < 0) return SendIllFormedResponse(packet, "Failed to parse signal number."); signals.push_back(signal); packet.SkipSpaces(); char separator = packet.GetChar(); if (separator == '\0') break; // End of string if (separator != ';') return SendIllFormedResponse(packet, "Invalid separator," " expected semicolon."); } // Fail if we don't have a current process. if (!m_debugged_process_sp) return SendErrorResponse(68); Status error = m_debugged_process_sp->IgnoreSignals(signals); if (error.Fail()) return SendErrorResponse(69); return SendOKResponse(); } void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); // Tell the stdio connection to shut down. if (m_stdio_communication.IsConnected()) { auto connection = m_stdio_communication.GetConnection(); if (connection) { Status error; connection->Disconnect(&error); if (error.Success()) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s disconnect process " "terminal stdio - SUCCESS", __FUNCTION__); } else { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s disconnect process " "terminal stdio - FAIL: %s", __FUNCTION__, error.AsCString()); } } } } NativeThreadProtocolSP GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( StringExtractorGDBRemote &packet) { NativeThreadProtocolSP thread_sp; // We have no thread if we don't have a process. if (!m_debugged_process_sp || m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID) return thread_sp; // If the client hasn't asked for thread suffix support, there will not be a // thread suffix. // Use the current thread in that case. if (!m_thread_suffix_supported) { const lldb::tid_t current_tid = GetCurrentThreadID(); if (current_tid == LLDB_INVALID_THREAD_ID) return thread_sp; else if (current_tid == 0) { // Pick a thread. return m_debugged_process_sp->GetThreadAtIndex(0); } else return m_debugged_process_sp->GetThreadByID(current_tid); } Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); // Parse out the ';'. if (packet.GetBytesLeft() < 1 || packet.GetChar() != ';') { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse " "error: expected ';' prior to start of thread suffix: packet " "contents = '%s'", __FUNCTION__, packet.GetStringRef().c_str()); return thread_sp; } if (!packet.GetBytesLeft()) return thread_sp; // Parse out thread: portion. if (strncmp(packet.Peek(), "thread:", strlen("thread:")) != 0) { if (log) log->Printf("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse " "error: expected 'thread:' but not found, packet contents = " "'%s'", __FUNCTION__, packet.GetStringRef().c_str()); return thread_sp; } packet.SetFilePos(packet.GetFilePos() + strlen("thread:")); const lldb::tid_t tid = packet.GetHexMaxU64(false, 0); if (tid != 0) return m_debugged_process_sp->GetThreadByID(tid); return thread_sp; } lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const { if (m_current_tid == 0 || m_current_tid == LLDB_INVALID_THREAD_ID) { // Use whatever the debug process says is the current thread id // since the protocol either didn't specify or specified we want // any/all threads marked as the current thread. if (!m_debugged_process_sp) return LLDB_INVALID_THREAD_ID; return m_debugged_process_sp->GetCurrentThreadID(); } // Use the specific current thread id set by the gdb remote protocol. return m_current_tid; } uint32_t GDBRemoteCommunicationServerLLGS::GetNextSavedRegistersID() { std::lock_guard guard(m_saved_registers_mutex); return m_next_saved_registers_id++; } void GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); LLDB_LOG(log, "clearing auxv buffer: {0}", m_active_auxv_buffer_up.get()); m_active_auxv_buffer_up.reset(); } FileSpec GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path, const ArchSpec &arch) { if (m_debugged_process_sp) { FileSpec file_spec; if (m_debugged_process_sp ->GetLoadedModuleFileSpec(module_path.c_str(), file_spec) .Success()) { if (file_spec.Exists()) return file_spec; } } return GDBRemoteCommunicationServerCommon::FindModuleFile(module_path, arch); } Index: vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h =================================================================== --- vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h (revision 320966) +++ vendor/lldb/dist/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h (revision 320967) @@ -1,261 +1,264 @@ //===-- GDBRemoteCommunicationServerLLGS.h ----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef liblldb_GDBRemoteCommunicationServerLLGS_h_ #define liblldb_GDBRemoteCommunicationServerLLGS_h_ // C Includes // C++ Includes #include #include // Other libraries and framework includes #include "lldb/Core/Communication.h" #include "lldb/Host/MainLoop.h" #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/lldb-private-forward.h" // Project includes #include "GDBRemoteCommunicationServerCommon.h" class StringExtractorGDBRemote; namespace lldb_private { namespace process_gdb_remote { class ProcessGDBRemote; class GDBRemoteCommunicationServerLLGS : public GDBRemoteCommunicationServerCommon, public NativeProcessProtocol::NativeDelegate { public: //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ - GDBRemoteCommunicationServerLLGS(MainLoop &mainloop); + GDBRemoteCommunicationServerLLGS( + MainLoop &mainloop, + const NativeProcessProtocol::Factory &process_factory); //------------------------------------------------------------------ /// Specify the program to launch and its arguments. /// /// @param[in] args /// The command line to launch. /// /// @param[in] argc /// The number of elements in the args array of cstring pointers. /// /// @return /// An Status object indicating the success or failure of making /// the setting. //------------------------------------------------------------------ Status SetLaunchArguments(const char *const args[], int argc); //------------------------------------------------------------------ /// Specify the launch flags for the process. /// /// @param[in] launch_flags /// The launch flags to use when launching this process. /// /// @return /// An Status object indicating the success or failure of making /// the setting. //------------------------------------------------------------------ Status SetLaunchFlags(unsigned int launch_flags); //------------------------------------------------------------------ /// Launch a process with the current launch settings. /// /// This method supports running an lldb-gdbserver or similar /// server in a situation where the startup code has been provided /// with all the information for a child process to be launched. /// /// @return /// An Status object indicating the success or failure of the /// launch. //------------------------------------------------------------------ Status LaunchProcess() override; //------------------------------------------------------------------ /// Attach to a process. /// /// This method supports attaching llgs to a process accessible via the /// configured Platform. /// /// @return /// An Status object indicating the success or failure of the /// attach operation. //------------------------------------------------------------------ Status AttachToProcess(lldb::pid_t pid); //------------------------------------------------------------------ // NativeProcessProtocol::NativeDelegate overrides //------------------------------------------------------------------ void InitializeDelegate(NativeProcessProtocol *process) override; void ProcessStateChanged(NativeProcessProtocol *process, lldb::StateType state) override; void DidExec(NativeProcessProtocol *process) override; Status InitializeConnection(std::unique_ptr &&connection); protected: MainLoop &m_mainloop; MainLoop::ReadHandleUP m_network_handle_up; - lldb::tid_t m_current_tid; - lldb::tid_t m_continue_tid; + const NativeProcessProtocol::Factory &m_process_factory; + lldb::tid_t m_current_tid = LLDB_INVALID_THREAD_ID; + lldb::tid_t m_continue_tid = LLDB_INVALID_THREAD_ID; std::recursive_mutex m_debugged_process_mutex; NativeProcessProtocolSP m_debugged_process_sp; Communication m_stdio_communication; MainLoop::ReadHandleUP m_stdio_handle_up; - lldb::StateType m_inferior_prev_state; + lldb::StateType m_inferior_prev_state = lldb::StateType::eStateInvalid; std::unique_ptr m_active_auxv_buffer_up; std::mutex m_saved_registers_mutex; std::unordered_map m_saved_registers_map; - uint32_t m_next_saved_registers_id; - bool m_handshake_completed : 1; + uint32_t m_next_saved_registers_id = 1; + bool m_handshake_completed = false; PacketResult SendONotification(const char *buffer, uint32_t len); PacketResult SendWResponse(NativeProcessProtocol *process); PacketResult SendStopReplyPacketForThread(lldb::tid_t tid); PacketResult SendStopReasonForState(lldb::StateType process_state); PacketResult Handle_k(StringExtractorGDBRemote &packet); PacketResult Handle_qProcessInfo(StringExtractorGDBRemote &packet); PacketResult Handle_qC(StringExtractorGDBRemote &packet); PacketResult Handle_QSetDisableASLR(StringExtractorGDBRemote &packet); PacketResult Handle_QSetWorkingDir(StringExtractorGDBRemote &packet); PacketResult Handle_qGetWorkingDir(StringExtractorGDBRemote &packet); PacketResult Handle_C(StringExtractorGDBRemote &packet); PacketResult Handle_c(StringExtractorGDBRemote &packet); PacketResult Handle_vCont(StringExtractorGDBRemote &packet); PacketResult Handle_vCont_actions(StringExtractorGDBRemote &packet); PacketResult Handle_stop_reason(StringExtractorGDBRemote &packet); PacketResult Handle_qRegisterInfo(StringExtractorGDBRemote &packet); PacketResult Handle_qfThreadInfo(StringExtractorGDBRemote &packet); PacketResult Handle_qsThreadInfo(StringExtractorGDBRemote &packet); PacketResult Handle_p(StringExtractorGDBRemote &packet); PacketResult Handle_P(StringExtractorGDBRemote &packet); PacketResult Handle_H(StringExtractorGDBRemote &packet); PacketResult Handle_I(StringExtractorGDBRemote &packet); PacketResult Handle_interrupt(StringExtractorGDBRemote &packet); // Handles $m and $x packets. PacketResult Handle_memory_read(StringExtractorGDBRemote &packet); PacketResult Handle_M(StringExtractorGDBRemote &packet); PacketResult Handle_qMemoryRegionInfoSupported(StringExtractorGDBRemote &packet); PacketResult Handle_qMemoryRegionInfo(StringExtractorGDBRemote &packet); PacketResult Handle_Z(StringExtractorGDBRemote &packet); PacketResult Handle_z(StringExtractorGDBRemote &packet); PacketResult Handle_s(StringExtractorGDBRemote &packet); PacketResult Handle_qXfer_auxv_read(StringExtractorGDBRemote &packet); PacketResult Handle_QSaveRegisterState(StringExtractorGDBRemote &packet); PacketResult Handle_jTraceStart(StringExtractorGDBRemote &packet); PacketResult Handle_jTraceRead(StringExtractorGDBRemote &packet); PacketResult Handle_jTraceStop(StringExtractorGDBRemote &packet); PacketResult Handle_jTraceConfigRead(StringExtractorGDBRemote &packet); PacketResult Handle_QRestoreRegisterState(StringExtractorGDBRemote &packet); PacketResult Handle_vAttach(StringExtractorGDBRemote &packet); PacketResult Handle_D(StringExtractorGDBRemote &packet); PacketResult Handle_qThreadStopInfo(StringExtractorGDBRemote &packet); PacketResult Handle_jThreadsInfo(StringExtractorGDBRemote &packet); PacketResult Handle_qWatchpointSupportInfo(StringExtractorGDBRemote &packet); PacketResult Handle_qFileLoadAddress(StringExtractorGDBRemote &packet); PacketResult Handle_QPassSignals(StringExtractorGDBRemote &packet); void SetCurrentThreadID(lldb::tid_t tid); lldb::tid_t GetCurrentThreadID() const; void SetContinueThreadID(lldb::tid_t tid); lldb::tid_t GetContinueThreadID() const { return m_continue_tid; } Status SetSTDIOFileDescriptor(int fd); FileSpec FindModuleFile(const std::string &module_path, const ArchSpec &arch) override; private: void HandleInferiorState_Exited(NativeProcessProtocol *process); void HandleInferiorState_Stopped(NativeProcessProtocol *process); NativeThreadProtocolSP GetThreadFromSuffix(StringExtractorGDBRemote &packet); uint32_t GetNextSavedRegistersID(); void MaybeCloseInferiorTerminalConnection(); void ClearProcessSpecificData(); void RegisterPacketHandlers(); void DataAvailableCallback(); void SendProcessOutput(); void StartSTDIOForwarding(); void StopSTDIOForwarding(); //------------------------------------------------------------------ // For GDBRemoteCommunicationServerLLGS only //------------------------------------------------------------------ DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationServerLLGS); }; } // namespace process_gdb_remote } // namespace lldb_private #endif // liblldb_GDBRemoteCommunicationServerLLGS_h_ Index: vendor/lldb/dist/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (revision 320967) @@ -1,5224 +1,5225 @@ //===-- ProcessGDBRemote.cpp ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/Host/Config.h" // C Includes #include #include #ifndef LLDB_DISABLE_POSIX #include #include // for mmap #include #endif #include #include #include // C++ Includes #include #include #include #include #include "lldb/Breakpoint/Watchpoint.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/Value.h" #include "lldb/DataFormatters/FormatManager.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/PseudoTerminal.h" #include "lldb/Host/StringConvert.h" #include "lldb/Host/Symbols.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/XML.h" #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/CommandObjectMultiword.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionGroupBoolean.h" #include "lldb/Interpreter/OptionGroupUInt64.h" #include "lldb/Interpreter/OptionValueProperties.h" #include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/Property.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/ABI.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/SystemRuntime.h" #include "lldb/Target/Target.h" #include "lldb/Target/TargetList.h" #include "lldb/Target/ThreadPlanCallFunction.h" #include "lldb/Utility/CleanUp.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" // Project includes #include "GDBRemoteRegisterContext.h" #include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h" #include "Plugins/Process/Utility/GDBRemoteSignals.h" #include "Plugins/Process/Utility/InferiorCallPOSIX.h" #include "Plugins/Process/Utility/StopInfoMachException.h" #include "ProcessGDBRemote.h" #include "ProcessGDBRemoteLog.h" #include "ThreadGDBRemote.h" #include "Utility/StringExtractorGDBRemote.h" #include "lldb/Host/Host.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Threading.h" #include "llvm/Support/raw_ostream.h" #define DEBUGSERVER_BASENAME "debugserver" using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; namespace lldb { // Provide a function that can easily dump the packet history if we know a // ProcessGDBRemote * value (which we can get from logs or from debugging). // We need the function in the lldb namespace so it makes it into the final // executable since the LLDB shared library only exports stuff in the lldb // namespace. This allows you to attach with a debugger and call this // function and get the packet history dumped to a file. void DumpProcessGDBRemotePacketHistory(void *p, const char *path) { StreamFile strm; Status error(strm.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate)); if (error.Success()) ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory(strm); } } namespace { static PropertyDefinition g_properties[] = { {"packet-timeout", OptionValue::eTypeUInt64, true, 1, NULL, NULL, "Specify the default packet timeout in seconds."}, {"target-definition-file", OptionValue::eTypeFileSpec, true, 0, NULL, NULL, "The file that provides the description for remote target registers."}, {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}}; enum { ePropertyPacketTimeout, ePropertyTargetDefinitionFile }; class PluginProperties : public Properties { public: static ConstString GetSettingName() { return ProcessGDBRemote::GetPluginNameStatic(); } PluginProperties() : Properties() { m_collection_sp.reset(new OptionValueProperties(GetSettingName())); m_collection_sp->Initialize(g_properties); } virtual ~PluginProperties() {} uint64_t GetPacketTimeout() { const uint32_t idx = ePropertyPacketTimeout; return m_collection_sp->GetPropertyAtIndexAsUInt64( NULL, idx, g_properties[idx].default_uint_value); } bool SetPacketTimeout(uint64_t timeout) { const uint32_t idx = ePropertyPacketTimeout; return m_collection_sp->SetPropertyAtIndexAsUInt64(NULL, idx, timeout); } FileSpec GetTargetDefinitionFile() const { const uint32_t idx = ePropertyTargetDefinitionFile; return m_collection_sp->GetPropertyAtIndexAsFileSpec(NULL, idx); } }; typedef std::shared_ptr ProcessKDPPropertiesSP; static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() { static ProcessKDPPropertiesSP g_settings_sp; if (!g_settings_sp) g_settings_sp.reset(new PluginProperties()); return g_settings_sp; } } // anonymous namespace end // TODO Randomly assigning a port is unsafe. We should get an unused // ephemeral port from the kernel and make sure we reserve it before passing // it to debugserver. #if defined(__APPLE__) #define LOW_PORT (IPPORT_RESERVED) #define HIGH_PORT (IPPORT_HIFIRSTAUTO) #else #define LOW_PORT (1024u) #define HIGH_PORT (49151u) #endif #if defined(__APPLE__) && \ (defined(__arm__) || defined(__arm64__) || defined(__aarch64__)) static bool rand_initialized = false; static inline uint16_t get_random_port() { if (!rand_initialized) { time_t seed = time(NULL); rand_initialized = true; srand(seed); } return (rand() % (HIGH_PORT - LOW_PORT)) + LOW_PORT; } #endif ConstString ProcessGDBRemote::GetPluginNameStatic() { static ConstString g_name("gdb-remote"); return g_name; } const char *ProcessGDBRemote::GetPluginDescriptionStatic() { return "GDB Remote protocol based debugging plug-in."; } void ProcessGDBRemote::Terminate() { PluginManager::UnregisterPlugin(ProcessGDBRemote::CreateInstance); } lldb::ProcessSP ProcessGDBRemote::CreateInstance(lldb::TargetSP target_sp, ListenerSP listener_sp, const FileSpec *crash_file_path) { lldb::ProcessSP process_sp; if (crash_file_path == NULL) process_sp.reset(new ProcessGDBRemote(target_sp, listener_sp)); return process_sp; } bool ProcessGDBRemote::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) { if (plugin_specified_by_name) return true; // For now we are just making sure the file exists for a given module Module *exe_module = target_sp->GetExecutableModulePointer(); if (exe_module) { ObjectFile *exe_objfile = exe_module->GetObjectFile(); // We can't debug core files... switch (exe_objfile->GetType()) { case ObjectFile::eTypeInvalid: case ObjectFile::eTypeCoreFile: case ObjectFile::eTypeDebugInfo: case ObjectFile::eTypeObjectFile: case ObjectFile::eTypeSharedLibrary: case ObjectFile::eTypeStubLibrary: case ObjectFile::eTypeJIT: return false; case ObjectFile::eTypeExecutable: case ObjectFile::eTypeDynamicLinker: case ObjectFile::eTypeUnknown: break; } return exe_module->GetFileSpec().Exists(); } // However, if there is no executable module, we return true since we might be // preparing to attach. return true; } //---------------------------------------------------------------------- // ProcessGDBRemote constructor //---------------------------------------------------------------------- ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, ListenerSP listener_sp) : Process(target_sp, listener_sp), m_flags(0), m_gdb_comm(), m_debugserver_pid(LLDB_INVALID_PROCESS_ID), m_last_stop_packet_mutex(), m_register_info(), m_async_broadcaster(NULL, "lldb.process.gdb-remote.async-broadcaster"), m_async_listener_sp( Listener::MakeListener("lldb.process.gdb-remote.async-listener")), m_async_thread_state_mutex(), m_thread_ids(), m_thread_pcs(), m_jstopinfo_sp(), m_jthreadsinfo_sp(), m_continue_c_tids(), m_continue_C_tids(), m_continue_s_tids(), m_continue_S_tids(), m_max_memory_size(0), m_remote_stub_max_memory_size(0), m_addr_to_mmap_size(), m_thread_create_bp_sp(), m_waiting_for_attach(false), m_destroy_tried_resuming(false), m_command_sp(), m_breakpoint_pc_offset(0), m_initial_tid(LLDB_INVALID_THREAD_ID) { m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, "async thread should exit"); m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, "async thread continue"); m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadDidExit, "async thread did exit"); Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_ASYNC)); const uint32_t async_event_mask = eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; if (m_async_listener_sp->StartListeningForEvents( &m_async_broadcaster, async_event_mask) != async_event_mask) { if (log) log->Printf("ProcessGDBRemote::%s failed to listen for " "m_async_broadcaster events", __FUNCTION__); } const uint32_t gdb_event_mask = Communication::eBroadcastBitReadThreadDidExit | GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify; if (m_async_listener_sp->StartListeningForEvents( &m_gdb_comm, gdb_event_mask) != gdb_event_mask) { if (log) log->Printf("ProcessGDBRemote::%s failed to listen for m_gdb_comm events", __FUNCTION__); } const uint64_t timeout_seconds = GetGlobalPluginProperties()->GetPacketTimeout(); if (timeout_seconds > 0) m_gdb_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds)); } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- ProcessGDBRemote::~ProcessGDBRemote() { // m_mach_process.UnregisterNotificationCallbacks (this); Clear(); // We need to call finalize on the process before destroying ourselves // to make sure all of the broadcaster cleanup goes as planned. If we // destruct this class, then Process::~Process() might have problems // trying to fully destroy the broadcaster. Finalize(); // The general Finalize is going to try to destroy the process and that SHOULD // shut down the async thread. However, if we don't kill it it will get // stranded and // its connection will go away so when it wakes up it will crash. So kill it // for sure here. StopAsyncThread(); KillDebugserverProcess(); } //---------------------------------------------------------------------- // PluginInterface //---------------------------------------------------------------------- ConstString ProcessGDBRemote::GetPluginName() { return GetPluginNameStatic(); } uint32_t ProcessGDBRemote::GetPluginVersion() { return 1; } bool ProcessGDBRemote::ParsePythonTargetDefinition( const FileSpec &target_definition_fspec) { ScriptInterpreter *interpreter = GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); Status error; StructuredData::ObjectSP module_object_sp( interpreter->LoadPluginModule(target_definition_fspec, error)); if (module_object_sp) { StructuredData::DictionarySP target_definition_sp( interpreter->GetDynamicSettings(module_object_sp, &GetTarget(), "gdb-server-target-definition", error)); if (target_definition_sp) { StructuredData::ObjectSP target_object( target_definition_sp->GetValueForKey("host-info")); if (target_object) { if (auto host_info_dict = target_object->GetAsDictionary()) { StructuredData::ObjectSP triple_value = host_info_dict->GetValueForKey("triple"); if (auto triple_string_value = triple_value->GetAsString()) { std::string triple_string = triple_string_value->GetValue(); ArchSpec host_arch(triple_string.c_str()); if (!host_arch.IsCompatibleMatch(GetTarget().GetArchitecture())) { GetTarget().SetArchitecture(host_arch); } } } } m_breakpoint_pc_offset = 0; StructuredData::ObjectSP breakpoint_pc_offset_value = target_definition_sp->GetValueForKey("breakpoint-pc-offset"); if (breakpoint_pc_offset_value) { if (auto breakpoint_pc_int_value = breakpoint_pc_offset_value->GetAsInteger()) m_breakpoint_pc_offset = breakpoint_pc_int_value->GetValue(); } if (m_register_info.SetRegisterInfo(*target_definition_sp, GetTarget().GetArchitecture()) > 0) { return true; } } } return false; } // If the remote stub didn't give us eh_frame or DWARF register numbers for a // register, // see if the ABI can provide them. // DWARF and eh_frame register numbers are defined as a part of the ABI. static void AugmentRegisterInfoViaABI(RegisterInfo ®_info, ConstString reg_name, ABISP abi_sp) { if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM || reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM) { if (abi_sp) { RegisterInfo abi_reg_info; if (abi_sp->GetRegisterInfoByName(reg_name, abi_reg_info)) { if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM && abi_reg_info.kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) { reg_info.kinds[eRegisterKindEHFrame] = abi_reg_info.kinds[eRegisterKindEHFrame]; } if (reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM && abi_reg_info.kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM) { reg_info.kinds[eRegisterKindDWARF] = abi_reg_info.kinds[eRegisterKindDWARF]; } if (reg_info.kinds[eRegisterKindGeneric] == LLDB_INVALID_REGNUM && abi_reg_info.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) { reg_info.kinds[eRegisterKindGeneric] = abi_reg_info.kinds[eRegisterKindGeneric]; } } } } } static size_t SplitCommaSeparatedRegisterNumberString( const llvm::StringRef &comma_separated_regiter_numbers, std::vector ®nums, int base) { regnums.clear(); std::pair value_pair; value_pair.second = comma_separated_regiter_numbers; do { value_pair = value_pair.second.split(','); if (!value_pair.first.empty()) { uint32_t reg = StringConvert::ToUInt32(value_pair.first.str().c_str(), LLDB_INVALID_REGNUM, base); if (reg != LLDB_INVALID_REGNUM) regnums.push_back(reg); } } while (!value_pair.second.empty()); return regnums.size(); } void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { if (!force && m_register_info.GetNumRegisters() > 0) return; m_register_info.Clear(); // Check if qHostInfo specified a specific packet timeout for this connection. // If so then lets update our setting so the user knows what the timeout is // and can see it. const auto host_packet_timeout = m_gdb_comm.GetHostDefaultPacketTimeout(); if (host_packet_timeout > std::chrono::seconds(0)) { GetGlobalPluginProperties()->SetPacketTimeout(host_packet_timeout.count()); } // Register info search order: // 1 - Use the target definition python file if one is specified. // 2 - If the target definition doesn't have any of the info from the // target.xml (registers) then proceed to read the target.xml. // 3 - Fall back on the qRegisterInfo packets. FileSpec target_definition_fspec = GetGlobalPluginProperties()->GetTargetDefinitionFile(); if (!target_definition_fspec.Exists()) { // If the filename doesn't exist, it may be a ~ not having been expanded - // try to resolve it. target_definition_fspec.ResolvePath(); } if (target_definition_fspec) { // See if we can get register definitions from a python file if (ParsePythonTargetDefinition(target_definition_fspec)) { return; } else { StreamSP stream_sp = GetTarget().GetDebugger().GetAsyncOutputStream(); stream_sp->Printf("ERROR: target description file %s failed to parse.\n", target_definition_fspec.GetPath().c_str()); } } const ArchSpec &target_arch = GetTarget().GetArchitecture(); const ArchSpec &remote_host_arch = m_gdb_comm.GetHostArchitecture(); const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture(); // Use the process' architecture instead of the host arch, if available ArchSpec arch_to_use; if (remote_process_arch.IsValid()) arch_to_use = remote_process_arch; else arch_to_use = remote_host_arch; if (!arch_to_use.IsValid()) arch_to_use = target_arch; if (GetGDBServerRegisterInfo(arch_to_use)) return; char packet[128]; uint32_t reg_offset = 0; uint32_t reg_num = 0; for (StringExtractorGDBRemote::ResponseType response_type = StringExtractorGDBRemote::eResponse; response_type == StringExtractorGDBRemote::eResponse; ++reg_num) { const int packet_len = ::snprintf(packet, sizeof(packet), "qRegisterInfo%x", reg_num); assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response, false) == GDBRemoteCommunication::PacketResult::Success) { response_type = response.GetResponseType(); if (response_type == StringExtractorGDBRemote::eResponse) { llvm::StringRef name; llvm::StringRef value; ConstString reg_name; ConstString alt_name; ConstString set_name; std::vector value_regs; std::vector invalidate_regs; std::vector dwarf_opcode_bytes; RegisterInfo reg_info = { NULL, // Name NULL, // Alt name 0, // byte size reg_offset, // offset eEncodingUint, // encoding eFormatHex, // format { LLDB_INVALID_REGNUM, // eh_frame reg num LLDB_INVALID_REGNUM, // DWARF reg num LLDB_INVALID_REGNUM, // generic reg num reg_num, // process plugin reg num reg_num // native register number }, NULL, NULL, NULL, // Dwarf expression opcode bytes pointer 0 // Dwarf expression opcode bytes length }; while (response.GetNameColonValue(name, value)) { if (name.equals("name")) { reg_name.SetString(value); } else if (name.equals("alt-name")) { alt_name.SetString(value); } else if (name.equals("bitsize")) { value.getAsInteger(0, reg_info.byte_size); reg_info.byte_size /= CHAR_BIT; } else if (name.equals("offset")) { if (value.getAsInteger(0, reg_offset)) reg_offset = UINT32_MAX; } else if (name.equals("encoding")) { const Encoding encoding = Args::StringToEncoding(value); if (encoding != eEncodingInvalid) reg_info.encoding = encoding; } else if (name.equals("format")) { Format format = eFormatInvalid; if (Args::StringToFormat(value.str().c_str(), format, NULL) .Success()) reg_info.format = format; else { reg_info.format = llvm::StringSwitch(value) .Case("binary", eFormatBinary) .Case("decimal", eFormatDecimal) .Case("hex", eFormatHex) .Case("float", eFormatFloat) .Case("vector-sint8", eFormatVectorOfSInt8) .Case("vector-uint8", eFormatVectorOfUInt8) .Case("vector-sint16", eFormatVectorOfSInt16) .Case("vector-uint16", eFormatVectorOfUInt16) .Case("vector-sint32", eFormatVectorOfSInt32) .Case("vector-uint32", eFormatVectorOfUInt32) .Case("vector-float32", eFormatVectorOfFloat32) .Case("vector-uint64", eFormatVectorOfUInt64) .Case("vector-uint128", eFormatVectorOfUInt128) .Default(eFormatInvalid); } } else if (name.equals("set")) { set_name.SetString(value); } else if (name.equals("gcc") || name.equals("ehframe")) { if (value.getAsInteger(0, reg_info.kinds[eRegisterKindEHFrame])) reg_info.kinds[eRegisterKindEHFrame] = LLDB_INVALID_REGNUM; } else if (name.equals("dwarf")) { if (value.getAsInteger(0, reg_info.kinds[eRegisterKindDWARF])) reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM; } else if (name.equals("generic")) { reg_info.kinds[eRegisterKindGeneric] = Args::StringToGenericRegister(value); } else if (name.equals("container-regs")) { SplitCommaSeparatedRegisterNumberString(value, value_regs, 16); } else if (name.equals("invalidate-regs")) { SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 16); } else if (name.equals("dynamic_size_dwarf_expr_bytes")) { size_t dwarf_opcode_len = value.size() / 2; assert(dwarf_opcode_len > 0); dwarf_opcode_bytes.resize(dwarf_opcode_len); reg_info.dynamic_size_dwarf_len = dwarf_opcode_len; StringExtractor opcode_extractor(value); uint32_t ret_val = opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes); assert(dwarf_opcode_len == ret_val); UNUSED_IF_ASSERT_DISABLED(ret_val); reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data(); } } reg_info.byte_offset = reg_offset; assert(reg_info.byte_size != 0); reg_offset += reg_info.byte_size; if (!value_regs.empty()) { value_regs.push_back(LLDB_INVALID_REGNUM); reg_info.value_regs = value_regs.data(); } if (!invalidate_regs.empty()) { invalidate_regs.push_back(LLDB_INVALID_REGNUM); reg_info.invalidate_regs = invalidate_regs.data(); } // We have to make a temporary ABI here, and not use the GetABI because // this code // gets called in DidAttach, when the target architecture (and // consequently the ABI we'll get from // the process) may be wrong. ABISP abi_to_use = ABI::FindPlugin(shared_from_this(), arch_to_use); AugmentRegisterInfoViaABI(reg_info, reg_name, abi_to_use); m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name); } else { break; // ensure exit before reg_num is incremented } } else { break; } } if (m_register_info.GetNumRegisters() > 0) { m_register_info.Finalize(GetTarget().GetArchitecture()); return; } // We didn't get anything if the accumulated reg_num is zero. See if we are // debugging ARM and fill with a hard coded register set until we can get an // updated debugserver down on the devices. // On the other hand, if the accumulated reg_num is positive, see if we can // add composite registers to the existing primordial ones. bool from_scratch = (m_register_info.GetNumRegisters() == 0); if (!target_arch.IsValid()) { if (arch_to_use.IsValid() && (arch_to_use.GetMachine() == llvm::Triple::arm || arch_to_use.GetMachine() == llvm::Triple::thumb) && arch_to_use.GetTriple().getVendor() == llvm::Triple::Apple) m_register_info.HardcodeARMRegisters(from_scratch); } else if (target_arch.GetMachine() == llvm::Triple::arm || target_arch.GetMachine() == llvm::Triple::thumb) { m_register_info.HardcodeARMRegisters(from_scratch); } // At this point, we can finalize our register info. m_register_info.Finalize(GetTarget().GetArchitecture()); } Status ProcessGDBRemote::WillLaunch(Module *module) { return WillLaunchOrAttach(); } Status ProcessGDBRemote::WillAttachToProcessWithID(lldb::pid_t pid) { return WillLaunchOrAttach(); } Status ProcessGDBRemote::WillAttachToProcessWithName(const char *process_name, bool wait_for_launch) { return WillLaunchOrAttach(); } Status ProcessGDBRemote::DoConnectRemote(Stream *strm, llvm::StringRef remote_url) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); Status error(WillLaunchOrAttach()); if (error.Fail()) return error; error = ConnectToDebugserver(remote_url); if (error.Fail()) return error; StartAsyncThread(); lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID(); if (pid == LLDB_INVALID_PROCESS_ID) { // We don't have a valid process ID, so note that we are connected // and could now request to launch or attach, or get remote process // listings... SetPrivateState(eStateConnected); } else { // We have a valid process SetID(pid); GetThreadList(); StringExtractorGDBRemote response; if (m_gdb_comm.GetStopReply(response)) { SetLastStopPacket(response); // '?' Packets must be handled differently in non-stop mode if (GetTarget().GetNonStopModeEnabled()) HandleStopReplySequence(); Target &target = GetTarget(); if (!target.GetArchitecture().IsValid()) { if (m_gdb_comm.GetProcessArchitecture().IsValid()) { target.SetArchitecture(m_gdb_comm.GetProcessArchitecture()); } else { target.SetArchitecture(m_gdb_comm.GetHostArchitecture()); } } const StateType state = SetThreadStopInfo(response); if (state != eStateInvalid) { SetPrivateState(state); } else error.SetErrorStringWithFormat( "Process %" PRIu64 " was reported after connecting to " "'%s', but state was not stopped: %s", pid, remote_url.str().c_str(), StateAsCString(state)); } else error.SetErrorStringWithFormat("Process %" PRIu64 " was reported after connecting to '%s', " "but no stop reply packet was received", pid, remote_url.str().c_str()); } if (log) log->Printf("ProcessGDBRemote::%s pid %" PRIu64 ": normalizing target architecture initial triple: %s " "(GetTarget().GetArchitecture().IsValid() %s, " "m_gdb_comm.GetHostArchitecture().IsValid(): %s)", __FUNCTION__, GetID(), GetTarget().GetArchitecture().GetTriple().getTriple().c_str(), GetTarget().GetArchitecture().IsValid() ? "true" : "false", m_gdb_comm.GetHostArchitecture().IsValid() ? "true" : "false"); if (error.Success() && !GetTarget().GetArchitecture().IsValid() && m_gdb_comm.GetHostArchitecture().IsValid()) { // Prefer the *process'* architecture over that of the *host*, if available. if (m_gdb_comm.GetProcessArchitecture().IsValid()) GetTarget().SetArchitecture(m_gdb_comm.GetProcessArchitecture()); else GetTarget().SetArchitecture(m_gdb_comm.GetHostArchitecture()); } if (log) log->Printf("ProcessGDBRemote::%s pid %" PRIu64 ": normalized target architecture triple: %s", __FUNCTION__, GetID(), GetTarget().GetArchitecture().GetTriple().getTriple().c_str()); if (error.Success()) { PlatformSP platform_sp = GetTarget().GetPlatform(); if (platform_sp && platform_sp->IsConnected()) SetUnixSignals(platform_sp->GetUnixSignals()); else SetUnixSignals(UnixSignals::Create(GetTarget().GetArchitecture())); } return error; } Status ProcessGDBRemote::WillLaunchOrAttach() { Status error; m_stdio_communication.Clear(); return error; } //---------------------------------------------------------------------- // Process Control //---------------------------------------------------------------------- Status ProcessGDBRemote::DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); Status error; if (log) log->Printf("ProcessGDBRemote::%s() entered", __FUNCTION__); uint32_t launch_flags = launch_info.GetFlags().Get(); FileSpec stdin_file_spec{}; FileSpec stdout_file_spec{}; FileSpec stderr_file_spec{}; FileSpec working_dir = launch_info.GetWorkingDirectory(); const FileAction *file_action; file_action = launch_info.GetFileActionForFD(STDIN_FILENO); if (file_action) { if (file_action->GetAction() == FileAction::eFileActionOpen) stdin_file_spec = file_action->GetFileSpec(); } file_action = launch_info.GetFileActionForFD(STDOUT_FILENO); if (file_action) { if (file_action->GetAction() == FileAction::eFileActionOpen) stdout_file_spec = file_action->GetFileSpec(); } file_action = launch_info.GetFileActionForFD(STDERR_FILENO); if (file_action) { if (file_action->GetAction() == FileAction::eFileActionOpen) stderr_file_spec = file_action->GetFileSpec(); } if (log) { if (stdin_file_spec || stdout_file_spec || stderr_file_spec) log->Printf("ProcessGDBRemote::%s provided with STDIO paths via " "launch_info: stdin=%s, stdout=%s, stderr=%s", __FUNCTION__, stdin_file_spec ? stdin_file_spec.GetCString() : "", stdout_file_spec ? stdout_file_spec.GetCString() : "", stderr_file_spec ? stderr_file_spec.GetCString() : ""); else log->Printf("ProcessGDBRemote::%s no STDIO paths given via launch_info", __FUNCTION__); } const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0; if (stdin_file_spec || disable_stdio) { // the inferior will be reading stdin from the specified file // or stdio is completely disabled m_stdin_forward = false; } else { m_stdin_forward = true; } // ::LogSetBitMask (GDBR_LOG_DEFAULT); // ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE | // LLDB_LOG_OPTION_PREPEND_TIMESTAMP | // LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD); // ::LogSetLogFile ("/dev/stdout"); ObjectFile *object_file = exe_module->GetObjectFile(); if (object_file) { error = EstablishConnectionIfNeeded(launch_info); if (error.Success()) { lldb_utility::PseudoTerminal pty; const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0; PlatformSP platform_sp(GetTarget().GetPlatform()); if (disable_stdio) { // set to /dev/null unless redirected to a file above if (!stdin_file_spec) stdin_file_spec.SetFile(FileSystem::DEV_NULL, false); if (!stdout_file_spec) stdout_file_spec.SetFile(FileSystem::DEV_NULL, false); if (!stderr_file_spec) stderr_file_spec.SetFile(FileSystem::DEV_NULL, false); } else if (platform_sp && platform_sp->IsHost()) { // If the debugserver is local and we aren't disabling STDIO, lets use // a pseudo terminal to instead of relying on the 'O' packets for stdio // since 'O' packets can really slow down debugging if the inferior // does a lot of output. if ((!stdin_file_spec || !stdout_file_spec || !stderr_file_spec) && pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, NULL, 0)) { FileSpec slave_name{pty.GetSlaveName(NULL, 0), false}; if (!stdin_file_spec) stdin_file_spec = slave_name; if (!stdout_file_spec) stdout_file_spec = slave_name; if (!stderr_file_spec) stderr_file_spec = slave_name; } if (log) log->Printf( "ProcessGDBRemote::%s adjusted STDIO paths for local platform " "(IsHost() is true) using slave: stdin=%s, stdout=%s, stderr=%s", __FUNCTION__, stdin_file_spec ? stdin_file_spec.GetCString() : "", stdout_file_spec ? stdout_file_spec.GetCString() : "", stderr_file_spec ? stderr_file_spec.GetCString() : ""); } if (log) log->Printf("ProcessGDBRemote::%s final STDIO paths after all " "adjustments: stdin=%s, stdout=%s, stderr=%s", __FUNCTION__, stdin_file_spec ? stdin_file_spec.GetCString() : "", stdout_file_spec ? stdout_file_spec.GetCString() : "", stderr_file_spec ? stderr_file_spec.GetCString() : ""); if (stdin_file_spec) m_gdb_comm.SetSTDIN(stdin_file_spec); if (stdout_file_spec) m_gdb_comm.SetSTDOUT(stdout_file_spec); if (stderr_file_spec) m_gdb_comm.SetSTDERR(stderr_file_spec); m_gdb_comm.SetDisableASLR(launch_flags & eLaunchFlagDisableASLR); m_gdb_comm.SetDetachOnError(launch_flags & eLaunchFlagDetachOnError); m_gdb_comm.SendLaunchArchPacket( GetTarget().GetArchitecture().GetArchitectureName()); const char *launch_event_data = launch_info.GetLaunchEventData(); if (launch_event_data != NULL && *launch_event_data != '\0') m_gdb_comm.SendLaunchEventDataPacket(launch_event_data); if (working_dir) { m_gdb_comm.SetWorkingDir(working_dir); } // Send the environment and the program + arguments after we connect const Args &environment = launch_info.GetEnvironmentEntries(); if (environment.GetArgumentCount()) { size_t num_environment_entries = environment.GetArgumentCount(); for (size_t i = 0; i < num_environment_entries; ++i) { const char *env_entry = environment.GetArgumentAtIndex(i); if (env_entry == NULL || m_gdb_comm.SendEnvironmentPacket(env_entry) != 0) break; } } { // Scope for the scoped timeout object GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm, std::chrono::seconds(10)); int arg_packet_err = m_gdb_comm.SendArgumentsPacket(launch_info); if (arg_packet_err == 0) { std::string error_str; if (m_gdb_comm.GetLaunchSuccess(error_str)) { SetID(m_gdb_comm.GetCurrentProcessID()); } else { error.SetErrorString(error_str.c_str()); } } else { error.SetErrorStringWithFormat("'A' packet returned an error: %i", arg_packet_err); } } if (GetID() == LLDB_INVALID_PROCESS_ID) { if (log) log->Printf("failed to connect to debugserver: %s", error.AsCString()); KillDebugserverProcess(); return error; } StringExtractorGDBRemote response; if (m_gdb_comm.GetStopReply(response)) { SetLastStopPacket(response); // '?' Packets must be handled differently in non-stop mode if (GetTarget().GetNonStopModeEnabled()) HandleStopReplySequence(); const ArchSpec &process_arch = m_gdb_comm.GetProcessArchitecture(); if (process_arch.IsValid()) { GetTarget().MergeArchitecture(process_arch); } else { const ArchSpec &host_arch = m_gdb_comm.GetHostArchitecture(); if (host_arch.IsValid()) GetTarget().MergeArchitecture(host_arch); } SetPrivateState(SetThreadStopInfo(response)); if (!disable_stdio) { if (pty.GetMasterFileDescriptor() != lldb_utility::PseudoTerminal::invalid_fd) SetSTDIOFileDescriptor(pty.ReleaseMasterFileDescriptor()); } } } else { if (log) log->Printf("failed to connect to debugserver: %s", error.AsCString()); } } else { // Set our user ID to an invalid process ID. SetID(LLDB_INVALID_PROCESS_ID); error.SetErrorStringWithFormat( "failed to get object file from '%s' for arch %s", exe_module->GetFileSpec().GetFilename().AsCString(), exe_module->GetArchitecture().GetArchitectureName()); } return error; } Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { Status error; // Only connect if we have a valid connect URL Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (!connect_url.empty()) { if (log) log->Printf("ProcessGDBRemote::%s Connecting to %s", __FUNCTION__, connect_url.str().c_str()); std::unique_ptr conn_ap( new ConnectionFileDescriptor()); if (conn_ap.get()) { const uint32_t max_retry_count = 50; uint32_t retry_count = 0; while (!m_gdb_comm.IsConnected()) { if (conn_ap->Connect(connect_url, &error) == eConnectionStatusSuccess) { m_gdb_comm.SetConnection(conn_ap.release()); break; } else if (error.WasInterrupted()) { // If we were interrupted, don't keep retrying. break; } retry_count++; if (retry_count >= max_retry_count) break; usleep(100000); } } } if (!m_gdb_comm.IsConnected()) { if (error.Success()) error.SetErrorString("not connected to remote gdb server"); return error; } // Start the communications read thread so all incoming data can be // parsed into packets and queued as they arrive. if (GetTarget().GetNonStopModeEnabled()) m_gdb_comm.StartReadThread(); // We always seem to be able to open a connection to a local port // so we need to make sure we can then send data to it. If we can't // then we aren't actually connected to anything, so try and do the // handshake with the remote GDB server and make sure that goes // alright. if (!m_gdb_comm.HandshakeWithServer(&error)) { m_gdb_comm.Disconnect(); if (error.Success()) error.SetErrorString("not connected to remote gdb server"); return error; } // Send $QNonStop:1 packet on startup if required if (GetTarget().GetNonStopModeEnabled()) GetTarget().SetNonStopModeEnabled(m_gdb_comm.SetNonStopMode(true)); m_gdb_comm.GetEchoSupported(); m_gdb_comm.GetThreadSuffixSupported(); m_gdb_comm.GetListThreadsInStopReplySupported(); m_gdb_comm.GetHostInfo(); m_gdb_comm.GetVContSupported('c'); m_gdb_comm.GetVAttachOrWaitSupported(); + m_gdb_comm.EnableErrorStringInPacket(); // Ask the remote server for the default thread id if (GetTarget().GetNonStopModeEnabled()) m_gdb_comm.GetDefaultThreadId(m_initial_tid); size_t num_cmds = GetExtraStartupCommands().GetArgumentCount(); for (size_t idx = 0; idx < num_cmds; idx++) { StringExtractorGDBRemote response; m_gdb_comm.SendPacketAndWaitForResponse( GetExtraStartupCommands().GetArgumentAtIndex(idx), response, false); } return error; } void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (log) log->Printf("ProcessGDBRemote::%s()", __FUNCTION__); if (GetID() != LLDB_INVALID_PROCESS_ID) { BuildDynamicRegisterInfo(false); // See if the GDB server supports the qHostInfo information // See if the GDB server supports the qProcessInfo packet, if so // prefer that over the Host information as it will be more specific // to our process. const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture(); if (remote_process_arch.IsValid()) { process_arch = remote_process_arch; if (log) log->Printf("ProcessGDBRemote::%s gdb-remote had process architecture, " "using %s %s", __FUNCTION__, process_arch.GetArchitectureName() ? process_arch.GetArchitectureName() : "", process_arch.GetTriple().getTriple().c_str() ? process_arch.GetTriple().getTriple().c_str() : ""); } else { process_arch = m_gdb_comm.GetHostArchitecture(); if (log) log->Printf("ProcessGDBRemote::%s gdb-remote did not have process " "architecture, using gdb-remote host architecture %s %s", __FUNCTION__, process_arch.GetArchitectureName() ? process_arch.GetArchitectureName() : "", process_arch.GetTriple().getTriple().c_str() ? process_arch.GetTriple().getTriple().c_str() : ""); } if (process_arch.IsValid()) { const ArchSpec &target_arch = GetTarget().GetArchitecture(); if (target_arch.IsValid()) { if (log) log->Printf( "ProcessGDBRemote::%s analyzing target arch, currently %s %s", __FUNCTION__, target_arch.GetArchitectureName() ? target_arch.GetArchitectureName() : "", target_arch.GetTriple().getTriple().c_str() ? target_arch.GetTriple().getTriple().c_str() : ""); // If the remote host is ARM and we have apple as the vendor, then // ARM executables and shared libraries can have mixed ARM // architectures. // You can have an armv6 executable, and if the host is armv7, then the // system will load the best possible architecture for all shared // libraries // it has, so we really need to take the remote host architecture as our // defacto architecture in this case. if ((process_arch.GetMachine() == llvm::Triple::arm || process_arch.GetMachine() == llvm::Triple::thumb) && process_arch.GetTriple().getVendor() == llvm::Triple::Apple) { GetTarget().SetArchitecture(process_arch); if (log) log->Printf("ProcessGDBRemote::%s remote process is ARM/Apple, " "setting target arch to %s %s", __FUNCTION__, process_arch.GetArchitectureName() ? process_arch.GetArchitectureName() : "", process_arch.GetTriple().getTriple().c_str() ? process_arch.GetTriple().getTriple().c_str() : ""); } else { // Fill in what is missing in the triple const llvm::Triple &remote_triple = process_arch.GetTriple(); llvm::Triple new_target_triple = target_arch.GetTriple(); if (new_target_triple.getVendorName().size() == 0) { new_target_triple.setVendor(remote_triple.getVendor()); if (new_target_triple.getOSName().size() == 0) { new_target_triple.setOS(remote_triple.getOS()); if (new_target_triple.getEnvironmentName().size() == 0) new_target_triple.setEnvironment( remote_triple.getEnvironment()); } ArchSpec new_target_arch = target_arch; new_target_arch.SetTriple(new_target_triple); GetTarget().SetArchitecture(new_target_arch); } } if (log) log->Printf("ProcessGDBRemote::%s final target arch after " "adjustments for remote architecture: %s %s", __FUNCTION__, target_arch.GetArchitectureName() ? target_arch.GetArchitectureName() : "", target_arch.GetTriple().getTriple().c_str() ? target_arch.GetTriple().getTriple().c_str() : ""); } else { // The target doesn't have a valid architecture yet, set it from // the architecture we got from the remote GDB server GetTarget().SetArchitecture(process_arch); } } // Find out which StructuredDataPlugins are supported by the // debug monitor. These plugins transmit data over async $J packets. auto supported_packets_array = m_gdb_comm.GetSupportedStructuredDataPlugins(); if (supported_packets_array) MapSupportedStructuredDataPlugins(*supported_packets_array); } } void ProcessGDBRemote::DidLaunch() { ArchSpec process_arch; DidLaunchOrAttach(process_arch); } Status ProcessGDBRemote::DoAttachToProcessWithID( lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); Status error; if (log) log->Printf("ProcessGDBRemote::%s()", __FUNCTION__); // Clear out and clean up from any current state Clear(); if (attach_pid != LLDB_INVALID_PROCESS_ID) { error = EstablishConnectionIfNeeded(attach_info); if (error.Success()) { m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError()); char packet[64]; const int packet_len = ::snprintf(packet, sizeof(packet), "vAttach;%" PRIx64, attach_pid); SetID(attach_pid); m_async_broadcaster.BroadcastEvent( eBroadcastBitAsyncContinue, new EventDataBytes(packet, packet_len)); } else SetExitStatus(-1, error.AsCString()); } return error; } Status ProcessGDBRemote::DoAttachToProcessWithName( const char *process_name, const ProcessAttachInfo &attach_info) { Status error; // Clear out and clean up from any current state Clear(); if (process_name && process_name[0]) { error = EstablishConnectionIfNeeded(attach_info); if (error.Success()) { StreamString packet; m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError()); if (attach_info.GetWaitForLaunch()) { if (!m_gdb_comm.GetVAttachOrWaitSupported()) { packet.PutCString("vAttachWait"); } else { if (attach_info.GetIgnoreExisting()) packet.PutCString("vAttachWait"); else packet.PutCString("vAttachOrWait"); } } else packet.PutCString("vAttachName"); packet.PutChar(';'); packet.PutBytesAsRawHex8(process_name, strlen(process_name), endian::InlHostByteOrder(), endian::InlHostByteOrder()); m_async_broadcaster.BroadcastEvent( eBroadcastBitAsyncContinue, new EventDataBytes(packet.GetString().data(), packet.GetSize())); } else SetExitStatus(-1, error.AsCString()); } return error; } lldb::user_id_t ProcessGDBRemote::StartTrace(const TraceOptions &options, Status &error) { return m_gdb_comm.SendStartTracePacket(options, error); } Status ProcessGDBRemote::StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) { return m_gdb_comm.SendStopTracePacket(uid, thread_id); } Status ProcessGDBRemote::GetData(lldb::user_id_t uid, lldb::tid_t thread_id, llvm::MutableArrayRef &buffer, size_t offset) { return m_gdb_comm.SendGetDataPacket(uid, thread_id, buffer, offset); } Status ProcessGDBRemote::GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id, llvm::MutableArrayRef &buffer, size_t offset) { return m_gdb_comm.SendGetMetaDataPacket(uid, thread_id, buffer, offset); } Status ProcessGDBRemote::GetTraceConfig(lldb::user_id_t uid, TraceOptions &options) { return m_gdb_comm.SendGetTraceConfigPacket(uid, options); } void ProcessGDBRemote::DidExit() { // When we exit, disconnect from the GDB server communications m_gdb_comm.Disconnect(); } void ProcessGDBRemote::DidAttach(ArchSpec &process_arch) { // If you can figure out what the architecture is, fill it in here. process_arch.Clear(); DidLaunchOrAttach(process_arch); } Status ProcessGDBRemote::WillResume() { m_continue_c_tids.clear(); m_continue_C_tids.clear(); m_continue_s_tids.clear(); m_continue_S_tids.clear(); m_jstopinfo_sp.reset(); m_jthreadsinfo_sp.reset(); return Status(); } Status ProcessGDBRemote::DoResume() { Status error; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (log) log->Printf("ProcessGDBRemote::Resume()"); ListenerSP listener_sp( Listener::MakeListener("gdb-remote.resume-packet-sent")); if (listener_sp->StartListeningForEvents( &m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent)) { listener_sp->StartListeningForEvents( &m_async_broadcaster, ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit); const size_t num_threads = GetThreadList().GetSize(); StreamString continue_packet; bool continue_packet_error = false; if (m_gdb_comm.HasAnyVContSupport()) { if (!GetTarget().GetNonStopModeEnabled() && (m_continue_c_tids.size() == num_threads || (m_continue_c_tids.empty() && m_continue_C_tids.empty() && m_continue_s_tids.empty() && m_continue_S_tids.empty()))) { // All threads are continuing, just send a "c" packet continue_packet.PutCString("c"); } else { continue_packet.PutCString("vCont"); if (!m_continue_c_tids.empty()) { if (m_gdb_comm.GetVContSupported('c')) { for (tid_collection::const_iterator t_pos = m_continue_c_tids.begin(), t_end = m_continue_c_tids.end(); t_pos != t_end; ++t_pos) continue_packet.Printf(";c:%4.4" PRIx64, *t_pos); } else continue_packet_error = true; } if (!continue_packet_error && !m_continue_C_tids.empty()) { if (m_gdb_comm.GetVContSupported('C')) { for (tid_sig_collection::const_iterator s_pos = m_continue_C_tids.begin(), s_end = m_continue_C_tids.end(); s_pos != s_end; ++s_pos) continue_packet.Printf(";C%2.2x:%4.4" PRIx64, s_pos->second, s_pos->first); } else continue_packet_error = true; } if (!continue_packet_error && !m_continue_s_tids.empty()) { if (m_gdb_comm.GetVContSupported('s')) { for (tid_collection::const_iterator t_pos = m_continue_s_tids.begin(), t_end = m_continue_s_tids.end(); t_pos != t_end; ++t_pos) continue_packet.Printf(";s:%4.4" PRIx64, *t_pos); } else continue_packet_error = true; } if (!continue_packet_error && !m_continue_S_tids.empty()) { if (m_gdb_comm.GetVContSupported('S')) { for (tid_sig_collection::const_iterator s_pos = m_continue_S_tids.begin(), s_end = m_continue_S_tids.end(); s_pos != s_end; ++s_pos) continue_packet.Printf(";S%2.2x:%4.4" PRIx64, s_pos->second, s_pos->first); } else continue_packet_error = true; } if (continue_packet_error) continue_packet.Clear(); } } else continue_packet_error = true; if (continue_packet_error) { // Either no vCont support, or we tried to use part of the vCont // packet that wasn't supported by the remote GDB server. // We need to try and make a simple packet that can do our continue const size_t num_continue_c_tids = m_continue_c_tids.size(); const size_t num_continue_C_tids = m_continue_C_tids.size(); const size_t num_continue_s_tids = m_continue_s_tids.size(); const size_t num_continue_S_tids = m_continue_S_tids.size(); if (num_continue_c_tids > 0) { if (num_continue_c_tids == num_threads) { // All threads are resuming... m_gdb_comm.SetCurrentThreadForRun(-1); continue_packet.PutChar('c'); continue_packet_error = false; } else if (num_continue_c_tids == 1 && num_continue_C_tids == 0 && num_continue_s_tids == 0 && num_continue_S_tids == 0) { // Only one thread is continuing m_gdb_comm.SetCurrentThreadForRun(m_continue_c_tids.front()); continue_packet.PutChar('c'); continue_packet_error = false; } } if (continue_packet_error && num_continue_C_tids > 0) { if ((num_continue_C_tids + num_continue_c_tids) == num_threads && num_continue_C_tids > 0 && num_continue_s_tids == 0 && num_continue_S_tids == 0) { const int continue_signo = m_continue_C_tids.front().second; // Only one thread is continuing if (num_continue_C_tids > 1) { // More that one thread with a signal, yet we don't have // vCont support and we are being asked to resume each // thread with a signal, we need to make sure they are // all the same signal, or we can't issue the continue // accurately with the current support... if (num_continue_C_tids > 1) { continue_packet_error = false; for (size_t i = 1; i < m_continue_C_tids.size(); ++i) { if (m_continue_C_tids[i].second != continue_signo) continue_packet_error = true; } } if (!continue_packet_error) m_gdb_comm.SetCurrentThreadForRun(-1); } else { // Set the continue thread ID continue_packet_error = false; m_gdb_comm.SetCurrentThreadForRun(m_continue_C_tids.front().first); } if (!continue_packet_error) { // Add threads continuing with the same signo... continue_packet.Printf("C%2.2x", continue_signo); } } } if (continue_packet_error && num_continue_s_tids > 0) { if (num_continue_s_tids == num_threads) { // All threads are resuming... m_gdb_comm.SetCurrentThreadForRun(-1); // If in Non-Stop-Mode use vCont when stepping if (GetTarget().GetNonStopModeEnabled()) { if (m_gdb_comm.GetVContSupported('s')) continue_packet.PutCString("vCont;s"); else continue_packet.PutChar('s'); } else continue_packet.PutChar('s'); continue_packet_error = false; } else if (num_continue_c_tids == 0 && num_continue_C_tids == 0 && num_continue_s_tids == 1 && num_continue_S_tids == 0) { // Only one thread is stepping m_gdb_comm.SetCurrentThreadForRun(m_continue_s_tids.front()); continue_packet.PutChar('s'); continue_packet_error = false; } } if (!continue_packet_error && num_continue_S_tids > 0) { if (num_continue_S_tids == num_threads) { const int step_signo = m_continue_S_tids.front().second; // Are all threads trying to step with the same signal? continue_packet_error = false; if (num_continue_S_tids > 1) { for (size_t i = 1; i < num_threads; ++i) { if (m_continue_S_tids[i].second != step_signo) continue_packet_error = true; } } if (!continue_packet_error) { // Add threads stepping with the same signo... m_gdb_comm.SetCurrentThreadForRun(-1); continue_packet.Printf("S%2.2x", step_signo); } } else if (num_continue_c_tids == 0 && num_continue_C_tids == 0 && num_continue_s_tids == 0 && num_continue_S_tids == 1) { // Only one thread is stepping with signal m_gdb_comm.SetCurrentThreadForRun(m_continue_S_tids.front().first); continue_packet.Printf("S%2.2x", m_continue_S_tids.front().second); continue_packet_error = false; } } } if (continue_packet_error) { error.SetErrorString("can't make continue packet for this resume"); } else { EventSP event_sp; if (!m_async_thread.IsJoinable()) { error.SetErrorString("Trying to resume but the async thread is dead."); if (log) log->Printf("ProcessGDBRemote::DoResume: Trying to resume but the " "async thread is dead."); return error; } m_async_broadcaster.BroadcastEvent( eBroadcastBitAsyncContinue, new EventDataBytes(continue_packet.GetString().data(), continue_packet.GetSize())); if (listener_sp->GetEvent(event_sp, std::chrono::seconds(5)) == false) { error.SetErrorString("Resume timed out."); if (log) log->Printf("ProcessGDBRemote::DoResume: Resume timed out."); } else if (event_sp->BroadcasterIs(&m_async_broadcaster)) { error.SetErrorString("Broadcast continue, but the async thread was " "killed before we got an ack back."); if (log) log->Printf("ProcessGDBRemote::DoResume: Broadcast continue, but the " "async thread was killed before we got an ack back."); return error; } } } return error; } void ProcessGDBRemote::HandleStopReplySequence() { while (true) { // Send vStopped StringExtractorGDBRemote response; m_gdb_comm.SendPacketAndWaitForResponse("vStopped", response, false); // OK represents end of signal list if (response.IsOKResponse()) break; // If not OK or a normal packet we have a problem if (!response.IsNormalResponse()) break; SetLastStopPacket(response); } } void ProcessGDBRemote::ClearThreadIDList() { std::lock_guard guard(m_thread_list_real.GetMutex()); m_thread_ids.clear(); m_thread_pcs.clear(); } size_t ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue(std::string &value) { m_thread_ids.clear(); m_thread_pcs.clear(); size_t comma_pos; lldb::tid_t tid; while ((comma_pos = value.find(',')) != std::string::npos) { value[comma_pos] = '\0'; // thread in big endian hex tid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_THREAD_ID, 16); if (tid != LLDB_INVALID_THREAD_ID) m_thread_ids.push_back(tid); value.erase(0, comma_pos + 1); } tid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_THREAD_ID, 16); if (tid != LLDB_INVALID_THREAD_ID) m_thread_ids.push_back(tid); return m_thread_ids.size(); } size_t ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue(std::string &value) { m_thread_pcs.clear(); size_t comma_pos; lldb::addr_t pc; while ((comma_pos = value.find(',')) != std::string::npos) { value[comma_pos] = '\0'; pc = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16); if (pc != LLDB_INVALID_ADDRESS) m_thread_pcs.push_back(pc); value.erase(0, comma_pos + 1); } pc = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16); if (pc != LLDB_INVALID_THREAD_ID) m_thread_pcs.push_back(pc); return m_thread_pcs.size(); } bool ProcessGDBRemote::UpdateThreadIDList() { std::lock_guard guard(m_thread_list_real.GetMutex()); if (m_jthreadsinfo_sp) { // If we have the JSON threads info, we can get the thread list from that StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray(); if (thread_infos && thread_infos->GetSize() > 0) { m_thread_ids.clear(); m_thread_pcs.clear(); thread_infos->ForEach([this](StructuredData::Object *object) -> bool { StructuredData::Dictionary *thread_dict = object->GetAsDictionary(); if (thread_dict) { // Set the thread stop info from the JSON dictionary SetThreadStopInfo(thread_dict); lldb::tid_t tid = LLDB_INVALID_THREAD_ID; if (thread_dict->GetValueForKeyAsInteger("tid", tid)) m_thread_ids.push_back(tid); } return true; // Keep iterating through all thread_info objects }); } if (!m_thread_ids.empty()) return true; } else { // See if we can get the thread IDs from the current stop reply packets // that might contain a "threads" key/value pair // Lock the thread stack while we access it // Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex); std::unique_lock stop_stack_lock( m_last_stop_packet_mutex, std::defer_lock); if (stop_stack_lock.try_lock()) { // Get the number of stop packets on the stack int nItems = m_stop_packet_stack.size(); // Iterate over them for (int i = 0; i < nItems; i++) { // Get the thread stop info StringExtractorGDBRemote &stop_info = m_stop_packet_stack[i]; const std::string &stop_info_str = stop_info.GetStringRef(); m_thread_pcs.clear(); const size_t thread_pcs_pos = stop_info_str.find(";thread-pcs:"); if (thread_pcs_pos != std::string::npos) { const size_t start = thread_pcs_pos + strlen(";thread-pcs:"); const size_t end = stop_info_str.find(';', start); if (end != std::string::npos) { std::string value = stop_info_str.substr(start, end - start); UpdateThreadPCsFromStopReplyThreadsValue(value); } } const size_t threads_pos = stop_info_str.find(";threads:"); if (threads_pos != std::string::npos) { const size_t start = threads_pos + strlen(";threads:"); const size_t end = stop_info_str.find(';', start); if (end != std::string::npos) { std::string value = stop_info_str.substr(start, end - start); if (UpdateThreadIDsFromStopReplyThreadsValue(value)) return true; } } } } } bool sequence_mutex_unavailable = false; m_gdb_comm.GetCurrentThreadIDs(m_thread_ids, sequence_mutex_unavailable); if (sequence_mutex_unavailable) { return false; // We just didn't get the list } return true; } bool ProcessGDBRemote::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) { // locker will keep a mutex locked until it goes out of scope Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_THREAD)); LLDB_LOGV(log, "pid = {0}", GetID()); size_t num_thread_ids = m_thread_ids.size(); // The "m_thread_ids" thread ID list should always be updated after each stop // reply packet, but in case it isn't, update it here. if (num_thread_ids == 0) { if (!UpdateThreadIDList()) return false; num_thread_ids = m_thread_ids.size(); } ThreadList old_thread_list_copy(old_thread_list); if (num_thread_ids > 0) { for (size_t i = 0; i < num_thread_ids; ++i) { tid_t tid = m_thread_ids[i]; ThreadSP thread_sp( old_thread_list_copy.RemoveThreadByProtocolID(tid, false)); if (!thread_sp) { thread_sp.reset(new ThreadGDBRemote(*this, tid)); LLDB_LOGV(log, "Making new thread: {0} for thread ID: {1:x}.", thread_sp.get(), thread_sp->GetID()); } else { LLDB_LOGV(log, "Found old thread: {0} for thread ID: {1:x}.", thread_sp.get(), thread_sp->GetID()); } SetThreadPc(thread_sp, i); new_thread_list.AddThreadSortedByIndexID(thread_sp); } } // Whatever that is left in old_thread_list_copy are not // present in new_thread_list. Remove non-existent threads from internal id // table. size_t old_num_thread_ids = old_thread_list_copy.GetSize(false); for (size_t i = 0; i < old_num_thread_ids; i++) { ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false)); if (old_thread_sp) { lldb::tid_t old_thread_id = old_thread_sp->GetProtocolID(); m_thread_id_to_index_id_map.erase(old_thread_id); } } return true; } void ProcessGDBRemote::SetThreadPc(const ThreadSP &thread_sp, uint64_t index) { if (m_thread_ids.size() == m_thread_pcs.size() && thread_sp.get() && GetByteOrder() != eByteOrderInvalid) { ThreadGDBRemote *gdb_thread = static_cast(thread_sp.get()); RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext()); if (reg_ctx_sp) { uint32_t pc_regnum = reg_ctx_sp->ConvertRegisterKindToRegisterNumber( eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); if (pc_regnum != LLDB_INVALID_REGNUM) { gdb_thread->PrivateSetRegisterValue(pc_regnum, m_thread_pcs[index]); } } } } bool ProcessGDBRemote::GetThreadStopInfoFromJSON( ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp) { // See if we got thread stop infos for all threads via the "jThreadsInfo" // packet if (thread_infos_sp) { StructuredData::Array *thread_infos = thread_infos_sp->GetAsArray(); if (thread_infos) { lldb::tid_t tid; const size_t n = thread_infos->GetSize(); for (size_t i = 0; i < n; ++i) { StructuredData::Dictionary *thread_dict = thread_infos->GetItemAtIndex(i)->GetAsDictionary(); if (thread_dict) { if (thread_dict->GetValueForKeyAsInteger( "tid", tid, LLDB_INVALID_THREAD_ID)) { if (tid == thread->GetID()) return (bool)SetThreadStopInfo(thread_dict); } } } } } return false; } bool ProcessGDBRemote::CalculateThreadStopInfo(ThreadGDBRemote *thread) { // See if we got thread stop infos for all threads via the "jThreadsInfo" // packet if (GetThreadStopInfoFromJSON(thread, m_jthreadsinfo_sp)) return true; // See if we got thread stop info for any threads valid stop info reasons // threads // via the "jstopinfo" packet stop reply packet key/value pair? if (m_jstopinfo_sp) { // If we have "jstopinfo" then we have stop descriptions for all threads // that have stop reasons, and if there is no entry for a thread, then // it has no stop reason. thread->GetRegisterContext()->InvalidateIfNeeded(true); if (!GetThreadStopInfoFromJSON(thread, m_jstopinfo_sp)) { thread->SetStopInfo(StopInfoSP()); } return true; } // Fall back to using the qThreadStopInfo packet StringExtractorGDBRemote stop_packet; if (GetGDBRemote().GetThreadStopInfo(thread->GetProtocolID(), stop_packet)) return SetThreadStopInfo(stop_packet) == eStateStopped; return false; } ThreadSP ProcessGDBRemote::SetThreadStopInfo( lldb::tid_t tid, ExpeditedRegisterMap &expedited_register_map, uint8_t signo, const std::string &thread_name, const std::string &reason, const std::string &description, uint32_t exc_type, const std::vector &exc_data, addr_t thread_dispatch_qaddr, bool queue_vars_valid, // Set to true if queue_name, queue_kind and // queue_serial are valid LazyBool associated_with_dispatch_queue, addr_t dispatch_queue_t, std::string &queue_name, QueueKind queue_kind, uint64_t queue_serial) { ThreadSP thread_sp; if (tid != LLDB_INVALID_THREAD_ID) { // Scope for "locker" below { // m_thread_list_real does have its own mutex, but we need to // hold onto the mutex between the call to // m_thread_list_real.FindThreadByID(...) // and the m_thread_list_real.AddThread(...) so it doesn't change on us std::lock_guard guard( m_thread_list_real.GetMutex()); thread_sp = m_thread_list_real.FindThreadByProtocolID(tid, false); if (!thread_sp) { // Create the thread if we need to thread_sp.reset(new ThreadGDBRemote(*this, tid)); m_thread_list_real.AddThread(thread_sp); } } if (thread_sp) { ThreadGDBRemote *gdb_thread = static_cast(thread_sp.get()); gdb_thread->GetRegisterContext()->InvalidateIfNeeded(true); auto iter = std::find(m_thread_ids.begin(), m_thread_ids.end(), tid); if (iter != m_thread_ids.end()) { SetThreadPc(thread_sp, iter - m_thread_ids.begin()); } for (const auto &pair : expedited_register_map) { StringExtractor reg_value_extractor; reg_value_extractor.GetStringRef() = pair.second; DataBufferSP buffer_sp(new DataBufferHeap( reg_value_extractor.GetStringRef().size() / 2, 0)); reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc'); gdb_thread->PrivateSetRegisterValue(pair.first, buffer_sp->GetData()); } thread_sp->SetName(thread_name.empty() ? NULL : thread_name.c_str()); gdb_thread->SetThreadDispatchQAddr(thread_dispatch_qaddr); // Check if the GDB server was able to provide the queue name, kind and // serial number if (queue_vars_valid) gdb_thread->SetQueueInfo(std::move(queue_name), queue_kind, queue_serial, dispatch_queue_t, associated_with_dispatch_queue); else gdb_thread->ClearQueueInfo(); gdb_thread->SetAssociatedWithLibdispatchQueue( associated_with_dispatch_queue); if (dispatch_queue_t != LLDB_INVALID_ADDRESS) gdb_thread->SetQueueLibdispatchQueueAddress(dispatch_queue_t); // Make sure we update our thread stop reason just once if (!thread_sp->StopInfoIsUpToDate()) { thread_sp->SetStopInfo(StopInfoSP()); // If there's a memory thread backed by this thread, we need to use it // to calcualte StopInfo. ThreadSP memory_thread_sp = m_thread_list.FindThreadByProtocolID(thread_sp->GetProtocolID()); if (memory_thread_sp) thread_sp = memory_thread_sp; if (exc_type != 0) { const size_t exc_data_size = exc_data.size(); thread_sp->SetStopInfo( StopInfoMachException::CreateStopReasonWithMachException( *thread_sp, exc_type, exc_data_size, exc_data_size >= 1 ? exc_data[0] : 0, exc_data_size >= 2 ? exc_data[1] : 0, exc_data_size >= 3 ? exc_data[2] : 0)); } else { bool handled = false; bool did_exec = false; if (!reason.empty()) { if (reason.compare("trace") == 0) { addr_t pc = thread_sp->GetRegisterContext()->GetPC(); lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess() ->GetBreakpointSiteList() .FindByAddress(pc); // If the current pc is a breakpoint site then the StopInfo should // be set to Breakpoint // Otherwise, it will be set to Trace. if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get())) { thread_sp->SetStopInfo( StopInfo::CreateStopReasonWithBreakpointSiteID( *thread_sp, bp_site_sp->GetID())); } else thread_sp->SetStopInfo( StopInfo::CreateStopReasonToTrace(*thread_sp)); handled = true; } else if (reason.compare("breakpoint") == 0) { addr_t pc = thread_sp->GetRegisterContext()->GetPC(); lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess() ->GetBreakpointSiteList() .FindByAddress(pc); if (bp_site_sp) { // If the breakpoint is for this thread, then we'll report the // hit, but if it is for another thread, // we can just report no reason. We don't need to worry about // stepping over the breakpoint here, that // will be taken care of when the thread resumes and notices // that there's a breakpoint under the pc. handled = true; if (bp_site_sp->ValidForThisThread(thread_sp.get())) { thread_sp->SetStopInfo( StopInfo::CreateStopReasonWithBreakpointSiteID( *thread_sp, bp_site_sp->GetID())); } else { StopInfoSP invalid_stop_info_sp; thread_sp->SetStopInfo(invalid_stop_info_sp); } } } else if (reason.compare("trap") == 0) { // Let the trap just use the standard signal stop reason below... } else if (reason.compare("watchpoint") == 0) { StringExtractor desc_extractor(description.c_str()); addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32); addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); watch_id_t watch_id = LLDB_INVALID_WATCH_ID; if (wp_addr != LLDB_INVALID_ADDRESS) { WatchpointSP wp_sp; ArchSpec::Core core = GetTarget().GetArchitecture().GetCore(); if ((core >= ArchSpec::kCore_mips_first && core <= ArchSpec::kCore_mips_last) || (core >= ArchSpec::eCore_arm_generic && core <= ArchSpec::eCore_arm_aarch64)) wp_sp = GetTarget().GetWatchpointList().FindByAddress( wp_hit_addr); if (!wp_sp) wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr); if (wp_sp) { wp_sp->SetHardwareIndex(wp_index); watch_id = wp_sp->GetID(); } } if (watch_id == LLDB_INVALID_WATCH_ID) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet( GDBR_LOG_WATCHPOINTS)); if (log) log->Printf("failed to find watchpoint"); } thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithWatchpointID( *thread_sp, watch_id, wp_hit_addr)); handled = true; } else if (reason.compare("exception") == 0) { thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException( *thread_sp, description.c_str())); handled = true; } else if (reason.compare("exec") == 0) { did_exec = true; thread_sp->SetStopInfo( StopInfo::CreateStopReasonWithExec(*thread_sp)); handled = true; } } else if (!signo) { addr_t pc = thread_sp->GetRegisterContext()->GetPC(); lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress( pc); // If the current pc is a breakpoint site then the StopInfo should // be set to Breakpoint // even though the remote stub did not set it as such. This can // happen when // the thread is involuntarily interrupted (e.g. due to stops on // other // threads) just as it is about to execute the breakpoint // instruction. if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get())) { thread_sp->SetStopInfo( StopInfo::CreateStopReasonWithBreakpointSiteID( *thread_sp, bp_site_sp->GetID())); handled = true; } } if (!handled && signo && did_exec == false) { if (signo == SIGTRAP) { // Currently we are going to assume SIGTRAP means we are either // hitting a breakpoint or hardware single stepping. handled = true; addr_t pc = thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset; lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess() ->GetBreakpointSiteList() .FindByAddress(pc); if (bp_site_sp) { // If the breakpoint is for this thread, then we'll report the // hit, but if it is for another thread, // we can just report no reason. We don't need to worry about // stepping over the breakpoint here, that // will be taken care of when the thread resumes and notices // that there's a breakpoint under the pc. if (bp_site_sp->ValidForThisThread(thread_sp.get())) { if (m_breakpoint_pc_offset != 0) thread_sp->GetRegisterContext()->SetPC(pc); thread_sp->SetStopInfo( StopInfo::CreateStopReasonWithBreakpointSiteID( *thread_sp, bp_site_sp->GetID())); } else { StopInfoSP invalid_stop_info_sp; thread_sp->SetStopInfo(invalid_stop_info_sp); } } else { // If we were stepping then assume the stop was the result of // the trace. If we were // not stepping then report the SIGTRAP. // FIXME: We are still missing the case where we single step // over a trap instruction. if (thread_sp->GetTemporaryResumeState() == eStateStepping) thread_sp->SetStopInfo( StopInfo::CreateStopReasonToTrace(*thread_sp)); else thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithSignal( *thread_sp, signo, description.c_str())); } } if (!handled) thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithSignal( *thread_sp, signo, description.c_str())); } if (!description.empty()) { lldb::StopInfoSP stop_info_sp(thread_sp->GetStopInfo()); if (stop_info_sp) { const char *stop_info_desc = stop_info_sp->GetDescription(); if (!stop_info_desc || !stop_info_desc[0]) stop_info_sp->SetDescription(description.c_str()); } else { thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException( *thread_sp, description.c_str())); } } } } } } return thread_sp; } lldb::ThreadSP ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) { static ConstString g_key_tid("tid"); static ConstString g_key_name("name"); static ConstString g_key_reason("reason"); static ConstString g_key_metype("metype"); static ConstString g_key_medata("medata"); static ConstString g_key_qaddr("qaddr"); static ConstString g_key_dispatch_queue_t("dispatch_queue_t"); static ConstString g_key_associated_with_dispatch_queue( "associated_with_dispatch_queue"); static ConstString g_key_queue_name("qname"); static ConstString g_key_queue_kind("qkind"); static ConstString g_key_queue_serial_number("qserialnum"); static ConstString g_key_registers("registers"); static ConstString g_key_memory("memory"); static ConstString g_key_address("address"); static ConstString g_key_bytes("bytes"); static ConstString g_key_description("description"); static ConstString g_key_signal("signal"); // Stop with signal and thread info lldb::tid_t tid = LLDB_INVALID_THREAD_ID; uint8_t signo = 0; std::string value; std::string thread_name; std::string reason; std::string description; uint32_t exc_type = 0; std::vector exc_data; addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS; ExpeditedRegisterMap expedited_register_map; bool queue_vars_valid = false; addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS; LazyBool associated_with_dispatch_queue = eLazyBoolCalculate; std::string queue_name; QueueKind queue_kind = eQueueKindUnknown; uint64_t queue_serial_number = 0; // Iterate through all of the thread dictionary key/value pairs from the // structured data dictionary thread_dict->ForEach([this, &tid, &expedited_register_map, &thread_name, &signo, &reason, &description, &exc_type, &exc_data, &thread_dispatch_qaddr, &queue_vars_valid, &associated_with_dispatch_queue, &dispatch_queue_t, &queue_name, &queue_kind, &queue_serial_number]( ConstString key, StructuredData::Object *object) -> bool { if (key == g_key_tid) { // thread in big endian hex tid = object->GetIntegerValue(LLDB_INVALID_THREAD_ID); } else if (key == g_key_metype) { // exception type in big endian hex exc_type = object->GetIntegerValue(0); } else if (key == g_key_medata) { // exception data in big endian hex StructuredData::Array *array = object->GetAsArray(); if (array) { array->ForEach([&exc_data](StructuredData::Object *object) -> bool { exc_data.push_back(object->GetIntegerValue()); return true; // Keep iterating through all array items }); } } else if (key == g_key_name) { thread_name = object->GetStringValue(); } else if (key == g_key_qaddr) { thread_dispatch_qaddr = object->GetIntegerValue(LLDB_INVALID_ADDRESS); } else if (key == g_key_queue_name) { queue_vars_valid = true; queue_name = object->GetStringValue(); } else if (key == g_key_queue_kind) { std::string queue_kind_str = object->GetStringValue(); if (queue_kind_str == "serial") { queue_vars_valid = true; queue_kind = eQueueKindSerial; } else if (queue_kind_str == "concurrent") { queue_vars_valid = true; queue_kind = eQueueKindConcurrent; } } else if (key == g_key_queue_serial_number) { queue_serial_number = object->GetIntegerValue(0); if (queue_serial_number != 0) queue_vars_valid = true; } else if (key == g_key_dispatch_queue_t) { dispatch_queue_t = object->GetIntegerValue(0); if (dispatch_queue_t != 0 && dispatch_queue_t != LLDB_INVALID_ADDRESS) queue_vars_valid = true; } else if (key == g_key_associated_with_dispatch_queue) { queue_vars_valid = true; bool associated = object->GetBooleanValue(); if (associated) associated_with_dispatch_queue = eLazyBoolYes; else associated_with_dispatch_queue = eLazyBoolNo; } else if (key == g_key_reason) { reason = object->GetStringValue(); } else if (key == g_key_description) { description = object->GetStringValue(); } else if (key == g_key_registers) { StructuredData::Dictionary *registers_dict = object->GetAsDictionary(); if (registers_dict) { registers_dict->ForEach( [&expedited_register_map](ConstString key, StructuredData::Object *object) -> bool { const uint32_t reg = StringConvert::ToUInt32(key.GetCString(), UINT32_MAX, 10); if (reg != UINT32_MAX) expedited_register_map[reg] = object->GetStringValue(); return true; // Keep iterating through all array items }); } } else if (key == g_key_memory) { StructuredData::Array *array = object->GetAsArray(); if (array) { array->ForEach([this](StructuredData::Object *object) -> bool { StructuredData::Dictionary *mem_cache_dict = object->GetAsDictionary(); if (mem_cache_dict) { lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS; if (mem_cache_dict->GetValueForKeyAsInteger( "address", mem_cache_addr)) { if (mem_cache_addr != LLDB_INVALID_ADDRESS) { llvm::StringRef str; if (mem_cache_dict->GetValueForKeyAsString("bytes", str)) { StringExtractor bytes(str); bytes.SetFilePos(0); const size_t byte_size = bytes.GetStringRef().size() / 2; DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0)); const size_t bytes_copied = bytes.GetHexBytes(data_buffer_sp->GetData(), 0); if (bytes_copied == byte_size) m_memory_cache.AddL1CacheData(mem_cache_addr, data_buffer_sp); } } } } return true; // Keep iterating through all array items }); } } else if (key == g_key_signal) signo = object->GetIntegerValue(LLDB_INVALID_SIGNAL_NUMBER); return true; // Keep iterating through all dictionary key/value pairs }); return SetThreadStopInfo(tid, expedited_register_map, signo, thread_name, reason, description, exc_type, exc_data, thread_dispatch_qaddr, queue_vars_valid, associated_with_dispatch_queue, dispatch_queue_t, queue_name, queue_kind, queue_serial_number); } StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { stop_packet.SetFilePos(0); const char stop_type = stop_packet.GetChar(); switch (stop_type) { case 'T': case 'S': { // This is a bit of a hack, but is is required. If we did exec, we // need to clear our thread lists and also know to rebuild our dynamic // register info before we lookup and threads and populate the expedited // register values so we need to know this right away so we can cleanup // and update our registers. const uint32_t stop_id = GetStopID(); if (stop_id == 0) { // Our first stop, make sure we have a process ID, and also make // sure we know about our registers if (GetID() == LLDB_INVALID_PROCESS_ID) { lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID(); if (pid != LLDB_INVALID_PROCESS_ID) SetID(pid); } BuildDynamicRegisterInfo(true); } // Stop with signal and thread info lldb::tid_t tid = LLDB_INVALID_THREAD_ID; const uint8_t signo = stop_packet.GetHexU8(); llvm::StringRef key; llvm::StringRef value; std::string thread_name; std::string reason; std::string description; uint32_t exc_type = 0; std::vector exc_data; addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS; bool queue_vars_valid = false; // says if locals below that start with "queue_" are valid addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS; LazyBool associated_with_dispatch_queue = eLazyBoolCalculate; std::string queue_name; QueueKind queue_kind = eQueueKindUnknown; uint64_t queue_serial_number = 0; ExpeditedRegisterMap expedited_register_map; while (stop_packet.GetNameColonValue(key, value)) { if (key.compare("metype") == 0) { // exception type in big endian hex value.getAsInteger(16, exc_type); } else if (key.compare("medata") == 0) { // exception data in big endian hex uint64_t x; value.getAsInteger(16, x); exc_data.push_back(x); } else if (key.compare("thread") == 0) { // thread in big endian hex if (value.getAsInteger(16, tid)) tid = LLDB_INVALID_THREAD_ID; } else if (key.compare("threads") == 0) { std::lock_guard guard( m_thread_list_real.GetMutex()); m_thread_ids.clear(); // A comma separated list of all threads in the current // process that includes the thread for this stop reply // packet lldb::tid_t tid; while (!value.empty()) { llvm::StringRef tid_str; std::tie(tid_str, value) = value.split(','); if (tid_str.getAsInteger(16, tid)) tid = LLDB_INVALID_THREAD_ID; m_thread_ids.push_back(tid); } } else if (key.compare("thread-pcs") == 0) { m_thread_pcs.clear(); // A comma separated list of all threads in the current // process that includes the thread for this stop reply // packet lldb::addr_t pc; while (!value.empty()) { llvm::StringRef pc_str; std::tie(pc_str, value) = value.split(','); if (pc_str.getAsInteger(16, pc)) pc = LLDB_INVALID_ADDRESS; m_thread_pcs.push_back(pc); } } else if (key.compare("jstopinfo") == 0) { StringExtractor json_extractor(value); std::string json; // Now convert the HEX bytes into a string value json_extractor.GetHexByteString(json); // This JSON contains thread IDs and thread stop info for all threads. // It doesn't contain expedited registers, memory or queue info. m_jstopinfo_sp = StructuredData::ParseJSON(json); } else if (key.compare("hexname") == 0) { StringExtractor name_extractor(value); std::string name; // Now convert the HEX bytes into a string value name_extractor.GetHexByteString(thread_name); } else if (key.compare("name") == 0) { thread_name = value; } else if (key.compare("qaddr") == 0) { value.getAsInteger(16, thread_dispatch_qaddr); } else if (key.compare("dispatch_queue_t") == 0) { queue_vars_valid = true; value.getAsInteger(16, dispatch_queue_t); } else if (key.compare("qname") == 0) { queue_vars_valid = true; StringExtractor name_extractor(value); // Now convert the HEX bytes into a string value name_extractor.GetHexByteString(queue_name); } else if (key.compare("qkind") == 0) { queue_kind = llvm::StringSwitch(value) .Case("serial", eQueueKindSerial) .Case("concurrent", eQueueKindConcurrent) .Default(eQueueKindUnknown); queue_vars_valid = queue_kind != eQueueKindUnknown; } else if (key.compare("qserialnum") == 0) { if (!value.getAsInteger(0, queue_serial_number)) queue_vars_valid = true; } else if (key.compare("reason") == 0) { reason = value; } else if (key.compare("description") == 0) { StringExtractor desc_extractor(value); // Now convert the HEX bytes into a string value desc_extractor.GetHexByteString(description); } else if (key.compare("memory") == 0) { // Expedited memory. GDB servers can choose to send back expedited // memory // that can populate the L1 memory cache in the process so that things // like // the frame pointer backchain can be expedited. This will help stack // backtracing be more efficient by not having to send as many memory // read // requests down the remote GDB server. // Key/value pair format: memory:=; // is a number whose base will be interpreted by the prefix: // "0x[0-9a-fA-F]+" for hex // "0[0-7]+" for octal // "[1-9]+" for decimal // is native endian ASCII hex bytes just like the register // values llvm::StringRef addr_str, bytes_str; std::tie(addr_str, bytes_str) = value.split('='); if (!addr_str.empty() && !bytes_str.empty()) { lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS; if (!addr_str.getAsInteger(0, mem_cache_addr)) { StringExtractor bytes(bytes_str); const size_t byte_size = bytes.GetBytesLeft() / 2; DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0)); const size_t bytes_copied = bytes.GetHexBytes(data_buffer_sp->GetData(), 0); if (bytes_copied == byte_size) m_memory_cache.AddL1CacheData(mem_cache_addr, data_buffer_sp); } } } else if (key.compare("watch") == 0 || key.compare("rwatch") == 0 || key.compare("awatch") == 0) { // Support standard GDB remote stop reply packet 'TAAwatch:addr' lldb::addr_t wp_addr = LLDB_INVALID_ADDRESS; value.getAsInteger(16, wp_addr); WatchpointSP wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr); uint32_t wp_index = LLDB_INVALID_INDEX32; if (wp_sp) wp_index = wp_sp->GetHardwareIndex(); reason = "watchpoint"; StreamString ostr; ostr.Printf("%" PRIu64 " %" PRIu32, wp_addr, wp_index); description = ostr.GetString(); } else if (key.compare("library") == 0) { LoadModules(); } else if (key.size() == 2 && ::isxdigit(key[0]) && ::isxdigit(key[1])) { uint32_t reg = UINT32_MAX; if (!key.getAsInteger(16, reg)) expedited_register_map[reg] = std::move(value); } } if (tid == LLDB_INVALID_THREAD_ID) { // A thread id may be invalid if the response is old style 'S' packet // which does not provide the // thread information. So update the thread list and choose the first one. UpdateThreadIDList(); if (!m_thread_ids.empty()) { tid = m_thread_ids.front(); } } ThreadSP thread_sp = SetThreadStopInfo( tid, expedited_register_map, signo, thread_name, reason, description, exc_type, exc_data, thread_dispatch_qaddr, queue_vars_valid, associated_with_dispatch_queue, dispatch_queue_t, queue_name, queue_kind, queue_serial_number); return eStateStopped; } break; case 'W': case 'X': // process exited return eStateExited; default: break; } return eStateInvalid; } void ProcessGDBRemote::RefreshStateAfterStop() { std::lock_guard guard(m_thread_list_real.GetMutex()); m_thread_ids.clear(); m_thread_pcs.clear(); // Set the thread stop info. It might have a "threads" key whose value is // a list of all thread IDs in the current process, so m_thread_ids might // get set. // Scope for the lock { // Lock the thread stack while we access it std::lock_guard guard(m_last_stop_packet_mutex); // Get the number of stop packets on the stack int nItems = m_stop_packet_stack.size(); // Iterate over them for (int i = 0; i < nItems; i++) { // Get the thread stop info StringExtractorGDBRemote stop_info = m_stop_packet_stack[i]; // Process thread stop info SetThreadStopInfo(stop_info); } // Clear the thread stop stack m_stop_packet_stack.clear(); } // Check to see if SetThreadStopInfo() filled in m_thread_ids? if (m_thread_ids.empty()) { // No, we need to fetch the thread list manually UpdateThreadIDList(); } // If we have queried for a default thread id if (m_initial_tid != LLDB_INVALID_THREAD_ID) { m_thread_list.SetSelectedThreadByID(m_initial_tid); m_initial_tid = LLDB_INVALID_THREAD_ID; } // Let all threads recover from stopping and do any clean up based // on the previous thread state (if any). m_thread_list_real.RefreshStateAfterStop(); } Status ProcessGDBRemote::DoHalt(bool &caused_stop) { Status error; if (m_public_state.GetValue() == eStateAttaching) { // We are being asked to halt during an attach. We need to just close // our file handle and debugserver will go away, and we can be done... m_gdb_comm.Disconnect(); } else caused_stop = m_gdb_comm.Interrupt(); return error; } Status ProcessGDBRemote::DoDetach(bool keep_stopped) { Status error; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (log) log->Printf("ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped); error = m_gdb_comm.Detach(keep_stopped); if (log) { if (error.Success()) log->PutCString( "ProcessGDBRemote::DoDetach() detach packet sent successfully"); else log->Printf("ProcessGDBRemote::DoDetach() detach packet send failed: %s", error.AsCString() ? error.AsCString() : ""); } if (!error.Success()) return error; // Sleep for one second to let the process get all detached... StopAsyncThread(); SetPrivateState(eStateDetached); ResumePrivateStateThread(); // KillDebugserverProcess (); return error; } Status ProcessGDBRemote::DoDestroy() { Status error; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (log) log->Printf("ProcessGDBRemote::DoDestroy()"); // There is a bug in older iOS debugservers where they don't shut down the // process // they are debugging properly. If the process is sitting at a breakpoint or // an exception, // this can cause problems with restarting. So we check to see if any of our // threads are stopped // at a breakpoint, and if so we remove all the breakpoints, resume the // process, and THEN // destroy it again. // // Note, we don't have a good way to test the version of debugserver, but I // happen to know that // the set of all the iOS debugservers which don't support // GetThreadSuffixSupported() and that of // the debugservers with this bug are equal. There really should be a better // way to test this! // // We also use m_destroy_tried_resuming to make sure we only do this once, if // we resume and then halt and // get called here to destroy again and we're still at a breakpoint or // exception, then we should // just do the straight-forward kill. // // And of course, if we weren't able to stop the process by the time we get // here, it isn't // necessary (or helpful) to do any of this. if (!m_gdb_comm.GetThreadSuffixSupported() && m_public_state.GetValue() != eStateRunning) { PlatformSP platform_sp = GetTarget().GetPlatform(); // FIXME: These should be ConstStrings so we aren't doing strcmp'ing. if (platform_sp && platform_sp->GetName() && platform_sp->GetName() == PlatformRemoteiOS::GetPluginNameStatic()) { if (m_destroy_tried_resuming) { if (log) log->PutCString("ProcessGDBRemote::DoDestroy() - Tried resuming to " "destroy once already, not doing it again."); } else { // At present, the plans are discarded and the breakpoints disabled // Process::Destroy, // but we really need it to happen here and it doesn't matter if we do // it twice. m_thread_list.DiscardThreadPlans(); DisableAllBreakpointSites(); bool stop_looks_like_crash = false; ThreadList &threads = GetThreadList(); { std::lock_guard guard(threads.GetMutex()); size_t num_threads = threads.GetSize(); for (size_t i = 0; i < num_threads; i++) { ThreadSP thread_sp = threads.GetThreadAtIndex(i); StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo(); StopReason reason = eStopReasonInvalid; if (stop_info_sp) reason = stop_info_sp->GetStopReason(); if (reason == eStopReasonBreakpoint || reason == eStopReasonException) { if (log) log->Printf( "ProcessGDBRemote::DoDestroy() - thread: 0x%4.4" PRIx64 " stopped with reason: %s.", thread_sp->GetProtocolID(), stop_info_sp->GetDescription()); stop_looks_like_crash = true; break; } } } if (stop_looks_like_crash) { if (log) log->PutCString("ProcessGDBRemote::DoDestroy() - Stopped at a " "breakpoint, continue and then kill."); m_destroy_tried_resuming = true; // If we are going to run again before killing, it would be good to // suspend all the threads // before resuming so they won't get into more trouble. Sadly, for // the threads stopped with // the breakpoint or exception, the exception doesn't get cleared if // it is suspended, so we do // have to run the risk of letting those threads proceed a bit. { std::lock_guard guard(threads.GetMutex()); size_t num_threads = threads.GetSize(); for (size_t i = 0; i < num_threads; i++) { ThreadSP thread_sp = threads.GetThreadAtIndex(i); StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo(); StopReason reason = eStopReasonInvalid; if (stop_info_sp) reason = stop_info_sp->GetStopReason(); if (reason != eStopReasonBreakpoint && reason != eStopReasonException) { if (log) log->Printf("ProcessGDBRemote::DoDestroy() - Suspending " "thread: 0x%4.4" PRIx64 " before running.", thread_sp->GetProtocolID()); thread_sp->SetResumeState(eStateSuspended); } } } Resume(); return Destroy(false); } } } } // Interrupt if our inferior is running... int exit_status = SIGABRT; std::string exit_string; if (m_gdb_comm.IsConnected()) { if (m_public_state.GetValue() != eStateAttaching) { StringExtractorGDBRemote response; bool send_async = true; GDBRemoteCommunication::ScopedTimeout(m_gdb_comm, std::chrono::seconds(3)); if (m_gdb_comm.SendPacketAndWaitForResponse("k", response, send_async) == GDBRemoteCommunication::PacketResult::Success) { char packet_cmd = response.GetChar(0); if (packet_cmd == 'W' || packet_cmd == 'X') { #if defined(__APPLE__) // For Native processes on Mac OS X, we launch through the Host // Platform, then hand the process off // to debugserver, which becomes the parent process through // "PT_ATTACH". Then when we go to kill // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then we // call waitpid which returns // with no error and the correct status. But amusingly enough that // doesn't seem to actually reap // the process, but instead it is left around as a Zombie. Probably // the kernel is in the process of // switching ownership back to lldb which was the original parent, and // gets confused in the handoff. // Anyway, so call waitpid here to finally reap it. PlatformSP platform_sp(GetTarget().GetPlatform()); if (platform_sp && platform_sp->IsHost()) { int status; ::pid_t reap_pid; reap_pid = waitpid(GetID(), &status, WNOHANG); if (log) log->Printf("Reaped pid: %d, status: %d.\n", reap_pid, status); } #endif SetLastStopPacket(response); ClearThreadIDList(); exit_status = response.GetHexU8(); } else { if (log) log->Printf("ProcessGDBRemote::DoDestroy - got unexpected response " "to k packet: %s", response.GetStringRef().c_str()); exit_string.assign("got unexpected response to k packet: "); exit_string.append(response.GetStringRef()); } } else { if (log) log->Printf("ProcessGDBRemote::DoDestroy - failed to send k packet"); exit_string.assign("failed to send the k packet"); } } else { if (log) log->Printf("ProcessGDBRemote::DoDestroy - killed or interrupted while " "attaching"); exit_string.assign("killed or interrupted while attaching."); } } else { // If we missed setting the exit status on the way out, do it here. // NB set exit status can be called multiple times, the first one sets the // status. exit_string.assign("destroying when not connected to debugserver"); } SetExitStatus(exit_status, exit_string.c_str()); StopAsyncThread(); KillDebugserverProcess(); return error; } void ProcessGDBRemote::SetLastStopPacket( const StringExtractorGDBRemote &response) { const bool did_exec = response.GetStringRef().find(";reason:exec;") != std::string::npos; if (did_exec) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (log) log->Printf("ProcessGDBRemote::SetLastStopPacket () - detected exec"); m_thread_list_real.Clear(); m_thread_list.Clear(); BuildDynamicRegisterInfo(true); m_gdb_comm.ResetDiscoverableSettings(did_exec); } // Scope the lock { // Lock the thread stack while we access it std::lock_guard guard(m_last_stop_packet_mutex); // We are are not using non-stop mode, there can only be one last stop // reply packet, so clear the list. if (GetTarget().GetNonStopModeEnabled() == false) m_stop_packet_stack.clear(); // Add this stop packet to the stop packet stack // This stack will get popped and examined when we switch to the // Stopped state m_stop_packet_stack.push_back(response); } } void ProcessGDBRemote::SetUnixSignals(const UnixSignalsSP &signals_sp) { Process::SetUnixSignals(std::make_shared(signals_sp)); } //------------------------------------------------------------------ // Process Queries //------------------------------------------------------------------ bool ProcessGDBRemote::IsAlive() { return m_gdb_comm.IsConnected() && Process::IsAlive(); } addr_t ProcessGDBRemote::GetImageInfoAddress() { // request the link map address via the $qShlibInfoAddr packet lldb::addr_t addr = m_gdb_comm.GetShlibInfoAddr(); // the loaded module list can also provides a link map address if (addr == LLDB_INVALID_ADDRESS) { LoadedModuleInfoList list; if (GetLoadedModuleList(list).Success()) addr = list.m_link_map; } return addr; } void ProcessGDBRemote::WillPublicStop() { // See if the GDB remote client supports the JSON threads info. // If so, we gather stop info for all threads, expedited registers, // expedited memory, runtime queue information (iOS and MacOSX only), // and more. Expediting memory will help stack backtracing be much // faster. Expediting registers will make sure we don't have to read // the thread registers for GPRs. m_jthreadsinfo_sp = m_gdb_comm.GetThreadsInfo(); if (m_jthreadsinfo_sp) { // Now set the stop info for each thread and also expedite any registers // and memory that was in the jThreadsInfo response. StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray(); if (thread_infos) { const size_t n = thread_infos->GetSize(); for (size_t i = 0; i < n; ++i) { StructuredData::Dictionary *thread_dict = thread_infos->GetItemAtIndex(i)->GetAsDictionary(); if (thread_dict) SetThreadStopInfo(thread_dict); } } } } //------------------------------------------------------------------ // Process Memory //------------------------------------------------------------------ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size, Status &error) { GetMaxMemorySize(); bool binary_memory_read = m_gdb_comm.GetxPacketSupported(); // M and m packets take 2 bytes for 1 byte of memory size_t max_memory_size = binary_memory_read ? m_max_memory_size : m_max_memory_size / 2; if (size > max_memory_size) { // Keep memory read sizes down to a sane limit. This function will be // called multiple times in order to complete the task by // lldb_private::Process so it is ok to do this. size = max_memory_size; } char packet[64]; int packet_len; packet_len = ::snprintf(packet, sizeof(packet), "%c%" PRIx64 ",%" PRIx64, binary_memory_read ? 'x' : 'm', (uint64_t)addr, (uint64_t)size); assert(packet_len + 1 < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response, true) == GDBRemoteCommunication::PacketResult::Success) { if (response.IsNormalResponse()) { error.Clear(); if (binary_memory_read) { // The lower level GDBRemoteCommunication packet receive layer has // already de-quoted any // 0x7d character escaping that was present in the packet size_t data_received_size = response.GetBytesLeft(); if (data_received_size > size) { // Don't write past the end of BUF if the remote debug server gave us // too // much data for some reason. data_received_size = size; } memcpy(buf, response.GetStringRef().data(), data_received_size); return data_received_size; } else { return response.GetHexBytes( llvm::MutableArrayRef((uint8_t *)buf, size), '\xdd'); } } else if (response.IsErrorResponse()) error.SetErrorStringWithFormat("memory read failed for 0x%" PRIx64, addr); else if (response.IsUnsupportedResponse()) error.SetErrorStringWithFormat( "GDB server does not support reading memory"); else error.SetErrorStringWithFormat( "unexpected response to GDB server memory read packet '%s': '%s'", packet, response.GetStringRef().c_str()); } else { error.SetErrorStringWithFormat("failed to send packet: '%s'", packet); } return 0; } size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf, size_t size, Status &error) { GetMaxMemorySize(); // M and m packets take 2 bytes for 1 byte of memory size_t max_memory_size = m_max_memory_size / 2; if (size > max_memory_size) { // Keep memory read sizes down to a sane limit. This function will be // called multiple times in order to complete the task by // lldb_private::Process so it is ok to do this. size = max_memory_size; } StreamString packet; packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size); packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(), endian::InlHostByteOrder()); StringExtractorGDBRemote response; if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, true) == GDBRemoteCommunication::PacketResult::Success) { if (response.IsOKResponse()) { error.Clear(); return size; } else if (response.IsErrorResponse()) error.SetErrorStringWithFormat("memory write failed for 0x%" PRIx64, addr); else if (response.IsUnsupportedResponse()) error.SetErrorStringWithFormat( "GDB server does not support writing memory"); else error.SetErrorStringWithFormat( "unexpected response to GDB server memory write packet '%s': '%s'", packet.GetData(), response.GetStringRef().c_str()); } else { error.SetErrorStringWithFormat("failed to send packet: '%s'", packet.GetData()); } return 0; } lldb::addr_t ProcessGDBRemote::DoAllocateMemory(size_t size, uint32_t permissions, Status &error) { Log *log( GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_EXPRESSIONS)); addr_t allocated_addr = LLDB_INVALID_ADDRESS; if (m_gdb_comm.SupportsAllocDeallocMemory() != eLazyBoolNo) { allocated_addr = m_gdb_comm.AllocateMemory(size, permissions); if (allocated_addr != LLDB_INVALID_ADDRESS || m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolYes) return allocated_addr; } if (m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolNo) { // Call mmap() to create memory in the inferior.. unsigned prot = 0; if (permissions & lldb::ePermissionsReadable) prot |= eMmapProtRead; if (permissions & lldb::ePermissionsWritable) prot |= eMmapProtWrite; if (permissions & lldb::ePermissionsExecutable) prot |= eMmapProtExec; if (InferiorCallMmap(this, allocated_addr, 0, size, prot, eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) m_addr_to_mmap_size[allocated_addr] = size; else { allocated_addr = LLDB_INVALID_ADDRESS; if (log) log->Printf("ProcessGDBRemote::%s no direct stub support for memory " "allocation, and InferiorCallMmap also failed - is stub " "missing register context save/restore capability?", __FUNCTION__); } } if (allocated_addr == LLDB_INVALID_ADDRESS) error.SetErrorStringWithFormat( "unable to allocate %" PRIu64 " bytes of memory with permissions %s", (uint64_t)size, GetPermissionsAsCString(permissions)); else error.Clear(); return allocated_addr; } Status ProcessGDBRemote::GetMemoryRegionInfo(addr_t load_addr, MemoryRegionInfo ®ion_info) { Status error(m_gdb_comm.GetMemoryRegionInfo(load_addr, region_info)); return error; } Status ProcessGDBRemote::GetWatchpointSupportInfo(uint32_t &num) { Status error(m_gdb_comm.GetWatchpointSupportInfo(num)); return error; } Status ProcessGDBRemote::GetWatchpointSupportInfo(uint32_t &num, bool &after) { Status error(m_gdb_comm.GetWatchpointSupportInfo( num, after, GetTarget().GetArchitecture())); return error; } Status ProcessGDBRemote::DoDeallocateMemory(lldb::addr_t addr) { Status error; LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory(); switch (supported) { case eLazyBoolCalculate: // We should never be deallocating memory without allocating memory // first so we should never get eLazyBoolCalculate error.SetErrorString( "tried to deallocate memory without ever allocating memory"); break; case eLazyBoolYes: if (!m_gdb_comm.DeallocateMemory(addr)) error.SetErrorStringWithFormat( "unable to deallocate memory at 0x%" PRIx64, addr); break; case eLazyBoolNo: // Call munmap() to deallocate memory in the inferior.. { MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); if (pos != m_addr_to_mmap_size.end() && InferiorCallMunmap(this, addr, pos->second)) m_addr_to_mmap_size.erase(pos); else error.SetErrorStringWithFormat( "unable to deallocate memory at 0x%" PRIx64, addr); } break; } return error; } //------------------------------------------------------------------ // Process STDIO //------------------------------------------------------------------ size_t ProcessGDBRemote::PutSTDIN(const char *src, size_t src_len, Status &error) { if (m_stdio_communication.IsConnected()) { ConnectionStatus status; m_stdio_communication.Write(src, src_len, status, NULL); } else if (m_stdin_forward) { m_gdb_comm.SendStdinNotification(src, src_len); } return 0; } Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { Status error; assert(bp_site != NULL); // Get logging info Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS)); user_id_t site_id = bp_site->GetID(); // Get the breakpoint address const addr_t addr = bp_site->GetLoadAddress(); // Log that a breakpoint was requested if (log) log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64, site_id, (uint64_t)addr); // Breakpoint already exists and is enabled if (bp_site->IsEnabled()) { if (log) log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)", site_id, (uint64_t)addr); return error; } // Get the software breakpoint trap opcode size const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site); // SupportsGDBStoppointPacket() simply checks a boolean, indicating if this // breakpoint type // is supported by the remote stub. These are set to true by default, and // later set to false // only after we receive an unimplemented response when sending a breakpoint // packet. This means // initially that unless we were specifically instructed to use a hardware // breakpoint, LLDB will // attempt to set a software breakpoint. HardwareRequired() also queries a // boolean variable which // indicates if the user specifically asked for hardware breakpoints. If true // then we will // skip over software breakpoints. if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware) && (!bp_site->HardwareRequired())) { // Try to send off a software breakpoint packet ($Z0) uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket( eBreakpointSoftware, true, addr, bp_op_size); if (error_no == 0) { // The breakpoint was placed successfully bp_site->SetEnabled(true); bp_site->SetType(BreakpointSite::eExternal); return error; } // SendGDBStoppointTypePacket() will return an error if it was unable to set // this // breakpoint. We need to differentiate between a error specific to placing // this breakpoint // or if we have learned that this breakpoint type is unsupported. To do // this, we // must test the support boolean for this breakpoint type to see if it now // indicates that // this breakpoint type is unsupported. If they are still supported then we // should return // with the error code. If they are now unsupported, then we would like to // fall through // and try another form of breakpoint. if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) { if (error_no != UINT8_MAX) error.SetErrorStringWithFormat( "error: %d sending the breakpoint request", errno); else error.SetErrorString("error sending the breakpoint request"); return error; } // We reach here when software breakpoints have been found to be // unsupported. For future // calls to set a breakpoint, we will not attempt to set a breakpoint with a // type that is // known not to be supported. if (log) log->Printf("Software breakpoints are unsupported"); // So we will fall through and try a hardware breakpoint } // The process of setting a hardware breakpoint is much the same as above. We // check the // supported boolean for this breakpoint type, and if it is thought to be // supported then we // will try to set this breakpoint with a hardware breakpoint. if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) { // Try to send off a hardware breakpoint packet ($Z1) uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket( eBreakpointHardware, true, addr, bp_op_size); if (error_no == 0) { // The breakpoint was placed successfully bp_site->SetEnabled(true); bp_site->SetType(BreakpointSite::eHardware); return error; } // Check if the error was something other then an unsupported breakpoint // type if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) { // Unable to set this hardware breakpoint if (error_no != UINT8_MAX) error.SetErrorStringWithFormat( "error: %d sending the hardware breakpoint request " "(hardware breakpoint resources might be exhausted or unavailable)", error_no); else error.SetErrorString("error sending the hardware breakpoint request " "(hardware breakpoint resources " "might be exhausted or unavailable)"); return error; } // We will reach here when the stub gives an unsupported response to a // hardware breakpoint if (log) log->Printf("Hardware breakpoints are unsupported"); // Finally we will falling through to a #trap style breakpoint } // Don't fall through when hardware breakpoints were specifically requested if (bp_site->HardwareRequired()) { error.SetErrorString("hardware breakpoints are not supported"); return error; } // As a last resort we want to place a manual breakpoint. An instruction // is placed into the process memory using memory write packets. return EnableSoftwareBreakpoint(bp_site); } Status ProcessGDBRemote::DisableBreakpointSite(BreakpointSite *bp_site) { Status error; assert(bp_site != NULL); addr_t addr = bp_site->GetLoadAddress(); user_id_t site_id = bp_site->GetID(); Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS)); if (log) log->Printf("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 ") addr = 0x%8.8" PRIx64, site_id, (uint64_t)addr); if (bp_site->IsEnabled()) { const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site); BreakpointSite::Type bp_type = bp_site->GetType(); switch (bp_type) { case BreakpointSite::eSoftware: error = DisableSoftwareBreakpoint(bp_site); break; case BreakpointSite::eHardware: if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, false, addr, bp_op_size)) error.SetErrorToGenericError(); break; case BreakpointSite::eExternal: { GDBStoppointType stoppoint_type; if (bp_site->IsHardware()) stoppoint_type = eBreakpointHardware; else stoppoint_type = eBreakpointSoftware; if (m_gdb_comm.SendGDBStoppointTypePacket(stoppoint_type, false, addr, bp_op_size)) error.SetErrorToGenericError(); } break; } if (error.Success()) bp_site->SetEnabled(false); } else { if (log) log->Printf("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", site_id, (uint64_t)addr); return error; } if (error.Success()) error.SetErrorToGenericError(); return error; } // Pre-requisite: wp != NULL. static GDBStoppointType GetGDBStoppointType(Watchpoint *wp) { assert(wp); bool watch_read = wp->WatchpointRead(); bool watch_write = wp->WatchpointWrite(); // watch_read and watch_write cannot both be false. assert(watch_read || watch_write); if (watch_read && watch_write) return eWatchpointReadWrite; else if (watch_read) return eWatchpointRead; else // Must be watch_write, then. return eWatchpointWrite; } Status ProcessGDBRemote::EnableWatchpoint(Watchpoint *wp, bool notify) { Status error; if (wp) { user_id_t watchID = wp->GetID(); addr_t addr = wp->GetLoadAddress(); Log *log( ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS)); if (log) log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ")", watchID); if (wp->IsEnabled()) { if (log) log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", watchID, (uint64_t)addr); return error; } GDBStoppointType type = GetGDBStoppointType(wp); // Pass down an appropriate z/Z packet... if (m_gdb_comm.SupportsGDBStoppointPacket(type)) { if (m_gdb_comm.SendGDBStoppointTypePacket(type, true, addr, wp->GetByteSize()) == 0) { wp->SetEnabled(true, notify); return error; } else error.SetErrorString("sending gdb watchpoint packet failed"); } else error.SetErrorString("watchpoints not supported"); } else { error.SetErrorString("Watchpoint argument was NULL."); } if (error.Success()) error.SetErrorToGenericError(); return error; } Status ProcessGDBRemote::DisableWatchpoint(Watchpoint *wp, bool notify) { Status error; if (wp) { user_id_t watchID = wp->GetID(); Log *log( ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS)); addr_t addr = wp->GetLoadAddress(); if (log) log->Printf("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 ") addr = 0x%8.8" PRIx64, watchID, (uint64_t)addr); if (!wp->IsEnabled()) { if (log) log->Printf("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", watchID, (uint64_t)addr); // See also 'class WatchpointSentry' within StopInfo.cpp. // This disabling attempt might come from the user-supplied actions, we'll // route it in order for // the watchpoint object to intelligently process this action. wp->SetEnabled(false, notify); return error; } if (wp->IsHardware()) { GDBStoppointType type = GetGDBStoppointType(wp); // Pass down an appropriate z/Z packet... if (m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr, wp->GetByteSize()) == 0) { wp->SetEnabled(false, notify); return error; } else error.SetErrorString("sending gdb watchpoint packet failed"); } // TODO: clear software watchpoints if we implement them } else { error.SetErrorString("Watchpoint argument was NULL."); } if (error.Success()) error.SetErrorToGenericError(); return error; } void ProcessGDBRemote::Clear() { m_flags = 0; m_thread_list_real.Clear(); m_thread_list.Clear(); } Status ProcessGDBRemote::DoSignal(int signo) { Status error; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (log) log->Printf("ProcessGDBRemote::DoSignal (signal = %d)", signo); if (!m_gdb_comm.SendAsyncSignal(signo)) error.SetErrorStringWithFormat("failed to send signal %i", signo); return error; } Status ProcessGDBRemote::EstablishConnectionIfNeeded(const ProcessInfo &process_info) { // Make sure we aren't already connected? if (m_gdb_comm.IsConnected()) return Status(); PlatformSP platform_sp(GetTarget().GetPlatform()); if (platform_sp && !platform_sp->IsHost()) return Status("Lost debug server connection"); auto error = LaunchAndConnectToDebugserver(process_info); if (error.Fail()) { const char *error_string = error.AsCString(); if (error_string == nullptr) error_string = "unable to launch " DEBUGSERVER_BASENAME; } return error; } #if defined(__APPLE__) #define USE_SOCKETPAIR_FOR_LOCAL_CONNECTION 1 #endif #ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION static bool SetCloexecFlag(int fd) { #if defined(FD_CLOEXEC) int flags = ::fcntl(fd, F_GETFD); if (flags == -1) return false; return (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0); #else return false; #endif } #endif Status ProcessGDBRemote::LaunchAndConnectToDebugserver( const ProcessInfo &process_info) { using namespace std::placeholders; // For _1, _2, etc. Status error; if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID) { // If we locate debugserver, keep that located version around static FileSpec g_debugserver_file_spec; ProcessLaunchInfo debugserver_launch_info; // Make debugserver run in its own session so signals generated by // special terminal key sequences (^C) don't affect debugserver. debugserver_launch_info.SetLaunchInSeparateProcessGroup(true); const std::weak_ptr this_wp = std::static_pointer_cast(shared_from_this()); debugserver_launch_info.SetMonitorProcessCallback( std::bind(MonitorDebugserverProcess, this_wp, _1, _2, _3, _4), false); debugserver_launch_info.SetUserID(process_info.GetUserID()); int communication_fd = -1; #ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION // Auto close the sockets we might open up unless everything goes OK. This // helps us not leak file descriptors when things go wrong. lldb_utility::CleanUp our_socket(-1, -1, close); lldb_utility::CleanUp gdb_socket(-1, -1, close); // Use a socketpair on Apple for now until other platforms can verify it // works and is fast enough { int sockets[2]; /* the pair of socket descriptors */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) { error.SetErrorToErrno(); return error; } our_socket.set(sockets[0]); gdb_socket.set(sockets[1]); } // Don't let any child processes inherit our communication socket SetCloexecFlag(our_socket.get()); communication_fd = gdb_socket.get(); #endif error = m_gdb_comm.StartDebugserverProcess( nullptr, GetTarget().GetPlatform().get(), debugserver_launch_info, nullptr, nullptr, communication_fd); if (error.Success()) m_debugserver_pid = debugserver_launch_info.GetProcessID(); else m_debugserver_pid = LLDB_INVALID_PROCESS_ID; if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) { #ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION // Our process spawned correctly, we can now set our connection to use our // end of the socket pair m_gdb_comm.SetConnection( new ConnectionFileDescriptor(our_socket.release(), true)); #endif StartAsyncThread(); } if (error.Fail()) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (log) log->Printf("failed to start debugserver process: %s", error.AsCString()); return error; } if (m_gdb_comm.IsConnected()) { // Finish the connection process by doing the handshake without connecting // (send NULL URL) ConnectToDebugserver(""); } else { error.SetErrorString("connection failed"); } } return error; } bool ProcessGDBRemote::MonitorDebugserverProcess( std::weak_ptr process_wp, lldb::pid_t debugserver_pid, bool exited, // True if the process did exit int signo, // Zero for no signal int exit_status // Exit value of process if signal is zero ) { // "debugserver_pid" argument passed in is the process ID for // debugserver that we are tracking... Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); const bool handled = true; if (log) log->Printf("ProcessGDBRemote::%s(process_wp, pid=%" PRIu64 ", signo=%i (0x%x), exit_status=%i)", __FUNCTION__, debugserver_pid, signo, signo, exit_status); std::shared_ptr process_sp = process_wp.lock(); if (log) log->Printf("ProcessGDBRemote::%s(process = %p)", __FUNCTION__, static_cast(process_sp.get())); if (!process_sp || process_sp->m_debugserver_pid != debugserver_pid) return handled; // Sleep for a half a second to make sure our inferior process has // time to set its exit status before we set it incorrectly when // both the debugserver and the inferior process shut down. usleep(500000); // If our process hasn't yet exited, debugserver might have died. // If the process did exit, then we are reaping it. const StateType state = process_sp->GetState(); if (state != eStateInvalid && state != eStateUnloaded && state != eStateExited && state != eStateDetached) { char error_str[1024]; if (signo) { const char *signal_cstr = process_sp->GetUnixSignals()->GetSignalAsCString(signo); if (signal_cstr) ::snprintf(error_str, sizeof(error_str), DEBUGSERVER_BASENAME " died with signal %s", signal_cstr); else ::snprintf(error_str, sizeof(error_str), DEBUGSERVER_BASENAME " died with signal %i", signo); } else { ::snprintf(error_str, sizeof(error_str), DEBUGSERVER_BASENAME " died with an exit status of 0x%8.8x", exit_status); } process_sp->SetExitStatus(-1, error_str); } // Debugserver has exited we need to let our ProcessGDBRemote // know that it no longer has a debugserver instance process_sp->m_debugserver_pid = LLDB_INVALID_PROCESS_ID; return handled; } void ProcessGDBRemote::KillDebugserverProcess() { m_gdb_comm.Disconnect(); if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) { Host::Kill(m_debugserver_pid, SIGINT); m_debugserver_pid = LLDB_INVALID_PROCESS_ID; } } void ProcessGDBRemote::Initialize() { static llvm::once_flag g_once_flag; llvm::call_once(g_once_flag, []() { PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, DebuggerInitialize); }); } void ProcessGDBRemote::DebuggerInitialize(Debugger &debugger) { if (!PluginManager::GetSettingForProcessPlugin( debugger, PluginProperties::GetSettingName())) { const bool is_global_setting = true; PluginManager::CreateSettingForProcessPlugin( debugger, GetGlobalPluginProperties()->GetValueProperties(), ConstString("Properties for the gdb-remote process plug-in."), is_global_setting); } } bool ProcessGDBRemote::StartAsyncThread() { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (log) log->Printf("ProcessGDBRemote::%s ()", __FUNCTION__); std::lock_guard guard(m_async_thread_state_mutex); if (!m_async_thread.IsJoinable()) { // Create a thread that watches our internal state and controls which // events make it to clients (into the DCProcess event queue). m_async_thread = ThreadLauncher::LaunchThread("", ProcessGDBRemote::AsyncThread, this, NULL); } else if (log) log->Printf("ProcessGDBRemote::%s () - Called when Async thread was " "already running.", __FUNCTION__); return m_async_thread.IsJoinable(); } void ProcessGDBRemote::StopAsyncThread() { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (log) log->Printf("ProcessGDBRemote::%s ()", __FUNCTION__); std::lock_guard guard(m_async_thread_state_mutex); if (m_async_thread.IsJoinable()) { m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit); // This will shut down the async thread. m_gdb_comm.Disconnect(); // Disconnect from the debug server. // Stop the stdio thread m_async_thread.Join(nullptr); m_async_thread.Reset(); } else if (log) log->Printf( "ProcessGDBRemote::%s () - Called when Async thread was not running.", __FUNCTION__); } bool ProcessGDBRemote::HandleNotifyPacket(StringExtractorGDBRemote &packet) { // get the packet at a string const std::string &pkt = packet.GetStringRef(); // skip %stop: StringExtractorGDBRemote stop_info(pkt.c_str() + 5); // pass as a thread stop info packet SetLastStopPacket(stop_info); // check for more stop reasons HandleStopReplySequence(); // if the process is stopped then we need to fake a resume // so that we can stop properly with the new break. This // is possible due to SetPrivateState() broadcasting the // state change as a side effect. if (GetPrivateState() == lldb::StateType::eStateStopped) { SetPrivateState(lldb::StateType::eStateRunning); } // since we have some stopped packets we can halt the process SetPrivateState(lldb::StateType::eStateStopped); return true; } thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { ProcessGDBRemote *process = (ProcessGDBRemote *)arg; Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (log) log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread starting...", __FUNCTION__, arg, process->GetID()); EventSP event_sp; bool done = false; while (!done) { if (log) log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID()); if (process->m_async_listener_sp->GetEvent(event_sp, llvm::None)) { const uint32_t event_type = event_sp->GetType(); if (event_sp->BroadcasterIs(&process->m_async_broadcaster)) { if (log) log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type); switch (event_type) { case eBroadcastBitAsyncContinue: { const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get()); if (continue_packet) { const char *continue_cstr = (const char *)continue_packet->GetBytes(); const size_t continue_cstr_len = continue_packet->GetByteSize(); if (log) log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr); if (::strstr(continue_cstr, "vAttach") == NULL) process->SetPrivateState(eStateRunning); StringExtractorGDBRemote response; // If in Non-Stop-Mode if (process->GetTarget().GetNonStopModeEnabled()) { // send the vCont packet if (!process->GetGDBRemote().SendvContPacket( llvm::StringRef(continue_cstr, continue_cstr_len), response)) { // Something went wrong done = true; break; } } // If in All-Stop-Mode else { StateType stop_state = process->GetGDBRemote().SendContinuePacketAndWaitForResponse( *process, *process->GetUnixSignals(), llvm::StringRef(continue_cstr, continue_cstr_len), response); // We need to immediately clear the thread ID list so we are sure // to get a valid list of threads. // The thread ID list might be contained within the "response", or // the stop reply packet that // caused the stop. So clear it now before we give the stop reply // packet to the process // using the process->SetLastStopPacket()... process->ClearThreadIDList(); switch (stop_state) { case eStateStopped: case eStateCrashed: case eStateSuspended: process->SetLastStopPacket(response); process->SetPrivateState(stop_state); break; case eStateExited: { process->SetLastStopPacket(response); process->ClearThreadIDList(); response.SetFilePos(1); int exit_status = response.GetHexU8(); std::string desc_string; if (response.GetBytesLeft() > 0 && response.GetChar('-') == ';') { llvm::StringRef desc_str; llvm::StringRef desc_token; while (response.GetNameColonValue(desc_token, desc_str)) { if (desc_token != "description") continue; StringExtractor extractor(desc_str); extractor.GetHexByteString(desc_string); } } process->SetExitStatus(exit_status, desc_string.c_str()); done = true; break; } case eStateInvalid: { // Check to see if we were trying to attach and if we got back // the "E87" error code from debugserver -- this indicates that // the process is not debuggable. Return a slightly more // helpful // error message about why the attach failed. if (::strstr(continue_cstr, "vAttach") != NULL && response.GetError() == 0x87) { process->SetExitStatus(-1, "cannot attach to process due to " "System Integrity Protection"); } // E01 code from vAttach means that the attach failed if (::strstr(continue_cstr, "vAttach") != NULL && response.GetError() == 0x1) { process->SetExitStatus(-1, "unable to attach"); } else { process->SetExitStatus(-1, "lost connection"); } break; } default: process->SetPrivateState(stop_state); break; } // switch(stop_state) } // else // if in All-stop-mode } // if (continue_packet) } // case eBroadcastBitAysncContinue break; case eBroadcastBitAsyncThreadShouldExit: if (log) log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID()); done = true; break; default: if (log) log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type); done = true; break; } } else if (event_sp->BroadcasterIs(&process->m_gdb_comm)) { switch (event_type) { case Communication::eBroadcastBitReadThreadDidExit: process->SetExitStatus(-1, "lost connection"); done = true; break; case GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify: { lldb_private::Event *event = event_sp.get(); const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event); StringExtractorGDBRemote notify( (const char *)continue_packet->GetBytes()); // Hand this over to the process to handle process->HandleNotifyPacket(notify); break; } default: if (log) log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type); done = true; break; } } } else { if (log) log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID()); done = true; } } if (log) log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread exiting...", __FUNCTION__, arg, process->GetID()); return NULL; } // uint32_t // ProcessGDBRemote::ListProcessesMatchingName (const char *name, StringList // &matches, std::vector &pids) //{ // // If we are planning to launch the debugserver remotely, then we need to // fire up a debugserver // // process and ask it for the list of processes. But if we are local, we // can let the Host do it. // if (m_local_debugserver) // { // return Host::ListProcessesMatchingName (name, matches, pids); // } // else // { // // FIXME: Implement talking to the remote debugserver. // return 0; // } // //} // bool ProcessGDBRemote::NewThreadNotifyBreakpointHit( void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id) { // I don't think I have to do anything here, just make sure I notice the new // thread when it starts to // run so I can stop it if that's what I want to do. Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (log) log->Printf("Hit New Thread Notification breakpoint."); return false; } Status ProcessGDBRemote::UpdateAutomaticSignalFiltering() { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); LLDB_LOG(log, "Check if need to update ignored signals"); // QPassSignals package is not supported by the server, // there is no way we can ignore any signals on server side. if (!m_gdb_comm.GetQPassSignalsSupported()) return Status(); // No signals, nothing to send. if (m_unix_signals_sp == nullptr) return Status(); // Signals' version hasn't changed, no need to send anything. uint64_t new_signals_version = m_unix_signals_sp->GetVersion(); if (new_signals_version == m_last_signals_version) { LLDB_LOG(log, "Signals' version hasn't changed. version={0}", m_last_signals_version); return Status(); } auto signals_to_ignore = m_unix_signals_sp->GetFilteredSignals(false, false, false); Status error = m_gdb_comm.SendSignalsToIgnore(signals_to_ignore); LLDB_LOG(log, "Signals' version changed. old version={0}, new version={1}, " "signals ignored={2}, update result={3}", m_last_signals_version, new_signals_version, signals_to_ignore.size(), error); if (error.Success()) m_last_signals_version = new_signals_version; return error; } bool ProcessGDBRemote::StartNoticingNewThreads() { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (m_thread_create_bp_sp) { if (log && log->GetVerbose()) log->Printf("Enabled noticing new thread breakpoint."); m_thread_create_bp_sp->SetEnabled(true); } else { PlatformSP platform_sp(GetTarget().GetPlatform()); if (platform_sp) { m_thread_create_bp_sp = platform_sp->SetThreadCreationBreakpoint(GetTarget()); if (m_thread_create_bp_sp) { if (log && log->GetVerbose()) log->Printf( "Successfully created new thread notification breakpoint %i", m_thread_create_bp_sp->GetID()); m_thread_create_bp_sp->SetCallback( ProcessGDBRemote::NewThreadNotifyBreakpointHit, this, true); } else { if (log) log->Printf("Failed to create new thread notification breakpoint."); } } } return m_thread_create_bp_sp.get() != NULL; } bool ProcessGDBRemote::StopNoticingNewThreads() { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (log && log->GetVerbose()) log->Printf("Disabling new thread notification breakpoint."); if (m_thread_create_bp_sp) m_thread_create_bp_sp->SetEnabled(false); return true; } DynamicLoader *ProcessGDBRemote::GetDynamicLoader() { if (m_dyld_ap.get() == NULL) m_dyld_ap.reset(DynamicLoader::FindPlugin(this, NULL)); return m_dyld_ap.get(); } Status ProcessGDBRemote::SendEventData(const char *data) { int return_value; bool was_supported; Status error; return_value = m_gdb_comm.SendLaunchEventDataPacket(data, &was_supported); if (return_value != 0) { if (!was_supported) error.SetErrorString("Sending events is not supported for this process."); else error.SetErrorStringWithFormat("Error sending event data: %d.", return_value); } return error; } const DataBufferSP ProcessGDBRemote::GetAuxvData() { DataBufferSP buf; if (m_gdb_comm.GetQXferAuxvReadSupported()) { std::string response_string; if (m_gdb_comm.SendPacketsAndConcatenateResponses("qXfer:auxv:read::", response_string) == GDBRemoteCommunication::PacketResult::Success) buf.reset(new DataBufferHeap(response_string.c_str(), response_string.length())); } return buf; } StructuredData::ObjectSP ProcessGDBRemote::GetExtendedInfoForThread(lldb::tid_t tid) { StructuredData::ObjectSP object_sp; if (m_gdb_comm.GetThreadExtendedInfoSupported()) { StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); SystemRuntime *runtime = GetSystemRuntime(); if (runtime) { runtime->AddThreadExtendedInfoPacketHints(args_dict); } args_dict->GetAsDictionary()->AddIntegerItem("thread", tid); StreamString packet; packet << "jThreadExtendedInfo:"; args_dict->Dump(packet, false); // FIXME the final character of a JSON dictionary, '}', is the escape // character in gdb-remote binary mode. lldb currently doesn't escape // these characters in its packet output -- so we add the quoted version // of the } character here manually in case we talk to a debugserver which // un-escapes the characters at packet read time. packet << (char)(0x7d ^ 0x20); StringExtractorGDBRemote response; response.SetResponseValidatorToJSON(); if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, false) == GDBRemoteCommunication::PacketResult::Success) { StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType(); if (response_type == StringExtractorGDBRemote::eResponse) { if (!response.Empty()) { object_sp = StructuredData::ParseJSON(response.GetStringRef()); } } } } return object_sp; } StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos( lldb::addr_t image_list_address, lldb::addr_t image_count) { StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); args_dict->GetAsDictionary()->AddIntegerItem("image_list_address", image_list_address); args_dict->GetAsDictionary()->AddIntegerItem("image_count", image_count); return GetLoadedDynamicLibrariesInfos_sender(args_dict); } StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos() { StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); args_dict->GetAsDictionary()->AddBooleanItem("fetch_all_solibs", true); return GetLoadedDynamicLibrariesInfos_sender(args_dict); } StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos( const std::vector &load_addresses) { StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); StructuredData::ArraySP addresses(new StructuredData::Array); for (auto addr : load_addresses) { StructuredData::ObjectSP addr_sp(new StructuredData::Integer(addr)); addresses->AddItem(addr_sp); } args_dict->GetAsDictionary()->AddItem("solib_addresses", addresses); return GetLoadedDynamicLibrariesInfos_sender(args_dict); } StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender( StructuredData::ObjectSP args_dict) { StructuredData::ObjectSP object_sp; if (m_gdb_comm.GetLoadedDynamicLibrariesInfosSupported()) { // Scope for the scoped timeout object GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm, std::chrono::seconds(10)); StreamString packet; packet << "jGetLoadedDynamicLibrariesInfos:"; args_dict->Dump(packet, false); // FIXME the final character of a JSON dictionary, '}', is the escape // character in gdb-remote binary mode. lldb currently doesn't escape // these characters in its packet output -- so we add the quoted version // of the } character here manually in case we talk to a debugserver which // un-escapes the characters at packet read time. packet << (char)(0x7d ^ 0x20); StringExtractorGDBRemote response; response.SetResponseValidatorToJSON(); if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, false) == GDBRemoteCommunication::PacketResult::Success) { StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType(); if (response_type == StringExtractorGDBRemote::eResponse) { if (!response.Empty()) { object_sp = StructuredData::ParseJSON(response.GetStringRef()); } } } } return object_sp; } StructuredData::ObjectSP ProcessGDBRemote::GetSharedCacheInfo() { StructuredData::ObjectSP object_sp; StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); if (m_gdb_comm.GetSharedCacheInfoSupported()) { StreamString packet; packet << "jGetSharedCacheInfo:"; args_dict->Dump(packet, false); // FIXME the final character of a JSON dictionary, '}', is the escape // character in gdb-remote binary mode. lldb currently doesn't escape // these characters in its packet output -- so we add the quoted version // of the } character here manually in case we talk to a debugserver which // un-escapes the characters at packet read time. packet << (char)(0x7d ^ 0x20); StringExtractorGDBRemote response; response.SetResponseValidatorToJSON(); if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, false) == GDBRemoteCommunication::PacketResult::Success) { StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType(); if (response_type == StringExtractorGDBRemote::eResponse) { if (!response.Empty()) { object_sp = StructuredData::ParseJSON(response.GetStringRef()); } } } } return object_sp; } Status ProcessGDBRemote::ConfigureStructuredData( const ConstString &type_name, const StructuredData::ObjectSP &config_sp) { return m_gdb_comm.ConfigureRemoteStructuredData(type_name, config_sp); } // Establish the largest memory read/write payloads we should use. // If the remote stub has a max packet size, stay under that size. // // If the remote stub's max packet size is crazy large, use a // reasonable largeish default. // // If the remote stub doesn't advertise a max packet size, use a // conservative default. void ProcessGDBRemote::GetMaxMemorySize() { const uint64_t reasonable_largeish_default = 128 * 1024; const uint64_t conservative_default = 512; if (m_max_memory_size == 0) { uint64_t stub_max_size = m_gdb_comm.GetRemoteMaxPacketSize(); if (stub_max_size != UINT64_MAX && stub_max_size != 0) { // Save the stub's claimed maximum packet size m_remote_stub_max_memory_size = stub_max_size; // Even if the stub says it can support ginormous packets, // don't exceed our reasonable largeish default packet size. if (stub_max_size > reasonable_largeish_default) { stub_max_size = reasonable_largeish_default; } // Memory packet have other overheads too like Maddr,size:#NN // Instead of calculating the bytes taken by size and addr every // time, we take a maximum guess here. if (stub_max_size > 70) stub_max_size -= 32 + 32 + 6; else { // In unlikely scenario that max packet size is less then 70, we will // hope that data being written is small enough to fit. Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet( GDBR_LOG_COMM | GDBR_LOG_MEMORY)); if (log) log->Warning("Packet size is too small. " "LLDB may face problems while writing memory"); } m_max_memory_size = stub_max_size; } else { m_max_memory_size = conservative_default; } } } void ProcessGDBRemote::SetUserSpecifiedMaxMemoryTransferSize( uint64_t user_specified_max) { if (user_specified_max != 0) { GetMaxMemorySize(); if (m_remote_stub_max_memory_size != 0) { if (m_remote_stub_max_memory_size < user_specified_max) { m_max_memory_size = m_remote_stub_max_memory_size; // user specified a // packet size too // big, go as big // as the remote stub says we can go. } else { m_max_memory_size = user_specified_max; // user's packet size is good } } else { m_max_memory_size = user_specified_max; // user's packet size is probably fine } } } bool ProcessGDBRemote::GetModuleSpec(const FileSpec &module_file_spec, const ArchSpec &arch, ModuleSpec &module_spec) { Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); const ModuleCacheKey key(module_file_spec.GetPath(), arch.GetTriple().getTriple()); auto cached = m_cached_module_specs.find(key); if (cached != m_cached_module_specs.end()) { module_spec = cached->second; return bool(module_spec); } if (!m_gdb_comm.GetModuleInfo(module_file_spec, arch, module_spec)) { if (log) log->Printf("ProcessGDBRemote::%s - failed to get module info for %s:%s", __FUNCTION__, module_file_spec.GetPath().c_str(), arch.GetTriple().getTriple().c_str()); return false; } if (log) { StreamString stream; module_spec.Dump(stream); log->Printf("ProcessGDBRemote::%s - got module info for (%s:%s) : %s", __FUNCTION__, module_file_spec.GetPath().c_str(), arch.GetTriple().getTriple().c_str(), stream.GetData()); } m_cached_module_specs[key] = module_spec; return true; } void ProcessGDBRemote::PrefetchModuleSpecs( llvm::ArrayRef module_file_specs, const llvm::Triple &triple) { auto module_specs = m_gdb_comm.GetModulesInfo(module_file_specs, triple); if (module_specs) { for (const FileSpec &spec : module_file_specs) m_cached_module_specs[ModuleCacheKey(spec.GetPath(), triple.getTriple())] = ModuleSpec(); for (const ModuleSpec &spec : *module_specs) m_cached_module_specs[ModuleCacheKey(spec.GetFileSpec().GetPath(), triple.getTriple())] = spec; } } bool ProcessGDBRemote::GetHostOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update) { if (m_gdb_comm.GetOSVersion(major, minor, update)) return true; // We failed to get the host OS version, defer to the base // implementation to correctly invalidate the arguments. return Process::GetHostOSVersion(major, minor, update); } namespace { typedef std::vector stringVec; typedef std::vector GDBServerRegisterVec; struct RegisterSetInfo { ConstString name; }; typedef std::map RegisterSetMap; struct GdbServerTargetInfo { std::string arch; std::string osabi; stringVec includes; RegisterSetMap reg_set_map; XMLNode feature_node; }; bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp, uint32_t &cur_reg_num, uint32_t ®_offset) { if (!feature_node) return false; feature_node.ForEachChildElementWithName( "reg", [&target_info, &dyn_reg_info, &cur_reg_num, ®_offset, &abi_sp](const XMLNode ®_node) -> bool { std::string gdb_group; std::string gdb_type; ConstString reg_name; ConstString alt_name; ConstString set_name; std::vector value_regs; std::vector invalidate_regs; std::vector dwarf_opcode_bytes; bool encoding_set = false; bool format_set = false; RegisterInfo reg_info = { NULL, // Name NULL, // Alt name 0, // byte size reg_offset, // offset eEncodingUint, // encoding eFormatHex, // format { LLDB_INVALID_REGNUM, // eh_frame reg num LLDB_INVALID_REGNUM, // DWARF reg num LLDB_INVALID_REGNUM, // generic reg num cur_reg_num, // process plugin reg num cur_reg_num // native register number }, NULL, NULL, NULL, // Dwarf Expression opcode bytes pointer 0 // Dwarf Expression opcode bytes length }; reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, ®_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, ®_info, ®_offset, &dwarf_opcode_bytes]( const llvm::StringRef &name, const llvm::StringRef &value) -> bool { if (name == "name") { reg_name.SetString(value); } else if (name == "bitsize") { reg_info.byte_size = StringConvert::ToUInt32(value.data(), 0, 0) / CHAR_BIT; } else if (name == "type") { gdb_type = value.str(); } else if (name == "group") { gdb_group = value.str(); } else if (name == "regnum") { const uint32_t regnum = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0); if (regnum != LLDB_INVALID_REGNUM) { reg_info.kinds[eRegisterKindProcessPlugin] = regnum; } } else if (name == "offset") { reg_offset = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0); } else if (name == "altname") { alt_name.SetString(value); } else if (name == "encoding") { encoding_set = true; reg_info.encoding = Args::StringToEncoding(value, eEncodingUint); } else if (name == "format") { format_set = true; Format format = eFormatInvalid; if (Args::StringToFormat(value.data(), format, NULL).Success()) reg_info.format = format; else if (value == "vector-sint8") reg_info.format = eFormatVectorOfSInt8; else if (value == "vector-uint8") reg_info.format = eFormatVectorOfUInt8; else if (value == "vector-sint16") reg_info.format = eFormatVectorOfSInt16; else if (value == "vector-uint16") reg_info.format = eFormatVectorOfUInt16; else if (value == "vector-sint32") reg_info.format = eFormatVectorOfSInt32; else if (value == "vector-uint32") reg_info.format = eFormatVectorOfUInt32; else if (value == "vector-float32") reg_info.format = eFormatVectorOfFloat32; else if (value == "vector-uint64") reg_info.format = eFormatVectorOfUInt64; else if (value == "vector-uint128") reg_info.format = eFormatVectorOfUInt128; } else if (name == "group_id") { const uint32_t set_id = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0); RegisterSetMap::const_iterator pos = target_info.reg_set_map.find(set_id); if (pos != target_info.reg_set_map.end()) set_name = pos->second.name; } else if (name == "gcc_regnum" || name == "ehframe_regnum") { reg_info.kinds[eRegisterKindEHFrame] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0); } else if (name == "dwarf_regnum") { reg_info.kinds[eRegisterKindDWARF] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0); } else if (name == "generic") { reg_info.kinds[eRegisterKindGeneric] = Args::StringToGenericRegister(value); } else if (name == "value_regnums") { SplitCommaSeparatedRegisterNumberString(value, value_regs, 0); } else if (name == "invalidate_regnums") { SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 0); } else if (name == "dynamic_size_dwarf_expr_bytes") { StringExtractor opcode_extractor; std::string opcode_string = value.str(); size_t dwarf_opcode_len = opcode_string.length() / 2; assert(dwarf_opcode_len > 0); dwarf_opcode_bytes.resize(dwarf_opcode_len); reg_info.dynamic_size_dwarf_len = dwarf_opcode_len; opcode_extractor.GetStringRef().swap(opcode_string); uint32_t ret_val = opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes); assert(dwarf_opcode_len == ret_val); UNUSED_IF_ASSERT_DISABLED(ret_val); reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data(); } else { printf("unhandled attribute %s = %s\n", name.data(), value.data()); } return true; // Keep iterating through all attributes }); if (!gdb_type.empty() && !(encoding_set || format_set)) { if (gdb_type.find("int") == 0) { reg_info.format = eFormatHex; reg_info.encoding = eEncodingUint; } else if (gdb_type == "data_ptr" || gdb_type == "code_ptr") { reg_info.format = eFormatAddressInfo; reg_info.encoding = eEncodingUint; } else if (gdb_type == "i387_ext" || gdb_type == "float") { reg_info.format = eFormatFloat; reg_info.encoding = eEncodingIEEE754; } } // Only update the register set name if we didn't get a "reg_set" // attribute. // "set_name" will be empty if we didn't have a "reg_set" attribute. if (!set_name && !gdb_group.empty()) set_name.SetCString(gdb_group.c_str()); reg_info.byte_offset = reg_offset; assert(reg_info.byte_size != 0); reg_offset += reg_info.byte_size; if (!value_regs.empty()) { value_regs.push_back(LLDB_INVALID_REGNUM); reg_info.value_regs = value_regs.data(); } if (!invalidate_regs.empty()) { invalidate_regs.push_back(LLDB_INVALID_REGNUM); reg_info.invalidate_regs = invalidate_regs.data(); } ++cur_reg_num; AugmentRegisterInfoViaABI(reg_info, reg_name, abi_sp); dyn_reg_info.AddRegister(reg_info, reg_name, alt_name, set_name); return true; // Keep iterating through all "reg" elements }); return true; } } // namespace {} // query the target of gdb-remote for extended target information // return: 'true' on success // 'false' on failure bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) { // Make sure LLDB has an XML parser it can use first if (!XMLDocument::XMLEnabled()) return false; // redirect libxml2's error handler since the default prints to stdout GDBRemoteCommunicationClient &comm = m_gdb_comm; // check that we have extended feature read support if (!comm.GetQXferFeaturesReadSupported()) return false; // request the target xml file std::string raw; lldb_private::Status lldberr; if (!comm.ReadExtFeature(ConstString("features"), ConstString("target.xml"), raw, lldberr)) { return false; } XMLDocument xml_document; if (xml_document.ParseMemory(raw.c_str(), raw.size(), "target.xml")) { GdbServerTargetInfo target_info; XMLNode target_node = xml_document.GetRootElement("target"); if (target_node) { XMLNode feature_node; target_node.ForEachChildElement([&target_info, &feature_node]( const XMLNode &node) -> bool { llvm::StringRef name = node.GetName(); if (name == "architecture") { node.GetElementText(target_info.arch); } else if (name == "osabi") { node.GetElementText(target_info.osabi); } else if (name == "xi:include" || name == "include") { llvm::StringRef href = node.GetAttributeValue("href"); if (!href.empty()) target_info.includes.push_back(href.str()); } else if (name == "feature") { feature_node = node; } else if (name == "groups") { node.ForEachChildElementWithName( "group", [&target_info](const XMLNode &node) -> bool { uint32_t set_id = UINT32_MAX; RegisterSetInfo set_info; node.ForEachAttribute( [&set_id, &set_info](const llvm::StringRef &name, const llvm::StringRef &value) -> bool { if (name == "id") set_id = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0); if (name == "name") set_info.name = ConstString(value); return true; // Keep iterating through all attributes }); if (set_id != UINT32_MAX) target_info.reg_set_map[set_id] = set_info; return true; // Keep iterating through all "group" elements }); } return true; // Keep iterating through all children of the target_node }); // Initialize these outside of ParseRegisters, since they should not be // reset inside each include feature uint32_t cur_reg_num = 0; uint32_t reg_offset = 0; // Don't use Process::GetABI, this code gets called from DidAttach, and in // that context we haven't // set the Target's architecture yet, so the ABI is also potentially // incorrect. ABISP abi_to_use_sp = ABI::FindPlugin(shared_from_this(), arch_to_use); if (feature_node) { ParseRegisters(feature_node, target_info, this->m_register_info, abi_to_use_sp, cur_reg_num, reg_offset); } for (const auto &include : target_info.includes) { // request register file std::string xml_data; if (!comm.ReadExtFeature(ConstString("features"), ConstString(include), xml_data, lldberr)) continue; XMLDocument include_xml_document; include_xml_document.ParseMemory(xml_data.data(), xml_data.size(), include.c_str()); XMLNode include_feature_node = include_xml_document.GetRootElement("feature"); if (include_feature_node) { ParseRegisters(include_feature_node, target_info, this->m_register_info, abi_to_use_sp, cur_reg_num, reg_offset); } } this->m_register_info.Finalize(arch_to_use); } } return m_register_info.GetNumRegisters() > 0; } Status ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) { // Make sure LLDB has an XML parser it can use first if (!XMLDocument::XMLEnabled()) return Status(0, ErrorType::eErrorTypeGeneric); Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS); if (log) log->Printf("ProcessGDBRemote::%s", __FUNCTION__); GDBRemoteCommunicationClient &comm = m_gdb_comm; // check that we have extended feature read support if (comm.GetQXferLibrariesSVR4ReadSupported()) { list.clear(); // request the loaded library list std::string raw; lldb_private::Status lldberr; if (!comm.ReadExtFeature(ConstString("libraries-svr4"), ConstString(""), raw, lldberr)) return Status(0, ErrorType::eErrorTypeGeneric); // parse the xml file in memory if (log) log->Printf("parsing: %s", raw.c_str()); XMLDocument doc; if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml")) return Status(0, ErrorType::eErrorTypeGeneric); XMLNode root_element = doc.GetRootElement("library-list-svr4"); if (!root_element) return Status(); // main link map structure llvm::StringRef main_lm = root_element.GetAttributeValue("main-lm"); if (!main_lm.empty()) { list.m_link_map = StringConvert::ToUInt64(main_lm.data(), LLDB_INVALID_ADDRESS, 0); } root_element.ForEachChildElementWithName( "library", [log, &list](const XMLNode &library) -> bool { LoadedModuleInfoList::LoadedModuleInfo module; library.ForEachAttribute( [&module](const llvm::StringRef &name, const llvm::StringRef &value) -> bool { if (name == "name") module.set_name(value.str()); else if (name == "lm") { // the address of the link_map struct. module.set_link_map(StringConvert::ToUInt64( value.data(), LLDB_INVALID_ADDRESS, 0)); } else if (name == "l_addr") { // the displacement as read from the field 'l_addr' of the // link_map struct. module.set_base(StringConvert::ToUInt64( value.data(), LLDB_INVALID_ADDRESS, 0)); // base address is always a displacement, not an absolute // value. module.set_base_is_offset(true); } else if (name == "l_ld") { // the memory address of the libraries PT_DYAMIC section. module.set_dynamic(StringConvert::ToUInt64( value.data(), LLDB_INVALID_ADDRESS, 0)); } return true; // Keep iterating over all properties of "library" }); if (log) { std::string name; lldb::addr_t lm = 0, base = 0, ld = 0; bool base_is_offset; module.get_name(name); module.get_link_map(lm); module.get_base(base); module.get_base_is_offset(base_is_offset); module.get_dynamic(ld); log->Printf("found (link_map:0x%08" PRIx64 ", base:0x%08" PRIx64 "[%s], ld:0x%08" PRIx64 ", name:'%s')", lm, base, (base_is_offset ? "offset" : "absolute"), ld, name.c_str()); } list.add(module); return true; // Keep iterating over all "library" elements in the root // node }); if (log) log->Printf("found %" PRId32 " modules in total", (int)list.m_list.size()); } else if (comm.GetQXferLibrariesReadSupported()) { list.clear(); // request the loaded library list std::string raw; lldb_private::Status lldberr; if (!comm.ReadExtFeature(ConstString("libraries"), ConstString(""), raw, lldberr)) return Status(0, ErrorType::eErrorTypeGeneric); if (log) log->Printf("parsing: %s", raw.c_str()); XMLDocument doc; if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml")) return Status(0, ErrorType::eErrorTypeGeneric); XMLNode root_element = doc.GetRootElement("library-list"); if (!root_element) return Status(); root_element.ForEachChildElementWithName( "library", [log, &list](const XMLNode &library) -> bool { LoadedModuleInfoList::LoadedModuleInfo module; llvm::StringRef name = library.GetAttributeValue("name"); module.set_name(name.str()); // The base address of a given library will be the address of its // first section. Most remotes send only one section for Windows // targets for example. const XMLNode §ion = library.FindFirstChildElementWithName("section"); llvm::StringRef address = section.GetAttributeValue("address"); module.set_base( StringConvert::ToUInt64(address.data(), LLDB_INVALID_ADDRESS, 0)); // These addresses are absolute values. module.set_base_is_offset(false); if (log) { std::string name; lldb::addr_t base = 0; bool base_is_offset; module.get_name(name); module.get_base(base); module.get_base_is_offset(base_is_offset); log->Printf("found (base:0x%08" PRIx64 "[%s], name:'%s')", base, (base_is_offset ? "offset" : "absolute"), name.c_str()); } list.add(module); return true; // Keep iterating over all "library" elements in the root // node }); if (log) log->Printf("found %" PRId32 " modules in total", (int)list.m_list.size()); } else { return Status(0, ErrorType::eErrorTypeGeneric); } return Status(); } lldb::ModuleSP ProcessGDBRemote::LoadModuleAtAddress(const FileSpec &file, lldb::addr_t link_map, lldb::addr_t base_addr, bool value_is_offset) { DynamicLoader *loader = GetDynamicLoader(); if (!loader) return nullptr; return loader->LoadModuleAtAddress(file, link_map, base_addr, value_is_offset); } size_t ProcessGDBRemote::LoadModules(LoadedModuleInfoList &module_list) { using lldb_private::process_gdb_remote::ProcessGDBRemote; // request a list of loaded libraries from GDBServer if (GetLoadedModuleList(module_list).Fail()) return 0; // get a list of all the modules ModuleList new_modules; for (LoadedModuleInfoList::LoadedModuleInfo &modInfo : module_list.m_list) { std::string mod_name; lldb::addr_t mod_base; lldb::addr_t link_map; bool mod_base_is_offset; bool valid = true; valid &= modInfo.get_name(mod_name); valid &= modInfo.get_base(mod_base); valid &= modInfo.get_base_is_offset(mod_base_is_offset); if (!valid) continue; if (!modInfo.get_link_map(link_map)) link_map = LLDB_INVALID_ADDRESS; FileSpec file(mod_name, true); lldb::ModuleSP module_sp = LoadModuleAtAddress(file, link_map, mod_base, mod_base_is_offset); if (module_sp.get()) new_modules.Append(module_sp); } if (new_modules.GetSize() > 0) { ModuleList removed_modules; Target &target = GetTarget(); ModuleList &loaded_modules = m_process->GetTarget().GetImages(); for (size_t i = 0; i < loaded_modules.GetSize(); ++i) { const lldb::ModuleSP loaded_module = loaded_modules.GetModuleAtIndex(i); bool found = false; for (size_t j = 0; j < new_modules.GetSize(); ++j) { if (new_modules.GetModuleAtIndex(j).get() == loaded_module.get()) found = true; } // The main executable will never be included in libraries-svr4, don't // remove it if (!found && loaded_module.get() != target.GetExecutableModulePointer()) { removed_modules.Append(loaded_module); } } loaded_modules.Remove(removed_modules); m_process->GetTarget().ModulesDidUnload(removed_modules, false); new_modules.ForEach([&target](const lldb::ModuleSP module_sp) -> bool { lldb_private::ObjectFile *obj = module_sp->GetObjectFile(); if (!obj) return true; if (obj->GetType() != ObjectFile::Type::eTypeExecutable) return true; lldb::ModuleSP module_copy_sp = module_sp; target.SetExecutableModule(module_copy_sp, false); return false; }); loaded_modules.AppendIfNeeded(new_modules); m_process->GetTarget().ModulesDidLoad(new_modules); } return new_modules.GetSize(); } size_t ProcessGDBRemote::LoadModules() { LoadedModuleInfoList module_list; return LoadModules(module_list); } Status ProcessGDBRemote::GetFileLoadAddress(const FileSpec &file, bool &is_loaded, lldb::addr_t &load_addr) { is_loaded = false; load_addr = LLDB_INVALID_ADDRESS; std::string file_path = file.GetPath(false); if (file_path.empty()) return Status("Empty file name specified"); StreamString packet; packet.PutCString("qFileLoadAddress:"); packet.PutCStringAsRawHex8(file_path.c_str()); StringExtractorGDBRemote response; if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, false) != GDBRemoteCommunication::PacketResult::Success) return Status("Sending qFileLoadAddress packet failed"); if (response.IsErrorResponse()) { if (response.GetError() == 1) { // The file is not loaded into the inferior is_loaded = false; load_addr = LLDB_INVALID_ADDRESS; return Status(); } return Status( "Fetching file load address from remote server returned an error"); } if (response.IsNormalResponse()) { is_loaded = true; load_addr = response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); return Status(); } return Status( "Unknown error happened during sending the load address packet"); } void ProcessGDBRemote::ModulesDidLoad(ModuleList &module_list) { // We must call the lldb_private::Process::ModulesDidLoad () first before we // do anything Process::ModulesDidLoad(module_list); // After loading shared libraries, we can ask our remote GDB server if // it needs any symbols. m_gdb_comm.ServeSymbolLookups(this); } void ProcessGDBRemote::HandleAsyncStdout(llvm::StringRef out) { AppendSTDOUT(out.data(), out.size()); } static const char *end_delimiter = "--end--;"; static const int end_delimiter_len = 8; void ProcessGDBRemote::HandleAsyncMisc(llvm::StringRef data) { std::string input = data.str(); // '1' to move beyond 'A' if (m_partial_profile_data.length() > 0) { m_partial_profile_data.append(input); input = m_partial_profile_data; m_partial_profile_data.clear(); } size_t found, pos = 0, len = input.length(); while ((found = input.find(end_delimiter, pos)) != std::string::npos) { StringExtractorGDBRemote profileDataExtractor( input.substr(pos, found).c_str()); std::string profile_data = HarmonizeThreadIdsForProfileData(profileDataExtractor); BroadcastAsyncProfileData(profile_data); pos = found + end_delimiter_len; } if (pos < len) { // Last incomplete chunk. m_partial_profile_data = input.substr(pos); } } std::string ProcessGDBRemote::HarmonizeThreadIdsForProfileData( StringExtractorGDBRemote &profileDataExtractor) { std::map new_thread_id_to_used_usec_map; std::string output; llvm::raw_string_ostream output_stream(output); llvm::StringRef name, value; // Going to assuming thread_used_usec comes first, else bail out. while (profileDataExtractor.GetNameColonValue(name, value)) { if (name.compare("thread_used_id") == 0) { StringExtractor threadIDHexExtractor(value); uint64_t thread_id = threadIDHexExtractor.GetHexMaxU64(false, 0); bool has_used_usec = false; uint32_t curr_used_usec = 0; llvm::StringRef usec_name, usec_value; uint32_t input_file_pos = profileDataExtractor.GetFilePos(); if (profileDataExtractor.GetNameColonValue(usec_name, usec_value)) { if (usec_name.equals("thread_used_usec")) { has_used_usec = true; usec_value.getAsInteger(0, curr_used_usec); } else { // We didn't find what we want, it is probably // an older version. Bail out. profileDataExtractor.SetFilePos(input_file_pos); } } if (has_used_usec) { uint32_t prev_used_usec = 0; std::map::iterator iterator = m_thread_id_to_used_usec_map.find(thread_id); if (iterator != m_thread_id_to_used_usec_map.end()) { prev_used_usec = m_thread_id_to_used_usec_map[thread_id]; } uint32_t real_used_usec = curr_used_usec - prev_used_usec; // A good first time record is one that runs for at least 0.25 sec bool good_first_time = (prev_used_usec == 0) && (real_used_usec > 250000); bool good_subsequent_time = (prev_used_usec > 0) && ((real_used_usec > 0) || (HasAssignedIndexIDToThread(thread_id))); if (good_first_time || good_subsequent_time) { // We try to avoid doing too many index id reservation, // resulting in fast increase of index ids. output_stream << name << ":"; int32_t index_id = AssignIndexIDToThread(thread_id); output_stream << index_id << ";"; output_stream << usec_name << ":" << usec_value << ";"; } else { // Skip past 'thread_used_name'. llvm::StringRef local_name, local_value; profileDataExtractor.GetNameColonValue(local_name, local_value); } // Store current time as previous time so that they can be compared // later. new_thread_id_to_used_usec_map[thread_id] = curr_used_usec; } else { // Bail out and use old string. output_stream << name << ":" << value << ";"; } } else { output_stream << name << ":" << value << ";"; } } output_stream << end_delimiter; m_thread_id_to_used_usec_map = new_thread_id_to_used_usec_map; return output_stream.str(); } void ProcessGDBRemote::HandleStopReply() { if (GetStopID() != 0) return; if (GetID() == LLDB_INVALID_PROCESS_ID) { lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID(); if (pid != LLDB_INVALID_PROCESS_ID) SetID(pid); } BuildDynamicRegisterInfo(true); } static const char *const s_async_json_packet_prefix = "JSON-async:"; static StructuredData::ObjectSP ParseStructuredDataPacket(llvm::StringRef packet) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (!packet.consume_front(s_async_json_packet_prefix)) { if (log) { log->Printf( "GDBRemoteCommmunicationClientBase::%s() received $J packet " "but was not a StructuredData packet: packet starts with " "%s", __FUNCTION__, packet.slice(0, strlen(s_async_json_packet_prefix)).str().c_str()); } return StructuredData::ObjectSP(); } // This is an asynchronous JSON packet, destined for a // StructuredDataPlugin. StructuredData::ObjectSP json_sp = StructuredData::ParseJSON(packet); if (log) { if (json_sp) { StreamString json_str; json_sp->Dump(json_str); json_str.Flush(); log->Printf("ProcessGDBRemote::%s() " "received Async StructuredData packet: %s", __FUNCTION__, json_str.GetData()); } else { log->Printf("ProcessGDBRemote::%s" "() received StructuredData packet:" " parse failure", __FUNCTION__); } } return json_sp; } void ProcessGDBRemote::HandleAsyncStructuredDataPacket(llvm::StringRef data) { auto structured_data_sp = ParseStructuredDataPacket(data); if (structured_data_sp) RouteAsyncStructuredData(structured_data_sp); } class CommandObjectProcessGDBRemoteSpeedTest : public CommandObjectParsed { public: CommandObjectProcessGDBRemoteSpeedTest(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "process plugin packet speed-test", "Tests packet speeds of various sizes to determine " "the performance characteristics of the GDB remote " "connection. ", NULL), m_option_group(), m_num_packets(LLDB_OPT_SET_1, false, "count", 'c', 0, eArgTypeCount, "The number of packets to send of each varying size " "(default is 1000).", 1000), m_max_send(LLDB_OPT_SET_1, false, "max-send", 's', 0, eArgTypeCount, "The maximum number of bytes to send in a packet. Sizes " "increase in powers of 2 while the size is less than or " "equal to this option value. (default 1024).", 1024), m_max_recv(LLDB_OPT_SET_1, false, "max-receive", 'r', 0, eArgTypeCount, "The maximum number of bytes to receive in a packet. Sizes " "increase in powers of 2 while the size is less than or " "equal to this option value. (default 1024).", 1024), m_json(LLDB_OPT_SET_1, false, "json", 'j', "Print the output as JSON data for easy parsing.", false, true) { m_option_group.Append(&m_num_packets, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Append(&m_max_send, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Append(&m_max_recv, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Append(&m_json, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Finalize(); } ~CommandObjectProcessGDBRemoteSpeedTest() {} Options *GetOptions() override { return &m_option_group; } bool DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); if (argc == 0) { ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext() .GetProcessPtr(); if (process) { StreamSP output_stream_sp( m_interpreter.GetDebugger().GetAsyncOutputStream()); result.SetImmediateOutputStream(output_stream_sp); const uint32_t num_packets = (uint32_t)m_num_packets.GetOptionValue().GetCurrentValue(); const uint64_t max_send = m_max_send.GetOptionValue().GetCurrentValue(); const uint64_t max_recv = m_max_recv.GetOptionValue().GetCurrentValue(); const bool json = m_json.GetOptionValue().GetCurrentValue(); const uint64_t k_recv_amount = 4 * 1024 * 1024; // Receive amount in bytes process->GetGDBRemote().TestPacketSpeed( num_packets, max_send, max_recv, k_recv_amount, json, output_stream_sp ? *output_stream_sp : result.GetOutputStream()); result.SetStatus(eReturnStatusSuccessFinishResult); return true; } } else { result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str()); } result.SetStatus(eReturnStatusFailed); return false; } protected: OptionGroupOptions m_option_group; OptionGroupUInt64 m_num_packets; OptionGroupUInt64 m_max_send; OptionGroupUInt64 m_max_recv; OptionGroupBoolean m_json; }; class CommandObjectProcessGDBRemotePacketHistory : public CommandObjectParsed { private: public: CommandObjectProcessGDBRemotePacketHistory(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "process plugin packet history", "Dumps the packet history buffer. ", NULL) {} ~CommandObjectProcessGDBRemotePacketHistory() {} bool DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); if (argc == 0) { ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext() .GetProcessPtr(); if (process) { process->GetGDBRemote().DumpHistory(result.GetOutputStream()); result.SetStatus(eReturnStatusSuccessFinishResult); return true; } } else { result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str()); } result.SetStatus(eReturnStatusFailed); return false; } }; class CommandObjectProcessGDBRemotePacketXferSize : public CommandObjectParsed { private: public: CommandObjectProcessGDBRemotePacketXferSize(CommandInterpreter &interpreter) : CommandObjectParsed( interpreter, "process plugin packet xfer-size", "Maximum size that lldb will try to read/write one one chunk.", NULL) {} ~CommandObjectProcessGDBRemotePacketXferSize() {} bool DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); if (argc == 0) { result.AppendErrorWithFormat("'%s' takes an argument to specify the max " "amount to be transferred when " "reading/writing", m_cmd_name.c_str()); result.SetStatus(eReturnStatusFailed); return false; } ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); if (process) { const char *packet_size = command.GetArgumentAtIndex(0); errno = 0; uint64_t user_specified_max = strtoul(packet_size, NULL, 10); if (errno == 0 && user_specified_max != 0) { process->SetUserSpecifiedMaxMemoryTransferSize(user_specified_max); result.SetStatus(eReturnStatusSuccessFinishResult); return true; } } result.SetStatus(eReturnStatusFailed); return false; } }; class CommandObjectProcessGDBRemotePacketSend : public CommandObjectParsed { private: public: CommandObjectProcessGDBRemotePacketSend(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "process plugin packet send", "Send a custom packet through the GDB remote " "protocol and print the answer. " "The packet header and footer will automatically " "be added to the packet prior to sending and " "stripped from the result.", NULL) {} ~CommandObjectProcessGDBRemotePacketSend() {} bool DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); if (argc == 0) { result.AppendErrorWithFormat( "'%s' takes a one or more packet content arguments", m_cmd_name.c_str()); result.SetStatus(eReturnStatusFailed); return false; } ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); if (process) { for (size_t i = 0; i < argc; ++i) { const char *packet_cstr = command.GetArgumentAtIndex(0); bool send_async = true; StringExtractorGDBRemote response; process->GetGDBRemote().SendPacketAndWaitForResponse( packet_cstr, response, send_async); result.SetStatus(eReturnStatusSuccessFinishResult); Stream &output_strm = result.GetOutputStream(); output_strm.Printf(" packet: %s\n", packet_cstr); std::string &response_str = response.GetStringRef(); if (strstr(packet_cstr, "qGetProfileData") != NULL) { response_str = process->HarmonizeThreadIdsForProfileData(response); } if (response_str.empty()) output_strm.PutCString("response: \nerror: UNIMPLEMENTED\n"); else output_strm.Printf("response: %s\n", response.GetStringRef().c_str()); } } return true; } }; class CommandObjectProcessGDBRemotePacketMonitor : public CommandObjectRaw { private: public: CommandObjectProcessGDBRemotePacketMonitor(CommandInterpreter &interpreter) : CommandObjectRaw(interpreter, "process plugin packet monitor", "Send a qRcmd packet through the GDB remote protocol " "and print the response." "The argument passed to this command will be hex " "encoded into a valid 'qRcmd' packet, sent and the " "response will be printed.") {} ~CommandObjectProcessGDBRemotePacketMonitor() {} bool DoExecute(const char *command, CommandReturnObject &result) override { if (command == NULL || command[0] == '\0') { result.AppendErrorWithFormat("'%s' takes a command string argument", m_cmd_name.c_str()); result.SetStatus(eReturnStatusFailed); return false; } ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr(); if (process) { StreamString packet; packet.PutCString("qRcmd,"); packet.PutBytesAsRawHex8(command, strlen(command)); bool send_async = true; StringExtractorGDBRemote response; process->GetGDBRemote().SendPacketAndWaitForResponse( packet.GetString(), response, send_async); result.SetStatus(eReturnStatusSuccessFinishResult); Stream &output_strm = result.GetOutputStream(); output_strm.Printf(" packet: %s\n", packet.GetData()); const std::string &response_str = response.GetStringRef(); if (response_str.empty()) output_strm.PutCString("response: \nerror: UNIMPLEMENTED\n"); else output_strm.Printf("response: %s\n", response.GetStringRef().c_str()); } return true; } }; class CommandObjectProcessGDBRemotePacket : public CommandObjectMultiword { private: public: CommandObjectProcessGDBRemotePacket(CommandInterpreter &interpreter) : CommandObjectMultiword(interpreter, "process plugin packet", "Commands that deal with GDB remote packets.", NULL) { LoadSubCommand( "history", CommandObjectSP( new CommandObjectProcessGDBRemotePacketHistory(interpreter))); LoadSubCommand( "send", CommandObjectSP( new CommandObjectProcessGDBRemotePacketSend(interpreter))); LoadSubCommand( "monitor", CommandObjectSP( new CommandObjectProcessGDBRemotePacketMonitor(interpreter))); LoadSubCommand( "xfer-size", CommandObjectSP( new CommandObjectProcessGDBRemotePacketXferSize(interpreter))); LoadSubCommand("speed-test", CommandObjectSP(new CommandObjectProcessGDBRemoteSpeedTest( interpreter))); } ~CommandObjectProcessGDBRemotePacket() {} }; class CommandObjectMultiwordProcessGDBRemote : public CommandObjectMultiword { public: CommandObjectMultiwordProcessGDBRemote(CommandInterpreter &interpreter) : CommandObjectMultiword( interpreter, "process plugin", "Commands for operating on a ProcessGDBRemote process.", "process plugin []") { LoadSubCommand( "packet", CommandObjectSP(new CommandObjectProcessGDBRemotePacket(interpreter))); } ~CommandObjectMultiwordProcessGDBRemote() {} }; CommandObject *ProcessGDBRemote::GetPluginCommandObject() { if (!m_command_sp) m_command_sp.reset(new CommandObjectMultiwordProcessGDBRemote( GetTarget().GetDebugger().GetCommandInterpreter())); return m_command_sp.get(); } Index: vendor/lldb/dist/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp (revision 320967) @@ -1,3188 +1,3186 @@ //===-- ScriptInterpreterPython.cpp -----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifdef LLDB_DISABLE_PYTHON // Python is disabled in this build #else // LLDB Python header must be included first #include "lldb-python.h" #include "PythonDataObjects.h" #include "PythonExceptionState.h" #include "ScriptInterpreterPython.h" #include #include #include #include #include "lldb/API/SBValue.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Breakpoint/WatchpointOptions.h" #include "lldb/Core/Communication.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/ValueObject.h" #include "lldb/DataFormatters/TypeSummary.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/Pipe.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" #include "lldb/Utility/Timer.h" #if defined(_WIN32) #include "lldb/Host/windows/ConnectionGenericFileWindows.h" #endif #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/FileSystem.h" using namespace lldb; using namespace lldb_private; static ScriptInterpreterPython::SWIGInitCallback g_swig_init_callback = nullptr; static ScriptInterpreterPython::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = nullptr; static ScriptInterpreterPython::SWIGWatchpointCallbackFunction g_swig_watchpoint_callback = nullptr; static ScriptInterpreterPython::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = nullptr; static ScriptInterpreterPython::SWIGPythonCreateSyntheticProvider g_swig_synthetic_script = nullptr; static ScriptInterpreterPython::SWIGPythonCreateCommandObject g_swig_create_cmd = nullptr; static ScriptInterpreterPython::SWIGPythonCalculateNumChildren g_swig_calc_children = nullptr; static ScriptInterpreterPython::SWIGPythonGetChildAtIndex g_swig_get_child_index = nullptr; static ScriptInterpreterPython::SWIGPythonGetIndexOfChildWithName g_swig_get_index_child = nullptr; static ScriptInterpreterPython::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = nullptr; static ScriptInterpreterPython::SWIGPythonGetValueObjectSPFromSBValue g_swig_get_valobj_sp_from_sbvalue = nullptr; static ScriptInterpreterPython::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = nullptr; static ScriptInterpreterPython::SWIGPythonMightHaveChildrenSynthProviderInstance g_swig_mighthavechildren_provider = nullptr; static ScriptInterpreterPython::SWIGPythonGetValueSynthProviderInstance g_swig_getvalue_provider = nullptr; static ScriptInterpreterPython::SWIGPythonCallCommand g_swig_call_command = nullptr; static ScriptInterpreterPython::SWIGPythonCallCommandObject g_swig_call_command_object = nullptr; static ScriptInterpreterPython::SWIGPythonCallModuleInit g_swig_call_module_init = nullptr; static ScriptInterpreterPython::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = nullptr; static ScriptInterpreterPython::SWIGPythonScriptKeyword_Process g_swig_run_script_keyword_process = nullptr; static ScriptInterpreterPython::SWIGPythonScriptKeyword_Thread g_swig_run_script_keyword_thread = nullptr; static ScriptInterpreterPython::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = nullptr; static ScriptInterpreterPython::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = nullptr; static ScriptInterpreterPython::SWIGPythonScriptKeyword_Value g_swig_run_script_keyword_value = nullptr; static ScriptInterpreterPython::SWIGPython_GetDynamicSetting g_swig_plugin_get = nullptr; static ScriptInterpreterPython::SWIGPythonCreateScriptedThreadPlan g_swig_thread_plan_script = nullptr; static ScriptInterpreterPython::SWIGPythonCallThreadPlan g_swig_call_thread_plan = nullptr; static bool g_initialized = false; namespace { // Initializing Python is not a straightforward process. We cannot control what // external code may have done before getting to this point in LLDB, including // potentially having already initialized Python, so we need to do a lot of work // to ensure that the existing state of the system is maintained across our // initialization. We do this by using an RAII pattern where we save off // initial // state at the beginning, and restore it at the end struct InitializePythonRAII { public: InitializePythonRAII() : m_gil_state(PyGILState_UNLOCKED), m_was_already_initialized(false) { // Python will muck with STDIN terminal state, so save off any current TTY // settings so we can restore them. m_stdin_tty_state.Save(STDIN_FILENO, false); InitializePythonHome(); // Python < 3.2 and Python >= 3.2 reversed the ordering requirements for // calling `Py_Initialize` and `PyEval_InitThreads`. < 3.2 requires that you // call `PyEval_InitThreads` first, and >= 3.2 requires that you call it last. #if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 2) || (PY_MAJOR_VERSION > 3) Py_InitializeEx(0); InitializeThreadsPrivate(); #else InitializeThreadsPrivate(); Py_InitializeEx(0); #endif } ~InitializePythonRAII() { if (m_was_already_initialized) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); LLDB_LOGV(log, "Releasing PyGILState. Returning to state = {0}locked", m_was_already_initialized == PyGILState_UNLOCKED ? "un" : ""); PyGILState_Release(m_gil_state); } else { // We initialized the threads in this function, just unlock the GIL. PyEval_SaveThread(); } m_stdin_tty_state.Restore(); } private: void InitializePythonHome() { #if defined(LLDB_PYTHON_HOME) #if PY_MAJOR_VERSION >= 3 size_t size = 0; static wchar_t *g_python_home = Py_DecodeLocale(LLDB_PYTHON_HOME, &size); #else static char g_python_home[] = LLDB_PYTHON_HOME; #endif Py_SetPythonHome(g_python_home); #endif } void InitializeThreadsPrivate() { if (PyEval_ThreadsInitialized()) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); m_was_already_initialized = true; m_gil_state = PyGILState_Ensure(); LLDB_LOGV(log, "Ensured PyGILState. Previous state = {0}locked\n", m_gil_state == PyGILState_UNLOCKED ? "un" : ""); return; } // InitThreads acquires the GIL if it hasn't been called before. PyEval_InitThreads(); } TerminalState m_stdin_tty_state; PyGILState_STATE m_gil_state; bool m_was_already_initialized; }; } ScriptInterpreterPython::Locker::Locker(ScriptInterpreterPython *py_interpreter, uint16_t on_entry, uint16_t on_leave, FILE *in, FILE *out, FILE *err) : ScriptInterpreterLocker(), m_teardown_session((on_leave & TearDownSession) == TearDownSession), m_python_interpreter(py_interpreter) { DoAcquireLock(); if ((on_entry & InitSession) == InitSession) { if (DoInitSession(on_entry, in, out, err) == false) { // Don't teardown the session if we didn't init it. m_teardown_session = false; } } } bool ScriptInterpreterPython::Locker::DoAcquireLock() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); m_GILState = PyGILState_Ensure(); LLDB_LOGV(log, "Ensured PyGILState. Previous state = {0}locked", m_GILState == PyGILState_UNLOCKED ? "un" : ""); // we need to save the thread state when we first start the command // because we might decide to interrupt it while some action is taking // place outside of Python (e.g. printing to screen, waiting for the network, // ...) // in that case, _PyThreadState_Current will be NULL - and we would be unable // to set the asynchronous exception - not a desirable situation m_python_interpreter->SetThreadState(PyThreadState_Get()); m_python_interpreter->IncrementLockCount(); return true; } bool ScriptInterpreterPython::Locker::DoInitSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err) { if (!m_python_interpreter) return false; return m_python_interpreter->EnterSession(on_entry_flags, in, out, err); } bool ScriptInterpreterPython::Locker::DoFreeLock() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); LLDB_LOGV(log, "Releasing PyGILState. Returning to state = {0}locked", m_GILState == PyGILState_UNLOCKED ? "un" : ""); PyGILState_Release(m_GILState); m_python_interpreter->DecrementLockCount(); return true; } bool ScriptInterpreterPython::Locker::DoTearDownSession() { if (!m_python_interpreter) return false; m_python_interpreter->LeaveSession(); return true; } ScriptInterpreterPython::Locker::~Locker() { if (m_teardown_session) DoTearDownSession(); DoFreeLock(); } ScriptInterpreterPython::ScriptInterpreterPython( CommandInterpreter &interpreter) : ScriptInterpreter(interpreter, eScriptLanguagePython), IOHandlerDelegateMultiline("DONE"), m_saved_stdin(), m_saved_stdout(), m_saved_stderr(), m_main_module(), m_lldb_module(), m_session_dict(PyInitialValue::Invalid), m_sys_module_dict(PyInitialValue::Invalid), m_run_one_line_function(), m_run_one_line_str_global(), m_dictionary_name( interpreter.GetDebugger().GetInstanceName().AsCString()), m_terminal_state(), m_active_io_handler(eIOHandlerNone), m_session_is_active(false), m_pty_slave_is_open(false), m_valid_session(true), m_lock_count(0), m_command_thread_state(nullptr) { InitializePrivate(); m_dictionary_name.append("_dict"); StreamString run_string; run_string.Printf("%s = dict()", m_dictionary_name.c_str()); Locker locker(this, ScriptInterpreterPython::Locker::AcquireLock, ScriptInterpreterPython::Locker::FreeAcquiredLock); PyRun_SimpleString(run_string.GetData()); run_string.Clear(); run_string.Printf( "run_one_line (%s, 'import copy, keyword, os, re, sys, uuid, lldb')", m_dictionary_name.c_str()); PyRun_SimpleString(run_string.GetData()); // Reloading modules requires a different syntax in Python 2 and Python 3. // This provides // a consistent syntax no matter what version of Python. run_string.Clear(); run_string.Printf("run_one_line (%s, 'from six.moves import reload_module')", m_dictionary_name.c_str()); PyRun_SimpleString(run_string.GetData()); // WARNING: temporary code that loads Cocoa formatters - this should be done // on a per-platform basis rather than loading the whole set // and letting the individual formatter classes exploit APIs to check whether // they can/cannot do their task run_string.Clear(); run_string.Printf( "run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp, pydoc')", m_dictionary_name.c_str()); PyRun_SimpleString(run_string.GetData()); run_string.Clear(); run_string.Printf("run_one_line (%s, 'import lldb.embedded_interpreter; from " "lldb.embedded_interpreter import run_python_interpreter; " "from lldb.embedded_interpreter import run_one_line')", m_dictionary_name.c_str()); PyRun_SimpleString(run_string.GetData()); run_string.Clear(); run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64 "; pydoc.pager = pydoc.plainpager')", m_dictionary_name.c_str(), interpreter.GetDebugger().GetID()); PyRun_SimpleString(run_string.GetData()); } ScriptInterpreterPython::~ScriptInterpreterPython() { // the session dictionary may hold objects with complex state // which means that they may need to be torn down with some level of smarts // and that, in turn, requires a valid thread state // force Python to procure itself such a thread state, nuke the session // dictionary // and then release it for others to use and proceed with the rest of the // shutdown auto gil_state = PyGILState_Ensure(); m_session_dict.Reset(); PyGILState_Release(gil_state); } void ScriptInterpreterPython::Initialize() { static llvm::once_flag g_once_flag; llvm::call_once(g_once_flag, []() { PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), lldb::eScriptLanguagePython, CreateInstance); }); } void ScriptInterpreterPython::Terminate() {} lldb::ScriptInterpreterSP ScriptInterpreterPython::CreateInstance(CommandInterpreter &interpreter) { return std::make_shared(interpreter); } lldb_private::ConstString ScriptInterpreterPython::GetPluginNameStatic() { static ConstString g_name("script-python"); return g_name; } const char *ScriptInterpreterPython::GetPluginDescriptionStatic() { return "Embedded Python interpreter"; } lldb_private::ConstString ScriptInterpreterPython::GetPluginName() { return GetPluginNameStatic(); } uint32_t ScriptInterpreterPython::GetPluginVersion() { return 1; } void ScriptInterpreterPython::IOHandlerActivated(IOHandler &io_handler) { const char *instructions = nullptr; switch (m_active_io_handler) { case eIOHandlerNone: break; case eIOHandlerBreakpoint: instructions = R"(Enter your Python command(s). Type 'DONE' to end. def function (frame, bp_loc, internal_dict): """frame: the lldb.SBFrame for the location at which you stopped bp_loc: an lldb.SBBreakpointLocation for the breakpoint location information internal_dict: an LLDB support object not to be used""" )"; break; case eIOHandlerWatchpoint: instructions = "Enter your Python command(s). Type 'DONE' to end.\n"; break; } if (instructions) { StreamFileSP output_sp(io_handler.GetOutputStreamFile()); if (output_sp) { output_sp->PutCString(instructions); output_sp->Flush(); } } } void ScriptInterpreterPython::IOHandlerInputComplete(IOHandler &io_handler, std::string &data) { io_handler.SetIsDone(true); bool batch_mode = m_interpreter.GetBatchCommandMode(); switch (m_active_io_handler) { case eIOHandlerNone: break; case eIOHandlerBreakpoint: { std::vector *bp_options_vec = (std::vector *)io_handler.GetUserData(); for (auto bp_options : *bp_options_vec) { if (!bp_options) continue; auto data_ap = llvm::make_unique(); if (!data_ap) break; data_ap->user_source.SplitIntoLines(data); if (GenerateBreakpointCommandCallbackData(data_ap->user_source, data_ap->script_source) .Success()) { auto baton_sp = std::make_shared( std::move(data_ap)); bp_options->SetCallback( ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp); } else if (!batch_mode) { StreamFileSP error_sp = io_handler.GetErrorStreamFile(); if (error_sp) { error_sp->Printf("Warning: No command attached to breakpoint.\n"); error_sp->Flush(); } } } m_active_io_handler = eIOHandlerNone; } break; case eIOHandlerWatchpoint: { WatchpointOptions *wp_options = (WatchpointOptions *)io_handler.GetUserData(); auto data_ap = llvm::make_unique(); data_ap->user_source.SplitIntoLines(data); if (GenerateWatchpointCommandCallbackData(data_ap->user_source, data_ap->script_source)) { auto baton_sp = std::make_shared(std::move(data_ap)); wp_options->SetCallback( ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp); } else if (!batch_mode) { StreamFileSP error_sp = io_handler.GetErrorStreamFile(); if (error_sp) { error_sp->Printf("Warning: No command attached to breakpoint.\n"); error_sp->Flush(); } } m_active_io_handler = eIOHandlerNone; } break; } } void ScriptInterpreterPython::ResetOutputFileHandle(FILE *fh) {} void ScriptInterpreterPython::SaveTerminalState(int fd) { // Python mucks with the terminal state of STDIN. If we can possibly avoid // this by setting the file handles up correctly prior to entering the // interpreter we should. For now we save and restore the terminal state // on the input file handle. m_terminal_state.Save(fd, false); } void ScriptInterpreterPython::RestoreTerminalState() { // Python mucks with the terminal state of STDIN. If we can possibly avoid // this by setting the file handles up correctly prior to entering the // interpreter we should. For now we save and restore the terminal state // on the input file handle. m_terminal_state.Restore(); } void ScriptInterpreterPython::LeaveSession() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); if (log) log->PutCString("ScriptInterpreterPython::LeaveSession()"); // checking that we have a valid thread state - since we use our own threading // and locking // in some (rare) cases during cleanup Python may end up believing we have no // thread state // and PyImport_AddModule will crash if that is the case - since that seems to // only happen // when destroying the SBDebugger, we can make do without clearing up stdout // and stderr // rdar://problem/11292882 // When the current thread state is NULL, PyThreadState_Get() issues a fatal // error. if (PyThreadState_GetDict()) { PythonDictionary &sys_module_dict = GetSysModuleDictionary(); if (sys_module_dict.IsValid()) { if (m_saved_stdin.IsValid()) { sys_module_dict.SetItemForKey(PythonString("stdin"), m_saved_stdin); m_saved_stdin.Reset(); } if (m_saved_stdout.IsValid()) { sys_module_dict.SetItemForKey(PythonString("stdout"), m_saved_stdout); m_saved_stdout.Reset(); } if (m_saved_stderr.IsValid()) { sys_module_dict.SetItemForKey(PythonString("stderr"), m_saved_stderr); m_saved_stderr.Reset(); } } } m_session_is_active = false; } bool ScriptInterpreterPython::SetStdHandle(File &file, const char *py_name, PythonFile &save_file, const char *mode) { if (file.IsValid()) { // Flush the file before giving it to python to avoid interleaved output. file.Flush(); PythonDictionary &sys_module_dict = GetSysModuleDictionary(); save_file = sys_module_dict.GetItemForKey(PythonString(py_name)) .AsType(); PythonFile new_file(file, mode); sys_module_dict.SetItemForKey(PythonString(py_name), new_file); return true; } else save_file.Reset(); return false; } bool ScriptInterpreterPython::EnterSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err) { // If we have already entered the session, without having officially 'left' // it, then there is no need to // 'enter' it again. Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); if (m_session_is_active) { if (log) log->Printf( "ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16 ") session is already active, returning without doing anything", on_entry_flags); return false; } if (log) log->Printf( "ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16 ")", on_entry_flags); m_session_is_active = true; StreamString run_string; if (on_entry_flags & Locker::InitGlobals) { run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID()); run_string.Printf( "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")", GetCommandInterpreter().GetDebugger().GetID()); run_string.PutCString("; lldb.target = lldb.debugger.GetSelectedTarget()"); run_string.PutCString("; lldb.process = lldb.target.GetProcess()"); run_string.PutCString("; lldb.thread = lldb.process.GetSelectedThread ()"); run_string.PutCString("; lldb.frame = lldb.thread.GetSelectedFrame ()"); run_string.PutCString("')"); } else { // If we aren't initing the globals, we should still always set the debugger // (since that is always unique.) run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID()); run_string.Printf( "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")", GetCommandInterpreter().GetDebugger().GetID()); run_string.PutCString("')"); } PyRun_SimpleString(run_string.GetData()); run_string.Clear(); PythonDictionary &sys_module_dict = GetSysModuleDictionary(); if (sys_module_dict.IsValid()) { File in_file(in, false); File out_file(out, false); File err_file(err, false); lldb::StreamFileSP in_sp; lldb::StreamFileSP out_sp; lldb::StreamFileSP err_sp; if (!in_file.IsValid() || !out_file.IsValid() || !err_file.IsValid()) m_interpreter.GetDebugger().AdoptTopIOHandlerFilesIfInvalid(in_sp, out_sp, err_sp); if (on_entry_flags & Locker::NoSTDIN) { m_saved_stdin.Reset(); } else { if (!SetStdHandle(in_file, "stdin", m_saved_stdin, "r")) { if (in_sp) SetStdHandle(in_sp->GetFile(), "stdin", m_saved_stdin, "r"); } } if (!SetStdHandle(out_file, "stdout", m_saved_stdout, "w")) { if (out_sp) SetStdHandle(out_sp->GetFile(), "stdout", m_saved_stdout, "w"); } if (!SetStdHandle(err_file, "stderr", m_saved_stderr, "w")) { if (err_sp) SetStdHandle(err_sp->GetFile(), "stderr", m_saved_stderr, "w"); } } if (PyErr_Occurred()) PyErr_Clear(); return true; } PythonObject &ScriptInterpreterPython::GetMainModule() { if (!m_main_module.IsValid()) m_main_module.Reset(PyRefType::Borrowed, PyImport_AddModule("__main__")); return m_main_module; } PythonDictionary &ScriptInterpreterPython::GetSessionDictionary() { if (m_session_dict.IsValid()) return m_session_dict; PythonObject &main_module = GetMainModule(); if (!main_module.IsValid()) return m_session_dict; PythonDictionary main_dict(PyRefType::Borrowed, PyModule_GetDict(main_module.get())); if (!main_dict.IsValid()) return m_session_dict; PythonObject item = main_dict.GetItemForKey(PythonString(m_dictionary_name)); m_session_dict.Reset(PyRefType::Borrowed, item.get()); return m_session_dict; } PythonDictionary &ScriptInterpreterPython::GetSysModuleDictionary() { if (m_sys_module_dict.IsValid()) return m_sys_module_dict; PythonObject sys_module(PyRefType::Borrowed, PyImport_AddModule("sys")); if (sys_module.IsValid()) m_sys_module_dict.Reset(PyRefType::Borrowed, PyModule_GetDict(sys_module.get())); return m_sys_module_dict; } static std::string GenerateUniqueName(const char *base_name_wanted, uint32_t &functions_counter, const void *name_token = nullptr) { StreamString sstr; if (!base_name_wanted) return std::string(); if (!name_token) sstr.Printf("%s_%d", base_name_wanted, functions_counter++); else sstr.Printf("%s_%p", base_name_wanted, name_token); return sstr.GetString(); } bool ScriptInterpreterPython::GetEmbeddedInterpreterModuleObjects() { if (m_run_one_line_function.IsValid()) return true; PythonObject module(PyRefType::Borrowed, PyImport_AddModule("lldb.embedded_interpreter")); if (!module.IsValid()) return false; PythonDictionary module_dict(PyRefType::Borrowed, PyModule_GetDict(module.get())); if (!module_dict.IsValid()) return false; m_run_one_line_function = module_dict.GetItemForKey(PythonString("run_one_line")); m_run_one_line_str_global = module_dict.GetItemForKey(PythonString("g_run_one_line_str")); return m_run_one_line_function.IsValid(); } static void ReadThreadBytesReceived(void *baton, const void *src, size_t src_len) { if (src && src_len) { Stream *strm = (Stream *)baton; strm->Write(src, src_len); strm->Flush(); } } bool ScriptInterpreterPython::ExecuteOneLine( const char *command, CommandReturnObject *result, const ExecuteScriptOptions &options) { if (!m_valid_session) return false; if (command && command[0]) { // We want to call run_one_line, passing in the dictionary and the command // string. We cannot do this through // PyRun_SimpleString here because the command string may contain escaped // characters, and putting it inside // another string to pass to PyRun_SimpleString messes up the escaping. So // we use the following more complicated // method to pass the command string directly down to Python. Debugger &debugger = m_interpreter.GetDebugger(); StreamFileSP input_file_sp; StreamFileSP output_file_sp; StreamFileSP error_file_sp; Communication output_comm( "lldb.ScriptInterpreterPython.ExecuteOneLine.comm"); bool join_read_thread = false; if (options.GetEnableIO()) { if (result) { input_file_sp = debugger.GetInputFile(); // Set output to a temporary file so we can forward the results on to // the result object Pipe pipe; Status pipe_result = pipe.CreateNew(false); if (pipe_result.Success()) { #if defined(_WIN32) lldb::file_t read_file = pipe.GetReadNativeHandle(); pipe.ReleaseReadFileDescriptor(); std::unique_ptr conn_ap( new ConnectionGenericFile(read_file, true)); #else std::unique_ptr conn_ap( new ConnectionFileDescriptor(pipe.ReleaseReadFileDescriptor(), true)); #endif if (conn_ap->IsConnected()) { output_comm.SetConnection(conn_ap.release()); output_comm.SetReadThreadBytesReceivedCallback( ReadThreadBytesReceived, &result->GetOutputStream()); output_comm.StartReadThread(); join_read_thread = true; FILE *outfile_handle = fdopen(pipe.ReleaseWriteFileDescriptor(), "w"); output_file_sp.reset(new StreamFile(outfile_handle, true)); error_file_sp = output_file_sp; if (outfile_handle) ::setbuf(outfile_handle, nullptr); result->SetImmediateOutputFile( debugger.GetOutputFile()->GetFile().GetStream()); result->SetImmediateErrorFile( debugger.GetErrorFile()->GetFile().GetStream()); } } } if (!input_file_sp || !output_file_sp || !error_file_sp) debugger.AdoptTopIOHandlerFilesIfInvalid(input_file_sp, output_file_sp, error_file_sp); } else { input_file_sp.reset(new StreamFile()); input_file_sp->GetFile().Open(FileSystem::DEV_NULL, File::eOpenOptionRead); output_file_sp.reset(new StreamFile()); output_file_sp->GetFile().Open(FileSystem::DEV_NULL, File::eOpenOptionWrite); error_file_sp = output_file_sp; } FILE *in_file = input_file_sp->GetFile().GetStream(); FILE *out_file = output_file_sp->GetFile().GetStream(); FILE *err_file = error_file_sp->GetFile().GetStream(); bool success = false; { // WARNING! It's imperative that this RAII scope be as tight as possible. // In particular, the // scope must end *before* we try to join the read thread. The reason for // this is that a // pre-requisite for joining the read thread is that we close the write // handle (to break the // pipe and cause it to wake up and exit). But acquiring the GIL as below // will redirect Python's // stdio to use this same handle. If we close the handle while Python is // still using it, bad // things will happen. Locker locker( this, ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | ((result && result->GetInteractive()) ? 0 : Locker::NoSTDIN), ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession, in_file, out_file, err_file); // Find the correct script interpreter dictionary in the main module. PythonDictionary &session_dict = GetSessionDictionary(); if (session_dict.IsValid()) { if (GetEmbeddedInterpreterModuleObjects()) { if (PyCallable_Check(m_run_one_line_function.get())) { PythonObject pargs( PyRefType::Owned, Py_BuildValue("(Os)", session_dict.get(), command)); if (pargs.IsValid()) { PythonObject return_value( PyRefType::Owned, PyObject_CallObject(m_run_one_line_function.get(), pargs.get())); if (return_value.IsValid()) success = true; else if (options.GetMaskoutErrors() && PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); } } } } } // Flush our output and error file handles ::fflush(out_file); if (out_file != err_file) ::fflush(err_file); } if (join_read_thread) { // Close the write end of the pipe since we are done with our // one line script. This should cause the read thread that // output_comm is using to exit output_file_sp->GetFile().Close(); // The close above should cause this thread to exit when it gets // to the end of file, so let it get all its data output_comm.JoinReadThread(); // Now we can close the read end of the pipe output_comm.Disconnect(); } if (success) return true; // The one-liner failed. Append the error message. if (result) result->AppendErrorWithFormat( "python failed attempting to evaluate '%s'\n", command); return false; } if (result) result->AppendError("empty command passed to python\n"); return false; } class IOHandlerPythonInterpreter : public IOHandler { public: IOHandlerPythonInterpreter(Debugger &debugger, ScriptInterpreterPython *python) : IOHandler(debugger, IOHandler::Type::PythonInterpreter), m_python(python) {} ~IOHandlerPythonInterpreter() override {} ConstString GetControlSequence(char ch) override { if (ch == 'd') return ConstString("quit()\n"); return ConstString(); } void Run() override { if (m_python) { int stdin_fd = GetInputFD(); if (stdin_fd >= 0) { Terminal terminal(stdin_fd); TerminalState terminal_state; const bool is_a_tty = terminal.IsATerminal(); if (is_a_tty) { terminal_state.Save(stdin_fd, false); terminal.SetCanonical(false); terminal.SetEcho(true); } ScriptInterpreterPython::Locker locker( m_python, ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | ScriptInterpreterPython::Locker::InitGlobals, ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession); // The following call drops into the embedded interpreter loop and stays // there until the // user chooses to exit from the Python interpreter. // This embedded interpreter will, as any Python code that performs I/O, // unlock the GIL before // a system call that can hang, and lock it when the syscall has // returned. // We need to surround the call to the embedded interpreter with calls // to PyGILState_Ensure and // PyGILState_Release (using the Locker above). This is because Python // has a global lock which must be held whenever we want // to touch any Python objects. Otherwise, if the user calls Python // code, the interpreter state will be off, // and things could hang (it's happened before). StreamString run_string; run_string.Printf("run_python_interpreter (%s)", m_python->GetDictionaryName()); PyRun_SimpleString(run_string.GetData()); if (is_a_tty) terminal_state.Restore(); } } SetIsDone(true); } void Cancel() override {} bool Interrupt() override { return m_python->Interrupt(); } void GotEOF() override {} protected: ScriptInterpreterPython *m_python; }; void ScriptInterpreterPython::ExecuteInterpreterLoop() { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); Debugger &debugger = GetCommandInterpreter().GetDebugger(); // At the moment, the only time the debugger does not have an input file // handle is when this is called // directly from Python, in which case it is both dangerous and unnecessary // (not to mention confusing) to // try to embed a running interpreter loop inside the already running Python // interpreter loop, so we won't // do it. if (!debugger.GetInputFile()->GetFile().IsValid()) return; IOHandlerSP io_handler_sp(new IOHandlerPythonInterpreter(debugger, this)); if (io_handler_sp) { debugger.PushIOHandler(io_handler_sp); } } bool ScriptInterpreterPython::Interrupt() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); if (IsExecutingPython()) { PyThreadState *state = PyThreadState_GET(); if (!state) state = GetThreadState(); if (state) { long tid = state->thread_id; PyThreadState_Swap(state); int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt); if (log) log->Printf("ScriptInterpreterPython::Interrupt() sending " "PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...", tid, num_threads); return true; } } if (log) log->Printf("ScriptInterpreterPython::Interrupt() python code not running, " "can't interrupt"); return false; } bool ScriptInterpreterPython::ExecuteOneLineWithReturn( const char *in_string, ScriptInterpreter::ScriptReturnType return_type, void *ret_value, const ExecuteScriptOptions &options) { Locker locker(this, ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | Locker::NoSTDIN, ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession); PythonObject py_return; PythonObject &main_module = GetMainModule(); PythonDictionary globals(PyRefType::Borrowed, PyModule_GetDict(main_module.get())); PythonObject py_error; bool ret_success = false; int success; PythonDictionary locals = GetSessionDictionary(); if (!locals.IsValid()) { locals.Reset( PyRefType::Owned, PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str())); } if (!locals.IsValid()) locals = globals; py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); if (py_error.IsValid()) PyErr_Clear(); if (in_string != nullptr) { { // scope for PythonInputReaderManager // PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL); py_return.Reset( PyRefType::Owned, PyRun_String(in_string, Py_eval_input, globals.get(), locals.get())); if (!py_return.IsValid()) { py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); if (py_error.IsValid()) PyErr_Clear(); py_return.Reset(PyRefType::Owned, PyRun_String(in_string, Py_single_input, globals.get(), locals.get())); } } if (py_return.IsValid()) { switch (return_type) { case eScriptReturnTypeCharPtr: // "char *" { const char format[3] = "s#"; success = PyArg_Parse(py_return.get(), format, (char **)ret_value); break; } case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return == // Py_None { const char format[3] = "z"; success = PyArg_Parse(py_return.get(), format, (char **)ret_value); break; } case eScriptReturnTypeBool: { const char format[2] = "b"; success = PyArg_Parse(py_return.get(), format, (bool *)ret_value); break; } case eScriptReturnTypeShortInt: { const char format[2] = "h"; success = PyArg_Parse(py_return.get(), format, (short *)ret_value); break; } case eScriptReturnTypeShortIntUnsigned: { const char format[2] = "H"; success = PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value); break; } case eScriptReturnTypeInt: { const char format[2] = "i"; success = PyArg_Parse(py_return.get(), format, (int *)ret_value); break; } case eScriptReturnTypeIntUnsigned: { const char format[2] = "I"; success = PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value); break; } case eScriptReturnTypeLongInt: { const char format[2] = "l"; success = PyArg_Parse(py_return.get(), format, (long *)ret_value); break; } case eScriptReturnTypeLongIntUnsigned: { const char format[2] = "k"; success = PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value); break; } case eScriptReturnTypeLongLong: { const char format[2] = "L"; success = PyArg_Parse(py_return.get(), format, (long long *)ret_value); break; } case eScriptReturnTypeLongLongUnsigned: { const char format[2] = "K"; success = PyArg_Parse(py_return.get(), format, (unsigned long long *)ret_value); break; } case eScriptReturnTypeFloat: { const char format[2] = "f"; success = PyArg_Parse(py_return.get(), format, (float *)ret_value); break; } case eScriptReturnTypeDouble: { const char format[2] = "d"; success = PyArg_Parse(py_return.get(), format, (double *)ret_value); break; } case eScriptReturnTypeChar: { const char format[2] = "c"; success = PyArg_Parse(py_return.get(), format, (char *)ret_value); break; } case eScriptReturnTypeOpaqueObject: { success = true; PyObject *saved_value = py_return.get(); Py_XINCREF(saved_value); *((PyObject **)ret_value) = saved_value; break; } } if (success) ret_success = true; else ret_success = false; } } py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); if (py_error.IsValid()) { ret_success = false; if (options.GetMaskoutErrors()) { if (PyErr_GivenExceptionMatches(py_error.get(), PyExc_SyntaxError)) PyErr_Print(); PyErr_Clear(); } } return ret_success; } Status ScriptInterpreterPython::ExecuteMultipleLines( const char *in_string, const ExecuteScriptOptions &options) { Status error; Locker locker(this, ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | Locker::NoSTDIN, ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession); PythonObject return_value; PythonObject &main_module = GetMainModule(); PythonDictionary globals(PyRefType::Borrowed, PyModule_GetDict(main_module.get())); PythonObject py_error; PythonDictionary locals = GetSessionDictionary(); if (!locals.IsValid()) locals.Reset( PyRefType::Owned, PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str())); if (!locals.IsValid()) locals = globals; py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); if (py_error.IsValid()) PyErr_Clear(); if (in_string != nullptr) { PythonObject code_object; code_object.Reset(PyRefType::Owned, Py_CompileString(in_string, "temp.py", Py_file_input)); if (code_object.IsValid()) { // In Python 2.x, PyEval_EvalCode takes a PyCodeObject, but in Python 3.x, it // takes // a PyObject. They are convertible (hence the function // PyCode_Check(PyObject*), so // we have to do the cast for Python 2.x #if PY_MAJOR_VERSION >= 3 PyObject *py_code_obj = code_object.get(); #else PyCodeObject *py_code_obj = reinterpret_cast(code_object.get()); #endif return_value.Reset( PyRefType::Owned, PyEval_EvalCode(py_code_obj, globals.get(), locals.get())); } } PythonExceptionState exception_state(!options.GetMaskoutErrors()); if (exception_state.IsError()) error.SetErrorString(exception_state.Format().c_str()); return error; } void ScriptInterpreterPython::CollectDataForBreakpointCommandCallback( std::vector &bp_options_vec, CommandReturnObject &result) { m_active_io_handler = eIOHandlerBreakpoint; m_interpreter.GetPythonCommandsFromIOHandler(" ", *this, true, &bp_options_vec); } void ScriptInterpreterPython::CollectDataForWatchpointCommandCallback( WatchpointOptions *wp_options, CommandReturnObject &result) { m_active_io_handler = eIOHandlerWatchpoint; m_interpreter.GetPythonCommandsFromIOHandler(" ", *this, true, wp_options); } void ScriptInterpreterPython::SetBreakpointCommandCallbackFunction( BreakpointOptions *bp_options, const char *function_name) { // For now just cons up a oneliner that calls the provided function. std::string oneliner("return "); oneliner += function_name; oneliner += "(frame, bp_loc, internal_dict)"; m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback( bp_options, oneliner.c_str()); } Status ScriptInterpreterPython::SetBreakpointCommandCallback( BreakpointOptions *bp_options, std::unique_ptr &cmd_data_up) { Status error; error = GenerateBreakpointCommandCallbackData(cmd_data_up->user_source, cmd_data_up->script_source); if (error.Fail()) { return error; } auto baton_sp = std::make_shared(std::move(cmd_data_up)); bp_options->SetCallback(ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp); return error; } // Set a Python one-liner as the callback for the breakpoint. Status ScriptInterpreterPython::SetBreakpointCommandCallback( BreakpointOptions *bp_options, const char *command_body_text) { auto data_ap = llvm::make_unique(); // Split the command_body_text into lines, and pass that to // GenerateBreakpointCommandCallbackData. That will // wrap the body in an auto-generated function, and return the function name // in script_source. That is what // the callback will actually invoke. data_ap->user_source.SplitIntoLines(command_body_text); Status error = GenerateBreakpointCommandCallbackData(data_ap->user_source, data_ap->script_source); if (error.Success()) { auto baton_sp = std::make_shared(std::move(data_ap)); bp_options->SetCallback(ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp); return error; } else return error; } // Set a Python one-liner as the callback for the watchpoint. void ScriptInterpreterPython::SetWatchpointCommandCallback( WatchpointOptions *wp_options, const char *oneliner) { auto data_ap = llvm::make_unique(); // It's necessary to set both user_source and script_source to the oneliner. // The former is used to generate callback description (as in watchpoint // command list) // while the latter is used for Python to interpret during the actual // callback. data_ap->user_source.AppendString(oneliner); data_ap->script_source.assign(oneliner); if (GenerateWatchpointCommandCallbackData(data_ap->user_source, data_ap->script_source)) { auto baton_sp = std::make_shared(std::move(data_ap)); wp_options->SetCallback(ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp); } return; } Status ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter( StringList &function_def) { // Convert StringList to one long, newline delimited, const char *. std::string function_def_string(function_def.CopyList()); Status error = ExecuteMultipleLines( function_def_string.c_str(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false)); return error; } Status ScriptInterpreterPython::GenerateFunction(const char *signature, const StringList &input) { Status error; int num_lines = input.GetSize(); if (num_lines == 0) { error.SetErrorString("No input data."); return error; } if (!signature || *signature == 0) { error.SetErrorString("No output function name."); return error; } StreamString sstr; StringList auto_generated_function; auto_generated_function.AppendString(signature); auto_generated_function.AppendString( " global_dict = globals()"); // Grab the global dictionary auto_generated_function.AppendString( " new_keys = internal_dict.keys()"); // Make a list of keys in the // session dict auto_generated_function.AppendString( " old_keys = global_dict.keys()"); // Save list of keys in global dict auto_generated_function.AppendString( " global_dict.update (internal_dict)"); // Add the session dictionary // to the // global dictionary. // Wrap everything up inside the function, increasing the indentation. auto_generated_function.AppendString(" if True:"); for (int i = 0; i < num_lines; ++i) { sstr.Clear(); sstr.Printf(" %s", input.GetStringAtIndex(i)); auto_generated_function.AppendString(sstr.GetData()); } auto_generated_function.AppendString( " for key in new_keys:"); // Iterate over all the keys from session // dict auto_generated_function.AppendString( " internal_dict[key] = global_dict[key]"); // Update session dict // values auto_generated_function.AppendString( " if key not in old_keys:"); // If key was not originally in // global dict auto_generated_function.AppendString( " del global_dict[key]"); // ...then remove key/value from // global dict // Verify that the results are valid Python. error = ExportFunctionDefinitionToInterpreter(auto_generated_function); return error; } bool ScriptInterpreterPython::GenerateTypeScriptFunction( StringList &user_input, std::string &output, const void *name_token) { static uint32_t num_created_functions = 0; user_input.RemoveBlankLines(); StreamString sstr; // Check to see if we have any data; if not, just return. if (user_input.GetSize() == 0) return false; // Take what the user wrote, wrap it all up inside one big auto-generated // Python function, passing in the // ValueObject as parameter to the function. std::string auto_generated_function_name( GenerateUniqueName("lldb_autogen_python_type_print_func", num_created_functions, name_token)); sstr.Printf("def %s (valobj, internal_dict):", auto_generated_function_name.c_str()); if (!GenerateFunction(sstr.GetData(), user_input).Success()) return false; // Store the name of the auto-generated function to be called. output.assign(auto_generated_function_name); return true; } bool ScriptInterpreterPython::GenerateScriptAliasFunction( StringList &user_input, std::string &output) { static uint32_t num_created_functions = 0; user_input.RemoveBlankLines(); StreamString sstr; // Check to see if we have any data; if not, just return. if (user_input.GetSize() == 0) return false; std::string auto_generated_function_name(GenerateUniqueName( "lldb_autogen_python_cmd_alias_func", num_created_functions)); sstr.Printf("def %s (debugger, args, result, internal_dict):", auto_generated_function_name.c_str()); if (!GenerateFunction(sstr.GetData(), user_input).Success()) return false; // Store the name of the auto-generated function to be called. output.assign(auto_generated_function_name); return true; } bool ScriptInterpreterPython::GenerateTypeSynthClass(StringList &user_input, std::string &output, const void *name_token) { static uint32_t num_created_classes = 0; user_input.RemoveBlankLines(); int num_lines = user_input.GetSize(); StreamString sstr; // Check to see if we have any data; if not, just return. if (user_input.GetSize() == 0) return false; // Wrap all user input into a Python class std::string auto_generated_class_name(GenerateUniqueName( "lldb_autogen_python_type_synth_class", num_created_classes, name_token)); StringList auto_generated_class; // Create the function name & definition string. sstr.Printf("class %s:", auto_generated_class_name.c_str()); auto_generated_class.AppendString(sstr.GetString()); // Wrap everything up inside the class, increasing the indentation. // we don't need to play any fancy indentation tricks here because there is no // surrounding code whose indentation we need to honor for (int i = 0; i < num_lines; ++i) { sstr.Clear(); sstr.Printf(" %s", user_input.GetStringAtIndex(i)); auto_generated_class.AppendString(sstr.GetString()); } // Verify that the results are valid Python. // (even though the method is ExportFunctionDefinitionToInterpreter, a class // will actually be exported) // (TODO: rename that method to ExportDefinitionToInterpreter) if (!ExportFunctionDefinitionToInterpreter(auto_generated_class).Success()) return false; // Store the name of the auto-generated class output.assign(auto_generated_class_name); return true; } StructuredData::GenericSP ScriptInterpreterPython::OSPlugin_CreatePluginObject( const char *class_name, lldb::ProcessSP process_sp) { if (class_name == nullptr || class_name[0] == '\0') return StructuredData::GenericSP(); if (!process_sp) return StructuredData::GenericSP(); void *ret_val; { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); ret_val = g_swig_create_os_plugin(class_name, m_dictionary_name.c_str(), process_sp); } return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); } StructuredData::DictionarySP ScriptInterpreterPython::OSPlugin_RegisterInfo( StructuredData::ObjectSP os_plugin_object_sp) { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); static char callee_name[] = "get_register_info"; if (!os_plugin_object_sp) return StructuredData::DictionarySP(); StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); if (!generic) return nullptr; PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); if (!implementor.IsAllocated()) return StructuredData::DictionarySP(); PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name)); if (PyErr_Occurred()) PyErr_Clear(); if (!pmeth.IsAllocated()) return StructuredData::DictionarySP(); if (PyCallable_Check(pmeth.get()) == 0) { if (PyErr_Occurred()) PyErr_Clear(); return StructuredData::DictionarySP(); } if (PyErr_Occurred()) PyErr_Clear(); // right now we know this function exists and is callable.. PythonObject py_return( PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr)); // if it fails, print the error but otherwise go on if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); } if (py_return.get()) { PythonDictionary result_dict(PyRefType::Borrowed, py_return.get()); return result_dict.CreateStructuredDictionary(); } return StructuredData::DictionarySP(); } StructuredData::ArraySP ScriptInterpreterPython::OSPlugin_ThreadsInfo( StructuredData::ObjectSP os_plugin_object_sp) { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); static char callee_name[] = "get_thread_info"; if (!os_plugin_object_sp) return StructuredData::ArraySP(); StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); if (!generic) return nullptr; PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); if (!implementor.IsAllocated()) return StructuredData::ArraySP(); PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name)); if (PyErr_Occurred()) PyErr_Clear(); if (!pmeth.IsAllocated()) return StructuredData::ArraySP(); if (PyCallable_Check(pmeth.get()) == 0) { if (PyErr_Occurred()) PyErr_Clear(); return StructuredData::ArraySP(); } if (PyErr_Occurred()) PyErr_Clear(); // right now we know this function exists and is callable.. PythonObject py_return( PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr)); // if it fails, print the error but otherwise go on if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); } if (py_return.get()) { PythonList result_list(PyRefType::Borrowed, py_return.get()); return result_list.CreateStructuredArray(); } return StructuredData::ArraySP(); } // GetPythonValueFormatString provides a system independent type safe way to // convert a variable's type into a python value format. Python value formats // are defined in terms of builtin C types and could change from system to // as the underlying typedef for uint* types, size_t, off_t and other values // change. template const char *GetPythonValueFormatString(T t); template <> const char *GetPythonValueFormatString(char *) { return "s"; } template <> const char *GetPythonValueFormatString(char) { return "b"; } template <> const char *GetPythonValueFormatString(unsigned char) { return "B"; } template <> const char *GetPythonValueFormatString(short) { return "h"; } template <> const char *GetPythonValueFormatString(unsigned short) { return "H"; } template <> const char *GetPythonValueFormatString(int) { return "i"; } template <> const char *GetPythonValueFormatString(unsigned int) { return "I"; } template <> const char *GetPythonValueFormatString(long) { return "l"; } template <> const char *GetPythonValueFormatString(unsigned long) { return "k"; } template <> const char *GetPythonValueFormatString(long long) { return "L"; } template <> const char *GetPythonValueFormatString(unsigned long long) { return "K"; } template <> const char *GetPythonValueFormatString(float t) { return "f"; } template <> const char *GetPythonValueFormatString(double t) { return "d"; } StructuredData::StringSP ScriptInterpreterPython::OSPlugin_RegisterContextData( StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid) { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); static char callee_name[] = "get_register_data"; static char *param_format = const_cast(GetPythonValueFormatString(tid)); if (!os_plugin_object_sp) return StructuredData::StringSP(); StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); if (!generic) return nullptr; PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); if (!implementor.IsAllocated()) return StructuredData::StringSP(); PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name)); if (PyErr_Occurred()) PyErr_Clear(); if (!pmeth.IsAllocated()) return StructuredData::StringSP(); if (PyCallable_Check(pmeth.get()) == 0) { if (PyErr_Occurred()) PyErr_Clear(); return StructuredData::StringSP(); } if (PyErr_Occurred()) PyErr_Clear(); // right now we know this function exists and is callable.. PythonObject py_return( PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, param_format, tid)); // if it fails, print the error but otherwise go on if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); } if (py_return.get()) { PythonBytes result(PyRefType::Borrowed, py_return.get()); return result.CreateStructuredString(); } return StructuredData::StringSP(); } StructuredData::DictionarySP ScriptInterpreterPython::OSPlugin_CreateThread( StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid, lldb::addr_t context) { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); static char callee_name[] = "create_thread"; std::string param_format; param_format += GetPythonValueFormatString(tid); param_format += GetPythonValueFormatString(context); if (!os_plugin_object_sp) return StructuredData::DictionarySP(); StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); if (!generic) return nullptr; PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); if (!implementor.IsAllocated()) return StructuredData::DictionarySP(); PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name)); if (PyErr_Occurred()) PyErr_Clear(); if (!pmeth.IsAllocated()) return StructuredData::DictionarySP(); if (PyCallable_Check(pmeth.get()) == 0) { if (PyErr_Occurred()) PyErr_Clear(); return StructuredData::DictionarySP(); } if (PyErr_Occurred()) PyErr_Clear(); // right now we know this function exists and is callable.. PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, ¶m_format[0], tid, context)); // if it fails, print the error but otherwise go on if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); } if (py_return.get()) { PythonDictionary result_dict(PyRefType::Borrowed, py_return.get()); return result_dict.CreateStructuredDictionary(); } return StructuredData::DictionarySP(); } StructuredData::ObjectSP ScriptInterpreterPython::CreateScriptedThreadPlan( const char *class_name, lldb::ThreadPlanSP thread_plan_sp) { if (class_name == nullptr || class_name[0] == '\0') return StructuredData::ObjectSP(); if (!thread_plan_sp.get()) return StructuredData::ObjectSP(); Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger(); ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); ScriptInterpreterPython *python_interpreter = static_cast(script_interpreter); if (!script_interpreter) return StructuredData::ObjectSP(); void *ret_val; { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); ret_val = g_swig_thread_plan_script( class_name, python_interpreter->m_dictionary_name.c_str(), thread_plan_sp); } return StructuredData::ObjectSP(new StructuredPythonObject(ret_val)); } bool ScriptInterpreterPython::ScriptedThreadPlanExplainsStop( StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) { bool explains_stop = true; StructuredData::Generic *generic = nullptr; if (implementor_sp) generic = implementor_sp->GetAsGeneric(); if (generic) { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); explains_stop = g_swig_call_thread_plan( generic->GetValue(), "explains_stop", event, script_error); if (script_error) return true; } return explains_stop; } bool ScriptInterpreterPython::ScriptedThreadPlanShouldStop( StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) { bool should_stop = true; StructuredData::Generic *generic = nullptr; if (implementor_sp) generic = implementor_sp->GetAsGeneric(); if (generic) { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); should_stop = g_swig_call_thread_plan(generic->GetValue(), "should_stop", event, script_error); if (script_error) return true; } return should_stop; } bool ScriptInterpreterPython::ScriptedThreadPlanIsStale( StructuredData::ObjectSP implementor_sp, bool &script_error) { bool is_stale = true; StructuredData::Generic *generic = nullptr; if (implementor_sp) generic = implementor_sp->GetAsGeneric(); if (generic) { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); is_stale = g_swig_call_thread_plan(generic->GetValue(), "is_stale", nullptr, script_error); if (script_error) return true; } return is_stale; } lldb::StateType ScriptInterpreterPython::ScriptedThreadPlanGetRunState( StructuredData::ObjectSP implementor_sp, bool &script_error) { bool should_step = false; StructuredData::Generic *generic = nullptr; if (implementor_sp) generic = implementor_sp->GetAsGeneric(); if (generic) { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); should_step = g_swig_call_thread_plan(generic->GetValue(), "should_step", NULL, script_error); if (script_error) should_step = true; } if (should_step) return lldb::eStateStepping; else return lldb::eStateRunning; } StructuredData::ObjectSP ScriptInterpreterPython::LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) { if (!file_spec.Exists()) { error.SetErrorString("no such file"); return StructuredData::ObjectSP(); } StructuredData::ObjectSP module_sp; if (LoadScriptingModule(file_spec.GetPath().c_str(), true, true, error, &module_sp)) return module_sp; return StructuredData::ObjectSP(); } StructuredData::DictionarySP ScriptInterpreterPython::GetDynamicSettings( StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name, lldb_private::Status &error) { if (!plugin_module_sp || !target || !setting_name || !setting_name[0] || !g_swig_plugin_get) return StructuredData::DictionarySP(); StructuredData::Generic *generic = plugin_module_sp->GetAsGeneric(); if (!generic) return StructuredData::DictionarySP(); PythonObject reply_pyobj; - { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - TargetSP target_sp(target->shared_from_this()); - reply_pyobj.Reset(PyRefType::Owned, - (PyObject *)g_swig_plugin_get(generic->GetValue(), - setting_name, target_sp)); - } + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + TargetSP target_sp(target->shared_from_this()); + reply_pyobj.Reset(PyRefType::Owned, + (PyObject *)g_swig_plugin_get(generic->GetValue(), + setting_name, target_sp)); PythonDictionary py_dict(PyRefType::Borrowed, reply_pyobj.get()); return py_dict.CreateStructuredDictionary(); } StructuredData::ObjectSP ScriptInterpreterPython::CreateSyntheticScriptedProvider( const char *class_name, lldb::ValueObjectSP valobj) { if (class_name == nullptr || class_name[0] == '\0') return StructuredData::ObjectSP(); if (!valobj.get()) return StructuredData::ObjectSP(); ExecutionContext exe_ctx(valobj->GetExecutionContextRef()); Target *target = exe_ctx.GetTargetPtr(); if (!target) return StructuredData::ObjectSP(); Debugger &debugger = target->GetDebugger(); ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *)script_interpreter; if (!script_interpreter) return StructuredData::ObjectSP(); void *ret_val = nullptr; { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); ret_val = g_swig_synthetic_script( class_name, python_interpreter->m_dictionary_name.c_str(), valobj); } return StructuredData::ObjectSP(new StructuredPythonObject(ret_val)); } StructuredData::GenericSP ScriptInterpreterPython::CreateScriptCommandObject(const char *class_name) { DebuggerSP debugger_sp( GetCommandInterpreter().GetDebugger().shared_from_this()); if (class_name == nullptr || class_name[0] == '\0') return StructuredData::GenericSP(); if (!debugger_sp.get()) return StructuredData::GenericSP(); void *ret_val; { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); ret_val = g_swig_create_cmd(class_name, m_dictionary_name.c_str(), debugger_sp); } return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); } bool ScriptInterpreterPython::GenerateTypeScriptFunction( const char *oneliner, std::string &output, const void *name_token) { StringList input; input.SplitIntoLines(oneliner, strlen(oneliner)); return GenerateTypeScriptFunction(input, output, name_token); } bool ScriptInterpreterPython::GenerateTypeSynthClass(const char *oneliner, std::string &output, const void *name_token) { StringList input; input.SplitIntoLines(oneliner, strlen(oneliner)); return GenerateTypeSynthClass(input, output, name_token); } Status ScriptInterpreterPython::GenerateBreakpointCommandCallbackData( StringList &user_input, std::string &output) { static uint32_t num_created_functions = 0; user_input.RemoveBlankLines(); StreamString sstr; Status error; if (user_input.GetSize() == 0) { error.SetErrorString("No input data."); return error; } std::string auto_generated_function_name(GenerateUniqueName( "lldb_autogen_python_bp_callback_func_", num_created_functions)); sstr.Printf("def %s (frame, bp_loc, internal_dict):", auto_generated_function_name.c_str()); error = GenerateFunction(sstr.GetData(), user_input); if (!error.Success()) return error; // Store the name of the auto-generated function to be called. output.assign(auto_generated_function_name); return error; } bool ScriptInterpreterPython::GenerateWatchpointCommandCallbackData( StringList &user_input, std::string &output) { static uint32_t num_created_functions = 0; user_input.RemoveBlankLines(); StreamString sstr; if (user_input.GetSize() == 0) return false; std::string auto_generated_function_name(GenerateUniqueName( "lldb_autogen_python_wp_callback_func_", num_created_functions)); sstr.Printf("def %s (frame, wp, internal_dict):", auto_generated_function_name.c_str()); if (!GenerateFunction(sstr.GetData(), user_input).Success()) return false; // Store the name of the auto-generated function to be called. output.assign(auto_generated_function_name); return true; } bool ScriptInterpreterPython::GetScriptedSummary( const char *python_function_name, lldb::ValueObjectSP valobj, StructuredData::ObjectSP &callee_wrapper_sp, const TypeSummaryOptions &options, std::string &retval) { static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); if (!valobj.get()) { retval.assign(""); return false; } void *old_callee = nullptr; StructuredData::Generic *generic = nullptr; if (callee_wrapper_sp) { generic = callee_wrapper_sp->GetAsGeneric(); if (generic) old_callee = generic->GetValue(); } void *new_callee = old_callee; bool ret_val; if (python_function_name && *python_function_name) { { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); { TypeSummaryOptionsSP options_sp(new TypeSummaryOptions(options)); static Timer::Category func_cat("g_swig_typescript_callback"); Timer scoped_timer(func_cat, "g_swig_typescript_callback"); ret_val = g_swig_typescript_callback( python_function_name, GetSessionDictionary().get(), valobj, &new_callee, options_sp, retval); } } } else { retval.assign(""); return false; } if (new_callee && old_callee != new_callee) callee_wrapper_sp.reset(new StructuredPythonObject(new_callee)); return ret_val; } void ScriptInterpreterPython::Clear() { // Release any global variables that might have strong references to // LLDB objects when clearing the python script interpreter. Locker locker(this, ScriptInterpreterPython::Locker::AcquireLock, ScriptInterpreterPython::Locker::FreeAcquiredLock); // This may be called as part of Py_Finalize. In that case the modules are // destroyed in random // order and we can't guarantee that we can access these. if (Py_IsInitialized()) PyRun_SimpleString("lldb.debugger = None; lldb.target = None; lldb.process " "= None; lldb.thread = None; lldb.frame = None"); } bool ScriptInterpreterPython::BreakpointCallbackFunction( void *baton, StoppointCallbackContext *context, user_id_t break_id, user_id_t break_loc_id) { CommandDataPython *bp_option_data = (CommandDataPython *)baton; const char *python_function_name = bp_option_data->script_source.c_str(); if (!context) return true; ExecutionContext exe_ctx(context->exe_ctx_ref); Target *target = exe_ctx.GetTargetPtr(); if (!target) return true; Debugger &debugger = target->GetDebugger(); ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *)script_interpreter; if (!script_interpreter) return true; if (python_function_name && python_function_name[0]) { const StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP()); BreakpointSP breakpoint_sp = target->GetBreakpointByID(break_id); if (breakpoint_sp) { const BreakpointLocationSP bp_loc_sp( breakpoint_sp->FindLocationByID(break_loc_id)); if (stop_frame_sp && bp_loc_sp) { bool ret_val = true; { Locker py_lock(python_interpreter, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); ret_val = g_swig_breakpoint_callback( python_function_name, python_interpreter->m_dictionary_name.c_str(), stop_frame_sp, bp_loc_sp); } return ret_val; } } } // We currently always true so we stop in case anything goes wrong when // trying to call the script function return true; } bool ScriptInterpreterPython::WatchpointCallbackFunction( void *baton, StoppointCallbackContext *context, user_id_t watch_id) { WatchpointOptions::CommandData *wp_option_data = (WatchpointOptions::CommandData *)baton; const char *python_function_name = wp_option_data->script_source.c_str(); if (!context) return true; ExecutionContext exe_ctx(context->exe_ctx_ref); Target *target = exe_ctx.GetTargetPtr(); if (!target) return true; Debugger &debugger = target->GetDebugger(); ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *)script_interpreter; if (!script_interpreter) return true; if (python_function_name && python_function_name[0]) { const StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP()); WatchpointSP wp_sp = target->GetWatchpointList().FindByID(watch_id); if (wp_sp) { if (stop_frame_sp && wp_sp) { bool ret_val = true; { Locker py_lock(python_interpreter, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); ret_val = g_swig_watchpoint_callback( python_function_name, python_interpreter->m_dictionary_name.c_str(), stop_frame_sp, wp_sp); } return ret_val; } } } // We currently always true so we stop in case anything goes wrong when // trying to call the script function return true; } size_t ScriptInterpreterPython::CalculateNumChildren( const StructuredData::ObjectSP &implementor_sp, uint32_t max) { if (!implementor_sp) return 0; StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); if (!generic) return 0; void *implementor = generic->GetValue(); if (!implementor) return 0; if (!g_swig_calc_children) return 0; size_t ret_val = 0; { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); ret_val = g_swig_calc_children(implementor, max); } return ret_val; } lldb::ValueObjectSP ScriptInterpreterPython::GetChildAtIndex( const StructuredData::ObjectSP &implementor_sp, uint32_t idx) { if (!implementor_sp) return lldb::ValueObjectSP(); StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); if (!generic) return lldb::ValueObjectSP(); void *implementor = generic->GetValue(); if (!implementor) return lldb::ValueObjectSP(); if (!g_swig_get_child_index || !g_swig_cast_to_sbvalue) return lldb::ValueObjectSP(); lldb::ValueObjectSP ret_val; { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); void *child_ptr = g_swig_get_child_index(implementor, idx); if (child_ptr != nullptr && child_ptr != Py_None) { lldb::SBValue *sb_value_ptr = (lldb::SBValue *)g_swig_cast_to_sbvalue(child_ptr); if (sb_value_ptr == nullptr) Py_XDECREF(child_ptr); else ret_val = g_swig_get_valobj_sp_from_sbvalue(sb_value_ptr); } else { Py_XDECREF(child_ptr); } } return ret_val; } int ScriptInterpreterPython::GetIndexOfChildWithName( const StructuredData::ObjectSP &implementor_sp, const char *child_name) { if (!implementor_sp) return UINT32_MAX; StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); if (!generic) return UINT32_MAX; void *implementor = generic->GetValue(); if (!implementor) return UINT32_MAX; if (!g_swig_get_index_child) return UINT32_MAX; int ret_val = UINT32_MAX; { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); ret_val = g_swig_get_index_child(implementor, child_name); } return ret_val; } bool ScriptInterpreterPython::UpdateSynthProviderInstance( const StructuredData::ObjectSP &implementor_sp) { bool ret_val = false; if (!implementor_sp) return ret_val; StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); if (!generic) return ret_val; void *implementor = generic->GetValue(); if (!implementor) return ret_val; if (!g_swig_update_provider) return ret_val; { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); ret_val = g_swig_update_provider(implementor); } return ret_val; } bool ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance( const StructuredData::ObjectSP &implementor_sp) { bool ret_val = false; if (!implementor_sp) return ret_val; StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); if (!generic) return ret_val; void *implementor = generic->GetValue(); if (!implementor) return ret_val; if (!g_swig_mighthavechildren_provider) return ret_val; { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); ret_val = g_swig_mighthavechildren_provider(implementor); } return ret_val; } lldb::ValueObjectSP ScriptInterpreterPython::GetSyntheticValue( const StructuredData::ObjectSP &implementor_sp) { lldb::ValueObjectSP ret_val(nullptr); if (!implementor_sp) return ret_val; StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); if (!generic) return ret_val; void *implementor = generic->GetValue(); if (!implementor) return ret_val; if (!g_swig_getvalue_provider || !g_swig_cast_to_sbvalue || !g_swig_get_valobj_sp_from_sbvalue) return ret_val; { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); void *child_ptr = g_swig_getvalue_provider(implementor); if (child_ptr != nullptr && child_ptr != Py_None) { lldb::SBValue *sb_value_ptr = (lldb::SBValue *)g_swig_cast_to_sbvalue(child_ptr); if (sb_value_ptr == nullptr) Py_XDECREF(child_ptr); else ret_val = g_swig_get_valobj_sp_from_sbvalue(sb_value_ptr); } else { Py_XDECREF(child_ptr); } } return ret_val; } ConstString ScriptInterpreterPython::GetSyntheticTypeName( const StructuredData::ObjectSP &implementor_sp) { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); static char callee_name[] = "get_type_name"; ConstString ret_val; bool got_string = false; std::string buffer; if (!implementor_sp) return ret_val; StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); if (!generic) return ret_val; PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); if (!implementor.IsAllocated()) return ret_val; PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name)); if (PyErr_Occurred()) PyErr_Clear(); if (!pmeth.IsAllocated()) return ret_val; if (PyCallable_Check(pmeth.get()) == 0) { if (PyErr_Occurred()) PyErr_Clear(); return ret_val; } if (PyErr_Occurred()) PyErr_Clear(); // right now we know this function exists and is callable.. PythonObject py_return( PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr)); // if it fails, print the error but otherwise go on if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); } if (py_return.IsAllocated() && PythonString::Check(py_return.get())) { PythonString py_string(PyRefType::Borrowed, py_return.get()); llvm::StringRef return_data(py_string.GetString()); if (!return_data.empty()) { buffer.assign(return_data.data(), return_data.size()); got_string = true; } } if (got_string) ret_val.SetCStringWithLength(buffer.c_str(), buffer.size()); return ret_val; } bool ScriptInterpreterPython::RunScriptFormatKeyword(const char *impl_function, Process *process, std::string &output, Status &error) { bool ret_val; if (!process) { error.SetErrorString("no process"); return false; } if (!impl_function || !impl_function[0]) { error.SetErrorString("no function to execute"); return false; } if (!g_swig_run_script_keyword_process) { error.SetErrorString("internal helper function missing"); return false; } { ProcessSP process_sp(process->shared_from_this()); Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); ret_val = g_swig_run_script_keyword_process( impl_function, m_dictionary_name.c_str(), process_sp, output); if (!ret_val) error.SetErrorString("python script evaluation failed"); } return ret_val; } bool ScriptInterpreterPython::RunScriptFormatKeyword(const char *impl_function, Thread *thread, std::string &output, Status &error) { bool ret_val; if (!thread) { error.SetErrorString("no thread"); return false; } if (!impl_function || !impl_function[0]) { error.SetErrorString("no function to execute"); return false; } if (!g_swig_run_script_keyword_thread) { error.SetErrorString("internal helper function missing"); return false; } { ThreadSP thread_sp(thread->shared_from_this()); Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); ret_val = g_swig_run_script_keyword_thread( impl_function, m_dictionary_name.c_str(), thread_sp, output); if (!ret_val) error.SetErrorString("python script evaluation failed"); } return ret_val; } bool ScriptInterpreterPython::RunScriptFormatKeyword(const char *impl_function, Target *target, std::string &output, Status &error) { bool ret_val; if (!target) { error.SetErrorString("no thread"); return false; } if (!impl_function || !impl_function[0]) { error.SetErrorString("no function to execute"); return false; } if (!g_swig_run_script_keyword_target) { error.SetErrorString("internal helper function missing"); return false; } { TargetSP target_sp(target->shared_from_this()); Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); ret_val = g_swig_run_script_keyword_target( impl_function, m_dictionary_name.c_str(), target_sp, output); if (!ret_val) error.SetErrorString("python script evaluation failed"); } return ret_val; } bool ScriptInterpreterPython::RunScriptFormatKeyword(const char *impl_function, StackFrame *frame, std::string &output, Status &error) { bool ret_val; if (!frame) { error.SetErrorString("no frame"); return false; } if (!impl_function || !impl_function[0]) { error.SetErrorString("no function to execute"); return false; } if (!g_swig_run_script_keyword_frame) { error.SetErrorString("internal helper function missing"); return false; } { StackFrameSP frame_sp(frame->shared_from_this()); Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); ret_val = g_swig_run_script_keyword_frame( impl_function, m_dictionary_name.c_str(), frame_sp, output); if (!ret_val) error.SetErrorString("python script evaluation failed"); } return ret_val; } bool ScriptInterpreterPython::RunScriptFormatKeyword(const char *impl_function, ValueObject *value, std::string &output, Status &error) { bool ret_val; if (!value) { error.SetErrorString("no value"); return false; } if (!impl_function || !impl_function[0]) { error.SetErrorString("no function to execute"); return false; } if (!g_swig_run_script_keyword_value) { error.SetErrorString("internal helper function missing"); return false; } { ValueObjectSP value_sp(value->GetSP()); Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); ret_val = g_swig_run_script_keyword_value( impl_function, m_dictionary_name.c_str(), value_sp, output); if (!ret_val) error.SetErrorString("python script evaluation failed"); } return ret_val; } uint64_t replace_all(std::string &str, const std::string &oldStr, const std::string &newStr) { size_t pos = 0; uint64_t matches = 0; while ((pos = str.find(oldStr, pos)) != std::string::npos) { matches++; str.replace(pos, oldStr.length(), newStr); pos += newStr.length(); } return matches; } bool ScriptInterpreterPython::LoadScriptingModule( const char *pathname, bool can_reload, bool init_session, lldb_private::Status &error, StructuredData::ObjectSP *module_sp) { if (!pathname || !pathname[0]) { error.SetErrorString("invalid pathname"); return false; } if (!g_swig_call_module_init) { error.SetErrorString("internal helper function missing"); return false; } lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this(); { FileSpec target_file(pathname, true); std::string basename(target_file.GetFilename().GetCString()); StreamString command_stream; // Before executing Python code, lock the GIL. Locker py_lock(this, Locker::AcquireLock | (init_session ? Locker::InitSession : 0) | Locker::NoSTDIN, Locker::FreeAcquiredLock | (init_session ? Locker::TearDownSession : 0)); namespace fs = llvm::sys::fs; fs::file_status st; std::error_code ec = status(target_file.GetPath(), st); if (ec || st.type() == fs::file_type::status_error || st.type() == fs::file_type::type_unknown || st.type() == fs::file_type::file_not_found) { // if not a valid file of any sort, check if it might be a filename still // dot can't be used but / and \ can, and if either is found, reject if (strchr(pathname, '\\') || strchr(pathname, '/')) { error.SetErrorString("invalid pathname"); return false; } basename = pathname; // not a filename, probably a package of some sort, // let it go through } else if (is_directory(st) || is_regular_file(st)) { std::string directory = target_file.GetDirectory().GetCString(); replace_all(directory, "\\", "\\\\"); replace_all(directory, "'", "\\'"); // now make sure that Python has "directory" in the search path StreamString command_stream; command_stream.Printf("if not (sys.path.__contains__('%s')):\n " "sys.path.insert(1,'%s');\n\n", directory.c_str(), directory.c_str()); bool syspath_retval = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions() .SetEnableIO(false) .SetSetLLDBGlobals(false)) .Success(); if (!syspath_retval) { error.SetErrorString("Python sys.path handling failed"); return false; } // strip .py or .pyc extension ConstString extension = target_file.GetFileNameExtension(); if (extension) { if (::strcmp(extension.GetCString(), "py") == 0) basename.resize(basename.length() - 3); else if (::strcmp(extension.GetCString(), "pyc") == 0) basename.resize(basename.length() - 4); } } else { error.SetErrorString("no known way to import this module specification"); return false; } // check if the module is already import-ed command_stream.Clear(); command_stream.Printf("sys.modules.__contains__('%s')", basename.c_str()); bool does_contain = false; // this call will succeed if the module was ever imported in any Debugger in // the lifetime of the process // in which this LLDB framework is living bool was_imported_globally = (ExecuteOneLineWithReturn( command_stream.GetData(), ScriptInterpreterPython::eScriptReturnTypeBool, &does_contain, ScriptInterpreter::ExecuteScriptOptions() .SetEnableIO(false) .SetSetLLDBGlobals(false)) && does_contain); // this call will fail if the module was not imported in this Debugger // before command_stream.Clear(); command_stream.Printf("sys.getrefcount(%s)", basename.c_str()); bool was_imported_locally = GetSessionDictionary() .GetItemForKey(PythonString(basename)) .IsAllocated(); bool was_imported = (was_imported_globally || was_imported_locally); if (was_imported == true && can_reload == false) { error.SetErrorString("module already imported"); return false; } // now actually do the import command_stream.Clear(); if (was_imported) { if (!was_imported_locally) command_stream.Printf("import %s ; reload_module(%s)", basename.c_str(), basename.c_str()); else command_stream.Printf("reload_module(%s)", basename.c_str()); } else command_stream.Printf("import %s", basename.c_str()); error = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions() .SetEnableIO(false) .SetSetLLDBGlobals(false)); if (error.Fail()) return false; // if we are here, everything worked // call __lldb_init_module(debugger,dict) if (!g_swig_call_module_init(basename.c_str(), m_dictionary_name.c_str(), debugger_sp)) { error.SetErrorString("calling __lldb_init_module failed"); return false; } if (module_sp) { // everything went just great, now set the module object command_stream.Clear(); command_stream.Printf("%s", basename.c_str()); void *module_pyobj = nullptr; if (ExecuteOneLineWithReturn( command_stream.GetData(), ScriptInterpreter::eScriptReturnTypeOpaqueObject, &module_pyobj) && module_pyobj) module_sp->reset(new StructuredPythonObject(module_pyobj)); } return true; } } bool ScriptInterpreterPython::IsReservedWord(const char *word) { if (!word || !word[0]) return false; llvm::StringRef word_sr(word); // filter out a few characters that would just confuse us // and that are clearly not keyword material anyway if (word_sr.find_first_of("'\"") != llvm::StringRef::npos) return false; StreamString command_stream; command_stream.Printf("keyword.iskeyword('%s')", word); bool result; ExecuteScriptOptions options; options.SetEnableIO(false); options.SetMaskoutErrors(true); options.SetSetLLDBGlobals(false); if (ExecuteOneLineWithReturn(command_stream.GetData(), ScriptInterpreter::eScriptReturnTypeBool, &result, options)) return result; return false; } ScriptInterpreterPython::SynchronicityHandler::SynchronicityHandler( lldb::DebuggerSP debugger_sp, ScriptedCommandSynchronicity synchro) : m_debugger_sp(debugger_sp), m_synch_wanted(synchro), m_old_asynch(debugger_sp->GetAsyncExecution()) { if (m_synch_wanted == eScriptedCommandSynchronicitySynchronous) m_debugger_sp->SetAsyncExecution(false); else if (m_synch_wanted == eScriptedCommandSynchronicityAsynchronous) m_debugger_sp->SetAsyncExecution(true); } ScriptInterpreterPython::SynchronicityHandler::~SynchronicityHandler() { if (m_synch_wanted != eScriptedCommandSynchronicityCurrentValue) m_debugger_sp->SetAsyncExecution(m_old_asynch); } bool ScriptInterpreterPython::RunScriptBasedCommand( const char *impl_function, const char *args, ScriptedCommandSynchronicity synchronicity, lldb_private::CommandReturnObject &cmd_retobj, Status &error, const lldb_private::ExecutionContext &exe_ctx) { if (!impl_function) { error.SetErrorString("no function to execute"); return false; } if (!g_swig_call_command) { error.SetErrorString("no helper function to run scripted commands"); return false; } lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this(); lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx)); if (!debugger_sp.get()) { error.SetErrorString("invalid Debugger pointer"); return false; } bool ret_val = false; std::string err_msg; { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN), Locker::FreeLock | Locker::TearDownSession); SynchronicityHandler synch_handler(debugger_sp, synchronicity); ret_val = g_swig_call_command(impl_function, m_dictionary_name.c_str(), debugger_sp, args, cmd_retobj, exe_ctx_ref_sp); } if (!ret_val) error.SetErrorString("unable to execute script function"); else error.Clear(); return ret_val; } bool ScriptInterpreterPython::RunScriptBasedCommand( StructuredData::GenericSP impl_obj_sp, const char *args, ScriptedCommandSynchronicity synchronicity, lldb_private::CommandReturnObject &cmd_retobj, Status &error, const lldb_private::ExecutionContext &exe_ctx) { if (!impl_obj_sp || !impl_obj_sp->IsValid()) { error.SetErrorString("no function to execute"); return false; } if (!g_swig_call_command_object) { error.SetErrorString("no helper function to run scripted commands"); return false; } lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this(); lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx)); if (!debugger_sp.get()) { error.SetErrorString("invalid Debugger pointer"); return false; } bool ret_val = false; std::string err_msg; { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN), Locker::FreeLock | Locker::TearDownSession); SynchronicityHandler synch_handler(debugger_sp, synchronicity); ret_val = g_swig_call_command_object(impl_obj_sp->GetValue(), debugger_sp, args, cmd_retobj, exe_ctx_ref_sp); } if (!ret_val) error.SetErrorString("unable to execute script function"); else error.Clear(); return ret_val; } // in Python, a special attribute __doc__ contains the docstring // for an object (function, method, class, ...) if any is defined // Otherwise, the attribute's value is None bool ScriptInterpreterPython::GetDocumentationForItem(const char *item, std::string &dest) { dest.clear(); if (!item || !*item) return false; std::string command(item); command += ".__doc__"; char *result_ptr = nullptr; // Python is going to point this to valid data if // ExecuteOneLineWithReturn returns successfully if (ExecuteOneLineWithReturn( command.c_str(), ScriptInterpreter::eScriptReturnTypeCharStrOrNone, &result_ptr, ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false))) { if (result_ptr) dest.assign(result_ptr); return true; } else { StreamString str_stream; str_stream.Printf( "Function %s was not found. Containing module might be missing.", item); dest = str_stream.GetString(); return false; } } bool ScriptInterpreterPython::GetShortHelpForCommandObject( StructuredData::GenericSP cmd_obj_sp, std::string &dest) { bool got_string = false; dest.clear(); Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); static char callee_name[] = "get_short_help"; if (!cmd_obj_sp) return false; PythonObject implementor(PyRefType::Borrowed, (PyObject *)cmd_obj_sp->GetValue()); if (!implementor.IsAllocated()) return false; PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name)); if (PyErr_Occurred()) PyErr_Clear(); if (!pmeth.IsAllocated()) return false; if (PyCallable_Check(pmeth.get()) == 0) { if (PyErr_Occurred()) PyErr_Clear(); return false; } if (PyErr_Occurred()) PyErr_Clear(); // right now we know this function exists and is callable.. PythonObject py_return( PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr)); // if it fails, print the error but otherwise go on if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); } if (py_return.IsAllocated() && PythonString::Check(py_return.get())) { PythonString py_string(PyRefType::Borrowed, py_return.get()); llvm::StringRef return_data(py_string.GetString()); dest.assign(return_data.data(), return_data.size()); got_string = true; } return got_string; } uint32_t ScriptInterpreterPython::GetFlagsForCommandObject( StructuredData::GenericSP cmd_obj_sp) { uint32_t result = 0; Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); static char callee_name[] = "get_flags"; if (!cmd_obj_sp) return result; PythonObject implementor(PyRefType::Borrowed, (PyObject *)cmd_obj_sp->GetValue()); if (!implementor.IsAllocated()) return result; PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name)); if (PyErr_Occurred()) PyErr_Clear(); if (!pmeth.IsAllocated()) return result; if (PyCallable_Check(pmeth.get()) == 0) { if (PyErr_Occurred()) PyErr_Clear(); return result; } if (PyErr_Occurred()) PyErr_Clear(); // right now we know this function exists and is callable.. PythonObject py_return( PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr)); // if it fails, print the error but otherwise go on if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); } if (py_return.IsAllocated() && PythonInteger::Check(py_return.get())) { PythonInteger int_value(PyRefType::Borrowed, py_return.get()); result = int_value.GetInteger(); } return result; } bool ScriptInterpreterPython::GetLongHelpForCommandObject( StructuredData::GenericSP cmd_obj_sp, std::string &dest) { bool got_string = false; dest.clear(); Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); static char callee_name[] = "get_long_help"; if (!cmd_obj_sp) return false; PythonObject implementor(PyRefType::Borrowed, (PyObject *)cmd_obj_sp->GetValue()); if (!implementor.IsAllocated()) return false; PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name)); if (PyErr_Occurred()) PyErr_Clear(); if (!pmeth.IsAllocated()) return false; if (PyCallable_Check(pmeth.get()) == 0) { if (PyErr_Occurred()) PyErr_Clear(); return false; } if (PyErr_Occurred()) PyErr_Clear(); // right now we know this function exists and is callable.. PythonObject py_return( PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr)); // if it fails, print the error but otherwise go on if (PyErr_Occurred()) { PyErr_Print(); PyErr_Clear(); } if (py_return.IsAllocated() && PythonString::Check(py_return.get())) { PythonString str(PyRefType::Borrowed, py_return.get()); llvm::StringRef str_data(str.GetString()); dest.assign(str_data.data(), str_data.size()); got_string = true; } return got_string; } std::unique_ptr ScriptInterpreterPython::AcquireInterpreterLock() { std::unique_ptr py_lock(new Locker( this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN, Locker::FreeLock | Locker::TearDownSession)); return py_lock; } void ScriptInterpreterPython::InitializeInterpreter( SWIGInitCallback swig_init_callback, SWIGBreakpointCallbackFunction swig_breakpoint_callback, SWIGWatchpointCallbackFunction swig_watchpoint_callback, SWIGPythonTypeScriptCallbackFunction swig_typescript_callback, SWIGPythonCreateSyntheticProvider swig_synthetic_script, SWIGPythonCreateCommandObject swig_create_cmd, SWIGPythonCalculateNumChildren swig_calc_children, SWIGPythonGetChildAtIndex swig_get_child_index, SWIGPythonGetIndexOfChildWithName swig_get_index_child, SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue, SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue, SWIGPythonUpdateSynthProviderInstance swig_update_provider, SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider, SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider, SWIGPythonCallCommand swig_call_command, SWIGPythonCallCommandObject swig_call_command_object, SWIGPythonCallModuleInit swig_call_module_init, SWIGPythonCreateOSPlugin swig_create_os_plugin, SWIGPythonScriptKeyword_Process swig_run_script_keyword_process, SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread, SWIGPythonScriptKeyword_Target swig_run_script_keyword_target, SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame, SWIGPythonScriptKeyword_Value swig_run_script_keyword_value, SWIGPython_GetDynamicSetting swig_plugin_get, SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script, SWIGPythonCallThreadPlan swig_call_thread_plan) { g_swig_init_callback = swig_init_callback; g_swig_breakpoint_callback = swig_breakpoint_callback; g_swig_watchpoint_callback = swig_watchpoint_callback; g_swig_typescript_callback = swig_typescript_callback; g_swig_synthetic_script = swig_synthetic_script; g_swig_create_cmd = swig_create_cmd; g_swig_calc_children = swig_calc_children; g_swig_get_child_index = swig_get_child_index; g_swig_get_index_child = swig_get_index_child; g_swig_cast_to_sbvalue = swig_cast_to_sbvalue; g_swig_get_valobj_sp_from_sbvalue = swig_get_valobj_sp_from_sbvalue; g_swig_update_provider = swig_update_provider; g_swig_mighthavechildren_provider = swig_mighthavechildren_provider; g_swig_getvalue_provider = swig_getvalue_provider; g_swig_call_command = swig_call_command; g_swig_call_command_object = swig_call_command_object; g_swig_call_module_init = swig_call_module_init; g_swig_create_os_plugin = swig_create_os_plugin; g_swig_run_script_keyword_process = swig_run_script_keyword_process; g_swig_run_script_keyword_thread = swig_run_script_keyword_thread; g_swig_run_script_keyword_target = swig_run_script_keyword_target; g_swig_run_script_keyword_frame = swig_run_script_keyword_frame; g_swig_run_script_keyword_value = swig_run_script_keyword_value; g_swig_plugin_get = swig_plugin_get; g_swig_thread_plan_script = swig_thread_plan_script; g_swig_call_thread_plan = swig_call_thread_plan; } void ScriptInterpreterPython::InitializePrivate() { if (g_initialized) return; g_initialized = true; static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); // RAII-based initialization which correctly handles multiple-initialization, // version- // specific differences among Python 2 and Python 3, and saving and restoring // various // other pieces of state that can get mucked with during initialization. InitializePythonRAII initialize_guard; if (g_swig_init_callback) g_swig_init_callback(); // Update the path python uses to search for modules to include the current // directory. PyRun_SimpleString("import sys"); AddToSysPath(AddLocation::End, "."); FileSpec file_spec; // Don't denormalize paths when calling file_spec.GetPath(). On platforms // that use // a backslash as the path separator, this will result in executing python // code containing // paths with unescaped backslashes. But Python also accepts forward slashes, // so to make // life easier we just use that. if (HostInfo::GetLLDBPath(ePathTypePythonDir, file_spec)) AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false)); if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, file_spec)) AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false)); PyRun_SimpleString("sys.dont_write_bytecode = 1; import " "lldb.embedded_interpreter; from " "lldb.embedded_interpreter import run_python_interpreter; " "from lldb.embedded_interpreter import run_one_line"); } void ScriptInterpreterPython::AddToSysPath(AddLocation location, std::string path) { std::string path_copy; std::string statement; if (location == AddLocation::Beginning) { statement.assign("sys.path.insert(0,\""); statement.append(path); statement.append("\")"); } else { statement.assign("sys.path.append(\""); statement.append(path); statement.append("\")"); } PyRun_SimpleString(statement.c_str()); } // void // ScriptInterpreterPython::Terminate () //{ // // We are intentionally NOT calling Py_Finalize here (this would be the // logical place to call it). Calling // // Py_Finalize here causes test suite runs to seg fault: The test suite // runs in Python. It registers // // SBDebugger::Terminate to be called 'at_exit'. When the test suite // Python harness finishes up, it calls // // Py_Finalize, which calls all the 'at_exit' registered functions. // SBDebugger::Terminate calls Debugger::Terminate, // // which calls lldb::Terminate, which calls ScriptInterpreter::Terminate, // which calls // // ScriptInterpreterPython::Terminate. So if we call Py_Finalize here, we // end up with Py_Finalize being called from // // within Py_Finalize, which results in a seg fault. // // // // Since this function only gets called when lldb is shutting down and // going away anyway, the fact that we don't // // actually call Py_Finalize should not cause any problems (everything // should shut down/go away anyway when the // // process exits). // // //// Py_Finalize (); //} #endif // #ifdef LLDB_DISABLE_PYTHON Index: vendor/lldb/dist/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp =================================================================== --- vendor/lldb/dist/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp (revision 320966) +++ vendor/lldb/dist/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp (revision 320967) @@ -1,1237 +1,1241 @@ //===-- x86AssemblyInspectionEngine.cpp -------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "x86AssemblyInspectionEngine.h" #include "llvm-c/Disassembler.h" #include "lldb/Core/Address.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/UnwindAssembly.h" using namespace lldb_private; using namespace lldb; x86AssemblyInspectionEngine::x86AssemblyInspectionEngine(const ArchSpec &arch) : m_cur_insn(nullptr), m_machine_ip_regnum(LLDB_INVALID_REGNUM), m_machine_sp_regnum(LLDB_INVALID_REGNUM), m_machine_fp_regnum(LLDB_INVALID_REGNUM), m_lldb_ip_regnum(LLDB_INVALID_REGNUM), m_lldb_sp_regnum(LLDB_INVALID_REGNUM), m_lldb_fp_regnum(LLDB_INVALID_REGNUM), m_reg_map(), m_arch(arch), m_cpu(k_cpu_unspecified), m_wordsize(-1), m_register_map_initialized(false), m_disasm_context() { m_disasm_context = ::LLVMCreateDisasm(arch.GetTriple().getTriple().c_str(), nullptr, /*TagType=*/1, nullptr, nullptr); } x86AssemblyInspectionEngine::~x86AssemblyInspectionEngine() { ::LLVMDisasmDispose(m_disasm_context); } void x86AssemblyInspectionEngine::Initialize(RegisterContextSP ®_ctx) { m_cpu = k_cpu_unspecified; m_wordsize = -1; m_register_map_initialized = false; const llvm::Triple::ArchType cpu = m_arch.GetMachine(); if (cpu == llvm::Triple::x86) m_cpu = k_i386; else if (cpu == llvm::Triple::x86_64) m_cpu = k_x86_64; if (m_cpu == k_cpu_unspecified) return; if (reg_ctx.get() == nullptr) return; if (m_cpu == k_i386) { m_machine_ip_regnum = k_machine_eip; m_machine_sp_regnum = k_machine_esp; m_machine_fp_regnum = k_machine_ebp; m_wordsize = 4; struct lldb_reg_info reginfo; reginfo.name = "eax"; m_reg_map[k_machine_eax] = reginfo; reginfo.name = "edx"; m_reg_map[k_machine_edx] = reginfo; reginfo.name = "esp"; m_reg_map[k_machine_esp] = reginfo; reginfo.name = "esi"; m_reg_map[k_machine_esi] = reginfo; reginfo.name = "eip"; m_reg_map[k_machine_eip] = reginfo; reginfo.name = "ecx"; m_reg_map[k_machine_ecx] = reginfo; reginfo.name = "ebx"; m_reg_map[k_machine_ebx] = reginfo; reginfo.name = "ebp"; m_reg_map[k_machine_ebp] = reginfo; reginfo.name = "edi"; m_reg_map[k_machine_edi] = reginfo; } else { m_machine_ip_regnum = k_machine_rip; m_machine_sp_regnum = k_machine_rsp; m_machine_fp_regnum = k_machine_rbp; m_wordsize = 8; struct lldb_reg_info reginfo; reginfo.name = "rax"; m_reg_map[k_machine_rax] = reginfo; reginfo.name = "rdx"; m_reg_map[k_machine_rdx] = reginfo; reginfo.name = "rsp"; m_reg_map[k_machine_rsp] = reginfo; reginfo.name = "rsi"; m_reg_map[k_machine_rsi] = reginfo; reginfo.name = "r8"; m_reg_map[k_machine_r8] = reginfo; reginfo.name = "r10"; m_reg_map[k_machine_r10] = reginfo; reginfo.name = "r12"; m_reg_map[k_machine_r12] = reginfo; reginfo.name = "r14"; m_reg_map[k_machine_r14] = reginfo; reginfo.name = "rip"; m_reg_map[k_machine_rip] = reginfo; reginfo.name = "rcx"; m_reg_map[k_machine_rcx] = reginfo; reginfo.name = "rbx"; m_reg_map[k_machine_rbx] = reginfo; reginfo.name = "rbp"; m_reg_map[k_machine_rbp] = reginfo; reginfo.name = "rdi"; m_reg_map[k_machine_rdi] = reginfo; reginfo.name = "r9"; m_reg_map[k_machine_r9] = reginfo; reginfo.name = "r11"; m_reg_map[k_machine_r11] = reginfo; reginfo.name = "r13"; m_reg_map[k_machine_r13] = reginfo; reginfo.name = "r15"; m_reg_map[k_machine_r15] = reginfo; } for (MachineRegnumToNameAndLLDBRegnum::iterator it = m_reg_map.begin(); it != m_reg_map.end(); ++it) { const RegisterInfo *ri = reg_ctx->GetRegisterInfoByName(it->second.name); if (ri) it->second.lldb_regnum = ri->kinds[eRegisterKindLLDB]; } uint32_t lldb_regno; if (machine_regno_to_lldb_regno(m_machine_sp_regnum, lldb_regno)) m_lldb_sp_regnum = lldb_regno; if (machine_regno_to_lldb_regno(m_machine_fp_regnum, lldb_regno)) m_lldb_fp_regnum = lldb_regno; if (machine_regno_to_lldb_regno(m_machine_ip_regnum, lldb_regno)) m_lldb_ip_regnum = lldb_regno; m_register_map_initialized = true; } void x86AssemblyInspectionEngine::Initialize( std::vector ®_info) { m_cpu = k_cpu_unspecified; m_wordsize = -1; m_register_map_initialized = false; const llvm::Triple::ArchType cpu = m_arch.GetMachine(); if (cpu == llvm::Triple::x86) m_cpu = k_i386; else if (cpu == llvm::Triple::x86_64) m_cpu = k_x86_64; if (m_cpu == k_cpu_unspecified) return; if (m_cpu == k_i386) { m_machine_ip_regnum = k_machine_eip; m_machine_sp_regnum = k_machine_esp; m_machine_fp_regnum = k_machine_ebp; m_wordsize = 4; struct lldb_reg_info reginfo; reginfo.name = "eax"; m_reg_map[k_machine_eax] = reginfo; reginfo.name = "edx"; m_reg_map[k_machine_edx] = reginfo; reginfo.name = "esp"; m_reg_map[k_machine_esp] = reginfo; reginfo.name = "esi"; m_reg_map[k_machine_esi] = reginfo; reginfo.name = "eip"; m_reg_map[k_machine_eip] = reginfo; reginfo.name = "ecx"; m_reg_map[k_machine_ecx] = reginfo; reginfo.name = "ebx"; m_reg_map[k_machine_ebx] = reginfo; reginfo.name = "ebp"; m_reg_map[k_machine_ebp] = reginfo; reginfo.name = "edi"; m_reg_map[k_machine_edi] = reginfo; } else { m_machine_ip_regnum = k_machine_rip; m_machine_sp_regnum = k_machine_rsp; m_machine_fp_regnum = k_machine_rbp; m_wordsize = 8; struct lldb_reg_info reginfo; reginfo.name = "rax"; m_reg_map[k_machine_rax] = reginfo; reginfo.name = "rdx"; m_reg_map[k_machine_rdx] = reginfo; reginfo.name = "rsp"; m_reg_map[k_machine_rsp] = reginfo; reginfo.name = "rsi"; m_reg_map[k_machine_rsi] = reginfo; reginfo.name = "r8"; m_reg_map[k_machine_r8] = reginfo; reginfo.name = "r10"; m_reg_map[k_machine_r10] = reginfo; reginfo.name = "r12"; m_reg_map[k_machine_r12] = reginfo; reginfo.name = "r14"; m_reg_map[k_machine_r14] = reginfo; reginfo.name = "rip"; m_reg_map[k_machine_rip] = reginfo; reginfo.name = "rcx"; m_reg_map[k_machine_rcx] = reginfo; reginfo.name = "rbx"; m_reg_map[k_machine_rbx] = reginfo; reginfo.name = "rbp"; m_reg_map[k_machine_rbp] = reginfo; reginfo.name = "rdi"; m_reg_map[k_machine_rdi] = reginfo; reginfo.name = "r9"; m_reg_map[k_machine_r9] = reginfo; reginfo.name = "r11"; m_reg_map[k_machine_r11] = reginfo; reginfo.name = "r13"; m_reg_map[k_machine_r13] = reginfo; reginfo.name = "r15"; m_reg_map[k_machine_r15] = reginfo; } for (MachineRegnumToNameAndLLDBRegnum::iterator it = m_reg_map.begin(); it != m_reg_map.end(); ++it) { for (size_t i = 0; i < reg_info.size(); ++i) { if (::strcmp(reg_info[i].name, it->second.name) == 0) { it->second.lldb_regnum = reg_info[i].lldb_regnum; break; } } } uint32_t lldb_regno; if (machine_regno_to_lldb_regno(m_machine_sp_regnum, lldb_regno)) m_lldb_sp_regnum = lldb_regno; if (machine_regno_to_lldb_regno(m_machine_fp_regnum, lldb_regno)) m_lldb_fp_regnum = lldb_regno; if (machine_regno_to_lldb_regno(m_machine_ip_regnum, lldb_regno)) m_lldb_ip_regnum = lldb_regno; m_register_map_initialized = true; } // This function expects an x86 native register number (i.e. the bits stripped // out of the // actual instruction), not an lldb register number. // // FIXME: This is ABI dependent, it shouldn't be hardcoded here. bool x86AssemblyInspectionEngine::nonvolatile_reg_p(int machine_regno) { if (m_cpu == k_i386) { switch (machine_regno) { case k_machine_ebx: case k_machine_ebp: // not actually a nonvolatile but often treated as such // by convention case k_machine_esi: case k_machine_edi: case k_machine_esp: return true; default: return false; } } if (m_cpu == k_x86_64) { switch (machine_regno) { case k_machine_rbx: case k_machine_rsp: case k_machine_rbp: // not actually a nonvolatile but often treated as such // by convention case k_machine_r12: case k_machine_r13: case k_machine_r14: case k_machine_r15: return true; default: return false; } } return false; } // Macro to detect if this is a REX mode prefix byte. #define REX_W_PREFIX_P(opcode) (((opcode) & (~0x5)) == 0x48) // The high bit which should be added to the source register number (the "R" // bit) #define REX_W_SRCREG(opcode) (((opcode)&0x4) >> 2) // The high bit which should be added to the destination register number (the // "B" bit) #define REX_W_DSTREG(opcode) ((opcode)&0x1) // pushq %rbp [0x55] bool x86AssemblyInspectionEngine::push_rbp_pattern_p() { uint8_t *p = m_cur_insn; if (*p == 0x55) return true; return false; } // pushq $0 ; the first instruction in start() [0x6a 0x00] bool x86AssemblyInspectionEngine::push_0_pattern_p() { uint8_t *p = m_cur_insn; if (*p == 0x6a && *(p + 1) == 0x0) return true; return false; } // pushq $0 // pushl $0 bool x86AssemblyInspectionEngine::push_imm_pattern_p() { uint8_t *p = m_cur_insn; if (*p == 0x68 || *p == 0x6a) return true; return false; } // pushl imm8(%esp) // // e.g. 0xff 0x74 0x24 0x20 - 'pushl 0x20(%esp)' // (same byte pattern for 'pushq 0x20(%rsp)' in an x86_64 program) // // 0xff (with opcode bits '6' in next byte, PUSH r/m32) // 0x74 (ModR/M byte with three bits used to specify the opcode) // mod == b01, opcode == b110, R/M == b100 // "+disp8" // 0x24 (SIB byte - scaled index = 0, r32 == esp) // 0x20 imm8 value bool x86AssemblyInspectionEngine::push_extended_pattern_p() { if (*m_cur_insn == 0xff) { // Get the 3 opcode bits from the ModR/M byte uint8_t opcode = (*(m_cur_insn + 1) >> 3) & 7; if (opcode == 6) { // I'm only looking for 0xff /6 here - I // don't really care what value is being pushed, // just that we're pushing a 32/64 bit value on // to the stack is enough. return true; } } return false; } // instructions only valid in 32-bit mode: // 0x0e - push cs // 0x16 - push ss // 0x1e - push ds // 0x06 - push es bool x86AssemblyInspectionEngine::push_misc_reg_p() { uint8_t p = *m_cur_insn; if (m_wordsize == 4) { if (p == 0x0e || p == 0x16 || p == 0x1e || p == 0x06) return true; } return false; } // pushq %rbx // pushl %ebx bool x86AssemblyInspectionEngine::push_reg_p(int ®no) { uint8_t *p = m_cur_insn; int regno_prefix_bit = 0; // If we have a rex prefix byte, check to see if a B bit is set if (m_wordsize == 8 && *p == 0x41) { regno_prefix_bit = 1 << 3; p++; } if (*p >= 0x50 && *p <= 0x57) { regno = (*p - 0x50) | regno_prefix_bit; return true; } return false; } // movq %rsp, %rbp [0x48 0x8b 0xec] or [0x48 0x89 0xe5] // movl %esp, %ebp [0x8b 0xec] or [0x89 0xe5] bool x86AssemblyInspectionEngine::mov_rsp_rbp_pattern_p() { uint8_t *p = m_cur_insn; if (m_wordsize == 8 && *p == 0x48) p++; if (*(p) == 0x8b && *(p + 1) == 0xec) return true; if (*(p) == 0x89 && *(p + 1) == 0xe5) return true; return false; } // subq $0x20, %rsp bool x86AssemblyInspectionEngine::sub_rsp_pattern_p(int &amount) { uint8_t *p = m_cur_insn; if (m_wordsize == 8 && *p == 0x48) p++; // 8-bit immediate operand if (*p == 0x83 && *(p + 1) == 0xec) { amount = (int8_t) * (p + 2); return true; } // 32-bit immediate operand if (*p == 0x81 && *(p + 1) == 0xec) { amount = (int32_t)extract_4(p + 2); return true; } return false; } // addq $0x20, %rsp bool x86AssemblyInspectionEngine::add_rsp_pattern_p(int &amount) { uint8_t *p = m_cur_insn; if (m_wordsize == 8 && *p == 0x48) p++; // 8-bit immediate operand if (*p == 0x83 && *(p + 1) == 0xc4) { amount = (int8_t) * (p + 2); return true; } // 32-bit immediate operand if (*p == 0x81 && *(p + 1) == 0xc4) { amount = (int32_t)extract_4(p + 2); return true; } return false; } // lea esp, [esp - 0x28] // lea esp, [esp + 0x28] bool x86AssemblyInspectionEngine::lea_rsp_pattern_p(int &amount) { uint8_t *p = m_cur_insn; if (m_wordsize == 8 && *p == 0x48) p++; // Check opcode if (*p != 0x8d) return false; // 8 bit displacement if (*(p + 1) == 0x64 && (*(p + 2) & 0x3f) == 0x24) { amount = (int8_t) * (p + 3); return true; } // 32 bit displacement if (*(p + 1) == 0xa4 && (*(p + 2) & 0x3f) == 0x24) { amount = (int32_t)extract_4(p + 3); return true; } return false; } // lea -0x28(%ebp), %esp // (32-bit and 64-bit variants, 8-bit and 32-bit displacement) bool x86AssemblyInspectionEngine::lea_rbp_rsp_pattern_p(int &amount) { uint8_t *p = m_cur_insn; if (m_wordsize == 8 && *p == 0x48) p++; // Check opcode if (*p != 0x8d) return false; ++p; // 8 bit displacement if (*p == 0x65) { amount = (int8_t)p[1]; return true; } // 32 bit displacement if (*p == 0xa5) { amount = (int32_t)extract_4(p + 1); return true; } return false; } // popq %rbx // popl %ebx bool x86AssemblyInspectionEngine::pop_reg_p(int ®no) { uint8_t *p = m_cur_insn; int regno_prefix_bit = 0; // If we have a rex prefix byte, check to see if a B bit is set if (m_wordsize == 8 && *p == 0x41) { regno_prefix_bit = 1 << 3; p++; } if (*p >= 0x58 && *p <= 0x5f) { regno = (*p - 0x58) | regno_prefix_bit; return true; } return false; } // popq %rbp [0x5d] // popl %ebp [0x5d] bool x86AssemblyInspectionEngine::pop_rbp_pattern_p() { uint8_t *p = m_cur_insn; return (*p == 0x5d); } // instructions valid only in 32-bit mode: // 0x1f - pop ds // 0x07 - pop es // 0x17 - pop ss bool x86AssemblyInspectionEngine::pop_misc_reg_p() { uint8_t p = *m_cur_insn; if (m_wordsize == 4) { if (p == 0x1f || p == 0x07 || p == 0x17) return true; } return false; } // leave [0xc9] bool x86AssemblyInspectionEngine::leave_pattern_p() { uint8_t *p = m_cur_insn; return (*p == 0xc9); } // call $0 [0xe8 0x0 0x0 0x0 0x0] bool x86AssemblyInspectionEngine::call_next_insn_pattern_p() { uint8_t *p = m_cur_insn; return (*p == 0xe8) && (*(p + 1) == 0x0) && (*(p + 2) == 0x0) && (*(p + 3) == 0x0) && (*(p + 4) == 0x0); } // Look for an instruction sequence storing a nonvolatile register // on to the stack frame. // movq %rax, -0x10(%rbp) [0x48 0x89 0x45 0xf0] // movl %eax, -0xc(%ebp) [0x89 0x45 0xf4] // The offset value returned in rbp_offset will be positive -- // but it must be subtraced from the frame base register to get // the actual location. The positive value returned for the offset // is a convention used elsewhere for CFA offsets et al. bool x86AssemblyInspectionEngine::mov_reg_to_local_stack_frame_p( int ®no, int &rbp_offset) { uint8_t *p = m_cur_insn; int src_reg_prefix_bit = 0; int target_reg_prefix_bit = 0; if (m_wordsize == 8 && REX_W_PREFIX_P(*p)) { src_reg_prefix_bit = REX_W_SRCREG(*p) << 3; target_reg_prefix_bit = REX_W_DSTREG(*p) << 3; if (target_reg_prefix_bit == 1) { // rbp/ebp don't need a prefix bit - we know this isn't the // reg we care about. return false; } p++; } if (*p == 0x89) { /* Mask off the 3-5 bits which indicate the destination register if this is a ModR/M byte. */ int opcode_destreg_masked_out = *(p + 1) & (~0x38); /* Is this a ModR/M byte with Mod bits 01 and R/M bits 101 and three bits between them, e.g. 01nnn101 We're looking for a destination of ebp-disp8 or ebp-disp32. */ int immsize; if (opcode_destreg_masked_out == 0x45) immsize = 2; else if (opcode_destreg_masked_out == 0x85) immsize = 4; else return false; int offset = 0; if (immsize == 2) offset = (int8_t) * (p + 2); if (immsize == 4) offset = (uint32_t)extract_4(p + 2); if (offset > 0) return false; regno = ((*(p + 1) >> 3) & 0x7) | src_reg_prefix_bit; rbp_offset = offset > 0 ? offset : -offset; return true; } return false; } // ret [0xc9] or [0xc2 imm8] or [0xca imm8] bool x86AssemblyInspectionEngine::ret_pattern_p() { uint8_t *p = m_cur_insn; if (*p == 0xc9 || *p == 0xc2 || *p == 0xca || *p == 0xc3) return true; return false; } uint32_t x86AssemblyInspectionEngine::extract_4(uint8_t *b) { uint32_t v = 0; for (int i = 3; i >= 0; i--) v = (v << 8) | b[i]; return v; } bool x86AssemblyInspectionEngine::instruction_length(uint8_t *insn_p, - int &length) { + int &length, + uint32_t buffer_remaining_bytes) { - const uint32_t max_op_byte_size = m_arch.GetMaximumOpcodeByteSize(); + uint32_t max_op_byte_size = std::min(buffer_remaining_bytes, m_arch.GetMaximumOpcodeByteSize()); llvm::SmallVector opcode_data; opcode_data.resize(max_op_byte_size); char out_string[512]; const size_t inst_size = ::LLVMDisasmInstruction(m_disasm_context, insn_p, max_op_byte_size, 0, out_string, sizeof(out_string)); length = inst_size; return true; } bool x86AssemblyInspectionEngine::machine_regno_to_lldb_regno( int machine_regno, uint32_t &lldb_regno) { MachineRegnumToNameAndLLDBRegnum::iterator it = m_reg_map.find(machine_regno); if (it != m_reg_map.end()) { lldb_regno = it->second.lldb_regnum; return true; } return false; return false; } bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( uint8_t *data, size_t size, AddressRange &func_range, UnwindPlan &unwind_plan) { unwind_plan.Clear(); if (data == nullptr || size == 0) return false; if (m_register_map_initialized == false) return false; addr_t current_func_text_offset = 0; int current_sp_bytes_offset_from_cfa = 0; UnwindPlan::Row::RegisterLocation initial_regloc; UnwindPlan::RowSP row(new UnwindPlan::Row); unwind_plan.SetPlanValidAddressRange(func_range); unwind_plan.SetRegisterKind(eRegisterKindLLDB); // At the start of the function, find the CFA by adding wordsize to the SP // register row->SetOffset(current_func_text_offset); row->GetCFAValue().SetIsRegisterPlusOffset(m_lldb_sp_regnum, m_wordsize); // caller's stack pointer value before the call insn is the CFA address initial_regloc.SetIsCFAPlusOffset(0); row->SetRegisterInfo(m_lldb_sp_regnum, initial_regloc); // saved instruction pointer can be found at CFA - wordsize. current_sp_bytes_offset_from_cfa = m_wordsize; initial_regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_cfa); row->SetRegisterInfo(m_lldb_ip_regnum, initial_regloc); unwind_plan.AppendRow(row); // Allocate a new Row, populate it with the existing Row contents. UnwindPlan::Row *newrow = new UnwindPlan::Row; *newrow = *row.get(); row.reset(newrow); // Track which registers have been saved so far in the prologue. // If we see another push of that register, it's not part of the prologue. // The register numbers used here are the machine register #'s // (i386_register_numbers, x86_64_register_numbers). std::vector saved_registers(32, false); // Once the prologue has completed we'll save a copy of the unwind // instructions // If there is an epilogue in the middle of the function, after that epilogue // we'll reinstate // the unwind setup -- we assume that some code path jumps over the // mid-function epilogue UnwindPlan::RowSP prologue_completed_row; // copy of prologue row of CFI int prologue_completed_sp_bytes_offset_from_cfa; // The sp value before the // epilogue started executed std::vector prologue_completed_saved_registers; while (current_func_text_offset < size) { int stack_offset, insn_len; int machine_regno; // register numbers masked directly out of instructions uint32_t lldb_regno; // register numbers in lldb's eRegisterKindLLDB // numbering scheme bool in_epilogue = false; // we're in the middle of an epilogue sequence bool row_updated = false; // The UnwindPlan::Row 'row' has been updated m_cur_insn = data + current_func_text_offset; - if (!instruction_length(m_cur_insn, insn_len) || insn_len == 0 || - insn_len > kMaxInstructionByteSize) { + if (!instruction_length(m_cur_insn, insn_len, size - current_func_text_offset) + || insn_len == 0 + || insn_len > kMaxInstructionByteSize) { // An unrecognized/junk instruction break; } if (push_rbp_pattern_p()) { current_sp_bytes_offset_from_cfa += m_wordsize; row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa); UnwindPlan::Row::RegisterLocation regloc; regloc.SetAtCFAPlusOffset(-row->GetCFAValue().GetOffset()); row->SetRegisterInfo(m_lldb_fp_regnum, regloc); saved_registers[m_machine_fp_regnum] = true; row_updated = true; } else if (mov_rsp_rbp_pattern_p()) { row->GetCFAValue().SetIsRegisterPlusOffset( m_lldb_fp_regnum, row->GetCFAValue().GetOffset()); row_updated = true; } // This is the start() function (or a pthread equivalent), it starts with a // pushl $0x0 which puts the // saved pc value of 0 on the stack. In this case we want to pretend we // didn't see a stack movement at all -- // normally the saved pc value is already on the stack by the time the // function starts executing. else if (push_0_pattern_p()) { } else if (push_reg_p(machine_regno)) { current_sp_bytes_offset_from_cfa += m_wordsize; // the PUSH instruction has moved the stack pointer - if the CFA is set in // terms of the stack pointer, // we need to add a new row of instructions. if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) { row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa); row_updated = true; } // record where non-volatile (callee-saved, spilled) registers are saved // on the stack if (nonvolatile_reg_p(machine_regno) && machine_regno_to_lldb_regno(machine_regno, lldb_regno) && saved_registers[machine_regno] == false) { UnwindPlan::Row::RegisterLocation regloc; regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_cfa); row->SetRegisterInfo(lldb_regno, regloc); saved_registers[machine_regno] = true; row_updated = true; } } else if (pop_reg_p(machine_regno)) { current_sp_bytes_offset_from_cfa -= m_wordsize; if (nonvolatile_reg_p(machine_regno) && machine_regno_to_lldb_regno(machine_regno, lldb_regno) && saved_registers[machine_regno] == true) { saved_registers[machine_regno] = false; row->RemoveRegisterInfo(lldb_regno); if (machine_regno == (int)m_machine_fp_regnum) { row->GetCFAValue().SetIsRegisterPlusOffset( m_lldb_sp_regnum, row->GetCFAValue().GetOffset()); } in_epilogue = true; row_updated = true; } // the POP instruction has moved the stack pointer - if the CFA is set in // terms of the stack pointer, // we need to add a new row of instructions. if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) { row->GetCFAValue().SetIsRegisterPlusOffset( m_lldb_sp_regnum, current_sp_bytes_offset_from_cfa); row_updated = true; } } else if (pop_misc_reg_p()) { current_sp_bytes_offset_from_cfa -= m_wordsize; if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) { row->GetCFAValue().SetIsRegisterPlusOffset( m_lldb_sp_regnum, current_sp_bytes_offset_from_cfa); row_updated = true; } } // The LEAVE instruction moves the value from rbp into rsp and pops // a value off the stack into rbp (restoring the caller's rbp value). // It is the opposite of ENTER, or 'push rbp, mov rsp rbp'. else if (leave_pattern_p()) { // We're going to copy the value in rbp into rsp, so re-set the sp offset // based on the CFAValue. Also, adjust it to recognize that we're popping // the saved rbp value off the stack. current_sp_bytes_offset_from_cfa = row->GetCFAValue().GetOffset(); current_sp_bytes_offset_from_cfa -= m_wordsize; row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa); // rbp is restored to the caller's value saved_registers[m_machine_fp_regnum] = false; row->RemoveRegisterInfo(m_lldb_fp_regnum); // cfa is now in terms of rsp again. row->GetCFAValue().SetIsRegisterPlusOffset( m_lldb_sp_regnum, row->GetCFAValue().GetOffset()); row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa); in_epilogue = true; row_updated = true; } else if (mov_reg_to_local_stack_frame_p(machine_regno, stack_offset) && nonvolatile_reg_p(machine_regno) && machine_regno_to_lldb_regno(machine_regno, lldb_regno) && saved_registers[machine_regno] == false) { saved_registers[machine_regno] = true; UnwindPlan::Row::RegisterLocation regloc; // stack_offset for 'movq %r15, -80(%rbp)' will be 80. // In the Row, we want to express this as the offset from the CFA. If the // frame base // is rbp (like the above instruction), the CFA offset for rbp is probably // 16. So we // want to say that the value is stored at the CFA address - 96. regloc.SetAtCFAPlusOffset( -(stack_offset + row->GetCFAValue().GetOffset())); row->SetRegisterInfo(lldb_regno, regloc); row_updated = true; } else if (sub_rsp_pattern_p(stack_offset)) { current_sp_bytes_offset_from_cfa += stack_offset; if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) { row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa); row_updated = true; } } else if (add_rsp_pattern_p(stack_offset)) { current_sp_bytes_offset_from_cfa -= stack_offset; if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) { row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa); row_updated = true; } in_epilogue = true; } else if (push_extended_pattern_p() || push_imm_pattern_p() || push_misc_reg_p()) { current_sp_bytes_offset_from_cfa += m_wordsize; if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) { row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa); row_updated = true; } } else if (lea_rsp_pattern_p(stack_offset)) { current_sp_bytes_offset_from_cfa -= stack_offset; if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) { row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa); row_updated = true; } if (stack_offset > 0) in_epilogue = true; } else if (lea_rbp_rsp_pattern_p(stack_offset) && row->GetCFAValue().GetRegisterNumber() == m_lldb_fp_regnum) { current_sp_bytes_offset_from_cfa = row->GetCFAValue().GetOffset() - stack_offset; } else if (ret_pattern_p() && prologue_completed_row.get()) { // Reinstate the saved prologue setup for any instructions // that come after the ret instruction UnwindPlan::Row *newrow = new UnwindPlan::Row; *newrow = *prologue_completed_row.get(); row.reset(newrow); current_sp_bytes_offset_from_cfa = prologue_completed_sp_bytes_offset_from_cfa; saved_registers.clear(); saved_registers.resize(prologue_completed_saved_registers.size(), false); for (size_t i = 0; i < prologue_completed_saved_registers.size(); ++i) { saved_registers[i] = prologue_completed_saved_registers[i]; } in_epilogue = true; row_updated = true; } // call next instruction // call 0 // => pop %ebx // This is used in i386 programs to get the PIC base address for finding // global data else if (call_next_insn_pattern_p()) { current_sp_bytes_offset_from_cfa += m_wordsize; if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) { row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa); row_updated = true; } } if (row_updated) { if (current_func_text_offset + insn_len < size) { row->SetOffset(current_func_text_offset + insn_len); unwind_plan.AppendRow(row); // Allocate a new Row, populate it with the existing Row contents. newrow = new UnwindPlan::Row; *newrow = *row.get(); row.reset(newrow); } } if (in_epilogue == false && row_updated) { // If we're not in an epilogue sequence, save the updated Row UnwindPlan::Row *newrow = new UnwindPlan::Row; *newrow = *row.get(); prologue_completed_row.reset(newrow); prologue_completed_saved_registers.clear(); prologue_completed_saved_registers.resize(saved_registers.size(), false); for (size_t i = 0; i < saved_registers.size(); ++i) { prologue_completed_saved_registers[i] = saved_registers[i]; } } // We may change the sp value without adding a new Row necessarily -- keep // track of it either way. if (in_epilogue == false) { prologue_completed_sp_bytes_offset_from_cfa = current_sp_bytes_offset_from_cfa; } m_cur_insn = m_cur_insn + insn_len; current_func_text_offset += insn_len; } unwind_plan.SetSourceName("assembly insn profiling"); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); return true; } bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite( uint8_t *data, size_t size, AddressRange &func_range, UnwindPlan &unwind_plan, RegisterContextSP ®_ctx) { Address addr_start = func_range.GetBaseAddress(); if (!addr_start.IsValid()) return false; // We either need a live RegisterContext, or we need the UnwindPlan to already // be in the lldb register numbering scheme. if (reg_ctx.get() == nullptr && unwind_plan.GetRegisterKind() != eRegisterKindLLDB) return false; // Is original unwind_plan valid? // unwind_plan should have at least one row which is ABI-default (CFA register // is sp), // and another row in mid-function. if (unwind_plan.GetRowCount() < 2) return false; UnwindPlan::RowSP first_row = unwind_plan.GetRowAtIndex(0); if (first_row->GetOffset() != 0) return false; uint32_t cfa_reg = first_row->GetCFAValue().GetRegisterNumber(); if (unwind_plan.GetRegisterKind() != eRegisterKindLLDB) { cfa_reg = reg_ctx->ConvertRegisterKindToRegisterNumber( unwind_plan.GetRegisterKind(), first_row->GetCFAValue().GetRegisterNumber()); } if (cfa_reg != m_lldb_sp_regnum || first_row->GetCFAValue().GetOffset() != m_wordsize) return false; UnwindPlan::RowSP original_last_row = unwind_plan.GetRowForFunctionOffset(-1); size_t offset = 0; int row_id = 1; bool unwind_plan_updated = false; UnwindPlan::RowSP row(new UnwindPlan::Row(*first_row)); m_cur_insn = data + offset; // After a mid-function epilogue we will need to re-insert the original unwind // rules // so unwinds work for the remainder of the function. These aren't common // with clang/gcc // on x86 but it is possible. bool reinstate_unwind_state = false; while (offset < size) { m_cur_insn = data + offset; int insn_len; - if (!instruction_length(m_cur_insn, insn_len) || insn_len == 0 || - insn_len > kMaxInstructionByteSize) { + if (!instruction_length(m_cur_insn, insn_len, size - offset) + || insn_len == 0 + || insn_len > kMaxInstructionByteSize) { // An unrecognized/junk instruction. break; } // Advance offsets. offset += insn_len; m_cur_insn = data + offset; // offset is pointing beyond the bounds of the // function; stop looping. if (offset >= size) continue; if (reinstate_unwind_state) { UnwindPlan::RowSP new_row(new UnwindPlan::Row()); *new_row = *original_last_row; new_row->SetOffset(offset); unwind_plan.AppendRow(new_row); row.reset(new UnwindPlan::Row()); *row = *new_row; reinstate_unwind_state = false; unwind_plan_updated = true; continue; } // If we already have one row for this instruction, we can continue. while (row_id < unwind_plan.GetRowCount() && unwind_plan.GetRowAtIndex(row_id)->GetOffset() <= offset) { row_id++; } UnwindPlan::RowSP original_row = unwind_plan.GetRowAtIndex(row_id - 1); if (original_row->GetOffset() == offset) { *row = *original_row; continue; } if (row_id == 0) { // If we are here, compiler didn't generate CFI for prologue. // This won't happen to GCC or clang. // In this case, bail out directly. return false; } // Inspect the instruction to check if we need a new row for it. cfa_reg = row->GetCFAValue().GetRegisterNumber(); if (unwind_plan.GetRegisterKind() != eRegisterKindLLDB) { cfa_reg = reg_ctx->ConvertRegisterKindToRegisterNumber( unwind_plan.GetRegisterKind(), row->GetCFAValue().GetRegisterNumber()); } if (cfa_reg == m_lldb_sp_regnum) { // CFA register is sp. // call next instruction // call 0 // => pop %ebx if (call_next_insn_pattern_p()) { row->SetOffset(offset); row->GetCFAValue().IncOffset(m_wordsize); UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); unwind_plan.InsertRow(new_row); unwind_plan_updated = true; continue; } // push/pop register int regno; if (push_reg_p(regno)) { row->SetOffset(offset); row->GetCFAValue().IncOffset(m_wordsize); UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); unwind_plan.InsertRow(new_row); unwind_plan_updated = true; continue; } if (pop_reg_p(regno)) { // Technically, this might be a nonvolatile register recover in // epilogue. // We should reset RegisterInfo for the register. // But in practice, previous rule for the register is still valid... // So we ignore this case. row->SetOffset(offset); row->GetCFAValue().IncOffset(-m_wordsize); UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); unwind_plan.InsertRow(new_row); unwind_plan_updated = true; continue; } if (pop_misc_reg_p()) { row->SetOffset(offset); row->GetCFAValue().IncOffset(-m_wordsize); UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); unwind_plan.InsertRow(new_row); unwind_plan_updated = true; continue; } // push imm if (push_imm_pattern_p()) { row->SetOffset(offset); row->GetCFAValue().IncOffset(m_wordsize); UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); unwind_plan.InsertRow(new_row); unwind_plan_updated = true; continue; } // push extended if (push_extended_pattern_p() || push_misc_reg_p()) { row->SetOffset(offset); row->GetCFAValue().IncOffset(m_wordsize); UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); unwind_plan.InsertRow(new_row); unwind_plan_updated = true; continue; } // add/sub %rsp/%esp int amount; if (add_rsp_pattern_p(amount)) { row->SetOffset(offset); row->GetCFAValue().IncOffset(-amount); UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); unwind_plan.InsertRow(new_row); unwind_plan_updated = true; continue; } if (sub_rsp_pattern_p(amount)) { row->SetOffset(offset); row->GetCFAValue().IncOffset(amount); UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); unwind_plan.InsertRow(new_row); unwind_plan_updated = true; continue; } // lea %rsp, [%rsp + $offset] if (lea_rsp_pattern_p(amount)) { row->SetOffset(offset); row->GetCFAValue().IncOffset(-amount); UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); unwind_plan.InsertRow(new_row); unwind_plan_updated = true; continue; } if (ret_pattern_p()) { reinstate_unwind_state = true; continue; } } else if (cfa_reg == m_lldb_fp_regnum) { // CFA register is fp. // The only case we care about is epilogue: // [0x5d] pop %rbp/%ebp // => [0xc3] ret if (pop_rbp_pattern_p() || leave_pattern_p()) { offset += 1; row->SetOffset(offset); row->GetCFAValue().SetIsRegisterPlusOffset( first_row->GetCFAValue().GetRegisterNumber(), m_wordsize); UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row)); unwind_plan.InsertRow(new_row); unwind_plan_updated = true; reinstate_unwind_state = true; continue; } } else { // CFA register is not sp or fp. // This must be hand-written assembly. // Just trust eh_frame and assume we have finished. break; } } unwind_plan.SetPlanValidAddressRange(func_range); if (unwind_plan_updated) { std::string unwind_plan_source(unwind_plan.GetSourceName().AsCString()); unwind_plan_source += " plus augmentation from assembly parsing"; unwind_plan.SetSourceName(unwind_plan_source.c_str()); unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); } return true; } bool x86AssemblyInspectionEngine::FindFirstNonPrologueInstruction( uint8_t *data, size_t size, size_t &offset) { offset = 0; if (m_register_map_initialized == false) return false; while (offset < size) { int regno; int insn_len; int scratch; m_cur_insn = data + offset; - if (!instruction_length(m_cur_insn, insn_len) || - insn_len > kMaxInstructionByteSize || insn_len == 0) { + if (!instruction_length(m_cur_insn, insn_len, size - offset) + || insn_len > kMaxInstructionByteSize + || insn_len == 0) { // An error parsing the instruction, i.e. probably data/garbage - stop // scanning break; } if (push_rbp_pattern_p() || mov_rsp_rbp_pattern_p() || sub_rsp_pattern_p(scratch) || push_reg_p(regno) || mov_reg_to_local_stack_frame_p(regno, scratch) || (lea_rsp_pattern_p(scratch) && offset == 0)) { offset += insn_len; continue; } // // Unknown non-prologue instruction - stop scanning break; } return true; } Index: vendor/lldb/dist/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h =================================================================== --- vendor/lldb/dist/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h (revision 320966) +++ vendor/lldb/dist/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h (revision 320967) @@ -1,182 +1,182 @@ //===-- x86AssemblyInspectionEngine.h ---------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef liblldb_x86AssemblyInspectionEngine_h_ #define liblldb_x86AssemblyInspectionEngine_h_ #include "llvm-c/Disassembler.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-forward.h" #include "lldb/lldb-private.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Utility/ConstString.h" #include #include namespace lldb_private { // x86AssemblyInspectionEngine - a class which will take a buffer of bytes // of i386/x86_64 instructions and create an UnwindPlan based on those // assembly instructions. class x86AssemblyInspectionEngine { public: /// default ctor x86AssemblyInspectionEngine(const lldb_private::ArchSpec &arch); /// default dtor ~x86AssemblyInspectionEngine(); /// One of the two initialize methods that can be called on this object; /// they must be called before any of the assembly inspection methods /// are called. This one should be used if the caller has access to a /// valid RegisterContext. void Initialize(lldb::RegisterContextSP ®_ctx); /// One of the two initialize methods that can be called on this object; /// they must be called before any of the assembly inspection methods /// are called. This one takes a vector of register name and lldb /// register numbers. struct lldb_reg_info { const char *name; uint32_t lldb_regnum; lldb_reg_info() : name(nullptr), lldb_regnum(LLDB_INVALID_REGNUM) {} }; void Initialize(std::vector ®_info); /// Create an UnwindPlan for a "non-call site" stack frame situation. /// This is usually when this function/method is currently executing, and may /// be at /// a location where exception-handling style unwind information (eh_frame, /// compact unwind info, arm unwind info) /// are not valid. /// \p data is a pointer to the instructions for the function /// \p size is the size of the instruction buffer above /// \p func_range is the start Address and size of the function, to be /// included in the UnwindPlan /// \p unwind_plan is the unwind plan that this method creates /// \returns true if it was able to create an UnwindPlan; false if not. bool GetNonCallSiteUnwindPlanFromAssembly(uint8_t *data, size_t size, lldb_private::AddressRange &func_range, lldb_private::UnwindPlan &unwind_plan); /// Take an existing UnwindPlan, probably from eh_frame which may be missing /// description /// of the epilogue instructions, and add the epilogue description to it based /// on the /// instructions in the function. /// /// The \p unwind_plan 's register numbers must be converted into the lldb /// register numbering /// scheme OR a RegisterContext must be provided in \p reg_ctx. If the \p /// unwind_plan /// register numbers are already in lldb register numbering, \p reg_ctx may be /// null. /// \returns true if the \p unwind_plan was updated, false if it was not. bool AugmentUnwindPlanFromCallSite(uint8_t *data, size_t size, lldb_private::AddressRange &func_range, lldb_private::UnwindPlan &unwind_plan, lldb::RegisterContextSP ®_ctx); bool FindFirstNonPrologueInstruction(uint8_t *data, size_t size, size_t &offset); private: bool nonvolatile_reg_p(int machine_regno); bool push_rbp_pattern_p(); bool push_0_pattern_p(); bool push_imm_pattern_p(); bool push_extended_pattern_p(); bool push_misc_reg_p(); bool mov_rsp_rbp_pattern_p(); bool sub_rsp_pattern_p(int &amount); bool add_rsp_pattern_p(int &amount); bool lea_rsp_pattern_p(int &amount); bool lea_rbp_rsp_pattern_p(int &amount); bool push_reg_p(int ®no); bool pop_reg_p(int ®no); bool pop_rbp_pattern_p(); bool pop_misc_reg_p(); bool leave_pattern_p(); bool call_next_insn_pattern_p(); bool mov_reg_to_local_stack_frame_p(int ®no, int &rbp_offset); bool ret_pattern_p(); uint32_t extract_4(uint8_t *b); - bool instruction_length(uint8_t *insn, int &length); + bool instruction_length(uint8_t *insn, int &length, uint32_t buffer_remaining_bytes); bool machine_regno_to_lldb_regno(int machine_regno, uint32_t &lldb_regno); enum CPU { k_i386, k_x86_64, k_cpu_unspecified }; enum i386_register_numbers { k_machine_eax = 0, k_machine_ecx = 1, k_machine_edx = 2, k_machine_ebx = 3, k_machine_esp = 4, k_machine_ebp = 5, k_machine_esi = 6, k_machine_edi = 7, k_machine_eip = 8 }; enum x86_64_register_numbers { k_machine_rax = 0, k_machine_rcx = 1, k_machine_rdx = 2, k_machine_rbx = 3, k_machine_rsp = 4, k_machine_rbp = 5, k_machine_rsi = 6, k_machine_rdi = 7, k_machine_r8 = 8, k_machine_r9 = 9, k_machine_r10 = 10, k_machine_r11 = 11, k_machine_r12 = 12, k_machine_r13 = 13, k_machine_r14 = 14, k_machine_r15 = 15, k_machine_rip = 16 }; enum { kMaxInstructionByteSize = 32 }; uint8_t *m_cur_insn; uint32_t m_machine_ip_regnum; uint32_t m_machine_sp_regnum; uint32_t m_machine_fp_regnum; uint32_t m_lldb_ip_regnum; uint32_t m_lldb_sp_regnum; uint32_t m_lldb_fp_regnum; typedef std::map MachineRegnumToNameAndLLDBRegnum; MachineRegnumToNameAndLLDBRegnum m_reg_map; lldb_private::ArchSpec m_arch; CPU m_cpu; int m_wordsize; bool m_register_map_initialized; ::LLVMDisasmContextRef m_disasm_context; DISALLOW_COPY_AND_ASSIGN(x86AssemblyInspectionEngine); }; } // namespace lldb_private #endif // liblldb_x86AssemblyInspectionEngine_h_ Index: vendor/lldb/dist/source/Utility/StringExtractorGDBRemote.cpp =================================================================== --- vendor/lldb/dist/source/Utility/StringExtractorGDBRemote.cpp (revision 320966) +++ vendor/lldb/dist/source/Utility/StringExtractorGDBRemote.cpp (revision 320967) @@ -1,578 +1,607 @@ //===-- StringExtractorGDBRemote.cpp ----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "Utility/StringExtractorGDBRemote.h" #include // for isxdigit #include StringExtractorGDBRemote::ResponseType StringExtractorGDBRemote::GetResponseType() const { if (m_packet.empty()) return eUnsupported; switch (m_packet[0]) { case 'E': - if (m_packet.size() == 3 && isxdigit(m_packet[1]) && isxdigit(m_packet[2])) - return eError; + if (isxdigit(m_packet[1]) && isxdigit(m_packet[2])) { + if (m_packet.size() == 3) + return eError; + llvm::StringRef packet_ref(m_packet); + if (packet_ref[3] == ';') { + auto err_string = packet_ref.substr(4); + for (auto e : err_string) + if (!isxdigit(e)) + return eResponse; + return eError; + } + } break; case 'O': if (m_packet.size() == 2 && m_packet[1] == 'K') return eOK; break; case '+': if (m_packet.size() == 1) return eAck; break; case '-': if (m_packet.size() == 1) return eNack; break; } return eResponse; } StringExtractorGDBRemote::ServerPacketType StringExtractorGDBRemote::GetServerPacketType() const { #define PACKET_MATCHES(s) \ ((packet_size == (sizeof(s) - 1)) && (strcmp((packet_cstr), (s)) == 0)) #define PACKET_STARTS_WITH(s) \ ((packet_size >= (sizeof(s) - 1)) && \ ::strncmp(packet_cstr, s, (sizeof(s) - 1)) == 0) // Empty is not a supported packet... if (m_packet.empty()) return eServerPacketType_invalid; const size_t packet_size = m_packet.size(); const char *packet_cstr = m_packet.c_str(); switch (m_packet[0]) { case '%': return eServerPacketType_notify; case '\x03': if (packet_size == 1) return eServerPacketType_interrupt; break; case '-': if (packet_size == 1) return eServerPacketType_nack; break; case '+': if (packet_size == 1) return eServerPacketType_ack; break; case 'A': return eServerPacketType_A; case 'Q': switch (packet_cstr[1]) { case 'E': if (PACKET_STARTS_WITH("QEnvironment:")) return eServerPacketType_QEnvironment; if (PACKET_STARTS_WITH("QEnvironmentHexEncoded:")) return eServerPacketType_QEnvironmentHexEncoded; + if (PACKET_STARTS_WITH("QEnableErrorStrings")) + return eServerPacketType_QEnableErrorStrings; break; case 'P': if (PACKET_STARTS_WITH("QPassSignals:")) return eServerPacketType_QPassSignals; case 'S': if (PACKET_MATCHES("QStartNoAckMode")) return eServerPacketType_QStartNoAckMode; if (PACKET_STARTS_WITH("QSaveRegisterState")) return eServerPacketType_QSaveRegisterState; if (PACKET_STARTS_WITH("QSetDisableASLR:")) return eServerPacketType_QSetDisableASLR; if (PACKET_STARTS_WITH("QSetDetachOnError:")) return eServerPacketType_QSetDetachOnError; if (PACKET_STARTS_WITH("QSetSTDIN:")) return eServerPacketType_QSetSTDIN; if (PACKET_STARTS_WITH("QSetSTDOUT:")) return eServerPacketType_QSetSTDOUT; if (PACKET_STARTS_WITH("QSetSTDERR:")) return eServerPacketType_QSetSTDERR; if (PACKET_STARTS_WITH("QSetWorkingDir:")) return eServerPacketType_QSetWorkingDir; if (PACKET_STARTS_WITH("QSetLogging:")) return eServerPacketType_QSetLogging; if (PACKET_STARTS_WITH("QSetMaxPacketSize:")) return eServerPacketType_QSetMaxPacketSize; if (PACKET_STARTS_WITH("QSetMaxPayloadSize:")) return eServerPacketType_QSetMaxPayloadSize; if (PACKET_STARTS_WITH("QSetEnableAsyncProfiling;")) return eServerPacketType_QSetEnableAsyncProfiling; if (PACKET_STARTS_WITH("QSyncThreadState:")) return eServerPacketType_QSyncThreadState; break; case 'L': if (PACKET_STARTS_WITH("QLaunchArch:")) return eServerPacketType_QLaunchArch; if (PACKET_MATCHES("QListThreadsInStopReply")) return eServerPacketType_QListThreadsInStopReply; break; case 'R': if (PACKET_STARTS_WITH("QRestoreRegisterState:")) return eServerPacketType_QRestoreRegisterState; break; case 'T': if (PACKET_MATCHES("QThreadSuffixSupported")) return eServerPacketType_QThreadSuffixSupported; break; } break; case 'q': switch (packet_cstr[1]) { case 's': if (PACKET_MATCHES("qsProcessInfo")) return eServerPacketType_qsProcessInfo; if (PACKET_MATCHES("qsThreadInfo")) return eServerPacketType_qsThreadInfo; break; case 'f': if (PACKET_STARTS_WITH("qfProcessInfo")) return eServerPacketType_qfProcessInfo; if (PACKET_STARTS_WITH("qfThreadInfo")) return eServerPacketType_qfThreadInfo; break; case 'C': if (packet_size == 2) return eServerPacketType_qC; break; case 'E': if (PACKET_STARTS_WITH("qEcho:")) return eServerPacketType_qEcho; break; case 'F': if (PACKET_STARTS_WITH("qFileLoadAddress:")) return eServerPacketType_qFileLoadAddress; break; case 'G': if (PACKET_STARTS_WITH("qGroupName:")) return eServerPacketType_qGroupName; if (PACKET_MATCHES("qGetWorkingDir")) return eServerPacketType_qGetWorkingDir; if (PACKET_MATCHES("qGetPid")) return eServerPacketType_qGetPid; if (PACKET_STARTS_WITH("qGetProfileData;")) return eServerPacketType_qGetProfileData; if (PACKET_MATCHES("qGDBServerVersion")) return eServerPacketType_qGDBServerVersion; break; case 'H': if (PACKET_MATCHES("qHostInfo")) return eServerPacketType_qHostInfo; break; case 'K': if (PACKET_STARTS_WITH("qKillSpawnedProcess")) return eServerPacketType_qKillSpawnedProcess; break; case 'L': if (PACKET_STARTS_WITH("qLaunchGDBServer")) return eServerPacketType_qLaunchGDBServer; if (PACKET_MATCHES("qLaunchSuccess")) return eServerPacketType_qLaunchSuccess; break; case 'M': if (PACKET_STARTS_WITH("qMemoryRegionInfo:")) return eServerPacketType_qMemoryRegionInfo; if (PACKET_MATCHES("qMemoryRegionInfo")) return eServerPacketType_qMemoryRegionInfoSupported; if (PACKET_STARTS_WITH("qModuleInfo:")) return eServerPacketType_qModuleInfo; break; case 'P': if (PACKET_STARTS_WITH("qProcessInfoPID:")) return eServerPacketType_qProcessInfoPID; if (PACKET_STARTS_WITH("qPlatform_shell:")) return eServerPacketType_qPlatform_shell; if (PACKET_STARTS_WITH("qPlatform_mkdir:")) return eServerPacketType_qPlatform_mkdir; if (PACKET_STARTS_WITH("qPlatform_chmod:")) return eServerPacketType_qPlatform_chmod; if (PACKET_MATCHES("qProcessInfo")) return eServerPacketType_qProcessInfo; break; case 'Q': if (PACKET_MATCHES("qQueryGDBServer")) return eServerPacketType_qQueryGDBServer; break; case 'R': if (PACKET_STARTS_WITH("qRcmd,")) return eServerPacketType_qRcmd; if (PACKET_STARTS_WITH("qRegisterInfo")) return eServerPacketType_qRegisterInfo; break; case 'S': if (PACKET_STARTS_WITH("qSpeedTest:")) return eServerPacketType_qSpeedTest; if (PACKET_MATCHES("qShlibInfoAddr")) return eServerPacketType_qShlibInfoAddr; if (PACKET_MATCHES("qStepPacketSupported")) return eServerPacketType_qStepPacketSupported; if (PACKET_STARTS_WITH("qSupported")) return eServerPacketType_qSupported; if (PACKET_MATCHES("qSyncThreadStateSupported")) return eServerPacketType_qSyncThreadStateSupported; break; case 'T': if (PACKET_STARTS_WITH("qThreadExtraInfo,")) return eServerPacketType_qThreadExtraInfo; if (PACKET_STARTS_WITH("qThreadStopInfo")) return eServerPacketType_qThreadStopInfo; break; case 'U': if (PACKET_STARTS_WITH("qUserName:")) return eServerPacketType_qUserName; break; case 'V': if (PACKET_MATCHES("qVAttachOrWaitSupported")) return eServerPacketType_qVAttachOrWaitSupported; break; case 'W': if (PACKET_STARTS_WITH("qWatchpointSupportInfo:")) return eServerPacketType_qWatchpointSupportInfo; if (PACKET_MATCHES("qWatchpointSupportInfo")) return eServerPacketType_qWatchpointSupportInfoSupported; break; case 'X': if (PACKET_STARTS_WITH("qXfer:auxv:read::")) return eServerPacketType_qXfer_auxv_read; break; } break; case 'j': if (PACKET_STARTS_WITH("jModulesInfo:")) return eServerPacketType_jModulesInfo; if (PACKET_MATCHES("jSignalsInfo")) return eServerPacketType_jSignalsInfo; if (PACKET_MATCHES("jThreadsInfo")) return eServerPacketType_jThreadsInfo; if (PACKET_STARTS_WITH("jTraceBufferRead:")) return eServerPacketType_jTraceBufferRead; if (PACKET_STARTS_WITH("jTraceConfigRead:")) return eServerPacketType_jTraceConfigRead; if (PACKET_STARTS_WITH("jTraceMetaRead:")) return eServerPacketType_jTraceMetaRead; if (PACKET_STARTS_WITH("jTraceStart:")) return eServerPacketType_jTraceStart; if (PACKET_STARTS_WITH("jTraceStop:")) return eServerPacketType_jTraceStop; break; case 'v': if (PACKET_STARTS_WITH("vFile:")) { if (PACKET_STARTS_WITH("vFile:open:")) return eServerPacketType_vFile_open; else if (PACKET_STARTS_WITH("vFile:close:")) return eServerPacketType_vFile_close; else if (PACKET_STARTS_WITH("vFile:pread")) return eServerPacketType_vFile_pread; else if (PACKET_STARTS_WITH("vFile:pwrite")) return eServerPacketType_vFile_pwrite; else if (PACKET_STARTS_WITH("vFile:size")) return eServerPacketType_vFile_size; else if (PACKET_STARTS_WITH("vFile:exists")) return eServerPacketType_vFile_exists; else if (PACKET_STARTS_WITH("vFile:stat")) return eServerPacketType_vFile_stat; else if (PACKET_STARTS_WITH("vFile:mode")) return eServerPacketType_vFile_mode; else if (PACKET_STARTS_WITH("vFile:MD5")) return eServerPacketType_vFile_md5; else if (PACKET_STARTS_WITH("vFile:symlink")) return eServerPacketType_vFile_symlink; else if (PACKET_STARTS_WITH("vFile:unlink")) return eServerPacketType_vFile_unlink; } else { if (PACKET_STARTS_WITH("vAttach;")) return eServerPacketType_vAttach; if (PACKET_STARTS_WITH("vAttachWait;")) return eServerPacketType_vAttachWait; if (PACKET_STARTS_WITH("vAttachOrWait;")) return eServerPacketType_vAttachOrWait; if (PACKET_STARTS_WITH("vAttachName;")) return eServerPacketType_vAttachName; if (PACKET_STARTS_WITH("vCont;")) return eServerPacketType_vCont; if (PACKET_MATCHES("vCont?")) return eServerPacketType_vCont_actions; } break; case '_': switch (packet_cstr[1]) { case 'M': return eServerPacketType__M; case 'm': return eServerPacketType__m; } break; case '?': if (packet_size == 1) return eServerPacketType_stop_reason; break; case 'c': return eServerPacketType_c; case 'C': return eServerPacketType_C; case 'D': if (packet_size == 1) return eServerPacketType_D; break; case 'g': if (packet_size == 1) return eServerPacketType_g; break; case 'G': return eServerPacketType_G; case 'H': return eServerPacketType_H; case 'I': return eServerPacketType_I; case 'k': if (packet_size == 1) return eServerPacketType_k; break; case 'm': return eServerPacketType_m; case 'M': return eServerPacketType_M; case 'p': return eServerPacketType_p; case 'P': return eServerPacketType_P; case 's': if (packet_size == 1) return eServerPacketType_s; break; case 'S': return eServerPacketType_S; case 'x': return eServerPacketType_x; case 'X': return eServerPacketType_X; case 'T': return eServerPacketType_T; case 'z': if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4') return eServerPacketType_z; break; case 'Z': if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4') return eServerPacketType_Z; break; } return eServerPacketType_unimplemented; } bool StringExtractorGDBRemote::IsOKResponse() const { return GetResponseType() == eOK; } bool StringExtractorGDBRemote::IsUnsupportedResponse() const { return GetResponseType() == eUnsupported; } bool StringExtractorGDBRemote::IsNormalResponse() const { return GetResponseType() == eResponse; } bool StringExtractorGDBRemote::IsErrorResponse() const { - return GetResponseType() == eError && m_packet.size() == 3 && - isxdigit(m_packet[1]) && isxdigit(m_packet[2]); + return GetResponseType() == eError && isxdigit(m_packet[1]) && + isxdigit(m_packet[2]); } uint8_t StringExtractorGDBRemote::GetError() { if (GetResponseType() == eError) { SetFilePos(1); return GetHexU8(255); } return 0; +} + +lldb_private::Status StringExtractorGDBRemote::GetStatus() { + lldb_private::Status error; + if (GetResponseType() == eError) { + SetFilePos(1); + uint8_t errc = GetHexU8(255); + error.SetError(errc, lldb::eErrorTypeGeneric); + + error.SetErrorStringWithFormat("Error %u", errc); + std::string error_messg; + if (GetChar() == ';') { + GetHexByteString(error_messg); + error.SetErrorString(error_messg); + } + } + return error; } size_t StringExtractorGDBRemote::GetEscapedBinaryData(std::string &str) { // Just get the data bytes in the string as // GDBRemoteCommunication::CheckForPacket() // already removes any 0x7d escaped characters. If any 0x7d characters are // left in // the packet, then they are supposed to be there... str.clear(); const size_t bytes_left = GetBytesLeft(); if (bytes_left > 0) { str.assign(m_packet, m_index, bytes_left); m_index += bytes_left; } return str.size(); } static bool OKErrorNotSupportedResponseValidator(void *, const StringExtractorGDBRemote &response) { switch (response.GetResponseType()) { case StringExtractorGDBRemote::eOK: case StringExtractorGDBRemote::eError: case StringExtractorGDBRemote::eUnsupported: return true; case StringExtractorGDBRemote::eAck: case StringExtractorGDBRemote::eNack: case StringExtractorGDBRemote::eResponse: break; } return false; } static bool JSONResponseValidator(void *, const StringExtractorGDBRemote &response) { switch (response.GetResponseType()) { case StringExtractorGDBRemote::eUnsupported: case StringExtractorGDBRemote::eError: return true; // Accept unsupported or EXX as valid responses case StringExtractorGDBRemote::eOK: case StringExtractorGDBRemote::eAck: case StringExtractorGDBRemote::eNack: break; case StringExtractorGDBRemote::eResponse: // JSON that is returned in from JSON query packets is currently always // either a dictionary which starts with a '{', or an array which // starts with a '['. This is a quick validator to just make sure the // response could be valid JSON without having to validate all of the // JSON content. switch (response.GetStringRef()[0]) { case '{': return true; case '[': return true; default: break; } break; } return false; } static bool ASCIIHexBytesResponseValidator(void *, const StringExtractorGDBRemote &response) { switch (response.GetResponseType()) { case StringExtractorGDBRemote::eUnsupported: case StringExtractorGDBRemote::eError: return true; // Accept unsupported or EXX as valid responses case StringExtractorGDBRemote::eOK: case StringExtractorGDBRemote::eAck: case StringExtractorGDBRemote::eNack: break; case StringExtractorGDBRemote::eResponse: { uint32_t valid_count = 0; for (const char ch : response.GetStringRef()) { if (!isxdigit(ch)) { return false; } if (++valid_count >= 16) break; // Don't validate all the characters in case the packet is very // large } return true; } break; } return false; } void StringExtractorGDBRemote::CopyResponseValidator( const StringExtractorGDBRemote &rhs) { m_validator = rhs.m_validator; m_validator_baton = rhs.m_validator_baton; } void StringExtractorGDBRemote::SetResponseValidator( ResponseValidatorCallback callback, void *baton) { m_validator = callback; m_validator_baton = baton; } void StringExtractorGDBRemote::SetResponseValidatorToOKErrorNotSupported() { m_validator = OKErrorNotSupportedResponseValidator; m_validator_baton = nullptr; } void StringExtractorGDBRemote::SetResponseValidatorToASCIIHexBytes() { m_validator = ASCIIHexBytesResponseValidator; m_validator_baton = nullptr; } void StringExtractorGDBRemote::SetResponseValidatorToJSON() { m_validator = JSONResponseValidator; m_validator_baton = nullptr; } bool StringExtractorGDBRemote::ValidateResponse() const { // If we have a validator callback, try to validate the callback if (m_validator) return m_validator(m_validator_baton, *this); else return true; // No validator, so response is valid } Index: vendor/lldb/dist/source/Utility/StringExtractorGDBRemote.h =================================================================== --- vendor/lldb/dist/source/Utility/StringExtractorGDBRemote.h (revision 320966) +++ vendor/lldb/dist/source/Utility/StringExtractorGDBRemote.h (revision 320967) @@ -1,200 +1,204 @@ //===-- StringExtractorGDBRemote.h ------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef utility_StringExtractorGDBRemote_h_ #define utility_StringExtractorGDBRemote_h_ +#include "lldb/Utility/Status.h" #include "lldb/Utility/StringExtractor.h" #include "llvm/ADT/StringRef.h" // for StringRef #include #include // for size_t #include // for uint8_t class StringExtractorGDBRemote : public StringExtractor { public: typedef bool (*ResponseValidatorCallback)( void *baton, const StringExtractorGDBRemote &response); StringExtractorGDBRemote() : StringExtractor(), m_validator(nullptr) {} StringExtractorGDBRemote(llvm::StringRef str) : StringExtractor(str), m_validator(nullptr) {} StringExtractorGDBRemote(const char *cstr) : StringExtractor(cstr), m_validator(nullptr) {} StringExtractorGDBRemote(const StringExtractorGDBRemote &rhs) : StringExtractor(rhs), m_validator(rhs.m_validator) {} virtual ~StringExtractorGDBRemote() {} bool ValidateResponse() const; void CopyResponseValidator(const StringExtractorGDBRemote &rhs); void SetResponseValidator(ResponseValidatorCallback callback, void *baton); void SetResponseValidatorToOKErrorNotSupported(); void SetResponseValidatorToASCIIHexBytes(); void SetResponseValidatorToJSON(); enum ServerPacketType { eServerPacketType_nack = 0, eServerPacketType_ack, eServerPacketType_invalid, eServerPacketType_unimplemented, eServerPacketType_interrupt, // CTRL+c packet or "\x03" eServerPacketType_A, // Program arguments packet eServerPacketType_qfProcessInfo, eServerPacketType_qsProcessInfo, eServerPacketType_qC, eServerPacketType_qEcho, eServerPacketType_qGroupName, eServerPacketType_qHostInfo, eServerPacketType_qLaunchGDBServer, eServerPacketType_qQueryGDBServer, eServerPacketType_qKillSpawnedProcess, eServerPacketType_qLaunchSuccess, eServerPacketType_qModuleInfo, eServerPacketType_qProcessInfoPID, eServerPacketType_qSpeedTest, eServerPacketType_qUserName, eServerPacketType_qGetWorkingDir, eServerPacketType_qFileLoadAddress, eServerPacketType_QEnvironment, + eServerPacketType_QEnableErrorStrings, eServerPacketType_QLaunchArch, eServerPacketType_QSetDisableASLR, eServerPacketType_QSetDetachOnError, eServerPacketType_QSetSTDIN, eServerPacketType_QSetSTDOUT, eServerPacketType_QSetSTDERR, eServerPacketType_QSetWorkingDir, eServerPacketType_QStartNoAckMode, eServerPacketType_qPlatform_shell, eServerPacketType_qPlatform_mkdir, eServerPacketType_qPlatform_chmod, eServerPacketType_vFile_open, eServerPacketType_vFile_close, eServerPacketType_vFile_pread, eServerPacketType_vFile_pwrite, eServerPacketType_vFile_size, eServerPacketType_vFile_mode, eServerPacketType_vFile_exists, eServerPacketType_vFile_md5, eServerPacketType_vFile_stat, eServerPacketType_vFile_symlink, eServerPacketType_vFile_unlink, // debug server packages eServerPacketType_QEnvironmentHexEncoded, eServerPacketType_QListThreadsInStopReply, eServerPacketType_QPassSignals, eServerPacketType_QRestoreRegisterState, eServerPacketType_QSaveRegisterState, eServerPacketType_QSetLogging, eServerPacketType_QSetMaxPacketSize, eServerPacketType_QSetMaxPayloadSize, eServerPacketType_QSetEnableAsyncProfiling, eServerPacketType_QSyncThreadState, eServerPacketType_QThreadSuffixSupported, eServerPacketType_jThreadsInfo, eServerPacketType_qsThreadInfo, eServerPacketType_qfThreadInfo, eServerPacketType_qGetPid, eServerPacketType_qGetProfileData, eServerPacketType_qGDBServerVersion, eServerPacketType_qMemoryRegionInfo, eServerPacketType_qMemoryRegionInfoSupported, eServerPacketType_qProcessInfo, eServerPacketType_qRcmd, eServerPacketType_qRegisterInfo, eServerPacketType_qShlibInfoAddr, eServerPacketType_qStepPacketSupported, eServerPacketType_qSupported, eServerPacketType_qSyncThreadStateSupported, eServerPacketType_qThreadExtraInfo, eServerPacketType_qThreadStopInfo, eServerPacketType_qVAttachOrWaitSupported, eServerPacketType_qWatchpointSupportInfo, eServerPacketType_qWatchpointSupportInfoSupported, eServerPacketType_qXfer_auxv_read, eServerPacketType_jSignalsInfo, eServerPacketType_jModulesInfo, eServerPacketType_vAttach, eServerPacketType_vAttachWait, eServerPacketType_vAttachOrWait, eServerPacketType_vAttachName, eServerPacketType_vCont, eServerPacketType_vCont_actions, // vCont? eServerPacketType_stop_reason, // '?' eServerPacketType_c, eServerPacketType_C, eServerPacketType_D, eServerPacketType_g, eServerPacketType_G, eServerPacketType_H, eServerPacketType_I, // stdin notification eServerPacketType_k, eServerPacketType_m, eServerPacketType_M, eServerPacketType_p, eServerPacketType_P, eServerPacketType_s, eServerPacketType_S, eServerPacketType_T, eServerPacketType_x, eServerPacketType_X, eServerPacketType_Z, eServerPacketType_z, eServerPacketType__M, eServerPacketType__m, eServerPacketType_notify, // '%' notification eServerPacketType_jTraceStart, eServerPacketType_jTraceBufferRead, eServerPacketType_jTraceMetaRead, eServerPacketType_jTraceStop, eServerPacketType_jTraceConfigRead, }; ServerPacketType GetServerPacketType() const; enum ResponseType { eUnsupported = 0, eAck, eNack, eError, eOK, eResponse }; ResponseType GetResponseType() const; bool IsOKResponse() const; bool IsUnsupportedResponse() const; bool IsNormalResponse() const; bool IsErrorResponse() const; // Returns zero if the packet isn't a EXX packet where XX are two hex // digits. Otherwise the error encoded in XX is returned. uint8_t GetError(); + + lldb_private::Status GetStatus(); size_t GetEscapedBinaryData(std::string &str); protected: ResponseValidatorCallback m_validator; void *m_validator_baton; }; #endif // utility_StringExtractorGDBRemote_h_ Index: vendor/lldb/dist/tools/lldb-server/CMakeLists.txt =================================================================== --- vendor/lldb/dist/tools/lldb-server/CMakeLists.txt (revision 320966) +++ vendor/lldb/dist/tools/lldb-server/CMakeLists.txt (revision 320967) @@ -1,82 +1,92 @@ if ( CMAKE_SYSTEM_NAME MATCHES "Linux" ) include_directories( ../../../../llvm/include ../../source/Plugins/Process/Linux ../../source/Plugins/Process/POSIX ) endif () if ( CMAKE_SYSTEM_NAME MATCHES "FreeBSD" ) include_directories( ../../../../llvm/include ../../source/Plugins/Process/FreeBSD ../../source/Plugins/Process/POSIX ) endif () if ( CMAKE_SYSTEM_NAME MATCHES "NetBSD" ) include_directories( ../../../../llvm/include ../../source/Plugins/Process/NetBSD ../../source/Plugins/Process/POSIX ) endif () include_directories(../../source) set(LLDB_SYSTEM_LIBS) if (NOT LLDB_DISABLE_LIBEDIT) list(APPEND LLDB_SYSTEM_LIBS edit) endif() if (NOT LLDB_DISABLE_CURSES) list(APPEND LLDB_SYSTEM_LIBS ${CURSES_LIBRARIES}) if(LLVM_ENABLE_TERMINFO AND HAVE_TERMINFO) list(APPEND LLDB_SYSTEM_LIBS ${TERMINFO_LIBS}) endif() endif() if (NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB ) list(APPEND LLDB_SYSTEM_LIBS atomic) endif() # On FreeBSD/NetBSD backtrace() is provided by libexecinfo, not libc. if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD" OR CMAKE_SYSTEM_NAME MATCHES "NetBSD") list(APPEND LLDB_SYSTEM_LIBS execinfo) endif() if (NOT LLDB_DISABLE_PYTHON AND NOT LLVM_BUILD_STATIC) list(APPEND LLDB_SYSTEM_LIBS ${PYTHON_LIBRARIES}) endif() list(APPEND LLDB_SYSTEM_LIBS ${system_libs}) if (LLVM_BUILD_STATIC) if (NOT LLDB_DISABLE_PYTHON) list(APPEND LLDB_SYSTEM_LIBS python2.7 util) endif() if (NOT LLDB_DISABLE_CURSES) list(APPEND LLDB_SYSTEM_LIBS gpm) endif() endif() +set(LLDB_PLUGINS) + +if(CMAKE_SYSTEM_NAME MATCHES "Linux|Android") + list(APPEND LLDB_PLUGINS lldbPluginProcessLinux) +endif() + +if(CMAKE_SYSTEM_NAME MATCHES "NetBSD") + list(APPEND LLDB_PLUGINS lldbPluginProcessNetBSD) +endif() + add_lldb_tool(lldb-server INCLUDE_IN_FRAMEWORK Acceptor.cpp lldb-gdbserver.cpp lldb-platform.cpp lldb-server.cpp LLDBServerUtilities.cpp LINK_LIBS lldbBase lldbCore lldbHost lldbInitialization lldbInterpreter - ${EXTRA_LLDB_LIBS} + ${LLDB_PLUGINS} ${LLDB_SYSTEM_LIBS} LINK_COMPONENTS Support ) target_link_libraries(lldb-server ${LLDB_SYSTEM_LIBS}) Index: vendor/lldb/dist/tools/lldb-server/lldb-gdbserver.cpp =================================================================== --- vendor/lldb/dist/tools/lldb-server/lldb-gdbserver.cpp (revision 320966) +++ vendor/lldb/dist/tools/lldb-server/lldb-gdbserver.cpp (revision 320967) @@ -1,484 +1,516 @@ //===-- lldb-gdbserver.cpp --------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // C Includes #include #include #include #include #include #ifndef _WIN32 #include #include #endif // C++ Includes #include "Acceptor.h" #include "LLDBServerUtilities.h" #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h" #include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h" #include "lldb/Core/PluginManager.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/HostGetOpt.h" #include "lldb/Host/OptionParser.h" #include "lldb/Host/Pipe.h" #include "lldb/Host/Socket.h" #include "lldb/Host/StringConvert.h" +#include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Utility/Status.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Errno.h" +#if defined(__linux__) +#include "Plugins/Process/Linux/NativeProcessLinux.h" +#elif defined(__NetBSD__) +#include "Plugins/Process/NetBSD/NativeProcessNetBSD.h" +#endif + #ifndef LLGS_PROGRAM_NAME #define LLGS_PROGRAM_NAME "lldb-server" #endif #ifndef LLGS_VERSION_STR #define LLGS_VERSION_STR "local_build" #endif using namespace llvm; using namespace lldb; using namespace lldb_private; using namespace lldb_private::lldb_server; using namespace lldb_private::process_gdb_remote; +namespace { +#if defined(__linux__) +typedef process_linux::NativeProcessLinux::Factory NativeProcessFactory; +#elif defined(__NetBSD__) +typedef process_netbsd::NativeProcessNetBSD::Factory NativeProcessFactory; +#else +// Dummy implementation to make sure the code compiles +class NativeProcessFactory : public NativeProcessProtocol::Factory { +public: + llvm::Expected + Launch(ProcessLaunchInfo &launch_info, + NativeProcessProtocol::NativeDelegate &delegate, + MainLoop &mainloop) const override { + llvm_unreachable("Not implemented"); + } + llvm::Expected + Attach(lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &delegate, + MainLoop &mainloop) const override { + llvm_unreachable("Not implemented"); + } +}; +#endif +} + //---------------------------------------------------------------------- // option descriptors for getopt_long_only() //---------------------------------------------------------------------- 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}}; //---------------------------------------------------------------------- // Watch for signals //---------------------------------------------------------------------- static int g_sighup_received_count = 0; #ifndef _WIN32 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); 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); } void handle_attach_to_pid(GDBRemoteCommunicationServerLLGS &gdb_server, lldb::pid_t pid) { Status 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(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(end_p - attach_target.c_str()) == attach_target.size()) handle_attach_to_pid(gdb_server, static_cast(pid)); else handle_attach_to_process_name(gdb_server, attach_target); } void handle_launch(GDBRemoteCommunicationServerLLGS &gdb_server, int argc, const char *const argv[]) { Status 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); } } Status 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); } Status 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); } Status writeSocketIdToPipe(int unnamed_pipe_fd, const std::string &socket_id) { #if defined(_WIN32) return Status("Unnamed pipes are not supported on Windows."); #else 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) { Status 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_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(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_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); } 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[]) { Status error; MainLoop mainloop; #ifndef _WIN32 // 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; #if __GLIBC__ optind = 0; #else optreset = 1; optind = 1; #endif 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; 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 '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 'r': // Do nothing, native regs is the default these days 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) { llvm::errs() << llvm::formatv( "failed to set new session id for {0} ({1})\n", LLGS_PROGRAM_NAME, llvm::sys::StrError()); } } 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 | LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION)) return -1; Log *log(lldb_private::GetLogIfAnyCategoriesSet(GDBR_LOG_PROCESS)); if (log) { log->Printf("lldb-server launch"); for (int i = 0; i < argc; i++) { log->Printf("argv[%i] = '%s'", i, argv[i]); } } // 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); + NativeProcessFactory factory; + GDBRemoteCommunicationServerLLGS gdb_server(mainloop, factory); 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; } Index: vendor/lldb/dist/tools/lldb-server/lldb-platform.cpp =================================================================== --- vendor/lldb/dist/tools/lldb-server/lldb-platform.cpp (revision 320966) +++ vendor/lldb/dist/tools/lldb-server/lldb-platform.cpp (revision 320967) @@ -1,385 +1,380 @@ //===-- lldb-platform.cpp ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // C Includes #include #if defined(__APPLE__) #include #endif #include #include #include #include #include #include // C++ Includes #include // Other libraries and framework includes #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/Host/ConnectionFileDescriptor.h" #include "lldb/Host/HostGetOpt.h" #include "lldb/Host/OptionParser.h" #include "lldb/Host/common/TCPSocket.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Status.h" using namespace lldb; using namespace lldb_private; using namespace lldb_private::lldb_server; using namespace lldb_private::process_gdb_remote; using namespace llvm; //---------------------------------------------------------------------- // option descriptors for getopt_long_only() //---------------------------------------------------------------------- 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) #else #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 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 Status save_socket_id_to_file(const std::string &socket_id, const FileSpec &file_spec) { FileSpec temp_file_spec(file_spec.GetDirectory().AsCString(), false); Status error(llvm::sys::fs::create_directory(temp_file_spec.GetPath())); if (error.Fail()) return Status("Failed to create directory %s: %s", temp_file_spec.GetCString(), error.AsCString()); llvm::SmallString<64> temp_file_path; temp_file_spec.AppendPathComponent("port-file.%%%%%%"); int FD; auto err_code = llvm::sys::fs::createUniqueFile(temp_file_spec.GetPath(), FD, temp_file_path); if (err_code) return Status("Failed to create temp file: %s", err_code.message().c_str()); llvm::FileRemover tmp_file_remover(temp_file_path); { llvm::raw_fd_ostream temp_file(FD, true); temp_file << socket_id; temp_file.close(); if (temp_file.has_error()) return Status("Failed to write to port file."); } err_code = llvm::sys::fs::rename(temp_file_path, file_spec.GetPath()); if (err_code) return Status("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 Status(); } //---------------------------------------------------------------------- // 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; Status 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; #else 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); + if (!llvm::to_integer(optarg, port_offset)) { + llvm::errs() << "error: invalid port offset string " << optarg << "\n"; option_error = 4; + break; } + if (port_offset < LOW_PORT || port_offset > HIGH_PORT) { + llvm::errs() << llvm::formatv("error: port offset {0} is not in the " + "valid user port range of {1} - {2}\n", + port_offset, LOW_PORT, HIGH_PORT); + option_error = 5; + } } 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); + uint16_t portnum; + if (!llvm::to_integer(optarg, portnum)) { + llvm::errs() << "error: invalid port number string " << optarg << "\n"; option_error = 2; + break; } + if (portnum < LOW_PORT || portnum > HIGH_PORT) { + llvm::errs() << llvm::formatv("error: port number {0} is not in the " + "valid user port range of {1} - {2}\n", + portnum, LOW_PORT, HIGH_PORT); + option_error = 1; + break; + } + if (ch == 'P') + gdbserver_portmap[portnum] = LLDB_INVALID_PROCESS_ID; + else if (ch == 'm') + min_gdbserver_port = portnum; + else + max_gdbserver_port = portnum; } 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(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_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; } } 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(); } } else { // If not running as a server, this process will not accept // connections while a connection is active. acceptor_up.reset(); } 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; Status 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(llvm::None, 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"); } } } while (g_server); fprintf(stderr, "lldb-server exiting...\n"); return 0; } Index: vendor/lldb/dist/unittests/Process/Linux/ProcessorTraceTest.cpp =================================================================== --- vendor/lldb/dist/unittests/Process/Linux/ProcessorTraceTest.cpp (revision 320966) +++ vendor/lldb/dist/unittests/Process/Linux/ProcessorTraceTest.cpp (revision 320967) @@ -1,152 +1,150 @@ //===-- ProcessorTraceMonitorTest.cpp ------------------------- -*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "gtest/gtest.h" #include "ProcessorTrace.h" #include "llvm/ADT/ArrayRef.h" // C Includes // C++ Includes using namespace lldb_private; using namespace process_linux; size_t ReadCylicBufferWrapper(void *buf, size_t buf_size, void *cyc_buf, size_t cyc_buf_size, size_t cyc_start, size_t offset) { llvm::MutableArrayRef dst(reinterpret_cast(buf), buf_size); llvm::MutableArrayRef src(reinterpret_cast(cyc_buf), cyc_buf_size); ProcessorTraceMonitor::ReadCyclicBuffer(dst, src, cyc_start, offset); return dst.size(); } TEST(CyclicBuffer, EdgeCases) { - size_t bytes_read = 0; + size_t bytes_read; uint8_t cyclic_buffer[6] = {'l', 'i', 'c', 'c', 'y', 'c'}; // We will always leave the last bytes untouched // so that string comparisions work. - char bigger_buffer[10] = {}; - char equal_size_buffer[7] = {}; char smaller_buffer[4] = {}; // empty buffer to read into bytes_read = ReadCylicBufferWrapper(smaller_buffer, 0, cyclic_buffer, sizeof(cyclic_buffer), 3, 0); - ASSERT_EQ(0, bytes_read); + ASSERT_EQ(0u, bytes_read); // empty cyclic buffer bytes_read = ReadCylicBufferWrapper(smaller_buffer, sizeof(smaller_buffer), cyclic_buffer, 0, 3, 0); - ASSERT_EQ(0, bytes_read); + ASSERT_EQ(0u, bytes_read); // bigger offset bytes_read = ReadCylicBufferWrapper(smaller_buffer, sizeof(smaller_buffer), cyclic_buffer, sizeof(cyclic_buffer), 3, 6); - ASSERT_EQ(0, bytes_read); + ASSERT_EQ(0u, bytes_read); // wrong offset bytes_read = ReadCylicBufferWrapper(smaller_buffer, sizeof(smaller_buffer), cyclic_buffer, sizeof(cyclic_buffer), 3, 7); - ASSERT_EQ(0, bytes_read); + ASSERT_EQ(0u, bytes_read); // wrong start bytes_read = ReadCylicBufferWrapper(smaller_buffer, sizeof(smaller_buffer), cyclic_buffer, sizeof(cyclic_buffer), 3, 7); - ASSERT_EQ(0, bytes_read); + ASSERT_EQ(0u, bytes_read); } TEST(CyclicBuffer, EqualSizeBuffer) { size_t bytes_read = 0; uint8_t cyclic_buffer[6] = {'l', 'i', 'c', 'c', 'y', 'c'}; char cyclic[] = "cyclic"; - for (int i = 0; i < sizeof(cyclic); i++) { + for (size_t i = 0; i < sizeof(cyclic); i++) { // We will always leave the last bytes untouched // so that string comparisions work. char equal_size_buffer[7] = {}; bytes_read = ReadCylicBufferWrapper(equal_size_buffer, sizeof(cyclic_buffer), cyclic_buffer, sizeof(cyclic_buffer), 3, i); ASSERT_EQ((sizeof(cyclic) - i - 1), bytes_read); ASSERT_STREQ(equal_size_buffer, (cyclic + i)); } } TEST(CyclicBuffer, SmallerSizeBuffer) { - size_t bytes_read = 0; + size_t bytes_read; uint8_t cyclic_buffer[6] = {'l', 'i', 'c', 'c', 'y', 'c'}; // We will always leave the last bytes untouched // so that string comparisions work. char smaller_buffer[4] = {}; bytes_read = ReadCylicBufferWrapper(smaller_buffer, (sizeof(smaller_buffer) - 1), cyclic_buffer, sizeof(cyclic_buffer), 3, 0); - ASSERT_EQ(3, bytes_read); + ASSERT_EQ(3u, bytes_read); ASSERT_STREQ(smaller_buffer, "cyc"); bytes_read = ReadCylicBufferWrapper(smaller_buffer, (sizeof(smaller_buffer) - 1), cyclic_buffer, sizeof(cyclic_buffer), 3, 1); - ASSERT_EQ(3, bytes_read); + ASSERT_EQ(3u, bytes_read); ASSERT_STREQ(smaller_buffer, "ycl"); bytes_read = ReadCylicBufferWrapper(smaller_buffer, (sizeof(smaller_buffer) - 1), cyclic_buffer, sizeof(cyclic_buffer), 3, 2); - ASSERT_EQ(3, bytes_read); + ASSERT_EQ(3u, bytes_read); ASSERT_STREQ(smaller_buffer, "cli"); bytes_read = ReadCylicBufferWrapper(smaller_buffer, (sizeof(smaller_buffer) - 1), cyclic_buffer, sizeof(cyclic_buffer), 3, 3); - ASSERT_EQ(3, bytes_read); + ASSERT_EQ(3u, bytes_read); ASSERT_STREQ(smaller_buffer, "lic"); { char smaller_buffer[4] = {}; bytes_read = ReadCylicBufferWrapper(smaller_buffer, (sizeof(smaller_buffer) - 1), cyclic_buffer, sizeof(cyclic_buffer), 3, 4); - ASSERT_EQ(2, bytes_read); + ASSERT_EQ(2u, bytes_read); ASSERT_STREQ(smaller_buffer, "ic"); } { char smaller_buffer[4] = {}; bytes_read = ReadCylicBufferWrapper(smaller_buffer, (sizeof(smaller_buffer) - 1), cyclic_buffer, sizeof(cyclic_buffer), 3, 5); - ASSERT_EQ(1, bytes_read); + ASSERT_EQ(1u, bytes_read); ASSERT_STREQ(smaller_buffer, "c"); } } TEST(CyclicBuffer, BiggerSizeBuffer) { size_t bytes_read = 0; uint8_t cyclic_buffer[6] = {'l', 'i', 'c', 'c', 'y', 'c'}; char cyclic[] = "cyclic"; - for (int i = 0; i < sizeof(cyclic); i++) { + for (size_t i = 0; i < sizeof(cyclic); i++) { // We will always leave the last bytes untouched // so that string comparisions work. char bigger_buffer[10] = {}; bytes_read = ReadCylicBufferWrapper(bigger_buffer, (sizeof(bigger_buffer) - 1), cyclic_buffer, sizeof(cyclic_buffer), 3, i); ASSERT_EQ((sizeof(cyclic) - i - 1), bytes_read); ASSERT_STREQ(bigger_buffer, (cyclic + i)); } } Index: vendor/lldb/dist/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp =================================================================== --- vendor/lldb/dist/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp (revision 320966) +++ vendor/lldb/dist/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp (revision 320967) @@ -1,2417 +1,2442 @@ //===-- Testx86AssemblyInspectionEngine.cpp ---------------------------*- C++ //-*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "gtest/gtest.h" #include #include "Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h" #include "lldb/Core/Address.h" #include "lldb/Core/AddressRange.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Utility/StreamString.h" #include "llvm/Support/TargetSelect.h" using namespace lldb; using namespace lldb_private; class Testx86AssemblyInspectionEngine : public testing::Test { public: static void SetUpTestCase(); // static void TearDownTestCase() { } // virtual void SetUp() override { } // virtual void TearDown() override { } protected: }; void Testx86AssemblyInspectionEngine::SetUpTestCase() { llvm::InitializeAllTargets(); llvm::InitializeAllAsmPrinters(); llvm::InitializeAllTargetMCs(); llvm::InitializeAllDisassemblers(); } // only defining the register names / numbers that the unwinder is actually // using today // names should match the constants below. These will be the eRegisterKindLLDB // register numbers. const char *x86_64_reg_names[] = {"rax", "rbx", "rcx", "rdx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "rip"}; enum x86_64_regs { k_rax = 0, k_rbx = 1, k_rcx = 2, k_rdx = 3, k_rsp = 4, k_rbp = 5, k_rsi = 6, k_rdi = 7, k_r8 = 8, k_r9 = 9, k_r10 = 10, k_r11 = 11, k_r12 = 12, k_r13 = 13, k_r14 = 14, k_r15 = 15, k_rip = 16 }; // names should match the constants below. These will be the eRegisterKindLLDB // register numbers. const char *i386_reg_names[] = {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip"}; enum i386_regs { k_eax = 0, k_ecx = 1, k_edx = 2, k_ebx = 3, k_esp = 4, k_ebp = 5, k_esi = 6, k_edi = 7, k_eip = 8 }; std::unique_ptr Getx86_64Inspector() { ArchSpec arch("x86_64-apple-macosx", nullptr); std::unique_ptr engine( new x86AssemblyInspectionEngine(arch)); std::vector lldb_regnums; int i = 0; for (const auto &name : x86_64_reg_names) { x86AssemblyInspectionEngine::lldb_reg_info ri; ri.name = name; ri.lldb_regnum = i++; lldb_regnums.push_back(ri); } engine->Initialize(lldb_regnums); return engine; } std::unique_ptr Geti386Inspector() { ArchSpec arch("i386-apple-macosx", nullptr); std::unique_ptr engine( new x86AssemblyInspectionEngine(arch)); std::vector lldb_regnums; int i = 0; for (const auto &name : i386_reg_names) { x86AssemblyInspectionEngine::lldb_reg_info ri; ri.name = name; ri.lldb_regnum = i++; lldb_regnums.push_back(ri); } engine->Initialize(lldb_regnums); return engine; } namespace lldb_private { static std::ostream &operator<<(std::ostream &OS, const UnwindPlan::Row::CFAValue &CFA) { StreamString S; CFA.Dump(S, nullptr, nullptr); return OS << S.GetData(); } } // namespace lldb_private TEST_F(Testx86AssemblyInspectionEngine, TestSimple64bitFrameFunction) { std::unique_ptr engine = Getx86_64Inspector(); // 'int main() { }' compiled for x86_64-apple-macosx with clang uint8_t data[] = { 0x55, // offset 0 -- pushq %rbp 0x48, 0x89, 0xe5, // offset 1 -- movq %rsp, %rbp 0x31, 0xc0, // offset 4 -- xorl %eax, %eax 0x5d, // offset 6 -- popq %rbp 0xc3 // offset 7 -- retq }; AddressRange sample_range(0x1000, sizeof(data)); UnwindPlan unwind_plan(eRegisterKindLLDB); EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); // Expect four unwind rows: // 0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8] // 1: CFA=rsp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8] // 4: CFA=rbp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8] // 7: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8] EXPECT_TRUE(unwind_plan.GetInitialCFARegister() == k_rsp); EXPECT_TRUE(unwind_plan.GetUnwindPlanValidAtAllInstructions() == eLazyBoolYes); EXPECT_TRUE(unwind_plan.GetSourcedFromCompiler() == eLazyBoolNo); UnwindPlan::Row::RegisterLocation regloc; // 0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8] UnwindPlan::RowSP row_sp = unwind_plan.GetRowForFunctionOffset(0); EXPECT_EQ(0ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); // 1: CFA=rsp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8] row_sp = unwind_plan.GetRowForFunctionOffset(1); EXPECT_EQ(1ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); // 4: CFA=rbp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8] row_sp = unwind_plan.GetRowForFunctionOffset(4); EXPECT_EQ(4ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rbp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); // 7: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8] row_sp = unwind_plan.GetRowForFunctionOffset(7); EXPECT_EQ(7ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestSimple32bitFrameFunction) { std::unique_ptr engine = Geti386Inspector(); // 'int main() { }' compiled for i386-apple-macosx with clang uint8_t data[] = { 0x55, // offset 0 -- pushl %ebp 0x89, 0xe5, // offset 1 -- movl %esp, %ebp 0x31, 0xc0, // offset 3 -- xorl %eax, %eax 0x5d, // offset 5 -- popl %ebp 0xc3 // offset 6 -- retl }; AddressRange sample_range(0x1000, sizeof(data)); UnwindPlan unwind_plan(eRegisterKindLLDB); EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); // Expect four unwind rows: // 0: CFA=esp +4 => esp=CFA+0 eip=[CFA-4] // 1: CFA=esp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4] // 3: CFA=ebp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4] // 6: CFA=esp +4 => esp=CFA+0 eip=[CFA-4] EXPECT_TRUE(unwind_plan.GetInitialCFARegister() == k_esp); EXPECT_TRUE(unwind_plan.GetUnwindPlanValidAtAllInstructions() == eLazyBoolYes); EXPECT_TRUE(unwind_plan.GetSourcedFromCompiler() == eLazyBoolNo); UnwindPlan::Row::RegisterLocation regloc; // offset 0 -- pushl %ebp UnwindPlan::RowSP row_sp = unwind_plan.GetRowForFunctionOffset(0); EXPECT_EQ(0ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_eip, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_TRUE(regloc.GetOffset() == -4); // 1: CFA=esp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4] row_sp = unwind_plan.GetRowForFunctionOffset(1); EXPECT_EQ(1ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_eip, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-4, regloc.GetOffset()); // 3: CFA=ebp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4] row_sp = unwind_plan.GetRowForFunctionOffset(3); EXPECT_EQ(3ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_ebp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_eip, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-4, regloc.GetOffset()); // 6: CFA=esp +4 => esp=CFA+0 eip=[CFA-4] row_sp = unwind_plan.GetRowForFunctionOffset(6); EXPECT_EQ(6ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_eip, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-4, regloc.GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, Test64bitFramelessBigStackFrame) { std::unique_ptr engine = Getx86_64Inspector(); // this source file: // // #include // int main (int argc, char **argv) // { // // const int arrsize = 60; // int buf[arrsize * arrsize]; // int accum = argc; // for (int i = 0; i < arrsize; i++) // for (int j = 0; j < arrsize; j++) // { // if (i > 0 && j > 0) // { // int n = buf[(i-1) * (j-1)] * 2; // int m = buf[(i-1) * (j-1)] / 2; // int j = buf[(i-1) * (j-1)] + 2; // int k = buf[(i-1) * (j-1)] - 2; // printf ("%d ", n + m + j + k); // buf[(i-1) * (j-1)] += n - m + j - k; // } // buf[i*j] = accum++; // } // // return buf[(arrsize * arrsize) - 2] + printf ("%d\n", buf[(arrsize * // arrsize) - 3]); // } // // compiled 'clang -fomit-frame-pointer -Os' for x86_64-apple-macosx uint8_t data[] = { 0x55, // offset 0 -- pushq %rbp 0x41, 0x57, // offset 1 -- pushq %r15 0x41, 0x56, // offset 3 -- pushq %r14 0x41, 0x55, // offset 5 -- pushq %r13 0x41, 0x54, // offset 7 -- pushq %r12 0x53, // offset 9 -- pushq %rbx 0x48, 0x81, 0xec, 0x68, 0x38, 0x00, 0x00, // offset 10 -- subq $0x3868, %rsp // .... 0x48, 0x81, 0xc4, 0x68, 0x38, 0x00, 0x00, // offset 17 -- addq $0x3868, %rsp 0x5b, // offset 24 -- popq %rbx 0x41, 0x5c, // offset 25 -- popq %r12 0x41, 0x5d, // offset 27 -- popq %r13 0x41, 0x5e, // offset 29 -- popq %r14 0x41, 0x5f, // offset 31 -- popq %r15 0x5d, // offset 33 -- popq %rbp 0xc3, // offset 34 -- retq 0xe8, 0x12, 0x34, 0x56, 0x78 // offset 35 -- callq whatever }; AddressRange sample_range(0x1000, sizeof(data)); UnwindPlan unwind_plan(eRegisterKindLLDB); EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); // Unwind rules should look like // 0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8] // 1: CFA=rsp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8] // 3: CFA=rsp+24 => rbp=[CFA-16] rsp=CFA+0 r15=[CFA-24] rip=[CFA-8] // 5: CFA=rsp+32 => rbp=[CFA-16] rsp=CFA+0 r14=[CFA-32] r15=[CFA-24] // rip=[CFA-8 // 7: CFA=rsp+40 => rbp=[CFA-16] rsp=CFA+0 r13=[CFA-40] r14=[CFA-32] // r15=[CFA-24] rip=[CFA-8] // 9: CFA=rsp+48 => rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48] r13=[CFA-40] // r14=[CFA-32] r15=[CFA-24] rip=[CFA-8] // 10: CFA=rsp+56 => rbx=[CFA-56] rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48] // r13=[CFA-40] r14=[CFA-32] r15=[CFA-24] rip=[CFA-8] // 17: CFA=rsp+14496 => rbx=[CFA-56] rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48] // r13=[CFA-40] r14=[CFA-32] r15=[CFA-24] rip=[CFA-8] // 24: CFA=rsp+56 => rbx=[CFA-56] rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48] // r13=[CFA-40] r14=[CFA-32] r15=[CFA-24] rip=[CFA-8] // 25: CFA=rsp+48 => rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48] r13=[CFA-40] // r14=[CFA-32] r15=[CFA-24] rip=[CFA-8] // 27: CFA=rsp+40 => rbp=[CFA-16] rsp=CFA+0 r13=[CFA-40] r14=[CFA-32] // r15=[CFA-24] rip=[CFA-8] // 29: CFA=rsp+32 => rbp=[CFA-16] rsp=CFA+0 r14=[CFA-32] r15=[CFA-24] // rip=[CFA-8] // 31: CFA=rsp+24 => rbp=[CFA-16] rsp=CFA+0 r15=[CFA-24] rip=[CFA-8] // 33: CFA=rsp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8] // 34: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8] UnwindPlan::Row::RegisterLocation regloc; // grab the Row for when the prologue has finished executing: // 17: CFA=rsp+14496 => rbx=[CFA-56] rbp=[CFA-16] rsp=CFA+0 r12=[CFA-48] // r13=[CFA-40] r14=[CFA-32] r15=[CFA-24] rip=[CFA-8] UnwindPlan::RowSP row_sp = unwind_plan.GetRowForFunctionOffset(17); EXPECT_EQ(17ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(14496, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_rbp, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-16, regloc.GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_r15, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-24, regloc.GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_r14, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-32, regloc.GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_r13, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-40, regloc.GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_r12, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-48, regloc.GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_rbx, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-56, regloc.GetOffset()); // grab the Row for when the epilogue has finished executing: // 34: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8] row_sp = unwind_plan.GetRowForFunctionOffset(34); EXPECT_EQ(34ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); // these could be set to IsSame and be valid -- meaning that the // register value is the same as the caller's -- but I'd rather // they not be mentioned at all. EXPECT_FALSE(row_sp->GetRegisterInfo(k_rax, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_rbx, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_rcx, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_rdx, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_rbp, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_rsi, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_rdi, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r8, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r9, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r10, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r11, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r12, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r13, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r14, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r15, regloc)); } TEST_F(Testx86AssemblyInspectionEngine, Test32bitFramelessBigStackFrame) { std::unique_ptr engine = Geti386Inspector(); // this source file: // // #include // int main (int argc, char **argv) // { // // const int arrsize = 60; // int buf[arrsize * arrsize]; // int accum = argc; // for (int i = 0; i < arrsize; i++) // for (int j = 0; j < arrsize; j++) // { // if (i > 0 && j > 0) // { // int n = buf[(i-1) * (j-1)] * 2; // int m = buf[(i-1) * (j-1)] / 2; // int j = buf[(i-1) * (j-1)] + 2; // int k = buf[(i-1) * (j-1)] - 2; // printf ("%d ", n + m + j + k); // buf[(i-1) * (j-1)] += n - m + j - k; // } // buf[i*j] = accum++; // } // // return buf[(arrsize * arrsize) - 2] + printf ("%d\n", buf[(arrsize * // arrsize) - 3]); // } // // compiled 'clang -arch i386 -fomit-frame-pointer -Os' for i386-apple-macosx // simplified assembly version of the above function, which is used as the // input // data: // // .section __TEXT,__text,regular,pure_instructions // .macosx_version_min 10, 12 // .globl _main // .align 4, 0x90 // _main: ## @main // ## BB#0: // pushl %ebp // pushl %ebx // pushl %edi // pushl %esi // L0$pb: // subl $0x386c, %esp // calll L1 // L1: // popl %ecx // movl %ecx, 0x8(%esp) // subl $0x8, %esp // pushl %eax // pushl 0x20(%esp) // calll _puts // addl $0x10, %esp // incl %ebx // addl $0x386c, %esp // popl %esi // popl %edi // popl %ebx // popl %ebp // retl // // .section __TEXT,__cstring,cstring_literals // L_.str: ## @.str // .asciz "HI" // // // .subsections_via_symbols uint8_t data[] = { 0x55, // offset 0 -- pushl %ebp 0x53, // offset 1 -- pushl %ebx 0x57, // offset 2 -- pushl %edi 0x56, // offset 3 -- pushl %esi 0x81, 0xec, 0x6c, 0x38, 0x00, 0x00, // offset 4 -- subl $0x386c, %esp 0xe8, 0x00, 0x00, 0x00, 0x00, // offset 10 -- calll 0 // call the next instruction, to put the pc on the stack 0x59, // offset 15 -- popl %ecx // pop the saved pc address into ecx 0x89, 0x4c, 0x24, 0x08, // offset 16 -- movl %ecx, 0x8(%esp) // .... 0x83, 0xec, 0x08, // offset 20 -- subl $0x8, %esp 0x50, // offset 23 -- pushl %eax 0xff, 0x74, 0x24, 0x20, // offset 24 -- pushl 0x20(%esp) 0xe8, 0x8c, 0x00, 0x00, 0x00, // offset 28 -- calll puts 0x83, 0xc4, 0x10, // offset 33 -- addl $0x10, %esp // get esp back to the value it was before the // alignment & argument saves for the puts call 0x43, // offset 36 -- incl %ebx // .... 0x81, 0xc4, 0x6c, 0x38, 0x00, 0x00, // offset 37 -- addl $0x386c, %esp 0x5e, // offset 43 -- popl %esi 0x5f, // offset 44 -- popl %edi 0x5b, // offset 45 -- popl %ebx 0x5d, // offset 46 -- popl %ebp 0xc3, // offset 47 -- retl 0xe8, 0x12, 0x34, 0x56, 0x78, // offset 48 -- calll __stack_chk_fail }; AddressRange sample_range(0x1000, sizeof(data)); UnwindPlan unwind_plan(eRegisterKindLLDB); EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); // Unwind rules should look like // // 0: CFA=esp +4 => esp=CFA+0 eip=[CFA-4] // 1: CFA=esp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4] // 2: CFA=esp+12 => ebx=[CFA-12] ebp=[CFA-8] esp=CFA+0 eip=[CFA-4] // 3: CFA=esp+16 => ebx=[CFA-12] edi=[CFA-16] ebp=[CFA-8] esp=CFA+0 // eip=[CFA-4] // 4: CFA=esp+20 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8] // esp=CFA+0 eip=[CFA-4] // 10: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8] // esp=CFA+0 eip=[CFA-4] // 15: CFA=esp+14468 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8] // esp=CFA+0 eip=[CFA-4] // 16: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8] // esp=CFA+0 eip=[CFA-4] // // .... // // 23: CFA=esp+14472 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8] // esp=CFA+0 eip=[CFA-4] // 24: CFA=esp+14476 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8] // esp=CFA+0 eip=[CFA-4] // 28: CFA=esp+14480 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8] // esp=CFA+0 eip=[CFA-4] // 36: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8] // esp=CFA+0 eip=[CFA-4] // // ..... // // 37: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8] // esp=CFA+0 eip=[CFA-4] // 43: CFA=esp+20 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8] // esp=CFA+0 eip=[CFA-4] // 44: CFA=esp+16 => ebx=[CFA-12] edi=[CFA-16] ebp=[CFA-8] esp=CFA+0 // eip=[CFA-4] // 45: CFA=esp+12 => ebx=[CFA-12] ebp=[CFA-8] esp=CFA+0 eip=[CFA-4] // 46: CFA=esp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4] // 47: CFA=esp +4 => esp=CFA+0 eip=[CFA-4] // 48: CFA=esp+14480 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8] // esp=CFA+0 eip=[CFA-4] UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; // Check that we get the CFA correct for the pic base setup sequence // CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8] // esp=CFA+0 eip=[CFA-4] row_sp = unwind_plan.GetRowForFunctionOffset(10); EXPECT_EQ(10ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(14464, row_sp->GetCFAValue().GetOffset()); // 15: CFA=esp+14468 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8] // esp=CFA+0 eip=[CFA-4] row_sp = unwind_plan.GetRowForFunctionOffset(15); EXPECT_EQ(15ull, row_sp->GetOffset()); EXPECT_EQ(14468, row_sp->GetCFAValue().GetOffset()); // 16: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8] // esp=CFA+0 eip=[CFA-4] row_sp = unwind_plan.GetRowForFunctionOffset(16); EXPECT_EQ(16ull, row_sp->GetOffset()); EXPECT_EQ(14464, row_sp->GetCFAValue().GetOffset()); // Check that the row for offset 16 has the registers saved that we expect EXPECT_TRUE(row_sp->GetRegisterInfo(k_eip, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-4, regloc.GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_ebp, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_ebx, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-12, regloc.GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_edi, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-16, regloc.GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_esi, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-20, regloc.GetOffset()); // // Check the pushing & popping around the call printf instruction // 23: CFA=esp+14472 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8] // esp=CFA+0 eip=[CFA-4] row_sp = unwind_plan.GetRowForFunctionOffset(23); EXPECT_EQ(23ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(14472, row_sp->GetCFAValue().GetOffset()); // 24: CFA=esp+14476 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8] // esp=CFA+0 eip=[CFA-4] row_sp = unwind_plan.GetRowForFunctionOffset(24); EXPECT_EQ(24ull, row_sp->GetOffset()); EXPECT_EQ(14476, row_sp->GetCFAValue().GetOffset()); // 28: CFA=esp+14480 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8] // esp=CFA+0 eip=[CFA-4] row_sp = unwind_plan.GetRowForFunctionOffset(28); EXPECT_EQ(28ull, row_sp->GetOffset()); EXPECT_EQ(14480, row_sp->GetCFAValue().GetOffset()); // 36: CFA=esp+14464 => ebx=[CFA-12] edi=[CFA-16] esi=[CFA-20] ebp=[CFA-8] // esp=CFA+0 eip=[CFA-4] row_sp = unwind_plan.GetRowForFunctionOffset(36); EXPECT_EQ(36ull, row_sp->GetOffset()); EXPECT_EQ(14464, row_sp->GetCFAValue().GetOffset()); // Check that the epilogue gets us back to the original unwind state // 47: CFA=esp +4 => esp=CFA+0 eip=[CFA-4] row_sp = unwind_plan.GetRowForFunctionOffset(47); EXPECT_EQ(47ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_eip, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-4, regloc.GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_esp, regloc)); EXPECT_TRUE(regloc.IsCFAPlusOffset()); EXPECT_EQ(0, regloc.GetOffset()); // Check that no unexpected registers were saved EXPECT_FALSE(row_sp->GetRegisterInfo(k_eax, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebx, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_ecx, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_edx, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_esi, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_edi, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebp, regloc)); } TEST_F(Testx86AssemblyInspectionEngine, Test64bitFramelessSmallStackFrame) { std::unique_ptr engine = Getx86_64Inspector(); // this source file: // #include // int main () { // puts ("HI"); // } // // compiled 'clang -fomit-frame-pointer' for x86_64-apple-macosx uint8_t data[] = { 0x50, // offset 0 -- pushq %rax 0x48, 0x8d, 0x3d, 0x32, 0x00, 0x00, 0x00, // offset 1 -- leaq 0x32(%rip), %rdi ; "HI" 0xe8, 0x0b, 0x00, 0x00, 0x00, // offset 8 -- callq 0x100000f58 ; puts 0x31, 0xc9, // offset 13 -- xorl %ecx, %ecx 0x89, 0x44, 0x24, 0x04, // offset 15 -- movl %eax, 0x4(%rsp) 0x89, 0xc8, // offset 19 -- movl %ecx, %eax 0x59, // offset 21 -- popq %rcx 0xc3 // offset 22 -- retq }; AddressRange sample_range(0x1000, sizeof(data)); UnwindPlan unwind_plan(eRegisterKindLLDB); EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); // Unwind rules should look like // 0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8] // 1: CFA=rsp+16 => rsp=CFA+0 rip=[CFA-8] // 22: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8] UnwindPlan::Row::RegisterLocation regloc; // grab the Row for when the prologue has finished executing: // 1: CFA=rsp+16 => rsp=CFA+0 rip=[CFA-8] UnwindPlan::RowSP row_sp = unwind_plan.GetRowForFunctionOffset(13); EXPECT_EQ(1ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); // none of these were spilled EXPECT_FALSE(row_sp->GetRegisterInfo(k_rax, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_rbx, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_rcx, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_rdx, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_rbp, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_rsi, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_rdi, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r8, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r9, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r10, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r11, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r12, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r13, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r14, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r15, regloc)); // grab the Row for when the epilogue has finished executing: // 22: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8] row_sp = unwind_plan.GetRowForFunctionOffset(22); EXPECT_EQ(22ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, Test32bitFramelessSmallStackFrame) { std::unique_ptr engine = Geti386Inspector(); // this source file: // #include // int main () { // puts ("HI"); // } // // compiled 'clang -arch i386 -fomit-frame-pointer' for i386-apple-macosx uint8_t data[] = { 0x83, 0xec, 0x0c, // offset 0 -- subl $0xc, %esp 0xe8, 0x00, 0x00, 0x00, 0x00, // offset 3 -- calll 0 {call the next instruction, to put the pc on // the stack} 0x58, // offset 8 -- popl %eax {pop the saved pc value off stack, into eax} 0x8d, 0x80, 0x3a, 0x00, 0x00, 0x00, // offset 9 -- leal 0x3a(%eax),%eax 0x89, 0x04, 0x24, // offset 15 -- movl %eax, (%esp) 0xe8, 0x0d, 0x00, 0x00, 0x00, // offset 18 -- calll 0x1f94 (puts) 0x31, 0xc9, // offset 23 -- xorl %ecx, %ecx 0x89, 0x44, 0x24, 0x08, // offset 25 -- movl %eax, 0x8(%esp) 0x89, 0xc8, // offset 29 -- movl %ecx, %eax 0x83, 0xc4, 0x0c, // offset 31 -- addl $0xc, %esp 0xc3 // offset 34 -- retl }; AddressRange sample_range(0x1000, sizeof(data)); UnwindPlan unwind_plan(eRegisterKindLLDB); EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); // Unwind rules should look like // row[0]: 0: CFA=esp +4 => esp=CFA+0 eip=[CFA-4] // row[1]: 3: CFA=esp+16 => esp=CFA+0 eip=[CFA-4] // row[2]: 8: CFA=esp+20 => esp=CFA+0 eip=[CFA-4] // row[3]: 9: CFA=esp+16 => esp=CFA+0 eip=[CFA-4] // row[4]: 34: CFA=esp +4 => esp=CFA+0 eip=[CFA-4] UnwindPlan::Row::RegisterLocation regloc; // Check unwind state before we set up the picbase register // 3: CFA=esp+16 => esp=CFA+0 eip=[CFA-4] UnwindPlan::RowSP row_sp = unwind_plan.GetRowForFunctionOffset(3); EXPECT_EQ(3ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); // Check unwind state after we call the next instruction // 8: CFA=esp+20 => esp=CFA+0 eip=[CFA-4] row_sp = unwind_plan.GetRowForFunctionOffset(8); EXPECT_EQ(8ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(20, row_sp->GetCFAValue().GetOffset()); // Check unwind state after we pop the pic base value off the stack // row[3]: 9: CFA=esp+16 => esp=CFA+0 eip=[CFA-4] row_sp = unwind_plan.GetRowForFunctionOffset(9); EXPECT_EQ(9ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); // Check that no unexpected registers were saved EXPECT_FALSE(row_sp->GetRegisterInfo(k_eax, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebx, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_ecx, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_edx, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_esi, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_edi, regloc)); EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebp, regloc)); // verify that we get back to the original unwind state before the ret // 34: CFA=esp +4 => esp=CFA+0 eip=[CFA-4] row_sp = unwind_plan.GetRowForFunctionOffset(34); EXPECT_EQ(34ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestPushRBP) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; uint8_t data[] = { 0x55, // pushq %rbp 0x90 // nop }; AddressRange sample_range(0x1000, sizeof(data)); UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine64 = Getx86_64Inspector(); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(1); EXPECT_EQ(1ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_rbp, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-16, regloc.GetOffset()); std::unique_ptr engine32 = Geti386Inspector(); EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(1); EXPECT_EQ(1ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_rbp, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestPushImm) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; uint8_t data[] = { 0x68, 0xff, 0xff, 0x01, 0x69, // pushq $0x6901ffff 0x6a, 0x7d, // pushl $0x7d 0x90 // nop }; AddressRange sample_range(0x1000, sizeof(data)); UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine64 = Getx86_64Inspector(); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(5); EXPECT_EQ(5ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); row_sp = unwind_plan.GetRowForFunctionOffset(7); EXPECT_EQ(7ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(24, row_sp->GetCFAValue().GetOffset()); std::unique_ptr engine32 = Geti386Inspector(); EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(5); EXPECT_EQ(5ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); row_sp = unwind_plan.GetRowForFunctionOffset(7); EXPECT_EQ(7ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(12, row_sp->GetCFAValue().GetOffset()); } // We treat 'pushq $0' / 'pushl $0' specially - this shows up // in the first function called in a new thread and it needs to // put a 0 as the saved pc. We pretend it didn't change the CFA. TEST_F(Testx86AssemblyInspectionEngine, TestPush0) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; uint8_t data[] = { 0x6a, 0x00, // pushq $0 0x90 // nop }; AddressRange sample_range(0x1000, sizeof(data)); UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine64 = Getx86_64Inspector(); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(2); // We're verifying that no row was created for the 'pushq $0' EXPECT_EQ(0ull, row_sp->GetOffset()); std::unique_ptr engine32 = Geti386Inspector(); EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(2); // We're verifying that no row was created for the 'pushq $0' EXPECT_EQ(0ull, row_sp->GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestPushExtended) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; uint8_t data[] = { 0xff, 0x74, 0x24, 0x20, // pushl 0x20(%esp) 0xff, 0xb6, 0xce, 0x01, 0xf0, 0x00, // pushl 0xf001ce(%esi) 0xff, 0x30, // pushl (%eax) 0x90 // nop }; AddressRange sample_range(0x1000, sizeof(data)); UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine64 = Getx86_64Inspector(); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(4); EXPECT_EQ(4ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); std::unique_ptr engine32 = Geti386Inspector(); EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(4); EXPECT_EQ(4ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); row_sp = unwind_plan.GetRowForFunctionOffset(10); EXPECT_EQ(10ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(12, row_sp->GetCFAValue().GetOffset()); row_sp = unwind_plan.GetRowForFunctionOffset(12); EXPECT_EQ(12ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestPushR15) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; uint8_t data[] = { 0x41, 0x57, // pushq %r15 0x90 // nop }; AddressRange sample_range(0x1000, sizeof(data)); UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine64 = Getx86_64Inspector(); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(2); EXPECT_EQ(2ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_r15, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-16, regloc.GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestPushR14) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; uint8_t data[] = { 0x41, 0x56, // pushq %r14 0x90 // nop }; AddressRange sample_range(0x1000, sizeof(data)); UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine64 = Getx86_64Inspector(); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(2); EXPECT_EQ(2ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_r14, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-16, regloc.GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestPushR13) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; uint8_t data[] = { 0x41, 0x55, // pushq %r13 0x90 // nop }; AddressRange sample_range(0x1000, sizeof(data)); UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine64 = Getx86_64Inspector(); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(2); EXPECT_EQ(2ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_r13, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-16, regloc.GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestPushR12) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; uint8_t data[] = { 0x41, 0x54, // pushq %r13 0x90 // nop }; AddressRange sample_range(0x1000, sizeof(data)); UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine64 = Getx86_64Inspector(); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(2); EXPECT_EQ(2ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_r12, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-16, regloc.GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestPushRBX) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; uint8_t data[] = { 0x53, // pushq %rbx 0x90 // nop }; AddressRange sample_range(0x1000, sizeof(data)); UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine64 = Getx86_64Inspector(); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(1); EXPECT_EQ(1ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_rbx, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-16, regloc.GetOffset()); } // The ABI is hardcoded in x86AssemblyInspectionEngine such that // eax, ecx, edx are all considered volatile and push/pops of them are // not tracked (except to keep track of stack pointer movement) TEST_F(Testx86AssemblyInspectionEngine, TestPushEAX) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine32 = Geti386Inspector(); uint8_t data[] = { 0x50, // pushl %eax 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(1); EXPECT_EQ(1ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_FALSE(row_sp->GetRegisterInfo(k_eax, regloc)); } // The ABI is hardcoded in x86AssemblyInspectionEngine such that // eax, ecx, edx are all considered volatile and push/pops of them are // not tracked (except to keep track of stack pointer movement) TEST_F(Testx86AssemblyInspectionEngine, TestPushECX) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine32 = Geti386Inspector(); uint8_t data[] = { 0x51, // pushl %ecx 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(1); EXPECT_EQ(1ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_FALSE(row_sp->GetRegisterInfo(k_ecx, regloc)); } // The ABI is hardcoded in x86AssemblyInspectionEngine such that // eax, ecx, edx are all considered volatile and push/pops of them are // not tracked (except to keep track of stack pointer movement) TEST_F(Testx86AssemblyInspectionEngine, TestPushEDX) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine32 = Geti386Inspector(); uint8_t data[] = { 0x52, // pushl %edx 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(1); EXPECT_EQ(1ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_FALSE(row_sp->GetRegisterInfo(k_edx, regloc)); } TEST_F(Testx86AssemblyInspectionEngine, TestPushEBX) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine32 = Geti386Inspector(); uint8_t data[] = { 0x53, // pushl %ebx 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(1); EXPECT_EQ(1ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_ebx, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestPushEBP) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine32 = Geti386Inspector(); uint8_t data[] = { 0x55, // pushl %ebp 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(1); EXPECT_EQ(1ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_ebp, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestPushESI) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine32 = Geti386Inspector(); uint8_t data[] = { 0x56, // pushl %esi 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(1); EXPECT_EQ(1ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_esi, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestPushEDI) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine32 = Geti386Inspector(); uint8_t data[] = { 0x57, // pushl %edi 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(1); EXPECT_EQ(1ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_edi, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestMovRSPtoRBP) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; uint8_t data64_1[] = { 0x48, 0x8b, 0xec, // movq %rsp, %rbp 0x90 // nop }; AddressRange sample_range(0x1000, sizeof(data64_1)); UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine64 = Getx86_64Inspector(); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data64_1, sizeof(data64_1), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(3); EXPECT_EQ(3ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rbp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); uint8_t data64_2[] = { 0x48, 0x89, 0xe5, // movq %rsp, %rbp 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data64_2)); unwind_plan.Clear(); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data64_2, sizeof(data64_2), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(3); EXPECT_EQ(3ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rbp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); uint8_t data32_1[] = { 0x8b, 0xec, // movl %rsp, %rbp 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data32_1)); unwind_plan.Clear(); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data32_1, sizeof(data32_1), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(2); EXPECT_EQ(2ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_ebp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); uint8_t data32_2[] = { 0x89, 0xe5, // movl %rsp, %rbp 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data32_2)); unwind_plan.Clear(); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data32_2, sizeof(data32_2), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(2); EXPECT_EQ(2ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_ebp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestSubRSP) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine64 = Getx86_64Inspector(); uint8_t data1[] = { 0x48, 0x81, 0xec, 0x00, 0x01, 0x00, 0x00, // subq $0x100, $rsp 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data1)); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data1, sizeof(data1), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(7); EXPECT_EQ(7ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(264, row_sp->GetCFAValue().GetOffset()); uint8_t data2[] = { 0x48, 0x83, 0xec, 0x10, // subq $0x10, %rsp 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data2)); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data2, sizeof(data2), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(4); EXPECT_EQ(4ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(24, row_sp->GetCFAValue().GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestSubESP) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine32 = Geti386Inspector(); uint8_t data1[] = { 0x81, 0xec, 0x00, 0x01, 0x00, 0x00, // subl $0x100, %esp 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data1)); EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( data1, sizeof(data1), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(6); EXPECT_EQ(6ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(260, row_sp->GetCFAValue().GetOffset()); uint8_t data2[] = { 0x83, 0xec, 0x10, // subq $0x10, %esp 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data2)); EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( data2, sizeof(data2), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(3); EXPECT_EQ(3ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(20, row_sp->GetCFAValue().GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestAddRSP) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine64 = Getx86_64Inspector(); uint8_t data1[] = { 0x48, 0x81, 0xc4, 0x00, 0x01, 0x00, 0x00, // addq $0x100, %rsp 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data1)); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data1, sizeof(data1), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(7); EXPECT_EQ(7ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8 - 256, row_sp->GetCFAValue().GetOffset()); uint8_t data2[] = { 0x48, 0x83, 0xc4, 0x10, // addq $0x10, %rsp 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data2)); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data2, sizeof(data2), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(4); EXPECT_EQ(4ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8 - 16, row_sp->GetCFAValue().GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestAddESP) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine32 = Geti386Inspector(); uint8_t data1[] = { 0x81, 0xc4, 0x00, 0x01, 0x00, 0x00, // addl $0x100, %esp 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data1)); EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( data1, sizeof(data1), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(6); EXPECT_EQ(6ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(4 - 256, row_sp->GetCFAValue().GetOffset()); uint8_t data2[] = { 0x83, 0xc4, 0x10, // addq $0x10, %esp 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data2)); EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( data2, sizeof(data2), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(3); EXPECT_EQ(3ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(4 - 16, row_sp->GetCFAValue().GetOffset()); } // FIXME add test for lea_rsp_pattern_p TEST_F(Testx86AssemblyInspectionEngine, TestPopRBX) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine = Getx86_64Inspector(); uint8_t data[] = { 0x53, // pushq %rbx 0x5b, // popq %rbx 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(2); EXPECT_EQ(2ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_FALSE(row_sp->GetRegisterInfo(k_rbx, regloc)); } TEST_F(Testx86AssemblyInspectionEngine, TestPopRBP) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine = Getx86_64Inspector(); uint8_t data[] = { 0x55, // pushq %rbp 0x5d, // popq %rbp 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(2); EXPECT_EQ(2ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_FALSE(row_sp->GetRegisterInfo(k_rbp, regloc)); } TEST_F(Testx86AssemblyInspectionEngine, TestPopR12) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine = Getx86_64Inspector(); uint8_t data[] = { 0x41, 0x54, // pushq %r12 0x41, 0x5c, // popq %r12 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(4); EXPECT_EQ(4ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r12, regloc)); } TEST_F(Testx86AssemblyInspectionEngine, TestPopR13) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine = Getx86_64Inspector(); uint8_t data[] = { 0x41, 0x55, // pushq %r13 0x41, 0x5d, // popq %r13 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(4); EXPECT_EQ(4ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r13, regloc)); } TEST_F(Testx86AssemblyInspectionEngine, TestPopR14) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine = Getx86_64Inspector(); uint8_t data[] = { 0x41, 0x56, // pushq %r14 0x41, 0x5e, // popq %r14 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(4); EXPECT_EQ(4ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r14, regloc)); } TEST_F(Testx86AssemblyInspectionEngine, TestPopR15) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine = Getx86_64Inspector(); uint8_t data[] = { 0x41, 0x57, // pushq %r15 0x41, 0x5f, // popq %r15 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(4); EXPECT_EQ(4ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_FALSE(row_sp->GetRegisterInfo(k_r15, regloc)); } TEST_F(Testx86AssemblyInspectionEngine, TestPopEBX) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine = Geti386Inspector(); uint8_t data[] = { 0x53, // pushl %ebx 0x5b, // popl %ebx 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(2); EXPECT_EQ(2ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset()); EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebx, regloc)); } TEST_F(Testx86AssemblyInspectionEngine, TestPopEBP) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine = Geti386Inspector(); uint8_t data[] = { 0x55, // pushl %ebp 0x5d, // popl %ebp 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(2); EXPECT_EQ(2ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset()); EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebp, regloc)); } TEST_F(Testx86AssemblyInspectionEngine, TestPopESI) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine = Geti386Inspector(); uint8_t data[] = { 0x56, // pushl %esi 0x5e, // popl %esi 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(2); EXPECT_EQ(2ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset()); EXPECT_FALSE(row_sp->GetRegisterInfo(k_esi, regloc)); } TEST_F(Testx86AssemblyInspectionEngine, TestPopEDI) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine = Geti386Inspector(); uint8_t data[] = { 0x57, // pushl %edi 0x5f, // popl %edi 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(2); EXPECT_EQ(2ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset()); EXPECT_FALSE(row_sp->GetRegisterInfo(k_edi, regloc)); } // We don't track these registers, but make sure the CFA address is updated // if we're defining the CFA in term of esp. TEST_F(Testx86AssemblyInspectionEngine, Testi386IgnoredRegisters) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine = Geti386Inspector(); uint8_t data[] = { 0x0e, // push cs 0x16, // push ss 0x1e, // push ds 0x06, // push es 0x07, // pop es 0x1f, // pop ds 0x17, // pop ss 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(4); EXPECT_EQ(4ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(20, row_sp->GetCFAValue().GetOffset()); row_sp = unwind_plan.GetRowForFunctionOffset(7); EXPECT_EQ(7ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestLEAVE) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine64 = Getx86_64Inspector(); std::unique_ptr engine32 = Geti386Inspector(); uint8_t data[] = { 0x55, // push %rbp/ebp 0xc9, // leave 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(2); EXPECT_EQ(2ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_FALSE(row_sp->GetRegisterInfo(k_rbp, regloc)); EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(2); EXPECT_EQ(2ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset()); EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebp, regloc)); } // In i386, which lacks pc-relative addressing, a common code sequence // is to call the next instruction (i.e. call imm32, value of 0) which // pushes the addr of the next insn on the stack, and then pop that value // into a register (the "pic base" register). TEST_F(Testx86AssemblyInspectionEngine, TestCALLNextInsn) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine32 = Geti386Inspector(); uint8_t data[] = { 0xe8, 0x00, 0x00, 0x00, 0x00, // call 0 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(5); EXPECT_EQ(5ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebp, regloc)); } TEST_F(Testx86AssemblyInspectionEngine, TestSpillRegToStackViaMOVx86_64) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine64 = Getx86_64Inspector(); uint8_t data[] = { 0x55, // pushq %rbp 0x48, 0x89, 0xe5, // movq %rsp, %rbp 0x4c, 0x89, 0x75, 0xc0, // movq %r14, -0x40(%rbp) 0x4c, 0x89, 0xbd, 0x28, 0xfa, 0xff, 0xff, // movq %r15, -0x5d8(%rbp) 0x48, 0x89, 0x5d, 0xb8, // movq %rbx, -0x48(%rbp) 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(19); EXPECT_EQ(19ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rbp); EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_r14, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-80, regloc.GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_r15, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-1512, regloc.GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_rbx, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-88, regloc.GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestSpillRegToStackViaMOVi386) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine32 = Geti386Inspector(); uint8_t data[] = { 0x55, // pushl %ebp 0x89, 0xe5, // movl %esp, %ebp 0x89, 0x9d, 0xb0, 0xfe, 0xff, 0xff, // movl %ebx, -0x150(%ebp) 0x89, 0x75, 0xe0, // movl %esi, -0x20(%ebp) 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(12); EXPECT_EQ(12ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rbp); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_ebx, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-344, regloc.GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_esi, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-40, regloc.GetOffset()); } TEST_F(Testx86AssemblyInspectionEngine, TestSimplex86_64Augmented) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine64 = Getx86_64Inspector(); uint8_t data[] = { 0x55, // pushq %rbp 0x48, 0x89, 0xe5, // movq %rsp, %rbp // x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite // has a bug where it can't augment a function that is just // prologue+epilogue - it needs at least one other instruction // in between. 0x90, // nop 0x5d, // popq %rbp 0xc3 // retq }; sample_range = AddressRange(0x1000, sizeof(data)); unwind_plan.SetSourceName("unit testing hand-created unwind plan"); unwind_plan.SetPlanValidAddressRange(sample_range); unwind_plan.SetRegisterKind(eRegisterKindLLDB); row_sp.reset(new UnwindPlan::Row); // Describe offset 0 row_sp->SetOffset(0); row_sp->GetCFAValue().SetIsRegisterPlusOffset(k_rsp, 8); regloc.SetAtCFAPlusOffset(-8); row_sp->SetRegisterInfo(k_rip, regloc); unwind_plan.AppendRow(row_sp); // Allocate a new Row, populate it with the existing Row contents. UnwindPlan::Row *new_row = new UnwindPlan::Row; *new_row = *row_sp.get(); row_sp.reset(new_row); // Describe offset 1 row_sp->SetOffset(1); row_sp->GetCFAValue().SetIsRegisterPlusOffset(k_rsp, 16); regloc.SetAtCFAPlusOffset(-16); row_sp->SetRegisterInfo(k_rbp, regloc); unwind_plan.AppendRow(row_sp); // Allocate a new Row, populate it with the existing Row contents. new_row = new UnwindPlan::Row; *new_row = *row_sp.get(); row_sp.reset(new_row); // Describe offset 4 row_sp->SetOffset(4); row_sp->GetCFAValue().SetIsRegisterPlusOffset(k_rbp, 16); unwind_plan.AppendRow(row_sp); RegisterContextSP reg_ctx_sp; EXPECT_TRUE(engine64->AugmentUnwindPlanFromCallSite( data, sizeof(data), sample_range, unwind_plan, reg_ctx_sp)); row_sp = unwind_plan.GetRowForFunctionOffset(6); EXPECT_EQ(6ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); // x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite // doesn't track register restores (pop'ing a reg value back from // the stack) - it was just written to make stepping work correctly. // Technically we should be able to do the following test, but it // won't work today - the unwind plan will still say that the caller's // rbp is on the stack. // EXPECT_FALSE(row_sp->GetRegisterInfo(k_rbp, regloc)); } TEST_F(Testx86AssemblyInspectionEngine, TestSimplei386ugmented) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine32 = Geti386Inspector(); uint8_t data[] = { 0x55, // pushl %ebp 0x89, 0xe5, // movl %esp, %ebp // x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite // has a bug where it can't augment a function that is just // prologue+epilogue - it needs at least one other instruction // in between. 0x90, // nop 0x5d, // popl %ebp 0xc3 // retl }; sample_range = AddressRange(0x1000, sizeof(data)); unwind_plan.SetSourceName("unit testing hand-created unwind plan"); unwind_plan.SetPlanValidAddressRange(sample_range); unwind_plan.SetRegisterKind(eRegisterKindLLDB); row_sp.reset(new UnwindPlan::Row); // Describe offset 0 row_sp->SetOffset(0); row_sp->GetCFAValue().SetIsRegisterPlusOffset(k_esp, 4); regloc.SetAtCFAPlusOffset(-4); row_sp->SetRegisterInfo(k_eip, regloc); unwind_plan.AppendRow(row_sp); // Allocate a new Row, populate it with the existing Row contents. UnwindPlan::Row *new_row = new UnwindPlan::Row; *new_row = *row_sp.get(); row_sp.reset(new_row); // Describe offset 1 row_sp->SetOffset(1); row_sp->GetCFAValue().SetIsRegisterPlusOffset(k_esp, 8); regloc.SetAtCFAPlusOffset(-8); row_sp->SetRegisterInfo(k_ebp, regloc); unwind_plan.AppendRow(row_sp); // Allocate a new Row, populate it with the existing Row contents. new_row = new UnwindPlan::Row; *new_row = *row_sp.get(); row_sp.reset(new_row); // Describe offset 3 row_sp->SetOffset(3); row_sp->GetCFAValue().SetIsRegisterPlusOffset(k_ebp, 8); unwind_plan.AppendRow(row_sp); RegisterContextSP reg_ctx_sp; EXPECT_TRUE(engine32->AugmentUnwindPlanFromCallSite( data, sizeof(data), sample_range, unwind_plan, reg_ctx_sp)); row_sp = unwind_plan.GetRowForFunctionOffset(5); EXPECT_EQ(5ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp); EXPECT_EQ(4, row_sp->GetCFAValue().GetOffset()); // x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite // doesn't track register restores (pop'ing a reg value back from // the stack) - it was just written to make stepping work correctly. // Technically we should be able to do the following test, but it // won't work today - the unwind plan will still say that the caller's // ebp is on the stack. // EXPECT_FALSE(row_sp->GetRegisterInfo(k_ebp, regloc)); } // Check that the i386 disassembler disassembles past an opcode that // is only valid in 32-bit mode (non-long mode), and the x86_64 disassembler // stops // disassembling at that point (long-mode). TEST_F(Testx86AssemblyInspectionEngine, Test32BitOnlyInstruction) { UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::RowSP row_sp; AddressRange sample_range; UnwindPlan unwind_plan(eRegisterKindLLDB); std::unique_ptr engine32 = Geti386Inspector(); std::unique_ptr engine64 = Getx86_64Inspector(); uint8_t data[] = { 0x43, // incl $ebx --- an invalid opcode in 64-bit mode 0x55, // pushl %ebp 0x90 // nop }; sample_range = AddressRange(0x1000, sizeof(data)); EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(2); EXPECT_EQ(2ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_TRUE(row_sp->GetRegisterInfo(k_ebp, regloc)); EXPECT_TRUE(regloc.IsAtCFAPlusOffset()); EXPECT_EQ(-8, regloc.GetOffset()); unwind_plan.Clear(); EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( data, sizeof(data), sample_range, unwind_plan)); row_sp = unwind_plan.GetRowForFunctionOffset(2); EXPECT_EQ(0ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(8, row_sp->GetCFAValue().GetOffset()); EXPECT_FALSE(row_sp->GetRegisterInfo(k_rbp, regloc)); } TEST_F(Testx86AssemblyInspectionEngine, TestStackRealign8BitDisp_i386) { std::unique_ptr engine = Geti386Inspector(); uint8_t data[] = { 0x55, // pushl %ebp 0x89, 0xe5, // movl %esp, %ebp 0x53, // pushl %ebx 0x83, 0xe4, 0xf0, // andl $-16, %esp 0x83, 0xec, 0x10, // subl $16, %esp 0x8d, 0x65, 0xfc, // leal -4(%ebp), %esp 0x5b, // popl %ebx 0x5d, // popl %ebp 0xc3, // retl }; AddressRange sample_range(0x1000, sizeof(data)); UnwindPlan plan(eRegisterKindLLDB); ASSERT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(data, sizeof(data), sample_range, plan)); UnwindPlan::Row::CFAValue esp_plus_4, esp_plus_8, ebp_plus_8; esp_plus_4.SetIsRegisterPlusOffset(k_esp, 4); esp_plus_8.SetIsRegisterPlusOffset(k_esp, 8); ebp_plus_8.SetIsRegisterPlusOffset(k_ebp, 8); EXPECT_EQ(esp_plus_4, plan.GetRowForFunctionOffset(0)->GetCFAValue()); EXPECT_EQ(esp_plus_8, plan.GetRowForFunctionOffset(1)->GetCFAValue()); for (size_t i = 3; i < sizeof(data) - 2; ++i) EXPECT_EQ(ebp_plus_8, plan.GetRowForFunctionOffset(i)->GetCFAValue()) << "i: " << i; EXPECT_EQ(esp_plus_4, plan.GetRowForFunctionOffset(sizeof(data) - 1)->GetCFAValue()); } TEST_F(Testx86AssemblyInspectionEngine, TestStackRealign32BitDisp_x86_64) { std::unique_ptr engine = Getx86_64Inspector(); uint8_t data[] = { 0x55, // pushq %rbp 0x48, 0x89, 0xe5, // movq %rsp, %rbp 0x53, // pushl %rbx 0x48, 0x83, 0xe4, 0xf0, // andq $-16, %rsp 0x48, 0x81, 0xec, 0x00, 0x01, 0x00, 0x00, // subq $256, %rsp 0x48, 0x8d, 0x65, 0xf8, // leaq -8(%rbp), %rsp 0x5b, // popq %rbx 0x5d, // popq %rbp 0xc3, // retq }; AddressRange sample_range(0x1000, sizeof(data)); UnwindPlan plan(eRegisterKindLLDB); ASSERT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(data, sizeof(data), sample_range, plan)); UnwindPlan::Row::CFAValue rsp_plus_8, rsp_plus_16, rbp_plus_16; rsp_plus_8.SetIsRegisterPlusOffset(k_rsp, 8); rsp_plus_16.SetIsRegisterPlusOffset(k_rsp, 16); rbp_plus_16.SetIsRegisterPlusOffset(k_rbp, 16); EXPECT_EQ(rsp_plus_8, plan.GetRowForFunctionOffset(0)->GetCFAValue()); EXPECT_EQ(rsp_plus_16, plan.GetRowForFunctionOffset(1)->GetCFAValue()); for (size_t i = 4; i < sizeof(data) - 2; ++i) EXPECT_EQ(rbp_plus_16, plan.GetRowForFunctionOffset(i)->GetCFAValue()) << "i: " << i; EXPECT_EQ(rsp_plus_8, plan.GetRowForFunctionOffset(sizeof(data) - 1)->GetCFAValue()); } + +// Give the disassembler random bytes to test that it doesn't exceed +// the bounds of the array when run under clang's address sanitizer. +TEST_F(Testx86AssemblyInspectionEngine, TestDisassemblyJunkBytes) { + AddressRange sample_range; + UnwindPlan unwind_plan(eRegisterKindLLDB); + std::unique_ptr engine32 = Geti386Inspector(); + std::unique_ptr engine64 = Getx86_64Inspector(); + + uint8_t data[] = { + 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + + sample_range = AddressRange(0x1000, sizeof(data)); + + EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly( + data, sizeof(data), sample_range, unwind_plan)); + + unwind_plan.Clear(); + + EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly( + data, sizeof(data), sample_range, unwind_plan)); + +} + Index: vendor/lldb/dist/www/architecture.html =================================================================== --- vendor/lldb/dist/www/architecture.html (revision 320966) +++ vendor/lldb/dist/www/architecture.html (nonexistent) @@ -1,294 +0,0 @@ - - - - - -LLDB Architecture - - - -
- The LLDB Debugger -
- -
-
- - - -
-
-

Architecture

-
- -

LLDB is a large and complex codebase. This section will help you become more familiar with - the pieces that make up LLDB and give a general overview of the general architecture.

-
- -
-
-

Code Layout

-
- -

LLDB has many code groupings that makeup the source base:

- -
- -
- -
-

API

-
- -

The API folder contains the public interface to LLDB.

-

We are currently vending a C++ API. In order to be able to add - methods to this API and allow people to link to our classes, - we have certain rules that we must follow:

-
    -
  • Classes can't inherit from any other classes.
  • -
  • Classes can't contain virtual methods.
  • -
  • Classes should be compatible with script bridging utilities like swig.
  • -
  • Classes should be lightweight and be backed by a single member. Pointers (or shared pointers) are the preferred choice since they allow changing the contents of the backend without affecting the public object layout.
  • -
  • The interface should be as minimal as possible in order to give a complete API.
  • -
-

By adhering to these rules we should be able to continue to - vend a C++ API, and make changes to the API as any additional - methods added to these classes will just be a dynamic loader - lookup and they won't affect the class layout (since they - aren't virtual methods, and no members can be added to the - class).

-
- -
- -
-

Breakpoint

-
- -

A collection of classes that implement our breakpoint classes. - Breakpoints are resolved symbolically and always continue to - resolve themselves as your program runs. Whether settings breakpoints - by file and line, by symbol name, by symbol regular expression, - or by address, breakpoints will keep trying to resolve new locations - each time shared libraries are loaded. Breakpoints will of course - unresolve themselves when shared libraries are unloaded. Breakpoints - can also be scoped to be set only in a specific shared library. By - default, breakpoints can be set in any shared library and will continue - to attempt to be resolved with each shared library load.

-

Breakpoint options can be set on the breakpoint, - or on the individual locations. This allows flexibility when dealing - with breakpoints and allows us to do what the user wants.

-
- -
- -
-

Commands

-
- -

The command source files represent objects that implement - the functionality for all textual commands available - in our command line interface.

-

Every command is backed by a lldb_private::CommandObject - or lldb_private::CommandObjectMultiword object.

-

lldb_private::CommandObjectMultiword are commands that - have subcommands and allow command line commands to be - logically grouped into a hierarchy.

-

lldb_private::CommandObject command line commands - are the objects that implement the functionality of the - command. They can optionally define - options for themselves, as well as group those options into - logical groups that can go together. The help system is - tied into these objects and can extract the syntax and - option groupings to display appropriate help for each - command.

-
- -
- -
-

Core

-
- -

The Core source files contain basic functionality that - is required in the debugger. A wide variety of classes - are implemented:

- -
    -
  • Address (section offset addressing)
  • -
  • AddressRange
  • -
  • Architecture specification
  • -
  • Broadcaster / Event / Listener
  • -
  • Communication classes that use Connection objects
  • -
  • Uniqued C strings
  • -
  • Data extraction
  • -
  • File specifications
  • -
  • Mangled names
  • -
  • Regular expressions
  • -
  • Source manager
  • -
  • Streams
  • -
  • Value objects
  • -
-
- -
- -
-

DataFormatters

-
- -

A collection of classes that implement the data formatters subsystem.

- -

For a general user-level introduction to data formatters, you can look here. -

A 10,000 foot view of the data formatters is based upon the DataVisualization class. - DataVisualization is the very high level entry point into the data formatters. It vends a stable interface in face of changing internals - and is the recommended entry point for components of LLDB that need to ask questions of the data formatters. - The main questions one can ask of DataVisualization are: -

    -
  • given a ValueObject, retrieve the formatters to be used for it
  • -
  • given a type, retrieve the formatters to be used for it. This is not an "exact" question, - i.e. one can retrieve a formatter from a type name which would not be used to then format ValueObjects of that type
  • -
  • given a name, retrieve a category of that name, optionally creating it if needed - more generally, categories management
  • -
  • given an identifier and a summary, store it as a named summary - more generally, named summary management
  • -
- -

For people actively maintaining the data formatters subsystem itself, however, the FormatManager class is the relevant point of entry. - This class is subject to more frequent changes as the formatters evolve. Currently, it provides a thin caching layer on top of a list of categories - that each export a group of formatters. -

-

From an end-user perspective, the "type" LLDB command is the point of access to the data formatters. A large group of generally-useful formatters - is provided by default and loaded upon debugger startup. -

- -
- -
-

Expression

-
- -

Expression parsing files cover everything from evaluating - DWARF expressions, to evaluating expressions using - Clang.

-

The DWARF expression parser has been heavily modified to - support type promotion, new opcodes needed for evaluating - expressions with symbolic variable references (expression local variables, - program variables), and other operators required by - typical expressions such as assign, address of, float/double/long - double floating point values, casting, and more. The - DWARF expression parser uses a stack of lldb_private::Value - objects. These objects know how to do the standard C type - promotion, and allow for symbolic references to variables - in the program and in the LLDB process (expression local - and expression global variables).

-

The expression parser uses a full instance of the Clang - compiler in order to accurately evaluate expressions. - Hooks have been put into Clang so that the compiler knows - to ask about identifiers it doesn't know about. Once - expressions have be compiled into an AST, we can then - traverse this AST and either generate a DWARF expression - that contains simple opcodes that can be quickly re-evaluated - each time an expression needs to be evaluated, or JIT'ed - up into code that can be run on the process being debugged.

-
- -
- -
-

Host

-
- -

LLDB tries to abstract itself from the host upon which - it is currently running by providing a host abstraction - layer. This layer involves everything from spawning, detaching, - joining and killing native in-process threads, to getting - current information about the current host.

-

Host functionality includes abstraction layers for:

-
    -
  • Mutexes
  • -
  • Conditions
  • -
  • Timing functions
  • -
  • Thread functions
  • -
  • Host target triple
  • -
  • Host child process notifications
  • -
  • Host specific types
  • -
-
- -
- -
-

Interpreter

-
- -

The interpreter classes are the classes responsible for - being the base classes needed for each command object, - and is responsible for tracking and running command line - commands.

-
- -
- -
-

Symbol

-
-

Symbol classes involve everything needed in order to parse - object files and debug symbols. All the needed classes - for compilation units (code and debug info for a source file), - functions, lexical blocks within functions, inlined - functions, types, declaration locations, and variables - are in this section.

-
- -
- -
-

Target

-
- -

Classes that are related to a debug target include:

-
    -
  • Target
  • -
  • Process
  • -
  • Thread
  • -
  • Stack frames
  • -
  • Stack frame registers
  • -
  • ABI for function calling in process being debugged
  • -
  • Execution context batons
  • -
-
- -
- -
-

Utility

-
- -

Utility files should be as stand alone as possible and - available for LLDB, plug-ins or related - applications to use.

-

Files found in the Utility section include:

-
    -
  • Pseudo-terminal support
  • -
  • Register numbering for specific architectures.
  • -
  • String data extractors
  • -
-
- -
-
-
-
- - Property changes on: vendor/lldb/dist/www/architecture.html ___________________________________________________________________ Deleted: svn:executable ## -1 +0,0 ## -* \ No newline at end of property Index: vendor/lldb/dist/www/architecture/index.html =================================================================== --- vendor/lldb/dist/www/architecture/index.html (revision 320966) +++ vendor/lldb/dist/www/architecture/index.html (revision 320967) @@ -1,281 +1,298 @@ LLDB Architecture
LLDB's Architecture

Architecture

LLDB is a large and complex codebase. This section will help you become more familiar with the pieces that make up LLDB and give a general overview of the general architecture.

Code Layout

LLDB has many code groupings that makeup the source base:

API

The API folder contains the public interface to LLDB.

We are currently vending a C++ API. In order to be able to add methods to this API and allow people to link to our classes, we have certain rules that we must follow:

  • Classes can't inherit from any other classes.
  • Classes can't contain virtual methods.
  • Classes should be compatible with script bridging utilities like swig.
  • Classes should be lightweight and be backed by a single member. Pointers (or shared pointers) are the preferred choice since they allow changing the contents of the backend without affecting the public object layout.
  • The interface should be as minimal as possible in order to give a complete API.

By adhering to these rules we should be able to continue to vend a C++ API, and make changes to the API as any additional methods added to these classes will just be a dynamic loader lookup and they won't affect the class layout (since they aren't virtual methods, and no members can be added to the class).

Breakpoint

A collection of classes that implement our breakpoint classes. Breakpoints are resolved symbolically and always continue to resolve themselves as your program runs. Whether settings breakpoints by file and line, by symbol name, by symbol regular expression, or by address, breakpoints will keep trying to resolve new locations each time shared libraries are loaded. Breakpoints will of course unresolve themselves when shared libraries are unloaded. Breakpoints can also be scoped to be set only in a specific shared library. By default, breakpoints can be set in any shared library and will continue to attempt to be resolved with each shared library load.

Breakpoint options can be set on the breakpoint, or on the individual locations. This allows flexibility when dealing with breakpoints and allows us to do what the user wants.

Commands

The command source files represent objects that implement the functionality for all textual commands available in our command line interface.

Every command is backed by a lldb_private::CommandObject or lldb_private::CommandObjectMultiword object.

lldb_private::CommandObjectMultiword are commands that have subcommands and allow command line commands to be logically grouped into a hierarchy.

lldb_private::CommandObject command line commands are the objects that implement the functionality of the command. They can optionally define options for themselves, as well as group those options into logical groups that can go together. The help system is tied into these objects and can extract the syntax and option groupings to display appropriate help for each command.

-

Core

-
- -

The Core source files contain basic functionality that - is required in the debugger. A wide variety of classes - are implemented:

- -
    -
  • Address (section offset addressing)
  • -
  • AddressRange
  • -
  • Architecture specification
  • -
  • Broadcaster / Event / Listener
  • -
  • Communication classes that use Connection objects
  • -
  • Uniqued C strings
  • -
  • Data extraction
  • -
  • File specifications
  • -
  • Mangled names
  • -
  • Regular expressions
  • -
  • Source manager
  • -
  • Streams
  • -
  • Value objects
  • -
-
- +

Core

+
+

+ The Core source files contain basic functionality + that is required in the debugger as well as the + class represeting the debugger it self (Debugger). A + wide variety of classes are implemented: +

+
    +
  • Address (section offset addressing)
  • +
  • AddressRange
  • +
  • Architecture specification
  • +
  • Broadcaster / Event / Listener
  • +
  • Communication classes that use Connection objects
  • +
  • Mangled names
  • +
  • Source manager
  • +
  • Value objects
  • +
+
+

DataFormatters

A collection of classes that implement the data formatters subsystem.

Data formatters provide a set of user-tweakable hooks in the ValueObjects world that allow to customize presentation aspects of variables. While users interact with formatters mostly through the type command, inside LLDB there are a few layers to the implementation: DataVisualization at the highest end of the spectrum, backed by classes implementing individual formatters, matching rules, ...

For a general user-level introduction to data formatters, you can look here.

More details on the architecture are to be found here.

Expression

Expression parsing files cover everything from evaluating DWARF expressions, to evaluating expressions using Clang.

The DWARF expression parser has been heavily modified to support type promotion, new opcodes needed for evaluating expressions with symbolic variable references (expression local variables, program variables), and other operators required by typical expressions such as assign, address of, float/double/long double floating point values, casting, and more. The DWARF expression parser uses a stack of lldb_private::Value objects. These objects know how to do the standard C type promotion, and allow for symbolic references to variables in the program and in the LLDB process (expression local and expression global variables).

The expression parser uses a full instance of the Clang compiler in order to accurately evaluate expressions. Hooks have been put into Clang so that the compiler knows to ask about identifiers it doesn't know about. Once expressions have be compiled into an AST, we can then traverse this AST and either generate a DWARF expression that contains simple opcodes that can be quickly re-evaluated each time an expression needs to be evaluated, or JIT'ed up into code that can be run on the process being debugged.

-

Host

-
- -

LLDB tries to abstract itself from the host upon which - it is currently running by providing a host abstraction - layer. This layer involves everything from spawning, detaching, - joining and killing native in-process threads, to getting - current information about the current host.

-

Host functionality includes abstraction layers for:

-
    -
  • Mutexes
  • -
  • Conditions
  • -
  • Timing functions
  • -
  • Thread functions
  • -
  • Host target triple
  • -
  • Host child process notifications
  • -
  • Host specific types
  • -
-
- +

Host

+
+

+ LLDB tries to abstract itself from the host upon which + it is currently running by providing a host abstraction + layer. This layer includes functionality, whose + implementation varies wildly from host to host. +

+

Host functionality includes abstraction layers for:

+
    +
  • Information about the host system (triple, list of running processes, etc.)
  • +
  • Launching processes
  • +
  • Various OS primitives like pipes and sockets
  • +
+

+ It also includes the base classes of the + NativeProcess/Thread hierarchy, which is used by + lldb-server. +

+
+

Interpreter

The interpreter classes are the classes responsible for being the base classes needed for each command object, and is responsible for tracking and running command line commands.

Symbol

Symbol classes involve everything needed in order to parse object files and debug symbols. All the needed classes for compilation units (code and debug info for a source file), functions, lexical blocks within functions, inlined functions, types, declaration locations, and variables are in this section.

Target

Classes that are related to a debug target include:

  • Target
  • Process
  • Thread
  • Stack frames
  • Stack frame registers
  • ABI for function calling in process being debugged
  • Execution context batons
-

Utility

-
- -

Utility files should be as stand alone as possible and - available for LLDB, plug-ins or related - applications to use.

-

Files found in the Utility section include:

-
    -
  • Pseudo-terminal support
  • -
  • Register numbering for specific architectures.
  • -
  • String data extractors
  • -
-
- +

Utility

+
+

+ This module contains the lowest layers of LLDB. A + lot of these classes don't really have anything to + do with debugging -- they are just there because the + higher layers of the debugger use these clasess + to implement their functionality. Others are data + structures used in many other parts of the debugger + (TraceOptions). Most of the functionality in this + module could be useful in an application that is + not a debugger; however, providing + a general purpose C++ library is an explicit + non-goal of this module. +

+

+ This module provides following functionality: +

+
    +
  • Abstract path manipulation (FileSpec)
  • +
  • Data buffers (DataBuffer, DataEncoder, DataExtractor)
  • +
  • Logging
  • +
  • Structured data manipulation (JSON)
  • +
  • Streams
  • +
  • Timers
  • +
  • etc.
  • +
+

+ For historic reasons, some of this functionality + overlaps that which is provided by the LLVM support + library. +

+
+
Index: vendor/lldb/dist/www/sidebar.incl =================================================================== --- vendor/lldb/dist/www/sidebar.incl (revision 320966) +++ vendor/lldb/dist/www/sidebar.incl (revision 320967) @@ -1,58 +1,58 @@