lldb: Displaying array as hex - lldb

In lldb is it possible to display a uint8_t array of bytes in a concatenated hex?
For instance the default behaviour for displaying the uint256 type described here is
{
[14] = '['
[15] = '\xbf'
[16] = '('
[17] = '\xc3'
[18] = 'O'
[19] = ':'
[20] = '^'
[21] = '3'
[22] = '*'
[23] = '\x1f'
[24] = '\xc7'
[25] = '\xb2'
[26] = '\xb7'
[27] = '<'
[28] = '\xf1'
[29] = '\x88'
[30] = '\x91'
[31] = '\x0f'
}
by running type summary add --summary-string "${var.data[0-31]%x}" uint256 I can display it like this:
[0x06,0x22,0x6e,0x46,0x11,0x1a,0x0b,0x59,0xca,0xaf,0x12,0x60,0x43,0xeb,0x5b,0xbf,0x28,0xc3,0x4f,0x3a,0x5e,0x33,0x2a,0x1f,0xc7,0xb2,0xb7,0x3c,0xf1,0x88,0x91,0x0f]
but I wanted something like this:
0x06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f

I can't think of a way to do this with the summary string formatters. We do some special purpose magic like this for char[] but that's behind the %s specifier which you don't want.
However, it is fairly easy to write a python summary to do this. Here's a simple example for the type uint8_t [32]:
def unvector_32 (valobj,internal_dict):
str = "0x"
for i in range(0,31):
str += ("%x"%(valobj.GetChildAtIndex(i).GetValueAsUnsigned())).zfill(2)
return str
def __lldb_init_module(debugger, internal_dict):
debugger.HandleCommand('type category define -e my_formatters')
debugger.HandleCommand('type summary add -w my_formatters -F %s.unvector_32 "uint8_t [32]" -v'%(__name__))
Put that in a .py file somewhere (I put all these in ~/.lldb) and do:
(lldb) com scr imp ~/.lldb/my_formatters.py
either in your lldb session or in your ~/.lldbinit. Then you will see:
(lldb) fr v data
(uint8_t [32]) data = 0x01020304050600000000000000000000000000000000000000000000000000
(lldb)
I think that's roughly the output you wanted. To apply this to the uint256 class you can change the match type to "uint256" when you add the summary, and have the summary function first get the data member using GetChildMemberWithName("data") then print the individual vector elements. You could also use a regex match against uint([0-9]+) and then get the number of elements in data with the GetNumChildren call if you want the formatter to be more general...
BTW, I find it handy to put all my formatters in a category so I can list them easily (type summary list -w my_formatters) and turn them all off easily if I've messed something up...
More on the SB API's is here:
http://lldb.llvm.org/python_reference/index.html

You can change formate of lldb debugger to another format
type format add -f bytes uint8_t
Bytes format to use
uiint8_t type to apply format on
For more details Link :- https://lldb.llvm.org/use/variable.html

Related

Problem to convert Array of a string to ruby object

I tried to pass array of string to use puts in ruby print it value with math operator. But get the wrong result. I thingk it need to convert to object to achieve this as follow.
my_string_array = ["100*(4+1)"]
my_string = my_string_array.join(' ') # => "100*(4+1)"
my_ruby_valuation = my_string.to_i # => 100 (Wrong)
What I expected is
puts my_ruby_valuation #=> 500
You should use eval kernel function.
https://apidock.com/ruby/Kernel/eval
my_string_array = ["100*(4+1)"]
eval(my_string_array[0])
I hope this helps.

Create a multidimensional symbolic array in Matlab 2013b

