cedric pushed a commit to branch master.

http://git.enlightenment.org/website/www-content.git/commit/?id=37f77dca4c6fde93bb3cb8aa131e8b7d5b912c35

commit 37f77dca4c6fde93bb3cb8aa131e8b7d5b912c35
Author: Clément Bénier <clement.ben...@openwide.fr>
Date:   Thu Jun 11 14:22:32 2015 +0200

    Wiki page apps-efl-debugging created
    
    Signed-off-by: Clément Bénier <clement.ben...@openwide.fr>
    Signed-off-by: Pierre Le Magourou <pierre.lemagou...@openwide.fr>
    Signed-off-by: Cedric BAIL <ced...@osg.samsung.com>
---
 media/clouseau.png                     | Bin 0 -> 71405 bytes
 media/clouseau_object.png              | Bin 0 -> 120066 bytes
 media/settings_clouseau.png            | Bin 0 -> 25360 bytes
 pages/debugging/apps_efl_debugging.txt | 550 +++++++++++++++++++++++++++++++++
 pages/docs.txt                         |   1 +
 5 files changed, 551 insertions(+)

diff --git a/media/clouseau.png b/media/clouseau.png
new file mode 100644
index 0000000..9205e32
Binary files /dev/null and b/media/clouseau.png differ
diff --git a/media/clouseau_object.png b/media/clouseau_object.png
new file mode 100644
index 0000000..bec3198
Binary files /dev/null and b/media/clouseau_object.png differ
diff --git a/media/settings_clouseau.png b/media/settings_clouseau.png
new file mode 100644
index 0000000..a38b78b
Binary files /dev/null and b/media/settings_clouseau.png differ
diff --git a/pages/debugging/apps_efl_debugging.txt 
b/pages/debugging/apps_efl_debugging.txt
new file mode 100644
index 0000000..c7adf87
--- /dev/null
+++ b/pages/debugging/apps_efl_debugging.txt
@@ -0,0 +1,550 @@
+~~Title: Apps debugging~~
+==== EFL application debugging ====
+
+This tutorial goal is to help you debug your EFL applications with several
+use cases that you can reproduce.
+It gives you approaches to know if the bug comes from your application or
+from EFL libraries.
+
+
+In this tutorial, log level and 4 use cases will be studied:
+  - [[apps_efl_debugging#Log level]]
+  - [[apps_efl_debugging#Wrong function on an object]]
+  - [[apps_efl_debugging#Segfault in callback function]]
+  - [[apps_efl_debugging#Memory leak]]
+  - [[apps_efl_debugging#Clouseau]]
+
+Before debugging, make sure your debug symbols are enabled. If not, go to the
+[[/docs-efl-start#Enable_debug_symbols_Optional|Enable debug symbols]]
+section.
+
+You can also have a look at the
+[[https://phab.enlightenment.org/w/coding_convention/|EFL coding convention]].
+
+=== Log level ===
+
+The Eina log module provides log level traces, there are 5 debugging levels
+with their respective macros:
+
+    - Critical log level:           EINA_LOG_LEVEL_CRITICAL()
+    - Error log level:              EINA_LOG_ERR()
+    - Warning log level:            EINA_LOG_WARN()
+    - Info log level:               EINA_LOG_INFO()
+    - Debug log level:              EINA_LOG_DBG()
+
+Global log level can be set with the EINA_LOG_LEVEL environment variable.
+
+<code bash>
+#debug log level
+EINA_LOG_LEVEL=5 ./my_test_efl
+</code>
+
+The EINA_LOG_LEVELS variable provide a way to activate logs only for specific
+modules.
+
+<code bash>
+#it will set respectively module1 and module2 level to 5 and to 2
+EINA_LOG_LEVELS=module1:5,module2:2 ./my_test_efl
+</code>
+
+----
+
+=== Wrong function on an object ===
+
+The code below creates 3 Elementary objects: win, box and btn. It displays a
+window with an //OK// button that closes the window when it is clicked.
+Here, the //elm_box_pack_end()// function is called on a wrong object (win)
+which generates an error:
+
+<code c hello.c>
+//hello.c
+#include <Elementary.h>
+    static void
+on_done(void *data, Evas_Object *obj, void *event_info)
+{
+    // quit the mainloop (elm_run function will return)
+    elm_exit();
+}
+
+    EAPI_MAIN int
+elm_main(int argc, char **argv)
+{
+    Evas_Object *win, *box, *btn;
+
+    // new window
+    win = elm_win_util_standard_add("hello", "Hello");
+
+    // add a box object
+    box = elm_box_add(win);
+
+    // add object as a resize object for the window (controls window minimum
+    // size as well as gets resized if window is resized)
+    elm_win_resize_object_add(win, box);
+    evas_object_show(box);
+
+    // add a button
+    btn = elm_button_add(win);
+
+    // set default text of button to "OK"
+    elm_object_text_set(btn, "OK");
+
+    // pack the button at the end of the box
+    /****ERROR****/
+    elm_box_pack_end(win, btn); //win instead of box
+    evas_object_show(btn);
+
+    // call on_done when button is clicked
+    evas_object_smart_callback_add(win, "clicked", on_done, NULL);
+
+    //show the window
+    evas_object_show(win);
+
+    // run the mainloop and process events and callbacks
+    elm_run();
+    return 0;
+}
+ELM_MAIN()
+</code>
+
+Compile with -g flag to have debugging symbols and execute it:
+
+<code bash>
+gcc -Wall -O1 -march=native -g -ggdb3 -o hello hello.c `pkg-config --cflags 
--libs elementary`
+./hello
+ERR<13670>:eo lib/eo/eo.c:780 _eo_api_op_id_get() in elm_box.eo.c:48: unable 
to resolve regular api func 'elm_obj_box_pack_end' 0x7f1128f50faf in class 
'Elm_Win'.
+</code>
+
+Here, the error log says that the //elm_obj_box_pack_end//
+is not in the api of Elm_win, and so, that this error is coming from your
+application and not from EFL. Guessing you have a more complicated
+application, this trace is not enough to find in your code where is the
+problem. Fortunately, EFL provide a macro to provide backtraces :
+//EINA_LOG_ABORT//.
+
+In fact, a message generated by CRI macro automatically call abort() once some
+given level message is printed. This is controlled by environment variable
+//EINA_LOG_ABORT// and the level to be considered critical with
+//EINA_LOG_ABORT_LEVEL//. That is to say the program will stop at the first
+error met with these two variables.
+
+Get a backtrace with the following command:
+
+<code gdb>
+EINA_LOG_ABORT_LEVEL=4 EINA_LOG_ABORT=1 gdb hello
+(gdb) run
+Starting program: /home/efl/test/hello
+[Thread debugging using libthread_db enabled]
+Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
+[New Thread 0x7fffea2da700 (LWP 13679)]
+ERR<13675>:eo lib/eo/eo.c:780 _eo_api_op_id_get() in elm_box.eo.c:48: unable
+to resolve regular api func 'elm_obj_box_pack_end' 0x7ffff7991faf in class
+'Elm_Win'.
+
+Program received signal SIGABRT, Aborted.
+0x00007ffff6c76cc9 in __GI_raise (sig=sig@entry=6) at 
../nptl/sysdeps/unix/sysv/linux/raise.c:56
+56  ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
+(gdb) bt
+#0  0x00007ffff6c76cc9 in __GI_raise (sig=sig@entry=6) at 
../nptl/sysdeps/unix/sysv/linux/raise.c:56
+#1  0x00007ffff6c7a0d8 in __GI_abort () at abort.c:89
+#2  0x00007ffff6387919 in eina_log_print_unlocked (args=0x7fffffffdac8, 
fmt=0x7ffff561c970 "in %s:%d: unable to resolve %s api func '%s' %p in class 
'%s'.", line=780,    fnc=0x7ffff561d330 <__FUNCTION__.12409> 
"_eo_api_op_id_get", file=0x7ffff561c48c "lib/eo/eo.c", 
level=EINA_LOG_LEVEL_ERR, domain=25) at lib/eina/eina_log.c:1274
+#3  eina_log_print (domain=25, level=level@entry=EINA_LOG_LEVEL_ERR, 
file=file@entry=0x7ffff561c48c "lib/eo/eo.c", fnc=fnc@entry=0x7ffff561d330 
<__FUNCTION__.12409> "_eo_api_op_id_get", line=line@entry=780, 
fmt=fmt@entry=0x7ffff561c970 "in %s:%d: unable to resolve %s api func '%s' %p 
in class '%s'.") at lib/eina/eina_log.c:2079
+#4  0x00007ffff56122c5 in _eo_api_op_id_get 
(api_func=api_func@entry=0x7ffff7991faf <elm_obj_box_pack_end>, 
is_main_loop=is_main_loop@entry=1 '\001', file=file@entry=0x7ffff7af39cc 
"elm_box.eo.c", line=line@entry=48) at lib/eo/eo.c:778
+#5  0x00007ffff7991fe3 in elm_obj_box_pack_end 
(subobj=subobj@entry=0x80000007e0000040) at elm_box.eo.c:48
+#6  0x00007ffff79940cf in elm_box_pack_end (obj=obj@entry=0x80000003a000001e, 
subobj=subobj@entry=0x80000007e0000040) at elm_box.eo.c:223
+#7  0x0000000000400b69 in elm_main (argc=argc@entry=1, 
argv=argv@entry=0x7fffffffddb8) at hello.c:34
+#8  0x0000000000400bcd in main (argc=1, argv=0x7fffffffddb8) at hello.c:47
+</code>
+
+//elm_obj_box_pack_end// is in frame 6, so called from frame 7
+
+Go to frame 7:
+
+<code gdb>
+(gdb) fr 7
+#7  0x0000000000400b69 in elm_main (argc=argc@entry=1, 
argv=argv@entry=0x7fffffffddb8) at hello.c:34
+34    elm_box_pack_end(win, btn); //win instead of box
+</code>
+
+You finally know that win is used as a parameter of //elm_box_pack_end// 
instead of
+box, at line 34 of hello.c.
+
+----
+
+=== Segfault in callback function ===
+
+Let's make a segfault in a callback function:
+
+<code c helloworld.c>
+#include <Elementary.h>
+    static void
+on_done(void *data, Evas_Object *obj, void *event_info)
+{
+    int *pi=(int *)0; //pointer on 0x0!!!
+    /**SEGFAULT**/
+    int i=*pi; //segfault accessing 0x0 address
+
+    // quit the mainloop (elm_run function will return)
+    elm_exit();
+}
+
+  EAPI_MAIN int
+elm_main(int argc, char **argv)
+{
+    Evas_Object *win, *box, *btn;
+
+    // new window
+    win = elm_win_util_standard_add("hello", "Hello");
+
+    // add a box object
+    box = elm_box_add(win);
+
+    // add object as a resize object for the window
+    elm_win_resize_object_add(win, box);
+    evas_object_show(box);
+
+    // add a button
+    btn = elm_button_add(win);
+
+    // set default text of button to "SEG"
+    elm_object_text_set(btn, "SEG");
+
+    // pack the button at the end of the box
+    elm_box_pack_end(box, btn);
+    evas_object_show(btn);
+
+    // call on_done when button is clicked
+    evas_object_smart_callback_add(btn, "clicked", on_done, NULL);
+
+    //show the window
+    evas_object_show(win);
+
+    // run the mainloop and process events and callbacks
+    elm_run();
+    return 0;
+}
+ELM_MAIN()
+</code>
+
+This program segfaults when the seg button is clicked that is to say that the
+program segfaults in the callback function:
+
+//**__How to get that with GDB?__**//
+
+<code gdb>
+gdb helloworld
+(gdb) run
+(gdb)bt
+#0  0x0000000000400c7f in on_done (data=0x0, obj=0x8000000800000041, 
event_info=0x0) at helloworld.c:6
+#1  0x00007ffff6c1cb84 in _eo_evas_smart_cb (data=<optimized out>, 
eo_obj=<optimized out>, desc=<optimized out>, event_info=<optimized out>) at
+    lib/evas/canvas/evas_object_smart.c:65
+#2  0x00007ffff5e43d22 in _eo_base_event_callback_call 
(obj_id=0x8000000800000041, pd=0x92b4f0, desc=0x94e320, event_info=0x0) at
+    lib/eo/eo_base_class.c:716
+#3  0x00007ffff5e42a97 in eo_event_callback_call (desc=desc@entry=0x94e320,
+    event_info=event_info@entry=0x0) at lib/eo/eo_base.eo.c:94
+#4  0x00007ffff6c1ebad in evas_object_smart_callback_call 
(eo_obj=eo_obj@entry=0x8000000800000041, event=event@entry=0x7ffff7af0bdf
+    <SIG_CLICKED> "clicked", event_info=event_info@entry=0x0) at 
lib/evas/canvas/evas_object_smart.c:791
+#5  0x00007ffff7994b8c in _activate (obj=0x8000000800000041) at elm_button.c:69
+#6  0x00007ffff7994bc2 in _on_clicked_signal (data=<optimized out>,
+    obj=<optimized out>, emission=<optimized out>, source=<optimized out>) at
+    elm_button.c:191
+#7  0x00007ffff60d0425 in edje_match_callback_exec_check_finals 
(prop=<optimized out>, ed=<optimized out>, source=<optimized out>,
+    sig=<optimized out>, source_states=<optimized out>, 
signal_states=<optimized out>, matches=<optimized out>, ssp=<optimized
+    out>) at lib/edje/edje_match.c:556
+#8  edje_match_callback_exec (ssp=0x0, ssp@entry=0x946520, 
matches=0x8000000800000041, sig=0x0, sig@entry=0x92c06c "elm,action,click",
+     source=0x0, source@entry=0x914f60 "elm", ed=0x7ffff5e471b7, 
ed@entry=0x92ba70, prop=94 '^', prop@entry=0 '\000') at
+     lib/edje/edje_match.c:712
+#9  0x00007ffff60d673d in _edje_emit_cb (prop=0 '\000', data=0x0, src=0x914f60
+    "elm", sig=0x92c06c "elm,action,click", ed=0x92ba70) at 
lib/edje/edje_program.c:1392
+#10 _edje_emit_handle (ed=0x92ba70, sig=0x92c06c "elm,action,click", 
src=0x914f60 "elm", sdata=0x0, prop=0 '\000') at lib/edje/edje_program.c:1345
+#11 0x00007ffff60d1296 in _edje_message_process (em=0x669cf0) at 
lib/edje/edje_message_queue.c:651
+#12 0x00007ffff60d178c in _edje_message_queue_process () at 
lib/edje/edje_message_queue.c:754
+#13 0x00007ffff60d18ec in _edje_job (data=<optimized out>) at 
lib/edje/edje_message_queue.c:155
+#14 0x00007ffff696d3e0 in _ecore_job_event_handler (data=<optimized out>, 
type=<optimized out>, ev=<optimized out>) at lib/ecore/ecore_job.c:113
+#15 0x00007ffff69680a4 in _ecore_call_handler_cb (event=<optimized out>,
+    type=<optimized out>, data=<optimized out>, func=<optimized out>) at 
lib/ecore/ecore_private.h:386
+#16 _ecore_event_call () at lib/ecore/ecore_events.c:565
+#17 0x00007ffff696f711 in _ecore_main_loop_iterate_internal 
(once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1927
+#18 0x00007ffff696f81e in ecore_main_loop_begin () at 
lib/ecore/ecore_main.c:983
+#19 0x00007ffff7a4559f in elm_run () at elm_main.c:1097
+#20 0x0000000000400d79 in elm_main (argc=1, argv=0x7fffffffe398) at 
helloworld.c:39
+#21 0x0000000000400dc2 in main (argc=1, argv=0x7fffffffe398) at helloworld.c:42
+</code>
+
+As you can see, the program failed in the callback function, meaning the
+problem comes from your application, even if callback functions are called
+from evas.
+
+Let's go deeply:
+  -Go to frame 0, the callback function
+  -print pi pointer
+  -print what it points
+<code bash>
+(gdb) fr 0
+#0  0x0000000000400c86 in on_done (data=0x0, obj=0x8000000800000041, 
event_info=0x0) at helloworld.c:6
+6     int i=*pi;
+(gdb) p pi
+$1 (int *) 0x0
+(gdb) p *pi
+Cannot access memory at address 0x0
+</code>
+
+Here in this easy example, the problem is quite clear, address 0x0 cannot be
+accessed! Eventually, even if callback functions are called from evas and so
+generate lots of traces, it is quite simple to know where the bug is coming
+from.
+
+----
+
+=== Memory leak ===
+
+Valgrind is composed of several tools especially memcheck which checks:
+  - read/write access
+  - memory leaks
+  - non initialized variables
+
+In this example, an Eina array is created on a callback function but it is
+never freed. This generates a memory leak.
+
+<code c hello_valgrind.c>
+//hello.c
+#include <Elementary.h>
+    static void
+on_done(void *data, Evas_Object *obj, void *event_info)
+{
+    Eina_Array *array;
+    eina_init();
+    array = eina_array_new(100);
+    eina_array_step_set(array, sizeof(*array), 20);
+    unsigned int i;
+    for (i = 0; i < 20; i++)
+        eina_array_push(array, strdup("hello"));
+
+    /****To free array****/
+    //while (eina_array_count(array))
+    //free(eina_array_pop(array));
+    //eina_array_free(array);
+
+    //eina_shutdown();
+
+    // quit the mainloop (elm_run function will return)
+    elm_exit();
+}
+
+  EAPI_MAIN int
+elm_main(int argc, char **argv)
+{
+    Evas_Object *win, *box, *btn;
+
+    // new window
+    win = elm_win_util_standard_add("hello", "Hello");
+
+    // add a box object
+    box = elm_box_add(win);
+
+    // add object as a resize object for the window (controls window minimum
+    // size as well as gets resized if window is resized)
+    elm_win_resize_object_add(win, box);
+    evas_object_show(box);
+
+    // add a button
+    btn = elm_button_add(win);
+
+    // set default text of button to "SEG"
+    elm_object_text_set(btn, "SEG");
+
+    // pack the button at the end of the box
+    elm_box_pack_end(box, btn);
+    evas_object_show(btn);
+
+
+    // call on_done when button is clicked
+    evas_object_smart_callback_add(btn, "clicked", on_done, NULL);
+
+    //show the window
+    evas_object_show(win);
+
+    // run the mainloop and process events and callbacks
+    elm_run();
+    return 0;
+}
+ELM_MAIN()
+</code>
+
+There can be other traces in the HEAD SUMMARY but here we are just interested
+at leak memories due to your application, so you may have to find
+those which directly depends on your application.
+
+<code bash>
+...
+valgrind --leak-check=full --track-origins=yes ./hello
+...
+==22370== 312 (32 direct, 280 indirect) bytes in 1 blocks are definitely lost
+in loss record 349 of 417
+==22370==    at 0x4C28C20: malloc (vg_replace_malloc.c:296)
+==22370==    by 0x55A585D: eina_array_new (eina_array.c:279)
+==22370==    by 0x400E4C: on_done (hello.c:7)
+==22370==    by 0x5CD1B83: _eo_evas_smart_cb (evas_object_smart.c:65)
+==22370==    by 0x6BCFD21: _eo_base_event_callback_call (eo_base_class.c:716)
+==22370==    by 0x6BCEA96: eo_event_callback_call (in
+/usr/local/lib/libeo.so.1.14.99)
+==22370==    by 0x5CD3BAC: evas_object_smart_callback_call
+(evas_object_smart.c:791)
+==22370==    by 0x4F34B8B: _activate (elm_button.c:69)
+==22370==    by 0x4F34BC1: _on_clicked_signal (elm_button.c:191)
+==22370==    by 0x6970424: edje_match_callback_exec_check_finals
+(edje_match.c:556)
+==22370==    by 0x6970424: edje_match_callback_exec (edje_match.c:712)
+==22370==    by 0x697673C: _edje_emit_cb (edje_program.c:1392)
+==22370==    by 0x697673C: _edje_emit_handle (edje_program.c:1345)
+==22370==    by 0x6971295: _edje_message_process (edje_message_queue.c:651)
+...
+</code>
+
+All the memory access pass through valgrind, so it shows you a backtrace when
+an allocation is done and not freed.
+
+As you see in the backtrace, an allocation took place in the //eina_array_new
+function//.
+This function itself is called from //on_done// function on hello.c file.
+You can go up but remember that a callback function is called from evas, so
+there are big chances that the allocation is done in your callback function.
+
+----
+
+=== Clouseau ===
+
+Clouseau is the EFL UI Inspection tool. It makes it easy to query UI
+components and structure. Moreover it supports remote debugging and works with
+Gdb.
+
+In fact, Clouseau gives information about the different widgets with
+their properties.
+
+You can get Clousseau fom git.
+
+<code bash>
+git clone http://git.enlightenment.org/tools/clouseau.git
+</code>
+
+Here is a simple helloworld to test with clouseau, it displays a window
+with some text and one button to exit.
+
+<code c hello_clouseau.c>
+#include <Elementary.h>
+    static void
+on_done(void *data, Evas_Object *obj, void *event_info)
+{
+    // quit the mainloop (elm_run function will return)
+    elm_exit();
+}
+
+    EAPI_MAIN int
+elm_main(int argc, char **argv)
+{
+    Evas_Object *win, *box, *lab, *btn;
+    // new window - new background
+    win = elm_win_util_standard_add("hello", "Hello");
+    // when the user clicks "close" on a window there is a request to delete
+    evas_object_smart_callback_add(win, "delete,request", on_done, NULL);
+    // add a box object - default is vertical. a box holds children in a row,
+    // either horizontally or vertically. nothing more.
+    box = elm_box_add(win);
+    // make the box horizontal
+    elm_box_horizontal_set(box, EINA_TRUE);
+    // add object as a resize object for the window (controls window minimum
+    // size as well as gets resized if window is resized)
+    elm_win_resize_object_add(win, box);
+    evas_object_show(box);
+    // add a label widget, set the text and put it in the pad frame
+    lab = elm_label_add(win);
+    // set default text of the label
+    elm_object_text_set(lab, "Hello out there world!");
+    // pack the label at the end of the box
+    elm_box_pack_end(box, lab);
+    evas_object_show(lab);
+    // add an ok button
+    btn = elm_button_add(win);
+    // set default text of button to "OK"
+    elm_object_text_set(btn, "OK");
+    // pack the button at the end of the box
+    elm_box_pack_end(box, btn);
+    evas_object_show(btn);
+    // call on_done when button is clicked
+    evas_object_smart_callback_add(btn, "clicked", on_done, NULL);
+    int *p;
+    // now we are done, show the window
+    evas_object_show(win);
+    // run the mainloop and process events and callbacks
+    elm_run();
+    return 0;
+}
+ELM_MAIN()
+</code>
+
+To launch it with clouseau :
+<code bash>
+clousseau ./helloworld
+</code>
+
+Here below a screenshot of clouseau and the helloworld application :
+
+{{:clouseau.png?direct|Clouseau}}
+
+  - Yellow : Helloworld application
+  - Red : the composition of Helloworld application
+  - Blue : The characteristic of Elm and Evas_object
+
+Let's see now what gives us clouseau to compare with code:
+
+First thing the application is composed of 3 main widgets : //Elm_win//,
+//Elm_bg//, //Elm_box//.
+
+<code c>
+win = elm_win_util_standard_add("hello", "Hello");
+...
+box = elm_box_add(win);
+</code>
+
+//elm_win_util_standard_add// function creates the window which is the root
+widget often used in an application. It also puts a standard background
+(//Elm_bg//). Then, //elm_box_add// function creates a box widget.
+
+<code c>
+elm_box_pack_end(box, lab);
+...
+elm_box_pack_end(box, btn);
+</code>
+
+//elm_box_pack_end// add lab and btn widgets at the end of the pack list. So
+the lab and btn widgets appear as inside the box widget.
+
+Otherwise, the blue section shows a certain number of characteristics of the
+object and widget : position, size, color, ... Of course some of these
+characteristics are dynamic and can be updated with the reload button of
+clouseau.
+
+<code c>
+elm_win_resize_object_add(win, box);
+</code>
+
+This function controls the size of the window such as it takes the minimum
+place. You can see in the blue section that the minimum and maximum size are
+equal as a consequence of this function call.
+
+//**__Show objects__**//
+
+As you can see on the picture below, click on setting in yellow and deselect
+//Only show Elementary widgets// in red.
+
+{{:settings_clouseau.png?direct|Clouseau settings}}
+
+In the result below, you see that all the objects are visible and you see that
+widgets are just gathered specific objects.
+
+{{:clouseau_object.png?direct|Clouseau Objects}}
+
+For example in yellow, it is the Elm_box which is an Evas_box composed of an
+Evas_rectangle, an Elm_Label and an ELm_Button.
+
+A Button widget is an Edje_Object which is composed of 4 Evas_rectangle, one
+Evas_image and 2 Evas_text.
diff --git a/pages/docs.txt b/pages/docs.txt
index 4d44943..bceee91 100644
--- a/pages/docs.txt
+++ b/pages/docs.txt
@@ -31,6 +31,7 @@ Go check the current available version of EFL on each 
distro/platform:
 === Debugging ===
 
     * [[debugging/enlightenment_debugging|Enlightenment debugging]]
+    * [[debugging/apps_efl_debugging|EFL application debugging]]
 
 ----
 

-- 


Reply via email to