How to print the contents of a memory address using LLDB? - xcode

I am using LLDB and wondering how to print the contents of a specific memory address, for example 0xb0987654.

To complement Michael's answer.
I tend to use:
memory read -s1 -fu -c10000 0xb0987654 --force
That will print in the debugger.
-s for bytes grouping so use 1 for uint8 for example and 4 for int
-f for format. I inherently forget the right symbol. Just put the statement with -f and it will snap back at you and give you the list of all the options
-c is for count of bytes
if you are printing more than 1024 bytes, append with --force
Hope this helps.

Xcode has a very nice Memory Browser window, which will very nicely display the contents of memory addresses. It also lets you control byte grouping and number of bytes displayed, and move back or forward a memory page:
You can access it by pressing ⌘^⌥⇧M. After entering it, press enter to open the memory browser in the main editor.
or
Debug --> Debug Workflow --> View Memory
Notice the field on its bottom left corner where you can paste the memory address you want to inspect!
Documentation here: https://developer.apple.com/library/ios/recipes/xcode_help-debugger/articles/viewing_memory.html
Related answer here: How do I open the memory browser in Xcode 4?

"me" is the command you're looking for.
For example, this lldb command:
me -r -o /tmp/mem.txt -c512 0xb0987654
will copy 512 bytes from your memory address into a file at /tmp/mem.txt.

for example, print memory of length 16x4 bytes.
x/16 0xb0987654

Here's a simple trick for displaying typed arrays of fixed-length in lldb. If your program contains a long* variable that points to 9 elements, you can declare a struct type that contains a fixed array of 9 long values and cast the pointer to that type:
long *values = new long[9]{...};
(lldb) expr typedef struct { long values[9]; } l9; *(l9 *)values
(l9) $1 = {
values = {
[0] = 0
[1] = 1
[2] = 4
[3] = 9
[4] = 16
[5] = 25
[6] = 36
[7] = 49
[8] = 64
}
}
I use the typedef when I'm coding in C, it's not needed in C++.

Related

SDL Keyboard Handling.

