How to call methods or execute code in LLDB debugger? - xcode

I know I can type print someFloatVariable when I set a breakpoint or po [self someIvarHoldingAnObject], but I can't do useful things like:
[self setAlpha:1];
Then it spits out:
error: '[self' is not a valid command.
Weird thing is that I can call po [self someIvarHoldingAnObject] and it will print it's description.
I believe I've seen a video a year ago where someone demonstrated how to execute code through the console at runtime, and if I am not mistaken this guy also provided arguments and assigned objects to pointers. How to do that?

The canonical reference for gdb v. lldb commands is http://lldb.llvm.org/lldb-gdb.html
You want to use the expr command which evaluates an expression. It's one of the lldb commands that takes "raw input" in addition to arguments so you often need a "--" to indicate where the arguments (to expr) end and the command(s) begin. e.g.
(lldb) expr -- [self setAlpha:1]
There is a shortcut, "p", which does the -- for you (but doesn't allow any arguments), e.g.
(lldb) p [self setAlpha:1]
If the function(s) you're calling are not part of your program, you'll often need to explicitly declare their return type so lldb knows how to call them. e.g.
(lldb) p printf("hi\n")
error: 'printf' has unknown return type; cast the call to its declared return type
error: 1 errors parsing expression
(lldb) p (int)printf("hi\n")
(int) $0 = 3
hi
(lldb)
There is a neat way to work around the floating point argument problem, BTW. You create an "expression prefix" file which is added to every expression you enter in lldb, with a prototype of your class methods. For instance, I have a class MyClass which inherits from NSObject, it has two methods of interest, "setArg:" and "getArg" which set and get a float ivar. This is a silly little example, but it shows how to use it. Here's a prefix file I wrote for lldb:
#interface NSObject
#end
#interface MyClass : NSObject
- init;
- setArg: (float)arg;
- (float) getArg;
#end
extern "C" {
int strcmp (const char *, const char *);
int printf(const char * __restrict, ...);
void puts (const char *);
}
in my ~/.lldbinit file I add
settings set target.expr-prefix /Users/jason/lldb-prefix.h
and now I can do
(lldb) p [var getArg]
(float) $0 = 0.5
(lldb) p [var setArg:0.7]
(id) $1 = 0x0000000100104740
(lldb) p [var getArg]
(float) $2 = 0.7
You'll notice I included a couple of standard C library functions in here too. After doing this, I don't need to cast the return types of these any more, e.g.
(lldb) p printf("HI\n")
<no result>
HI
(lldb) p strcmp ("HI", "THERE")
(int) $3 = -12
(a fix for that "<no result>" thing has been committed to the lldb TOT sources already.)

If you need multiline, use expression:
expression
do {
try thing.save()
} catch {
print(error)
}
// code will execute now
Blank line to finish and execute the code.

Related

LLDB stop at breakpoint while expr function

for example
void foo()
{
int a = 0;
printf("%d",a);
}
I set a breakpoint at foo function, and then use expr to evaluate it, it just run the function, didn't stop at breakpoint.
(lldb) br set -n foo
(lldb) expr foo()
Is there a way to run any function/code while lldb breakpoint still working?
Yes, I found expr has a option --ignore-breakpoints
expr --ignore-breakpoints false -- foo()
will be working

risk of compile warning

I have mainly two kinds of compile warning:
1. implicit declaration of function
in a.c, it has char *foo(char *ptr1, char *ptr2), in b.c, some functions use this foo function without any declaration, and I found seems compiler will treat the function foo return value as integer, and even I can pass some variables less or more than foo function declaration
2. enumerated type mixed with another type
My target chip is ARM11, it seems that even I don't solve these two kinds of compile warning, my program can run without any issues, but I believe it must have some risk behind these. Can anyone give me some good example that these two kinds of compile warning can cause some unexpected issues?
Meanwhile, if these two warnings have potential risk, why c compiler allow these kinds warning happen but not set them to error directly? any story behind?
Implicit declaration. E.g. you have function: float foo(float a), which isn't declared when you call it. Implicit rules will create auto-declaration with following signature: int foo(double) (if passed argument is float). So value you pass will be converted to double, but foo expects float. The same with return - calling code expects int, but returned float. Values would be a complete mess.
enum mixed with other type. Enumerated type have list of values it could take. If you trying to assign numeric value to it, there is a chance that it isn't one of listed values; if later your code expects only specified range and presumes nothing else could be there - it could misbehave.
Simple example:
File: warn.c
#include <stdio.h>
double foo(double x)
{
return myid(x);
}
int
main (void)
{
double x = 1.0;
fprintf (stderr, "%lg == %lg\n", x, foo (x));
return 0;
}
File: foo.c
double
myid (double x)
{
return x;
}
Compile and run:
$ gcc warn.c foo.c -Wall
warn.c: In function ‘foo’:
warn.c:5: warning: implicit declaration of function ‘myfabs’
$ ./a.out
1 == 0
Old C standard (C90) had this strange "default int" rule and for compatibility it is supported even in latest compilers.

GCC: Customizing printf for string output

GCC allows customization of printf specifiers. However, I don't see how I can "teach" it to accept my string class for %s specifier. My string class is a simple wrapper over char pointer and has exactly one member variable (char * data) and no virtual functions. So, it's kind of ok to pass it as-is to printf-like functions in place of regular char *. The problem is that on gcc static analyzer prevents me from doing so and I have to explicitly cast it to const char * to avoid warnings or errors.
My cstring looks something like this:
class cstring
{
cstring() : data(NULL){}
cstring(const char * str) : data(strdup(str)){}
cstring(const cstring & str) : data(strdup(str.data)){}
~cstring()
{
free(data);
}
...
const char * c_str() const
{
return data;
}
private:
char * data;
};
Example code that uses cstring:
cstring str("my string");
printf("str: '%s'", str);
On GCC I get this error:
error: cannot pass objects of non-trivially-copyable type 'class cstring' through '...'
error: format '%s' expects argument of type 'char*', but argument 1 has type 'cstring' [-Werror=format]
cc1plus.exe: all warnings being treated as errors
The C++ standard doesn't require compilers to support this sort of code, and not all versions of gcc support it. (https://gcc.gnu.org/onlinedocs/gcc/Conditionally-supported-behavior.html suggests that gcc-6.0 does, at least - an open question whether it will work with classes such as the one here.)
The relevant section in the C++11 standard is 5.2.2 section 7:
When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the argument by invoking va_arg ...
Passing a potentially-evaluated argument of class type (Clause 9)
having a non-trivial copy constructor, a non-trivial move constructor,
or a non-trivial destructor, with no corresponding parameter, is
conditionally-supported with implementation-defined semantics.
(But look on the bright side: if you get into the habit of using c_str, then at least you won't get tripped up when/if you use std::string.)

Portable getopt_long equivalent for use in shell scripting

I would like to parse long options in a shell script. POSIX only provides getopts to parse single letter options. Does anyone know of a portable (POSIX) way to implement long option parsing in the shell? I've looked at what autoconf does when generating configure scripts, but the result is far from elegant. I can live with accepting only the full spellings of long options. Single letter options should still be allowed, possibly in groups.
I'm thinking of a shell function taking a space separated list of args of the form option[=flags], where the flags indicate that the option takes an arg or can be specified multiple times. Unlike its C counterpart there is no need to distinguish between strings, integers and floats.
Design notes towards a portable shell getopt_long command
I have a program getoptx which works with single-letter options (hence it is not the answer to your problem), but it handles arguments with spaces correctly, which the original getopt command (as opposed to the shell built-in getopts) does not. The specification in the source code says:
/*
** Usage: eval set -- $(getoptx abc: "$#")
** eval set -- $(getoptx abc: -a -c 'a b c' -b abc 'd e f')
** The positional parameters are:
** $1 = "-a"
** $2 = "-c"
** $3 = "a b c"
** $4 = "-b"
** $5 = "--"
** $6 = "abc"
** $7 = "d e f"
**
** The advantage of this over the standard getopt program is that it handles
** spaces and other metacharacters (including single quotes) in the option
** values and other arguments. The standard code does not! The downside is
** the non-standard invocation syntax compared with:
**
** set -- $(getopt abc: "$#")
*/
I recommend the eval set -- $(getopt_long "$optspec" "$#") notation for your getopt_long.
One major issue with getopt_long is the complexity of the argument specification — the $optspec in the example.
You may want to look at the notation used in the Solaris CLIP (Command Line Interface Paradigm) for the notation; it uses a single string (like the original getopt() function) to describe the options. (Google: 'solaris clip command line interface paradigm'; using just 'solaris clip' gets you to video clips.)
This material is a partial example derived from Sun's getopt_clip():
/*
Example 2: Check Options and Arguments.
The following example parses a set of command line options and prints
messages to standard output for each option and argument that it
encounters.
This example can be expanded to be CLIP-compliant by substituting the
long string for the optstring argument:
While not encouraged by the CLIP specification, multiple long-option
aliases can also be assigned as shown in the following example:
:a(ascii)b(binary):(in-file)(input)o:(outfile)(output)V(version)?(help)
*/
static const char *arg0 = 0;
static void print_help(void)
{
printf("Usage: %s [-a][-b][-V][-?][-f file][-o file][path ...]\n", arg0);
printf("Usage: %s [-ascii][-binary][-version][-in-file file][-out-file file][path ...]\n", arg0);
exit(0);
}
static const char optstr[] =
":a(ascii)b(binary)f:(in-file)o:(out-file)V(version)?(help)";
int main(int argc, char **argv)
{
int c;
char *filename;
arg0 = argv[0];
while ((c = getopt_clip(argc, argv, optstr)) != -1)
{
...
}
...
}

GCC error when compiling: "lvalue required as left operand of assignment" with function pointer

I have a C code which records a procedure address in an array
void* lpProcAddress[5];
typedef unsigned long (*MyFunction_TYPE) (void*);
#define MyFunctionInArray ( (MyFunction_TYPE) lpProcAddress[0] )
unsigned long AnyFunction ( void* lpPointerToAny )
{
/* Some Code */
return 0;
}
int main()
{
MyFunctionInArray =
AnyFunction; // Displays: "error: lvalue required as left operand of assignment"
}
GCC displays "error: lvalue required as left operand of assignment".
How can I fix this?
For my purpose, I could not call directly AnyFunction().
This will expand to:
(type)xxx = ...
This is not legal. However, you could use something like:
* (type *)& xxx = ...
Try assigning to lpProcAddress[0] directly instead of to MyFunctionInArray.
This should work and you can just keep it that way.
However, if you are interested in why it did not work with your define keep reading, there is a way to do that too:
What you are doing in your #define is cast a pointer-type to MyFunction_TYPE
1) you dont really need to cast the pointer-array to anything, you can just assign the function-pointers into its slots
2) if you really want to cast the pointer-array before assigning into it you have to cast it to a function-pointer-type (and do that before dereferencing so use parenthesis before [0]).
Instead of defining lpProcAddress as void* why not just define as MyFunction_TYPE, e.g.:
typedef unsigned long (*MyFunction_TYPE) (void*);
MyFunction_TYPE lpProcAddress[5];
Then in your main function you can just do:
lpProcAddress[0] = AnyFunction;
Without needing to care about casting.
Likewise to call the function you can then just do:
result = lpProcAddress[0]( some_ptr );

Resources