LLDB equivalent of GDB's macros - objective-c

I have a very useful macro defined in .gdbinit
define rc
call (int)[$arg0 retainCount]
end
Is there anyway to define the same macro for lldb ?

You can do that with the following command definition in lldb:
command regex rc 's/(.+)/print (int)[%1 retainCount]/'
Example:
(lldb) rc indexPath
print (int)[indexPath retainCount]
(int) $2 = 2
You can put that into ~/.lldbinit (and restart Xcode).
One should think that something like
command alias rc print (int)[%1 retainCount]
should work, but as explained in I can't get this simple LLDB alias to work the %1 expansion does not work with expression, and command regex is a workaround.

Incidentally, on architectures where function arguments are passed in registers (x86_64, armv7), lldb defines a series of register aliases that map to the register used to pass the integral values -- arg1, arg2, etc. For instance,
#include <stdio.h>
int main ()
{
char *mytext = "hello world\n";
puts (mytext);
return 0;
}
and we can easily see what argument is passed in to puts without having to remember the ABI conventions,
4 char *mytext = "hello world\n";
-> 5 puts (mytext);
6 return 0;
7 }
(lldb) p mytext
(char *) $0 = 0x0000000100000f54 "hello world\n"
(lldb) br se -n puts
Breakpoint created: 2: name = 'puts', locations = 1, resolved = 1
(lldb) c
Process 2325 resuming
Process 2325 stopped
libsystem_c.dylib`puts:
-> 0x7fff99ce1d9a: pushq %rbp
0x7fff99ce1d9b: movq %rsp, %rbp
0x7fff99ce1d9e: pushq %rbx
0x7fff99ce1d9f: subq $56, %rsp
(lldb) p/x $arg1
(unsigned long) $2 = 0x0000000100000f54
(lldb)
x86_64 and armv7 both pass the first "few" integral values in registers - beyond that they can get stored on the stack or other places and these aliases don't work. lldb doesn't currently provide similar convenience aliases for floating point arguments. But for the most common cases, this is covers what people need.

Related

What's the protocol for calling Raku code from C code?

2023 update The last person to edit this Q deleted the critically important "LATEST LATEST UPDATE" part that #zentrunix had added near the top. I'm reinstating it.
LATEST LATEST UPDATE
Please see my answer below.
Thanks to everyone who took the time to answer and understand this question.
Original question
Say I have my event-driven TCP communications library in C.
From my Raku application, I can call a function in the C library using NativeCall.
my $server = create-server("127.0.0.1", 4000);
Now, from my callback in C (say onAccept) I want to call out to a Raku function in my application (say on-accept(connection) where connection will be a pointer to a C struct).
So, how can I do that: call my Raku function on-accept from my C function onAccept ?
ps. I tried posting using a simple title "How to call Raku code from C code", but for whatever reason stackoverflow.com wouldn't let me do it. Because of that I concocted this fancy title.
I was creating a 32-bit DLL.
We have to explicitly tell CMake to configure a 64-bit build.
cmake -G "Visual Studio 14 2015 Win64" ..
Anyway, now that the code runs, it's not really what I asked for, because the callback is still in C.
It seems that what I asked for it's not really possible.
I tried to use the approach suggested by Haakon, though I'm afraid I don't understand how it would work.
I'm in Windows, and unfortunately, Raku can't find my dlls, even if I put them in C:\Windows\System32. It finds "msvcrt" (C runtime), but not my dlls.
The dll code (Visual Studio 2015).
#include <stdio.h>
#define EXPORTED __declspec(dllexport)
typedef int (*proto)(const char*);
proto raku_callback;
extern EXPORTED void set_callback(proto);
extern EXPORTED void foo(void);
void set_callback(proto arg)
{
printf("In set_callback()..\n");
raku_callback = arg;
}
void foo(void)
{
printf("In foo()..\n");
int res = raku_callback("hello");
printf("Raku return value: %d\n", res);
}
Cmake code for the
CMAKE_MINIMUM_REQUIRED (VERSION 3.1)
add_library (my_c_dll SHARED my_c_dll.c)
Raku code.
use v6.d;
use NativeCall;
sub set_callback(&callback (Str --> int32))
is native("./my_c_dll"){ * }
sub foo()
is native("./my_c_dll"){ * }
sub callback(Str $str --> Int) {
say "Raku callback.. got string: {$str} from C";
return 32;
}
## sub _getch() returns int32 is native("msvcrt") {*};
## print "-> ";
## say "got ", _getch();
set_callback(&callback);
# foo();
When I run
$ raku test-dll.raku
Cannot locate native library '(null)': error 0xc1
in method setup at D:\tools\raku\share\perl6\core\sources
\947BDAB9F96E0E5FCCB383124F923A6BF6F8D76B (NativeCall) line 298
in block set_callback at D:\tools\raku\share\perl6\core\sources
\947BDAB9F96E0E5FCCB383124F923A6BF6F8D76B (NativeCall) line 594
in block <unit> at test-dll.raku line 21
Raku version.
$ raku -v
This is Rakudo version 2020.05.1 built on MoarVM version 2020.05
implementing Raku 6.d.
Another approach could be to save a callback statically in the C library, for example (libmylib.c):
#include <stdio.h>
static int (*raku_callback)(char *arg);
void set_callback(int (*callback)(char * arg)) {
printf("In set_callback()..\n");
raku_callback = callback;
}
void foo() {
printf("In foo()..\n");
int res = raku_callback("hello");
printf("Raku return value: %d\n", res);
}
Then from Raku:
use v6;
use NativeCall;
sub set_callback(&callback (Str --> int32)) is native('./libmylib.so') { * }
sub foo() is native('./libmylib.so') { * }
sub callback(Str $str --> Int) {
say "Raku callback.. got string: {$str} from C";
return 32;
}
set_callback(&callback);
foo();
Output:
In set_callback()..
In foo()..
Raku callback.. got string: hello from C
Raku return value: 32
Raku is a compiled language; depending on the implementation you've got, it will be compiled to MoarVM, JVM or Javascript. Through compilation, Raku code becomes bytecode in the corresponding virtual machine. So it's never, actually, binary code.
However, Raku code seems to be cleverly organized in a way that an object is actually a pointer to a C endpoint, as proved by Haakon Hagland answer.
WRT to your latest problem, please bear in mind that what you are calling is not a path, but a name that is converted to a navive shared library name and also uses local library path conventions to look for them (it's `PATH' on Windows). So if it's not finding it, add local path to it of simply copy the DLL to one of the searched directories.
First of all, my apologies to #Håkon and #raiph.
Sorry for being so obtuse. :)
Håkon's answer does indeed answer my question, although for whatever reason I have failed to see that until now.
Now the code I played with in order to understand Håkon's solution.
// my_c_dll.c
// be sure to create a 64-bit dll
#include <stdio.h>
#define EXPORTED __declspec(dllexport)
typedef int (*proto)(const char*);
proto raku_function;
extern EXPORTED void install_raku_function(proto);
extern EXPORTED void start_c_processing(void);
void install_raku_function(proto arg)
{
printf("installing raku function\n");
raku_function = arg;
}
void start_c_processing(void)
{
printf("* ----> starting C processing..\n");
for (int i = 0; i < 100; i++)
{
printf("* %d calling raku function\n", i);
int res = raku_function("hello");
printf("* %d raku function returned: %d\n", i, res);
Sleep(1000);
}
}
# test-dll.raku
use v6.d;
use NativeCall;
sub install_raku_function(&raku_function (Str --> int32))
is native("./my_c_dll.dll") { * }
sub start_c_processing()
is native("./my_c_dll.dll") { * }
sub my_raku_function(Str $str --> Int)
{
say "# raku function called from C with parameter [{$str}]";
return 32;
}
install_raku_function &my_raku_function;
start { start_c_processing; }
for ^1000 -> $i
{
say "# $i idling in raku";
sleep 1;
}
$ raku test-dll.raku
installing raku function
# 0 idling in raku
* ----> starting C processing..
* 0 calling raku function
# 0 raku function called from C with parameter [hello]
* 0 raku function returned: 32
# 1 idling in raku
* 1 calling raku function
# 1 raku function called from C with parameter [hello]
* 1 raku function returned: 32
# 2 idling in raku
* 2 calling raku function
# 2 raku function called from C with parameter [hello]
* 2 raku function returned: 32
# 3 idling in raku
* 3 calling raku function
# 3 raku function called from C with parameter [hello]
* 3 raku function returned: 32
# 4 idling in raku
* 4 calling raku function
# 4 raku function called from C with parameter [hello]
* 4 raku function returned: 32
# 5 idling in raku
* 5 calling raku function
# 5 raku function called from C with parameter [hello]
* 5 raku function returned: 32
^CTerminate batch job (Y/N)?
^C
What amazes me is that the Raku signature for my_raku_function maps cleanly to the C signature ... isn't Raku wonderful ? :)