SDL is a hardware abstraction layer, so it's understandable that it would map whatever the local system keys are onto a virtual keyboard.
Their wiki has this entry; https://wiki.libsdl.org/SDL_Keycode
But it never seems to take modifier keys into account when reporting the event, so that this code:
if(e.type==SDL_KEYDOWN)
{
std::cout << SDL_GetKeyName(e.key.keysym.sym) << ":" << e.key.keysym.sym << std::endl;
}
Generates this result: (UK Keyboard)
Input: 1 causes output: 1:49
Input: 2 causes output: 2:50
Input: 3 causes output: 3:51
Input: 4 causes output: 4:52
Input: Shift+1 (!) causes output: 1:49
Input: Shift+2 (") causes output: 2:50
Input: Shift+3 (£) causes output: 3:51
Input: Shift+4 ($) causes output: 4:52
Yes, I understand that I can do something like this; SDL_Keymod _keystate = SDL_GetModState(); And take each key case by case. But that would limit it to my keyboard layoyt, would be ugly code, and quite frankly would make almost everything on this page worthless; https://wiki.libsdl.org/SDL_Keycode.
So. What am I missing, it obviously isn't applying modifiers by default? Is there a way to get it do so?

Reading freely available UVR data using gfortran on mac OSX

I would like to use fortran to read ultraviolet radiation data that has been produced by the Japan Aerospace Exploration Agency. This data is at a daily and monthly temporal resolution from 2000-2010 at a ~5 km spatial resolution. This question is worth answering as the data could be useful for a number of environment/health projects and is freely available, with proper acknowledgement of source and sharing of preprint of any subsequent publications, from:
ftp://suzaku.eorc.jaxa.jp/pub/GLI/glical/Global_05km/monthly/uvb/
There is a readme file available, which provides instructions on how to read data using fortran as follows:
Instructions for _le files
Header
Read header (size= pixel size *2byte):
character head*14400
read(10,rec=1) head
read(head,'(2i6,2f8.2,f8.4,2e12.5,a1,a8,a1,a40)')
& npixel,nline,lon_min,lat_max,reso,slope,offset,',',
& para,',',outfile
Read data (e.g., fortran77)
parameter(nl=7200, ml=3601)
... open file by "unformatted", "recl=nl*2(byte)" (,"bytereclen")
integer*2 i2buf(nl,ml)
do m=1,ml
read(10,rec=1+m) (i2buf(n,m), n=1,nl)
do n=1,nl
par=i2buf(n,m)*slope+offset
write(6,*) 'PAR[Ein/m^2/day]=',par
enddo
enddo
slope values
par__le : daily PAR [Ein/m^2/day] = DN * 0.01
dpar_le : direct PAR = DN * 0.01
swr__le : daily mean shortwave radiation [W/m^2] = DN * 0.01
tip__le : transmittance of instantaneous PAR at noon = DN * 0.0001
uva__le : daily mean UVA [W/m^2] = DN * 0.001
uvb__le : daily mean UVB [W/m^2] = DN * 0.0001
rpar_le : PAR-range surface reflectance (TOP of canopy/solid surfaces) = DN * 0.0001 (monthly data only)
error values
-1 as signed short integer (int16)
65535 as unsigned short integer (uint16)
Progress so far
I have downloaded and installed gfortran successfully on mac OSX. I have downloaded a test file (MOD02SSH_A20000224Av6_v601_7200_3601_uvb__le.gz) and decompressed it. I have created a program file:
PROGRAM readuvr
IMPLICIT NONE
!some code
END PROGRAM
I will then type the following into the command line to create an executable and run it to extract the data.
gfortran -o executable
./executable
As a complete beginner to fortran, my question is: how can I use the instructions provided to build a program that can read the data and output it into a text file?
Well, that file expands to 51,868,800 bytes. The comments imply the header is 14,400 bytes, which leaves 51,854,400 bytes of actual data payload.
There seem to be 7200 lines of data, so that means there are 7202 bytes per line. There seem to be 2 bytes (16-bit samples) so if we assume 2 bytes/sample, that means there are 3601 samples per line, which matches the ml=3601.
So basically, you need to read 14,400 bytes of header, then 7200 lines of data, each line consisting of 3601 values, each of those being 2 bytes wide...
Actually, if you are that unfamiliar with FORTRAN, you may like to extract the data with Perl which is already installed and available on OS X anyway. I have started a VERY SIMPLISTIC Perl program that reads the dat and prints the first 2 values on each line:
#!/usr/bin/perl
use strict;
use warnings;
# Read 14,400 bytes of header
my $buffer;
my $nBytes = 14400;
my $bytesRead = read (STDIN, $buffer, $nBytes) ;
my ($npixel,$nline,$lon_min,$lat_max,$reso,$slope,$offset,$junk)=split(' ',$buffer);
print "npixel:$npixel\n";
print "nline:$nline\n";
print "lon_min:$lon_min\n";
print "lat_max:$lat_max\n";
print "reso:$reso\n";
print "slope:$slope\n";
$offset =~ s/,.*//; # strip trailing comma and junk
print "offset:$offset\n";
# Read actual lines of data
my $line;
for(my $m=1;$m<=$nline;$m++){
read(STDIN,$line,$npixel*2);
my $x=$npixel*2;
my #values=unpack("S$x",$line);
printf "Line: %d",$m;
for(my $j=0;$j<2;$j++){
printf ",%f",$values[$j]*$slope+$offset;
}
printf "\n"; # newline
}
Save it as go.pl and then in the Terminal, type the following once to make it executable
chmod +x go.pl
and then run it like this
./go.pl < MOD02SSH_A20000224Av6_v601_7200_3601_uvb__le
Sample output extract:
npixel:7200
nline:3601
lon_min:0.00
lat_max:90.00
reso:0.0500
slope:0.10000E-03
offset:0.00000E+00
...
...
Line: 3306,0.099800,0.099800
Line: 3307,0.099900,0.099900
Line: 3308,0.099400,0.074200
Line: 3309,0.098900,0.098900
Line: 3310,0.098400,0.098400
Line: 3311,0.074300,0.074200
Line: 3312,0.071300,0.071200
fortran (f2003 or so) solution. (The linked instructions are awful by the way )
implicit none
character*80 para,outfile
character(len=:),allocatable::header,infile
integer npixel,nline,blen,i
c note kind=2 is not standard. This needs to be a 2-byte integer.
integer(kind=2),allocatable :: data(:,:)
real lon_min,lat_max,reso,slope,off
c header is plain text, so first open formatted and
c directly read header data
infile='MOD02SSH_A20000224Av6_v601_7200_3601_uvb__le'
open(10,file=infile)
read(10,*)npixel,nline,lon_min,lat_max,reso,slope,off,
$ para,outfile
close(10)
write(*,*)npixel,nline,lon_min,lat_max,reso,slope,off,
$ trim(para),' ',trim(outfile)
blen=2*npixel
allocate(character(len=blen)::header)
allocate(data(npixel,nline))
if( sizeof(data(1,1)).ne.2 )then
write(*,*)'error kind=2 did not give a 2 byte integer'
stop
endif
c now close and reopen for binary read.
c direct access approach:
open(20,file=infile,access='direct',recl=blen/4)
c note the granularity of the recl= specifier is not standard.
c ifort uses 4 bytes. (note this will break if npixel is not even )
read(20,rec=1)header
write(*,*)trim(header)
do i=1,nline
read(20,rec=i+1)data(:,i)
enddo
c note streams if available is simpler: (we don't need to know rec len )
c open(20,file=infile,access='stream')
c read(20)header,data
end
This is not actually validated because I don't have known file content to compare against.

lldb - How to display float with decimals using "type format add"

I have a variable of type float. Xcode displays it using scientific notation (i.e. 3.37626e+07). I'm trying to get it to display using dot notation (i.e. 33762616.00).
I've tried every format provided by lldb, but none displays the float using decimals. I read other posts and watched the WWDC2012 session 415 (as suggested here), but I must be too close the forest to see the trees. Any help would be greatly appreciated!
Try adding a custom data formatter in your ~/.lldbinit file for type float. e.g.
Process 13204 stopped
* thread #1: tid = 0xb6f8d, 0x0000000100000f33 a.out`main + 35 at a.c:5, stop reason = step over
#0: 0x0000000100000f33 a.out`main + 35 at a.c:5
2 int main ()
3 {
4 float f = 33762616.0;
-> 5 printf ("%f\n", f);
6 }
(lldb) p f
(float) $0 = 3.37626e+07
(lldb) type summ add -v -o "return '%f' % valobj.GetData().GetFloat(lldb.SBError(), 0)" float
(lldb) p f
(float) $1 = 33762616.000000
(lldb)
The default set of formatters provided by lldb can't do this, but dropping into Python allows you a lot of flexibility.

reading file with UPC

I'm starting to learn UPC, and I have the following piece of code to read a file:
upc_file_t *fileIn;
int n;
fileIn = upc_all_fopen("input_small", UPC_RDONLY | UPC_INDIVIDUAL_FP , 0, NULL);
upc_all_fread_local(fileIn, &n, sizeof(int), 1, UPC_IN_ALLSYNC | UPC_OUT_ALLSYNC);
upc_barrier;
printf("%d\n", n);
upc_all_fclose(fileIn);
However, the output (value of n) is always 808651319, which means something is wrong, and I can't find what is it. The first line of the file I'm giving as input is '7', so the result of the printf should be 7...
Any idea why this happens?
Thanks in advance!
UPC Parallel I/O library performs unformatted (binary) input/output, not formatted one like what you get with (f)printf(3)/(f)scanf(3) from the standard C library. Parallel I/O cannot handle text files because of their intrinsic properties like variable-length records.
upc_all_fread_local(fileIn, &n, sizeof(int), 1, UPC_IN_ALLSYNC | UPC_OUT_ALLSYNC)
behaves like the following call to the standard C library function for unformatted read from a file:
fread(&n, sizeof(int), 1, fh)
You are just reading 1 element of sizeof(int) bytes from the file (4 bytes on most platforms) into the address of n. The number you got 808651319 in hexadecimal is 0x30330A37. On little endian systems like x86/x64 this is stored in memory and on disk as 0x37 0x0A 0x33 0x30 (reversed byte order). These are the ASCII codes of the first 4 bytes of the string 7\n30 (\n or LF is the line feed/new line symbol) so I'd guess your input_small file looked like:
7
30...
...
You should prepare your input data in binary format using fwrite(3) instead of using (f)printf(3) or your text editor of choice.

Interpreting valgrind error Invalid write of size 4

I was recently trying to track down some bugs in a program I am working on using valgrind, and one of the errors I got was:
==6866== Invalid write of size 4
==6866== at 0x40C9E2: superneuron::read(_IO_FILE*) (superneuron.cc:414)
the offending line # 414 reads
amplitudes__[points_read] = 0x0;
and amplitudes__ is defined earlier as
uint32_t * amplitudes__ = (uint32_t* ) amplitudes;
Now obviously a uint32_t is 4 bytes long, so this is the write size, but could someone tell me why it's invalid ?
points_read is most likely out of bounds, you're writing past (or before) the memory you allocated for amplitudes.
A typical mistake new programmers do to get this warning is:
struct a *many_a;
many_a = malloc(sizeof *many_a * size + 1);
and then try to read or write to the memory at location 'size':
many_a[size] = ...;
Here the allocation should be:
many_a = malloc(sizeof *many_a * (size + 1));

Resources