How to create a call graph of an iOS app? - ios

I'm looking for a relatively simple way of creating a call graph of an iOS app (or a framework), using it's Xcode project or the obj code it emits.
The project files are a combination of Objective C, Swift and C++.
I've already tried clang's scan-build, but haven't had any luck turning the .dot files into graphViz graphs. I ended up with hundreds of .dot files and after dot, for over an hour, tries to load them up, nothing happens.
I've also tried to use opt, by adding this to my build line:
-S -emit-llvm -o - | opt -dot-callgraph -S
(from this SO question
but I get only a 107 byte callgraph.dot file and that doesn't have anything notable in it.
I think these errors are what make the output useless:
clang-5.0: warning: 'linker' input unused [-Wunused-command-line-argument]
clang-5.0: warning: argument unused during compilation: '-emit-llvm' [-Wunused-command-line-argument]

Related

How do I tell clang memory sanitizer to ignore data from certain libraries?

For example I'd like to ignore sqlite and zlib because I know they're well tested. I grabbed the zpipe.c example and built it like this. Keep in mind I'm using -lz and not building zlib myself. I'm only building zpipe myself and want to limit the sanitize to that one file
clang -g -fsanitize=undefined,memory zpipe.c -lz
I ran echo Test | ./a.out and I got the following error
Uninitialized bytes in __interceptor_fwrite at offset 0 inside [0x7ffd61230bc0, 13)
==50435==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x55767941cd85 in def /tmp/zlib-1.2.12/examples/zpipe.c:70:17
#1 0x55767941e709 in main /tmp/zlib-1.2.12/examples/zpipe.c:186:15
#2 0x7f65e834e30f in __libc_start_call_main libc-start.c
#3 0x7f65e834e3c0 in __libc_start_main#GLIBC_2.2.5 (/usr/lib/libc.so.6+0x2d3c0)
#4 0x5576793981d4 in _start (/tmp/zlib-1.2.12/examples/a.out+0x211d4)
SUMMARY: MemorySanitizer: use-of-uninitialized-value /tmp/zlib-1.2.12/examples/zpipe.c:70:17 in def
Is there a way I can say assume any data that goes in and out of zlib or sqlite to be safe to use? I'll be linking both and only want to sanitize my own code
You can use an ignore list file. https://clang.llvm.org/docs/SanitizerSpecialCaseList.html
Usage:
clang -fsanitize=address -fsanitize-ignorelist=ignorelist.txt foo.c
See the documentation for details on the format of the file.

Some exported symbols disappear after creating a dynamic framework with the ios_framework rule

I am facing quite a strange situation trying to build a mixed-language dynamic iOS framework with Bazel.
The source code of the framework consists of *.c, *.cpp, *.m, *.mm, *.h, *.hpp files.
My first naive attempt was to declare a single objc_library rule referencing all the sources. That failed with an error message reading something about conflicting rules. Then I declared four distinct objc_library rules for *.m, *.mm, *.c, and *.cpp files respectively, and then referenced all these four rules as dependencies for the final ios_framework rule.
At this point, everything compiled and linked just fine (barring several compiler warnings which were expected). However, now the black magic begins:
The static library resulting from compiling ObjectiveC++ sources does contain all the necessary symbols (verified with the "nm" tool)
The .apple_binary_lipobin file resulting from the linking phase does not contain symbols from ObjectiveC++ sources
I believe I carefully went through the command lines used for compiling and linking, both for Bazel and xcodebuild.
The only anomalies I was able to spot:
xcodebuild passes a -single_module argument when linking, while Bazel cross tool does not.
Bazel cross tool adds '-stdlib=libc++' '-std=gnu++11' command line arguments when invoking wrapped_clang_pp during linking, while xcodebuild does not pass these arguments. I guess Bazel does this because there're these lines in the default Apple CROSSTOOL:
action_config {
config_name: "objc++-executable"
action_name: "objc++-executable"
tool {
tool_path: "wrapped_clang_pp"
execution_requirement: "requires-darwin"
}
flag_set {
flag_group {
flag: "-stdlib=libc++"
flag: "-std=gnu++11"
}
but I am not sure if these flags are really needed when invoking the linker.
I must admit I've run out of ideas except for trying to patch the CROSSTOOl file to make it behave as close as xcodebuild as possible.
Please help.
Can you try adding alwayslink = 1 to the objc_library target containing the C++ symbols? The linker is deadstripping the C++ symbols as they are not being referenced anywhere in the binary.

My Lex code receiving segmentation fault (core dump) at line *yy_cp = yy_hold_char

Here a snippet of generated .c code from .Lex.
And the Coredump is coming at the very first Iteration
while (1) /* loops until end-of-file is reached */{
yy_cp = yy_c_buf_p;
/* Support of yytext. */
*yy_cp = yy_hold_char; // receiving coredump here
/* yy_bp points to the position in yy_ch_buf of the start of
* the current run.*/
yy_bp = yy_cp;
yy_current_state = yy_start;}
Here you can find code
I have answer of my own question. Here are some explanation of Solution
I have two .Lex (Type1_Lex.l & Type2_Lex.l)and two .Yacc (Type1_Yacc.y & Type2_Yacc.y) code
I am compiling all and relevant .c (Type1_Lex.c, Type2_Lex.c, Type1_Yacc.c & Type2_Yacc.v) and .h files are getting generated
And further compilation of .c with generates Type1_Lex.o, Type2_Lex.o, Type1_Yacc.o Type2_Yacc.o
Further I am putting all these object files in a single .a
The Problems are Here
...
ld: Warning: size of symbol `yy_create_buffer' changed from 318 in libuperbe.a(TYPE1_Lex.o) to 208 in libxxx.a (TYPE2_Lex.o)
ld: Warning: size of symbol `yy_load_buffer_state' changed from 262 in libuperbe.a(TYPE1_Lex.o) to 146 in libxxx.a(TYPE2_Lex.o)
ld: Warning: size of symbol `yy_init_buffer' changed from 278 in libuperbe.a(TYPE1_Lex.o) to 164 in libxxx.a(TYPE2_Lex.o)
Some symbols are same in both generated .c (TYPE1_Lex.c & TYPE2_Lex.c)
When both object file bind in a single .a the similar
(yy_create_buffer,yy_init_buffer,yy_load_buffer_state) symbols got
overridden.
At the runtime when the methods yy_create_buffer(),yy_init_buffer(), yy_load_buffer_state() should be called defined in TYPE2_Lex.c but in actual those methods are called from the file TYPE1_Lex.c and the leads to the memory corruption some how.
For moving ahead I decided to use sed with following patterns :
Sed TYPE2_Lex.c with :
s/yy_create_buffer()/TYPE1_create_buffer/g
s/yy_init_buffer()/TYPE1_init_buffer/g
s/yy_load_buffer_state()/TYPE1_load_buffer_state/g
Sed TYPE2_Lex.c with
s/yy_create_buffer()/TYPE2_create_buffer/g
s/yy_init_buffer()/TYPE2_init_buffer/g
s/yy_load_buffer_state()/TYPE2_load_buffer_state/g
So that the Loader can easily differentiate the symbol. And at the run time confusion between the methods name become null.
After all these Step I am able to move ahead :)
Thanks all for your help :)

Why can't I set a breakpoint in my library?

the goal is to debug a method deep within a library.
We can debug c functions in that same library (as long as they are not in the .m files), but apparently no Objective-C code, or even c code within any .m file.
When I try to set breakpoints manually, (break set -n), I get:
WARNING: Unable to resolve breakpoint to any actual locations.
The code does get called, the trusty logger confirms that.
My hunch is that debugging information gets lost somewhere along the way: We are building a static library, then another static library ("Framework" style), and finally we are linking this into our app. Yes, that's complicated but, historical reasons, you know.
I have tried to examine the first .a file to see what is going on, but when I try to load it into lldb I have to create a target. And target creation fails for either architecture:
target create -d --arch i386 libFoo.a
error: 'libFoo.a' doesn't contain the architecture i386
target create -d --arch armv7 libFoo.a
error: 'libFoo.a' doesn't contain any 'remote-ios' platform architectures: arm64, armv7, armv7f, armv7k, armv7s, armv7m, armv7em, armv6m, armv6, armv5, armv4, arm, thumbv7, thumbv7k, thumbv7s, thumbv7f, thumbv7m, thumbv7em, thumbv6m, thumbv6, thumbv5, thumbv4t, thumb
lipo -info libFoo.a
Architectures in the fat file: libFoo.a are: armv7 i386
Does anyone have a good idea how to best tackle this issue? The code is definitely linked, working, but lldb can not set breakpoints.
Thanks a lot
Addendum:
I have created the most simple setup I could think of, and I see very, very odd results:
If I try to lookup certain things, some will return a file and a line number, others will not:
image lookup -s Foo::faz()
1 symbols match 'Foo::faz()' in […]/Build/Products/Debug-iphoneos/Test.app/Test:
Address: Test[0x00010334] (Test.__TEXT.__text + 22060)
Summary: Test'Foo::faz() at Foo.cpp:858
image lookup -s FazBar
1 symbols match 'FazBar' in […]/Build/Products/Debug-iphoneos/Test.app/Test:
Address: Test[0x00038eb4] (Test.__TEXT.__text + 188844)
Summary: Test'FazBar
Trying to set breakpoints in the corresponding files yields, well, expected results:
(lldb) break set -f Foo.cpp -l 877
Breakpoint 5: where = Test'Foo::faz() + 76 at Foo.cpp:877, address = 0x000cb380
(lldb) break set -f bar.c -l 585
Breakpoint 6: no locations (pending).
WARNING: Unable to resolve breakpoint to any actual locations.
How can I dig into the .a file to see why certain files are not found?
Well, someone (actually not me, had the absolutely bright idea of setting
GCC_GENERATE_DEBUGGING_SYMBOLS = NO
somewhere hidden deep.
Setting it to yes, well, you guessed it, solves the issue
Alex
set exception break point like above
go to brekpoint navigation click on + and slecte add exception brak point
Try using DYLD_BIND_AT_LOAD environment variable set. This should disable lazy binding, which often fails to hit symbolic breaküpints

Cannot link a minimal Lua program

I have the following trivial Lua program which I copied from the book Programming In Lua
#include <stdio.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
int main (void)
{
char buff[256];
int error;
lua_State *L = luaL_newstate(); /* opens Lua */
luaL_openlibs(L); /* opens the standard libraries */
while (fgets(buff, sizeof(buff), stdin) != NULL)
{
error = luaL_loadbuffer(L, buff, strlen(buff), "line") ||
lua_pcall(L, 0, 0, 0);
if (error)
{
fprintf(stderr, "%s", lua_tostring(L, -1));
lua_pop(L, 1); /* pop error message from the stack */
}
}
lua_close(L);
return 0;
}
my environment is cywin
my make file looks like this:
CC=gcc
INCLUDE='-I/home/xyz/c_drive/Program Files/Lua/5.1/include'
LINKFLAGS='-L/home/xyz/c_drive/Program Files/Lua/5.1/lib' -llua51
li.o:li.c
$(CC) $(INCLUDE) -c li.c
main:li.o
$(CC) -o main $(LINKFLAGS) li.o
clean:
rm *.o
rm main
My /home/xyz/c_drive/Program Files/Lua/5.1/lib directory contains lua5.1.dll lua5.1.lib lua51.dll and lua51.lib
Trying to build my main target I am getting the following errors:
li.o:li.c:(.text+0x35): undefined reference to `_luaL_newstate'
li.o:li.c:(.text+0x49): undefined reference to `_luaL_openlibs'
li.o:li.c:(.text+0xaf): undefined reference to `_luaL_loadbuffer'
li.o:li.c:(.text+0xd9): undefined reference to `_lua_pcall'
li.o:li.c:(.text+0x120): undefined reference to `_lua_tolstring'
li.o:li.c:(.text+0x154): undefined reference to `_lua_settop'
li.o:li.c:(.text+0x167): undefined reference to `_lua_close'
Any ideas about what I might be doing wrong here?
The problem is that you have named the libraries on the link command line before the object files that require them. The linker loads modules from left to right on the command line. At the point on the line where you name -llua51, no undefined symbols that could be satisfied by that library are known. Then you name li.o, which does have unknown symbols.
Some Unix-like environments don't treat this as an error because part of the link process is deferred to the program load when reference to .so files are satisfied. But Cygwin, MinGW, and Windows in general must treat this as an error because DLLs work quite differently from .so files.
The solution is to put -llua51 after all the .o files on your link line.
Edit: Incidentally, it appears you are linking against the Lua for Windows distribution, but building with GCC under Cygwin. You will want to use Dependency Walker to make sure that your program does not depend on the Cygwin runtime, and that it does depend on the same C runtime as the lua51.dll from Lua for Windows. IIRC, that will be the runtime for the previous version of Visual Studio. It is possible to make GCC link against that, but you will need to be using the MinGW port (which you can use from Cygwin), and link against a couple of specific libraries to get that version. I'm away from my usual PC, or I'd quote an exact link line. (I believe you need -lmoldname -lmsvcr80 or something like that, as the last items on the link line.)
It will cause mysterious and very hard to diagnose problems if more than one C runtime library is in use. The easy answer is to use the same one as your preferred Lua DLL. Another alternative is that the Lua Binaries project has pre-compiled Lua DLLs for a wide array of C toolchains on Windows. If you need a Lua application that understands the Cygwin environment, you will want one that is built by GCC for Cygwin and not the Lua for Windows flavor. Lua Binaries will be your friend, or you can build Lua your self from source.
The names in the Lua API do not have those leading underscores. Try compiling with -fno-leading-underscore.

Resources