Stange behavior with my C string reverse function

I'm just an amateur programmer...
And when reading, for the second time, and more than two years apart, kochan's "Programming in Objective-C", now the 6th ed., reaching the pointer chapter i tried to revive the old days when i started programming with C...
So, i tried to program a reverse C string function, using char pointers...
At the end i got the desired result, but... got also a very strange behavior, i cannot explain with my little programming experience...
First the code:
This is a .m file,
#import <Foundation/Foundation.h>
#import "*pathToFolder*/NSPrint.m"
int main(int argc, char const *argv[])
{
#autoreleasepool
{
char * reverseString(char * str);
char *ch;
if (argc < 2)
{
NSPrint(#"No word typed in the command line!");
return 1;
}
NSPrint(#"Reversing arguments:");
for (int i = 1; argv[i]; i++)
{
ch = reverseString(argv[i]);
printf("%s\n", ch);
//NSPrint(#"%s - %s", argv[i], ch);
}
}
return 0;
}
char * reverseString(char * str)
{
int size = 0;
for ( ; *(str + size) != '\0'; size++) ;
//printf("Size: %i\n", size);
char result[size + 1];
int i = 0;
for (size-- ; size >= 0; size--, i++)
{
result[i] = *(str + size);
//printf("%c, %c\n", result[i], *(str + size));
}
result[i] = '\0';
//printf("result location: %lu\n", result);
//printf("%s\n", result);
return result;
}
Second some notes:
This code is compiled in a MacBook Pro, with MAC OS X Maverick, with CLANG (clang -fobjc-arc $file_name -o $file_name_base)
That NSPrint is just a wrapper for printf to print a NSString constructed with stringWithFormat:arguments:
And third the strange behavior:
If I uncomment all those commented printf declarations, everything work just fine, i.e., all printf functions print what they have to print, including the last printf inside main function.
If I uncomment one, and just one, randomly chosen, of those comment printf functions, again everything work just fine, and I got the correct printf results, including the last printf inside main function.
If I leave all those commented printf functions as they are, I GOT ONLY BLANK LINES with the last printf inside main block, and one black line for each argument passed...
Worst, if I use that NSPrint function inside main, instead of the printf one, I get the desired result :!
Can anyone bring some light here please :)
You're returning a local array, that goes out of scope as the function exits. Dereferencing that memory causes undefined behavior.
You are returning a pointer to a local variable of the function that was called. When that function returns, the memory for the local variable becomes invalid, and the pointer returned is rubbish.

Why is LLDB using the wrong field of my struct for arithmetic?

I'm using a struct from cocos3d called CC3IntPoint:
typedef struct {
GLint x; /**< The X-componenent of the point. */
GLint y; /**< The Y-componenent of the point. */
} CC3IntPoint;
When I run my program, it looks normal in the debugger:
(lldb) p pos
(CC3IntPoint) $5 = {
(GLint) x = 48
(GLint) y = 91
}
(lldb) p pos.y
(GLint) $6 = 91
However, if I do any math on pos.y, it uses pos.x! For example:
(lldb) p pos.y+1
(int) $7 = 49
(lldb) p pos.y*1
(int) $8 = 48
Am I missing something obvious here? Any ideas on how to fix?
That looks very much like a bug.
Please file it.
I'd say this is some kind of pointer arithmetic magic, but I can't imagine that is the case.
If you really want to explore the issue, I would suggest grabbing the address of various sub-experssions and seeing if you can find where it decides to grab the wrong field.
See Jason's comment on the original question; that should really be the answer.

Use LEA (LEAL) to create an x86 assembly counter

I'm trying to make an assembly program that adds together an unknown number of int's, like
sum(int a,int b, ...)
My code is
.globl notnull
notnull:
leal 4(%esp),%ebx
jmp next2
next:
leal 4(%ebx),%ebx
next2:
cmp $0,(%ebx)
je end
movl (%ebx),%eax
jmp next
end:
ret
I test it with this program:
#include <stdio.h>
extern int notnull();
int main()
{
int x=notnull(3,2,1,0);
printf("3,2,1,0 = %d\n",x);
x=notnull(2,1,0);
printf("2,1,0 = %d\n",x);
x=notnull(1,0);
printf("1,0 = %d\n",x);
x=notnull(0);
printf("0 = %d\n",x);
x=notnull();
printf("_ = %d\n",x);
return 0;
}
Wich gives me this output:
3,2,1,0 = 1 (#1)
2,1,0 = 1 (#2)
1,0 = 1 (#3)
0 = 8 (#4)
_ = 8 (#5)
What I want is the program to return 0 when there are no variables (see #5), and also make it work without having to have 0 as the last digit.
The perfect output of notnull(3,2) would 2 and notnull()=0
You need to read up on C argument passing conventions.
Basically, there is no way to automatically determine how many arguments are being passed to a function.
This is why all C functions either have a fixed number of arguments, or if they use variable arguments (varargs) they have one fixed argument before the variable part, which somehow expresses how many additional arguments are being passed.
Using an empty argument list makes it possible to validly call the function in any manner, but it doesn't help with the core problem of (in the function) determining how many arguments are available.
You might be able to figure it out by inspecting the stack, but of course that requires intimate knowledge of exactly how your particular compiler choses to implement the call. This might vary for different number of arguments, too.

Getting around LLDB printing problems e.g. CLLocationCoordinate2D and recognizing Macros in debugger

LLDB has various problems printing struct fields of double type, as documented here:
strange-behavior-in-lldb-when-printing-a-double-type-struct-member.
In my own case I tried to print a struct of type CLLocationCoordinate2D. As of Xcode 4.5.2 the error in printing CLLocationCoordinate2D persists.
Looking for ways around this bug I came across a nice macro, LOG_EXPR, in this blog:
http://vgable.com/blog/2010/08/19/the-most-useful-objective-c-code-ive-ever-written/
It does a great job of logging types into the debugger, but can't be called from the debugger.
Has anyone figured out a way to do something like LOG_EXPR while debugging in the LLDB command line interface, or any other improved printing that will work on arbitrary structs from the command line, other than switching back to GDB?
Here's what happens when I type in LLDB:
(lldb) p (CLLocationCoordinate2D)[self mapSetPointLatLon]
(CLLocationCoordinate2D) $4 = {
(CLLocationDegrees) latitude = 42.4604
(CLLocationDegrees) longitude = 42.4604
(double) easting = 42.4604
(double) northing = -71.5179
}
Notice the redundant and wrong lines added by lldb.
Here's what happens (at the same breakpoint) when I compile LOG_EXPR into my code:
Line of Code (not debugger):
LOG_EXPR(self.mapSetPointLatLon);
produces the correct output in the debugger output:
2013-01-26 14:02:17.555 S6E11[79116:c07] self.mapSetPointLatLon = {latitude=42.4604,longitude=-71.5179}
At the same breakpoint if I try to invoke LOG_EXPR from the command line, this is what happens:
(lldb) expr LOG_EXPR(self.mapSetPointLatLon);
error: use of undeclared identifier 'LOG_EXPR'
error: 1 errors parsing expression
(lldb)
Here's another example, since it turns out there is a case when you can get the debugger to do the right thing.
Here's my code fragment where I assign the struct 2 ways:
CLLocationCoordinate2D defloc = CLLocationCoordinate2DMake(kStartingLat, kStartingLon);
[[self.verticalPagingViewController mapPagingViewController] setMapSetPointLatLon: defloc];
If I just print the variable it works.
(lldb) p defloc
(CLLocationCoordinate2D) $1 = {
(CLLocationDegrees) latitude = 42.4604
(CLLocationDegrees) longitude = -71.5179
}
If I'm casting the type of the return value of an accessor method, it fails.
(lldb) p (CLLocationCoordinate2D)[[self.verticalPagingViewController mapPagingViewController] mapSetPointLatLon]
(CLLocationCoordinate2D) $2 = {
(CLLocationDegrees) latitude = 0
(CLLocationDegrees) longitude = 0
(double) easting = 0
(double) northing = 0
}