+@lldb_command('savekcdata', 'T:O:')
+def SaveKCDataToFile(cmd_args=None, cmd_options={}):
+ """ Save the data referred by the kcdata_descriptor structure.
+ options:
+ -T: <task_t> pointer to task if memory referenced is in userstask.
+ -O: <output file path> path to file to save data. default: /tmp/kcdata.<timestamp>.bin
+ Usage: (lldb) savekcdata <kcdata_descriptor_t> -T <task_t> -O /path/to/outputfile.bin
+ """
+ if not cmd_args:
+ raise ArgumentError('Please provide the kcdata descriptor.')
+
+ kcdata = kern.GetValueFromAddress(cmd_args[0], 'kcdata_descriptor_t')
+
+ outputfile = '/tmp/kcdata.{:s}.bin'.format(str(time.time()))
+ task = None
+ if '-O' in cmd_options:
+ outputfile = cmd_options['-O']
+ if '-T' in cmd_options:
+ task = kern.GetValueFromAddress(cmd_options['-T'], 'task_t')
+
+ memory_begin_address = unsigned(kcdata.kcd_addr_begin)
+ memory_size = 16 + unsigned(kcdata.kcd_addr_end) - memory_begin_address
+ flags_copyout = unsigned(kcdata.kcd_flags)
+ if flags_copyout:
+ if not task:
+ raise ArgumentError('Invalid task pointer provided.')
+ memory_data = GetUserDataAsString(task, memory_begin_address, memory_size)
+ else:
+ data_ptr = kern.GetValueFromAddress(memory_begin_address, 'uint8_t *')
+ if data_ptr == 0:
+ print "Kcdata descriptor is NULL"
+ return False
+ memory_data = []
+ for i in range(memory_size):
+ memory_data.append(chr(data_ptr[i]))
+ if i % 50000 == 0:
+ print "%d of %d \r" % (i, memory_size),
+ memory_data = ''.join(memory_data)
+
+ if len(memory_data) != memory_size:
+ print "Failed to read {:d} bytes from address {: <#020x}".format(memory_size, memory_begin_address)
+ return False
+
+ fh = open(outputfile, 'w')
+ fh.write(memory_data)
+ fh.close()
+ print "Saved {:d} bytes to file {:s}".format(memory_size, outputfile)
+ return True
+