According to the Matlab R2016a documentation, a symbolic multidimensional array can be comfortably created by using the sym command as follows:
A = sym('a',[2 2 2])
and the output is
A(:,:,1) =
[ a1_1_1, a1_2_1;
a2_1_1, a2_2_1]
A(:,:,2) =
[ a1_1_2, a1_2_2;
a2_1_2, a2_2_2]
However, I'm using Matlab 2013b and this command doesn't work for multiple dimensions. Is there any other way to create such variables for the 2013b version?
I'm not yet using R2016a, but looking around the code for the sym class (type edit sym in your Command Window), it's not too hard to write one's own function to do this:
function s = ndSym(x,a)
a = a(:).';
format = repmat('%d_',[1 numel(a)]);
x = [x format(1:end-1)];
s = cellfun(#createCharArrayElement,num2cell(1:prod(a)),'UniformOutput',false);
s = sym(reshape(s,a));
function s = createCharArrayElement(k)
[v{1:numel(a)}] = ind2sub(a,k);
s = sprintf(x,v{:});
end
end
You can the test it via A = ndSym('A',[2 2 2]), which returns:
A(:,:,1) =
[ A1_1_1, A1_2_1]
[ A2_1_1, A2_2_1]
A(:,:,2) =
[ A1_1_2, A1_2_2]
[ A2_1_2, A2_2_2]
This function should work for arrays with an arbitrary number of dimensions. I tested it in R2013b and R2015b. However, note that the function above doesn't incorporate any input validation and many of the options/niceties supported by sym. These could be added. Also, be aware that many pre-R2016a symbolic math functions may not support such multi-dimensional arrays.

Formatting a byte array as a C-89 initializer expression in LLDB

I have an array which is initialized with a regular C89 initializer:
uint8_t data[] = {0x05,0x48,0x45,0x4c,0x4c,0x4f,0x01,0x00 ... }
When I print this array in lldb, I get this monstrosity:
(lldb) p data
(uint8_t [200]) $0 = {
[0] = '\x05'
[1] = 'H'
[2] = 'E'
[3] = 'L'
[4] = 'L'
[5] = 'O'
[6] = '\x01'
...
I'm trying to coerce lldb's output into the original C89 syntax so I can simply paste contents of the array from lldb back into my code (e.g. so I can write unit tests that use arrays I catch during debugging).
How can I tell lldb to format its output to look like a normal C89 initializer?
You can write a python summary printer to print the contents of the array in the correct format but the SBValue object that is passed in to the python won't have the name of the variable available.
(lldb) type summ add uint8_t[] -P
[...]
print '{',
for i in xrange(0, valobj.GetNumChildren()):
print '0x%02x' % valobj.GetChildAtIndex(i).GetValueAsUnsigned(),
if (i != valobj.GetNumChildren() - 1):
print ',',
print '};'
DONE
(lldb) p data
{ 0x05 , 0x48 , 0x45 , 0x4c , 0x4c , 0x4f , 0x01 , 0x00 };
(uint8_t [8]) $1 = {
[0] = 0x05
[1] = 0x48
[2] = 0x45
[3] = 0x4c
[4] = 0x4c
[5] = 0x4f
[6] = 0x01
[7] = 0x00
}
Use type format add -f x uint8_t to get nearly what you want:
(lldb) p data
(uint8_t [8]) $4 = {
[0] = 0x05
[1] = 0x48
[2] = 0x45
[3] = 0x4c
[4] = 0x4c
[5] = 0x4f
[6] = 0x01
[7] = 0x00
}
You just need to add "," after each line to have a source code line (for the array) that will compile. If this is too bothersome, I suspect you will have to write something in python.
To see what other formats (besides "x" used above, which stands for hex), use help format.
EDIT: following Brandin's hint above, it turns out you can format your array in the way that you want by additionally using
(lldb) type summary add --summary-string "," uint8_t
This will add a "," after each line:
(lldb) p data
(uint8_t [8]) $3 = {
[0] = 0x05 ,
[1] = 0x48 ,
[2] = 0x45 ,
[3] = 0x4c ,
[4] = 0x4c ,
[5] = 0x4f ,
[6] = 0x01 ,
[7] = 0x00 ,
}
which you can copy & paste 1:1 into your source code (final semicolon needs to be added of course).
Another quick way to get pretty much the same thing Jason showed without having to know any Python is to use the -c and -O options to type summary add, like:
(lldb) type summary add -c -O uint8_t[]
(lldb) expr array
(uint8_t [8]) $2 = ('\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\a', '\b')
This is generally useful if you have some type that you just want to view all the elements of a structure or array "flat" like this rather than in turned out form.

textscan() reading result is a nested cell array?

I have a data file containing 100 lines with the following format
0,device1,3
1,device2,33
2,device3,3
3,device4,34
...
99,device100,36
Now I wish to read them into a 100x3 cell array in MATLAB. I did the following:
allData = textscan(fID,'%s %s %f', 'delimiter', ',');
Then, I noticed that allData is a 1x3 cell array with each item being another 100x1 cell array. (The first two columns are string-type cell arrays, whereas the third column is double-type cell array)
In other words, the reading result is a nested array, which I don't want.
How may I achieve 100x3 cell array directly while reading?
With that textscan, the variable allData looks something like (just 4 rows) this:
allData =
{4x1 cell} {4x1 cell} [4x1 double]
You can only merge into a single cell array directly with textscan via the 'CollectOutput' option when all data has the same type.
One possible workaround, which unfortunately converts all numeric data to double (not a problem in your case),
C = cell(numel(allData{1}),numel(allData));
areCells = cellfun(#iscell,allData);
C(:,areCells) = [allData{areCells}];
C(:,~areCells) = num2cell([allData{~areCells}])
C =
'0' 'device1' [ 3]
'1' 'device2' [33]
'2' 'device3' [ 3]
'3' 'device4' [34]
Again, the drawback of this is that the last statement will convert all non-cell types (e.g. uint8, char, etc.) into doubles. To avoid this possible conversion:
% after copying cell array data (areCells) as above, but before ~areCells data
Cn = arrayfun(#(ii)num2cell(allData{ii}),find(~areCells),'uni',0);
C(:,~areCells) = [Cn{:}];
Code -
sz = 100; % Line count
out=cell(sz,size(allData,2));
for k = 1:size(allData,2)
t1 = allData(k);
t2 = [t1{:}];
if isnumeric(t2) % Takes care of floats
out(:,k) = num2cell(t2);
else
out(:,k) = t2
end
end
Thus, the first four lines would be shown as -
out =
'0' 'device1' [ 3]
'1' 'device2' [33]
'2' 'device3' [ 3]
'3' 'device4' [34]

Call an input file doesn't work

I'm using Gviz library from bioconductor. I input a tab delimited file containing CNV position that I need to plot on my chromosome ideogram.
My input file is defined by dat and has 4 columns
[1] chromosome
[2] start
[3] end
[4] width (could '+' or '-' depending on the orientation of the Copy Number)
So I did that :
library(IRanges)
libraray(Gviz)
gen <- "mm9"
chr <- "chr1"
itrack <- IdeogramTrack(genome = gen, chromosome = chr)
gtrack <- GenomeAxisTrack()
dat <- read.delim("C:/R/1ips_chr1.txt", header = FALSE, sep ="\t")
s <- dat[2]
e <- dat[3]
l <- dat[4]
It shows an error message when I call the file dat :
atrack1 <- AnnotationTrack( start = s, width = l , chromosome = chr, genome = gen, name = "Sample1")
Error : function (classes, fdef, mtable) : unable to find an inherited method for function ".buildRange", for signature "NULL", "data.frame", "NULL", "data.frame"
Obviously the way I call a the inputed file (in dat) doesn't satisfy R .. Someone help me please :)
From the reference manual for the Gviz package (with which I am not familiar), the arguments start and width in the AnnotationTrack function need to be integer vectors. When you subset dat using the single square bracket [, the resulting object is a data.frame (see ?`[.data.frame` for more on this). Try instead
s <- dat[[2]]
e <- dat[[3]]
l <- dat[[4]]
to obtain integer vectors.

Resources