Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Write 'Hello, world!' program #1

Open
midenok opened this issue Dec 9, 2013 · 28 comments
Open

Write 'Hello, world!' program #1

midenok opened this issue Dec 9, 2013 · 28 comments

Comments

@midenok
Copy link
Contributor

midenok commented Dec 9, 2013

Program should connect to 'jabber.ru' server and send 'Hello, world!' to an account specified from command line.

@midenok
Copy link
Contributor Author

midenok commented Dec 9, 2013

Катя:

Привет, у меня пока особо ничего не сделано.
libpurple - разбираюсь с вот этим туториалом http://libpurple.com/category/getting-started/ ,
mojolicious - простой hello world запустила (раздел Getting started на http://mojolicio.us/).

@midenok
Copy link
Contributor Author

midenok commented Dec 9, 2013

Верно: берём финч и выкидываем всё кроме инициализации. Затем находим вызов, который отвечает за отправку сообщения и пытаемся его вызвать.

Эту ссылку тоже стоит посмотреть: http://libpurple.com/category/getting-started/

@kei91
Copy link
Member

kei91 commented Dec 11, 2013

Немного непонятно:
fakeroot debian/rules build -j 2 и ./configure - это две эквивалентные команды? (ну за исключением fakeroot - используем его для того, чтобы в самой системе ничего не менялось?)

И еще вопрос по той ошибке:

error: XML::Parser perl module is required for intltool

Я еще попробовала так sudo cpan install XML::Parser , но ошибка осталась. Я так понимаю, что система не находит этот модуль во время сборки (хотя он лежит здесь /usr/lib/perl5/XML/Parser/ ) , тогда вопрос как его явно указать?

@midenok
Copy link
Contributor Author

midenok commented Dec 11, 2013

Здесь решение:

/usr/bin/perl -e "require XML::Parser" 

Нет, это не эквивалентные команды. debian/rules build конфигурирует и собирает программу для пакета. Именно с теми опциями, которые нужны для пакета. Я пользуюсь прежде всего этой командой, чтобы не разбираться с деталями конфигурирования каждого отдельного софта. Единственное, что нужно изменить в сборке -- это добавить debug info и отключить оптимизацию, чтобы в отладчике было комфортней работать.

@kei91
Copy link
Member

kei91 commented Jan 6, 2014

Всех с праздниками!
И вопрос по gdb.
Запускаю gdb -tui finch .

После gnt_main() появляется сам finch

и вопрос - как посмотреть, какие функции в этот момент работают (в появившемся finch'e я отправляю сообщение, но не получается посмотреть, какая функция за это отвечает, можно ли как-то в gdb обратно перейти? ). Если закрыть finch (alt+q), то gdb указывает на строку purple_core_quit();

@midenok
Copy link
Contributor Author

midenok commented Jan 7, 2014

Привет! С Рождеством!

2 хинта насчёт отладки:

  1. Заходить внутрь gnt_main() (Step in). А там шагать Step Over.
  2. Ставить Break point на нужный системный вызов в нужный момент времени. Затем смотреть Stack trace.

Для события отправки сообщения удобнее всего ставить breakpoint на send() или родственные вызовы. Возможно write(), но он словит много ненужных событий -- поэтому его в последнюю очередь, если send(), sendto(), sendmsg() не сработают.

Универсальный совет: не забывай, что программа как чёрный ящик для нас неизвестная система. Поэтому не предполагай, что первый сработавший breakpoint будет именно тем, чем надо. Посчитай все сработавшие брейки, сравни их стеки (а иногда ещё и аргументы) и только тогда делай выводы.

@kei91
Copy link
Member

kei91 commented Jan 13, 2014

С gdb опять вопрос.
Захожу в gnt_main() и ставлю breakpoint:

(gdb) s
gnt_main () at /home/kei/src/pidgin-2.10.7/./finch/libgnt/gntmain.c:520
(gdb) b send
Breakpoint 2 at 0xb7b97d70 (2 locations)
(gdb) i b
Num     Type           Disp Enb Address    What
2       breakpoint     keep y   <MULTIPLE> 
2.1                         y     0xb7b97d70 <send>
2.2                         y     0xb7ac9e20 <send>

в gnt_main() шагаю, пока не

Breakpoint 2, 0xb7b97d70 in send () from /lib/i386-linux-gnu/libpthread.so.0
(gdb) backtrace
#0  0xb7b97d70 in send () from /lib/i386-linux-gnu/libpthread.so.0
#1  0xb744236d in ?? () from /lib/i386-linux-gnu/libresolv.so.2
#2  0xb743fe1f in __libc_res_nquery () from /lib/i386-linux-gnu/libresolv.so.2
#3  0xb74404a0 in ?? () from /lib/i386-linux-gnu/libresolv.so.2
#4  0xb7440b43 in __libc_res_nsearch () from /lib/i386-linux-gnu/libresolv.so.2
#5  0xb4fa2231 in _nss_dns_gethostbyname3_r () from /lib/i386-linux-gnu/libnss_dns.so.2
#6  0xb4fa25a1 in _nss_dns_gethostbyname_r () from /lib/i386-linux-gnu/libnss_dns.so.2
#7  0xb7ae0853 in gethostbyname_r () from /lib/i386-linux-gnu/libc.so.6
#8  0xb7ae000c in gethostbyname () from /lib/i386-linux-gnu/libc.so.6
#9  0xb7c28cc5 in ?? () from /usr/lib/libpurple.so.0
#10 0xb7c294fd in ?? () from /usr/lib/libpurple.so.0
#11 0xb7c297dd in ?? () from /usr/lib/libpurple.so.0
#12 0xb7d5e4b1 in ?? () from /lib/i386-linux-gnu/libglib-2.0.so.0
#13 0xb7d5d82e in g_main_context_dispatch () from /lib/i386-linux-gnu/libglib-2.0.so.0
#14 0xb7d5dbd8 in ?? () from /lib/i386-linux-gnu/libglib-2.0.so.0
#15 0xb7d5e03b in g_main_loop_run () from /lib/i386-linux-gnu/libglib-2.0.so.0
#16 0xb7d09f81 in gnt_main () at /home/kei/src/pidgin-2.10.7/./finch/libgnt/gntmain.c:521
#17 0x80024c98 in main (argc=1, argv=0xbffff1a4) at /home/kei/src/pidgin-2.10.7/./finch/finch.c:457

Но здесь одни библиотеки, получается это не то, что нам надо. Или надо здесь что-то искать?
Если сделать disable 2.1, то тогда вообще нигде не останавливается (заходит в finch и во во время отправки сообщения тоже ничего).
Похожая ситуация с sendto, sendmsg, write (хотя write больше похоже на запись в файл).

Мне непонятно я что-то не то делаю и надо ставить точки останова на другие вызовы или же надо как-то разбираться вот с этими so библиотеками.

@midenok
Copy link
Contributor Author

midenok commented Jan 13, 2014

Пожалуйста, посмотри на стек повнимательнее: gethostbyname() это DNS запрос. Он тебе не нужен. Ищи другой вызов send(). Ещё раз осмысли "универсальный совет".

Также, у тебя подключилась системная libpurple, поэтому ты не видишь её символов. Подключи свою откомпилированную (LD_LIBRARY_PATH).

@kei91
Copy link
Member

kei91 commented Jan 13, 2014

Тогда sendmsg получается (#12 jabber_send () - это же нам нужно, правильно?)

Breakpoint 2, 0xb7b97df0 in sendmsg () from /lib/i386-linux-gnu/libpthread.so.0
(gdb) where
#0  0xb7b97df0 in sendmsg () from /lib/i386-linux-gnu/libpthread.so.0
#1  0xb74d62e9 in ?? () from /lib/i386-linux-gnu/libdbus-1.so.3
#2  0xb74cf70c in ?? () from /lib/i386-linux-gnu/libdbus-1.so.3
#3  0xb74cf932 in ?? () from /lib/i386-linux-gnu/libdbus-1.so.3
#4  0xb74ce439 in ?? () from /lib/i386-linux-gnu/libdbus-1.so.3
#5  0xb74b5f84 in ?? () from /lib/i386-linux-gnu/libdbus-1.so.3
#6  0xb74b6076 in ?? () from /lib/i386-linux-gnu/libdbus-1.so.3
#7  0xb74b74a7 in ?? () from /lib/i386-linux-gnu/libdbus-1.so.3
#8  0xb74b7541 in dbus_connection_send () from /lib/i386-linux-gnu/libdbus-1.so.3
#9  0xb7c724bc in purple_dbus_signal_emit_purple () from /usr/lib/libpurple.so.0
#10 0xb7c268fd in purple_signal_emit_vargs () from /usr/lib/libpurple.so.0
#11 0xb7c269a3 in purple_signal_emit () from /usr/lib/libpurple.so.0
#12 0xb55e650d in jabber_send () from /usr/lib/purple-2/libjabber.so.0
#13 0xb55cc4fa in jabber_auth_start () from /usr/lib/purple-2/libjabber.so.0
#14 0xb55e92e3 in jabber_stream_features_parse () from /usr/lib/purple-2/libjabber.so.0
#15 0xb55eca2b in jabber_process_packet () from /usr/lib/purple-2/libjabber.so.0
#16 0xb55fb363 in ?? () from /usr/lib/purple-2/libjabber.so.0
#17 0xb78aa4de in ?? () from /usr/lib/i386-linux-gnu/libxml2.so.2
#18 0xb78aff08 in ?? () from /usr/lib/i386-linux-gnu/libxml2.so.2
#19 0xb78b19e3 in xmlParseChunk () from /usr/lib/i386-linux-gnu/libxml2.so.2
#20 0xb55fb900 in jabber_parser_process () from /usr/lib/purple-2/libjabber.so.0
#21 0xb55e8421 in ?? () from /usr/lib/purple-2/libjabber.so.0
#22 0xb7c2fe3c in ?? () from /usr/lib/libpurple.so.0
#23 0x8002459c in purple_gnt_io_invoke (source=0x80346008, condition=G_IO_IN, data=0x8009b770) at /home/kei/src/pidgin-2.10.7/./finch/finch.c:186
#24 0xb7da18b5 in ?? () from /lib/i386-linux-gnu/libglib-2.0.so.0
#25 0xb7d5d82e in g_main_context_dispatch () from /lib/i386-linux-gnu/libglib-2.0.so.0
#26 0xb7d5dbd8 in ?? () from /lib/i386-linux-gnu/libglib-2.0.so.0
#27 0xb7d5e03b in g_main_loop_run () from /lib/i386-linux-gnu/libglib-2.0.so.0
#28 0xb7d09f81 in gnt_main () at /home/kei/src/pidgin-2.10.7/./finch/libgnt/gntmain.c:521
#29 0x80024c98 in main (argc=1, argv=0xbffff1a4) at /home/kei/src/pidgin-2.10.7/./finch/finch.c:457

@midenok
Copy link
Contributor Author

midenok commented Jan 13, 2014

Возможно да, возможно нет. Ты мне скажи. "Универсальный совет" выполнила? Не спеши с вопросами. Сделай всё как положено:

Также, у тебя подключилась системная libpurple, поэтому ты не видишь её символов. Подключи свою откомпилированную (LD_LIBRARY_PATH).

@kei91
Copy link
Member

kei91 commented Jan 13, 2014

Да, если я все правильно поняла. Вывод, который я скидывала, 11-ый (на 20-ом еще jabber_close () появляется), всего 22:

(gdb) i b
Num     Type           Disp Enb Address    What
2       breakpoint     keep y   <MULTIPLE> 
    breakpoint already hit 22 times
2.1                         y     0xb7b97df0 <sendmsg>
2.2                         y     0xb7ac9ea0 <sendmsg>

Про LD_LIBRARY_PATH я ее в .bashrc подключала
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/home/kei/src/pidgin-2.10.7/build/finch/libgnt/.libs
или она так не сработает?

@midenok
Copy link
Contributor Author

midenok commented Jan 13, 2014

Между 11-м и 20-м jabber_auth_start() не исчезает? Или с 11 по 19 стек всегда одинаковый?

Не надо это в .bashrc делать. Создай свой отдельный скрипт для запуска данного приложения в gdb (положи его прям в исходники или рядом). libpurple.so.0 и libjabber.so.0 лежат в /home/kei/src/pidgin-2.10.7/build/finch/libgnt/.libs?

@kei91
Copy link
Member

kei91 commented Jan 13, 2014

Исчезает

@midenok
Copy link
Contributor Author

midenok commented Jan 13, 2014

Ну вот. Проанализируй подробнее. Выбери все варианты стеков с 11 по 19.

@midenok
Copy link
Contributor Author

midenok commented Jan 13, 2014

Кстати, тебе нужны только те стеки, которые появляются непосредственно после того как ты нажала "Отправить сообщение". И всё, больше никаких других событий в программе не производишь.

@kei91
Copy link
Member

kei91 commented Jan 22, 2014

Привет! Извиняюсь, что так долго не писала.
Посмотри, пожалуйста, стеки: 1, 2, 3.

Мне кажется, то, что нужно в первом это 12-ый фрейм (common_send), во втором 20-ый (serv_send_im), в третьем 12-ый (purple_conversation_write) и возможно 14-ый (finch_write_im).

Теперь мне соответственно надо смотреть conversation.c, server.c, gntconv.c ?

@midenok
Copy link
Contributor Author

midenok commented Jan 22, 2014

Нет, теперь просто breakpoint-ом встаёшь на 4 этих вызова и выбираешь из них только те, которые срабатывают только на отправке сообщения.

@kei91
Copy link
Member

kei91 commented Jan 28, 2014

Все 4 вызова срабатывают только при отправке сообщения, таким образом:

Breakpoint 3, common_send (conv=0x803a8220, message=0x803a7c58 "test", msgflags=PURPLE_MESSAGE_SEND) 
   at /home/kei/src/pidgin-2.10.7/./libpurple/conversation.c:142
142     char *displayed = NULL, *sent = NULL;

Breakpoint 2, serv_send_im (gc=0x800a95e8, name=0x800b2c50 "[email protected]", message=0x803a8108 "test", flags=PURPLE_MESSAGE_SEND) 
   at /home/kei/src/pidgin-2.10.7/./libpurple/server.c:123
123     PurpleConversation *conv = NULL;

Breakpoint 5, finch_write_im (conv=0x803a8220, who=0x0, message=0x803a7c68 "test", flags=PURPLE_MESSAGE_SEND, mtime=1390768519)  
   at /home/kei/src/pidgin-2.10.7/./finch/gntconv.c:1019
1019        PurpleAccount *account = purple_conversation_get_account(conv);

Breakpoint 4, purple_conversation_write (conv=0x803a8220, who=0x803a64d0 "[email protected]/4002410108", message=0x803a7c68 "test", flags=PURPLE_MESSAGE_SEND, mtime=1390768519) 
   at /home/kei/src/pidgin-2.10.7/./libpurple/conversation.c:932
932     PurplePluginProtocolInfo *prpl_info = NULL;

Breakpoint 5, finch_write_im (conv=0x803a8220, who=0x80388828 "[email protected]/4002410108", message=0x8034ac68 "test", flags=PURPLE_MESSAGE_RECV, mtime=1390768604)  
   at /home/kei/src/pidgin-2.10.7/./finch/gntconv.c:1019
1019        PurpleAccount *account = purple_conversation_get_account(conv);

Breakpoint 4, purple_conversation_write (conv=0x803a8220, who=0x8033e7a0 "[email protected]", message=0x8034ac68 "test", flags=PURPLE_MESSAGE_RECV, mtime=1390768604)
   at /home/kei/src/pidgin-2.10.7/./libpurple/conversation.c:932
932     PurplePluginProtocolInfo *prpl_info = NULL;

Теперь надо исходники смотреть, в смысле больше никак нельзя уточнить, какой вызов отвечает за отправку? Скорее всего, судя по аргументам, server.с получается.

@midenok
Copy link
Contributor Author

midenok commented Jan 28, 2014

Вообще-то это очевидно, что все они срабатывают только на отправку (сорри, я посмотрел стеки только сейчас). Почему: во всех стеках есть вызов purple_conv_im_send_with_flags() (тот который нам нужен, очевидно по названию). А теперь ответь пожалуйста на вопрос, какими будут стеки ниже этого вызова (внизу списка) -- одинаковые или разные? Почему? Попробуй сначала ответить и только потом посмотри и сравни.

@kei91
Copy link
Member

kei91 commented Feb 5, 2014

Посмотри, пожалуйста, ошибки при компиляции.
Сам код:

#include "account.h"
#include "conversation.h"

int main() {

    PurpleAccount *account = purple_account_new("[email protected]", "prpl-jabber");
    purple_account_set_password(account, pass);
    purple_accounts_add(account);

    PurpleConversation *conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, "test");
    purple_conv_im_send_with_flags(PURPLE_CONV_IM(conv), "Hello, world!", PURPLE_MESSAGE_SEND);
    return 0;
}

Компилирую так:

gcc -I /home/kei/src/pidgin_2.10.7/finch -I /home/kei/src/pidgin-2.10.7/libpurple/ -I /usr/include/libpurple/ -I /usr/include/glib-2.0/ hello_purple.c -o hello_purple

Ошибки:

/tmp/ccPhniMo.o: In function `main':
hello_purple.c:(.text+0x19): undefined reference to `purple_account_new'
hello_purple.c:(.text+0x31): undefined reference to `purple_account_set_password'
hello_purple.c:(.text+0x3d): undefined reference to `purple_accounts_add'
hello_purple.c:(.text+0x59): undefined reference to `purple_conversation_new'
hello_purple.c:(.text+0x69): undefined reference to `purple_conversation_get_im_data'
hello_purple.c:(.text+0x81): undefined reference to `purple_conv_im_send_with_flags'
collect2: error: ld returned 1 exit status

Непонятно почему undefined reference, ведь я добавила директории через -I в gcc.

@midenok
Copy link
Contributor Author

midenok commented Feb 5, 2014

Опция -I тебе не поможет. Почитай пожалуйста про опции -I и -l в man gcc.

@kei91
Copy link
Member

kei91 commented Feb 7, 2014

Спасибо, добавила в конец команды -lpurple и теперь компилируется, но при запуске:

** (process:6201): CRITICAL **: purple_dbus_register_pointer: assertion 'map_node_id' failed
** (process:6201): CRITICAL **: purple_eventloop_get_ui_ops: assertion 'eventloop_ui_ops != NULL' failed
Segmentation fault (core dumped)

Теперь мне надо в gdb смотреть как вызываются purple_dbus_register_pointer и purple_eventloop_get_ui_ops , а потом добавить эти вызовы в свою программу?

@midenok
Copy link
Contributor Author

midenok commented Feb 7, 2014

Ты сравнивала содержимое своего conv с настоящим? Наверняка что-то проинициализировано не до конца. Думаю, можно и по коду посмотреть где и чего ты забыла вызвать.

Теперь мне надо в gdb смотреть как вызываются purple_dbus_register_pointer и purple_eventloop_get_ui_ops , а потом добавить эти вызовы в свою программу?

Если эти вызовы исполняются, зачем ты их хочешь добавлять в программу?

@kei91
Copy link
Member

kei91 commented Feb 11, 2014

Добавила init_libpurple() , выглядит теперь так . Мало чем отличается от туториала .
Ошибки пропали, но при попытки отослать сообщение срабатывает report_disconnect_reason:

Connection disconnected: "[email protected]" (prpl-jabber)
  >Error: 0
  >Reason: Lost connection with server: Bad file descriptor

Я не понимаю, что происходит с моей переменной conv, вот, содержимое настоящего conv:

(gdb) print *im->conv
$3 = {type = PURPLE_CONV_TYPE_IM, account = 0x800a7a80, 
  name = 0x8034b060 "[email protected]", title = 0x80329ba8 "[email protected]", 
  logging = 1, logs = 0x80325d30, u = {im = 0x80359fc8, chat = 0x80359fc8, 
    misc = 0x80359fc8}, ui_ops = 0x80044120, ui_data = 0x80359ba0, 
  data = 0x802fb5a0, features = 1793, message_history = 0x0}

а это мой:

(gdb) print *conv
$1 = {type = 1764796, account = 0xb7fdcb00, 
  name = 0xb7ff2970 "PQR\213T$\020\213D$\f萛\377\377Z\213\f$\211\004$\213D$\004\302\f", title = 0xb7ce4276 "h", logging = -1210814112, logs = 0xb7d46cb0, 
  u = {im = 0xb7d768e0, chat = 0xb7d768e0, misc = 0xb7d768e0}, 
  ui_ops = 0xb7ce42b6, ui_data = 0xb7d63900, data = 0xb7e16560, 
  features = 3083748070, message_history = 0xb7ce42f6}

(оба из вызова purple_conv_im_send_with_flags )
Непонятно как и откуда вообще заполняется переменная conv, я сначала думала, что только с помощью purple_conversation_new, но тогда откуда name такой странный?

@midenok
Copy link
Contributor Author

midenok commented Feb 11, 2014

Вообще-то не name странный, а очевидно, что все поля содержат мусор. Это значит, что твоя структура не проинициализировалась как положено. account проверяла? Нормальные значения содержит? Инициализацию прошагивала (настоящую и свою)?

Ещё, используй мой .gdbinit пожалуйста. Там человеческие настройки (set print pretty on).

@kei91
Copy link
Member

kei91 commented Feb 11, 2014

В account всё нормально, сколько я могу судить, разница только в содержимом переменной user_info.
account мой:

(gdb) print *account
$3 = {
  username = 0x8052c68 "[email protected]", 
  alias = 0x0, 
  password = 0x80b5ae0 "", 
  user_info = 0x0, 
  buddy_icon_path = 0x0, 
  remember_pass = 0, 
  protocol_id = 0x80b3fa8 "prpl-jabber", 
  gc = 0x80b5bc0, 
  disconnecting = 0, 
  settings = 0x80a34b0, 
  ui_settings = 0x80a34e8, 
  proxy_info = 0x0, 
  permit = 0x0, 
  deny = 0x0, 
  perm_deny = PURPLE_PRIVACY_ALLOW_ALL, 
  status_types = 0x80b41d0, 
  presence = 0x80b5060, 
  system_log = 0x0, 
  ui_data = 0x0, 
  registration_cb = 0, 
  registration_cb_user_data = 0x0, 
  priv = 0x80b3448
}

настоящий:

(gdb) print *im->conv->account
$6 = {
  username = 0x800a7868 "[email protected]/", 
  alias = 0x0, 
  password = 0x800ab148 "", 
  user_info = 0x80359580 "<vCard xmlns='vcard-temp'>\n<NICKNAME>kei91</NICKNAME>\n</vCard>", 
  buddy_icon_path = 0x0, 
  remember_pass = 1, 
  protocol_id = 0x800a7840 "prpl-jabber", 
  gc = 0x800aed18, 
  disconnecting = 0, 
  settings = 0x8009d490, 
  ui_settings = 0x8009d4c8, 
  proxy_info = 0x0, 
  permit = 0x0, 
  deny = 0x0, 
  perm_deny = PURPLE_PRIVACY_ALLOW_ALL, 
  status_types = 0x800a7b10, 
  presence = 0x800a52a8, 
  system_log = 0x0, 
  ui_data = 0x0, 
  registration_cb = 0, 
  registration_cb_user_data = 0x0, 
  priv = 0x800a2bf8
}

Инициализацию я прошагивала, меня что-то конкретное должно интересовать?

@midenok
Copy link
Contributor Author

midenok commented Feb 11, 2014

Да, похоже account нормальный. Шагаешь и смотришь как ведут себя переменные. Находишь отличия. В графической оболочке это очень удобно делать.

Также можно отследить весь путь жизни conv от начала (purple_conversation_new()) до конца (purple_conv_im_send_with_flags()) и найти место в котором она приобретает содержимое.

@kei91
Copy link
Member

kei91 commented Feb 12, 2014

Что-то вышло :), по крайней мере сообщение отсылает.
https://github.com/train-it/libpurple-snippets/blob/master/hello_purple.c
Проблема была в том, что аккаунт не подключала (purple_signal_connect , purple_connection_get_account).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants