Показаны сообщения с ярлыком dev. Показать все сообщения
Показаны сообщения с ярлыком dev. Показать все сообщения

среда, 26 февраля 2014 г.

SIGILL при переходе на следующую строчку после breakpoint в GDB на Android

В случае если вам хочется обойтись без Eclipse/Android Studio и прочих IDE для отладки вашего приложения для Андройда, то можно воспользоваться обычным GDB из NDK. Если вы просто подключаетесь к gdbserver'у из этого обычного GDB, то может возникнуть следующая ошибка: 

(gdb) b f_close 
Breakpoint 1 at 0x5c309018: file api/test.c, line 359.
(gdb) c
Continuing.
[New Thread 24337]
[Switching to Thread 24337]

Breakpoint 1, f_close () at api/test.c:359
359     int err = 0;
(gdb) n

Program received signal SIGILL, Illegal instruction.


Если после этого продолжить выполнение, то программа упадёт по сигналу SIGILL или SIGSEGV. В NDK есть специальный скрипт - ndk-gdb, который запускает gdbserver и делает ещё кучу других вещей. В том числе он исправляет эту проблему.

Решение


Загрузите с вашего Андройд-устройства следующие файлы:

* /system/lib/libc.so
* /system/bin/app_process
* /system/bin/linker
И поместите их в папку с вашими бинарниками на хосте (например ./obj/local/armeabi/). После этого воспользуйтесь следующими командами для подключения к gdbserver'у:


file obj/local/armeabi/app_process
target remote :5039
set solib-search-path obj/local/armeabi/

Убедитесь что бинарники подгрузились с помощью команд info sharedlibrary и info file.

Теперь можно пошагово выполнять приложение без проблем!

четверг, 31 января 2013 г.

Android glxinfo

Под катом находятся исходники простой утилиты, выводящей информацию об OpenGL в Android 4.

Обратите внимание что код расчитан на компиляцию системой сборки Android (вам понадобятся исходники платформы чтобы собрать). Я не пробовал собирать с помощью NDK.

Например она выводит следуюущую информацию, если запущена на PandaBoard Rev.B ES:
EGL version 1.4
EGL_VERSION = 1.4 Android META-EGL
EGL_VENDOR = Android
EGL_EXTENSIONS = EGL_KHR_image EGL_KHR_image_base EGL_KHR_image_base 
EGL_KHR_gl_texture_2D_image EGL_KHR_gl_texture_cubemap_image EGL_KHR_gl_renderbuffer_image 
EGL_KHR_fence_sync EGL_ANDROID_image_native_buffer EGL_ANDROID_image_native_buffer
EGL_CLIENT_APIS = OpenGL ES
На эмуляторе Android 4.0:
EGL version 1.4
EGL_VERSION = 1.4 Android META-EGL
EGL_VENDOR = Android
EGL_EXTENSIONS = EGL_KHR_image EGL_KHR_image_base EGL_KHR_image_pixmap 
EGL_KHR_gl_texture_2D_image EGL_KHR_gl_texture_cubemap_image EGL_KHR_gl_renderbuffer_image 
EGL_KHR_fence_sync EGL_ANDROID_image_native_buffer EGL_ANDROID_swap_rectangle 
EGL_NV_system_time
EGL_CLIENT_APIS = OpenGL ES

вторник, 1 января 2013 г.

Пример перехвата сетевого траффика с помощью Raw Sockets

Иногда бывает необходимость в получении сырых данных поступающих на сетевой интерфейс. Один из вариантов решения задачи — создать сетевой драйвер использующий интерфейсы netfilter. Хотя этот вариант будет иметь наибольшую производительность, существует более простой путь с точки зрения реализации. Для этого не надо писать никаких драйверов, достаточно просто открыть Raw Socket (сырой сокет) в программе рижима пользователя.

Ниже приведён пример программы, печатающей на экран весь входящий трафик:


#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <linux/if_ether.h> // ETH_P_ALL
#include <linux/if_packet.h> // sockaddr_ll

int main(int argc, char **argv)
{
    int s;
    struct sockaddr_in src_addr;
    char packet[50] = {0};
    struct sockaddr_ll    sll = {0};

    if ((s = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) < 0) { // (1)
        perror("socket");
        return -1;
    }

    sll.sll_family        = AF_PACKET;
    sll.sll_ifindex        = 3; // Interface index (2)
    sll.sll_protocol    = htons(ETH_P_ALL);

    if( bind(s, (struct sockaddr *) &sll, sizeof(sll)) == -1 ) {
        perror("bind");
    }

    socklen_t *len = (socklen_t *)sizeof(src_addr);
    int fromlen = sizeof(src_addr);

    while(1) {
        if (recvfrom(s, &packet, sizeof(packet), 0,
                    (struct sockaddr *)&src_addr, &fromlen) < 0)
            perror("recvfrom");

        int i = sizeof(struct iphdr); // print the payload

        for(; i < sizeof(packet); i++) {
            printf("%02X ", (unsigned char) packet[i]);
        }

        printf("\n");
    }
    return 0;
}
 

Комментарии:

  1. Чтобы открыть сырой сокет, необходимы права суперпользователя. 
  2. Номер интерфейса можно получить в том числе командой "ip addr sh"
Код тестировался на Ubuntu 12.04 x64

Ссылки:

  1. Код основан на примере из ответа на stackoverflow . Оригинальный код у меня не заработал и я его немного изменил.
  2.  libpcap использует этот-же механизм для перехвата траффика (pcap-linux.c/activate_new()). Эту библиотеку используют такие популярные утилиты как tcpdump и wireshark.

среда, 7 декабря 2011 г.

Как получить список изменённых файлов в Linux

Предположим у нас есть папка с исходным набором файлов ${ORIG} и рабочая папка ${ORIG_WITH_CHANGES}, в которую изначально были скопированы файлы из ${ORIG} и произведены некоторые изменения. Задача состоит в том, чтобы получить третью папку ${CHANGES}, которая содержала бы только изменённые файлы с сохранением структуры папок.

Добиться поставленной задачи нам поможет команда rsync:

rsync --progress --exclude out -a -c \
        --compare-dest=${ORIG} ${ORIG_WITH_CHANGES} ${CHANGES} 
cd ${CHANGES} 
find -depth -type d -empty -delete
find . -name .git -print0 | xargs -0 rm -rf

Использованные параметры команды rsync:
--progress: с этим ключём rsync печатает список обработанных файлов во время работы
--exclude out: игнорировать папку out
-a: включает архивный режим. Это сокращение к следующей комбинации ключей: -rlptgoD
-с: игнорировать время изменения и проверять изменился ли файл, сравнивая его побитно с оригиналом.
--compare-dest=${ORIG}: по умолчанию rsync первый раз скопирует все файлы в папку ${CHANGES}. Нам же нужны только изменённые по сравнению с оригиналом. Эта опция включает сравнение с оригиналом

Первая строка  создаёт искомую директорию, но помимо изменённых файлов, она ещё хранит кучу пустых папок. Следующие две команды очищают ${CHANGES} от пустых папок и удаляют все папки с названием ".git".

Эта заметка основана на ответах к моему вопросу на unix.stackexchange.com.

вторник, 6 декабря 2011 г.

Автоматическая пересборка проекта при изменении файлов

Данная задача актуальна в первую очередь вэб-проектам — в данном случае сборка обычно заключается в быстром препроцессинге и копировании файлов, так что хочется чтобы она происходила постоянно при каждом изменении файлов. В Django например подобная функциональность встроена в его вэб-сервер, который следит за изменениями файлов в проекте и перезапускает сам себя, если таковые обнаружит. Если же, как в моём случае, никакого django не используется, а применяется простой GNU Make, приходится прибегать к встроенной возможности ОС Linux — инструменту inotify.

Итак, если вы используете Ubuntu, надо установить пакет inotify-tools — оттуда нам понадобится утилита inotifywait. Получается вот такой Makefile:

.PHONY: watch ❶

all:
    echo "Make all called!"

watch:
    while inotifywait -e modify -r ../ \
        --exclude "(\./build/.*|.*\.swp)" ; \
    do make -C $(CURDIR); done # Call this Makefile again with default target
  1. Отмечаем нашу цель как .PHONY — это значит что она не создаёт никаких файлов и будет выполнена в любом случае (даже если файл watch уже существует)
  2. Конкретно в нашей целе мы бесконечно ждём события modify в папке уровнем выше, за исключением папки "build" (в ней находится этот Makefile) и файлов с расширением .swp (их создаёт редактор Vim  и постоянно обновляет, при каждом введённом символе).
    Если это событие наступает, мы воплняем цель по умолчанию из этого же Makefile (по умолчанию это цель all)
Похожий вопрос на Superuser.com.

понедельник, 31 октября 2011 г.

Отладка сервисов в Android

Чтобы Eclipse начал останавливаться в точках останова, надо перед такой точкой вставить следующую строку:
android.os.Debug.waitForDebugger();

Так же в манифесте надо прописать android:debuggable="true"

среда, 26 октября 2011 г.

Ошибка cmake/make в Windows: *** target pattern contains no `%'. Stop.

Во время сборки проекта, используя cmake на Windows можно наткнутся на такую проблему:
 *** target pattern contains no `%'. Stop. 


Ошибка возникает в GNU Make 3.81 установленным через Cygwin. Проблема вызвана некорректной работой make (подробности), причём проблема эта была поправлена ещё в далёком 2008, но до сих пор по-умолчанию cygwin ставит именно неработающую версию.

Решение

  1. Исправленную версию make скачиваем тут: http://www.cmake.org/files/cygwin/make.exe 
  2. Копируем скачанный файл в C:\cygwin\bin. 
  3. Переименовываем или создаём ссылку для файла cygintl-8.dll -> cygintl-3.dll всё в той же директории c:\cygwin\bin

вторник, 2 августа 2011 г.

Бесконечный цикл в командной строке Windows

for /L %I in (1, 0, 2) do echo 1
Таким образом автообновляемый список интерфейсов выглядит так (обновление раз в 5 сек):
for /L %I in (1, 0, 2) do ping -n 5 127.0.0.1 >NUL && ipconfig /all
Version 2:
for /L %I in (1, 0, 2) do @ping -n 5 127.0.0.1 >NUL && cls && ipconfig /all
@ping -n 5 127.0.0.1 >NUL -- используется для эмуляции команды sleep 
(просто происходит пауза в выполнении в данном случае 5 сек.)

вторник, 5 июля 2011 г.

Окошко, меняющее размеры в зависимости от содержимого

В конструкторе вашего наследника QDialog надо добавить эту строку:

// make the dialog adjust to its layout
layout()->setSizeConstraint(QLayout::SetFixedSize); // <- this does the trick!


Страница на QtC
Ещё один вариант

среда, 1 июня 2011 г.

Список файлов в lua

Windows-версия
for f in io.popen("dir /B"):lines() do print(f) end


Linux-версия:
for f in io.popen("ls"):lines() do print(f) end

четверг, 19 мая 2011 г.

Как получить время сборки из .exe или .dll

Если приложение падает, то Windows 7 показывает такое окошко:
Тут ясно видно какие версии компонентов программы упали. Как же можно извлеч эту информацию?

Сначала я подумал, что надо использовать VERSIONINFO, но как выяснилось эти данные надо отдельно описывать в ресурсном файле (.rc) и отдельно вкомпилять в экзешник.

Затем мне объяснили что время сборки добавляется линкером в специальном заголовке. Все эти exe/dll являются файлами формата Portable Executable и в состав вижуал студии даже входит специальная утилита dumpbin, с помощью которой эти загаловки можно просмотреть:
> dumpbin /all lib.dll

------------------8-<-------------------------------------------

FILE HEADER VALUES
14C machine (x86)
5 number of sections
4DD3E95F time date stamp Wed May 18 19:44:31 2011 ← Вот оно!
0 file pointer to symbol table
0 number of symbols
E0 size of optional header

---------------8-<----------------------------------

Если это смог извлечь dumpbin, то сможем и мы. В файле windows.h описана структура
IMAGE_DOS_HEADERS и IMAGE_NT_HEADERS. В файле они расположены подряд, один за другим. Адрес следующего заголовка лежит в IMAGE_DOS_HEADERS::e_lfanew. Само же время сборки лежит тут: IMAGE_NT_HEADERS::IMAGE_FILE_HEADER::FileHeader.TimeDateStamp (в секундах с начала эпохи UNIX).

Получается такой код:

void print_timestamp(QString fpath)
{
IMAGE_NT_HEADERS header = {0};
IMAGE_DOS_HEADER dosHeader = {0};
QFile f(fpath);

if (!f.open(QIODevice::ReadOnly))
{
return;
}

f.read(reinterpret_cast<char*>(&dosHeader), sizeof(dosHeader));
if (dosHeader.e_magic == IMAGE_DOS_SIGNATURE
&& f.seek(dosHeader.e_lfanew)
&& f.read(reinterpret_cast<char*>(&header), sizeof(header)))
{
QDateTime dt;
dt.setTime_t(header.FileHeader.TimeDateStamp);
qDebug("Timestamp: 0x%0X (%s UTC)",
header.FileHeader.TimeDateStamp,
qPrintable(dt.toUTC().toString("dd.MM.yyyy hh:mm:ss")));
}

f.close();
}


Рекомендую изучить: хорошая статья о PE формате

пятница, 22 апреля 2011 г.

Работа с образами файловых систем в Windows

Для работы с образами файловых систем можно использовать opensource утилиту ImDisk. Вот пример использования:

set DRIVELETTER=V

copy data\empty.fat image.fat (1)

imdisk -a -t file -m %DRIVELETTER%:\ -f image.fat -o rw (2)
xcopy /E FILES %DRIVELETTER%:\ (3)

imdisk -d -m %DRIVELETTER%:\ (4)
Этот batch-скрипт копирует предворительно созданный пустой образ файловой системы (1), затем монтирует его на диск заданный пользователем (в данном случае диск V:\) с возможностью записи и чтения (2), потом копирует на этот диск все файлы и папки из директории FILES (3) и наконец демонтирует образ (4).

Теперь в файле image.fat лежат все файлы из директории FILES

среда, 23 февраля 2011 г.

Сравнение вещественных чисел в bash

Я продолжаю писать инструмент для слежения за самодельным вэб-сервером.
Сегодня наткнулся на новую особенность bash — он не умеет работать с вещественными числами (с плавующей точкой). Например он не может их сравнивать:
if [ 0.1 -gt 0.3 ]

возвращает ошибку «bin/run.bash: строка 44: [: 0.1: ожидается числовое выражение».
Пользователь MoneyCat пишет что лучше для этого использовать операторы <, >, <=, >=:
if [ 0.1 > 0.3 ]

Ошибка хоть и перестала появляться, но зато скрипт начал просто неверно работать.
Как нам дружелюбно напоминает Advanced Bash-Scripting Guide:
Bash does not understand floating point arithmetic. It treats numbers containing a decimal point as strings.
Чтобы обойти это ограничение можно воспользоваться bc:
if [ $(echo "$max < $i" | bc) -eq 1 ]


Теперь мой скрипт так же умеет следить и за загрузкой процессора. Он получает % от используемого моей программой процессорного времени в виде вещественного числа от команды ps:
CPUUSE=$(ps h -p $TARG_PID -o pcpu)

Слежение за процессом из bash скрипта

Я решил поднять у себя на машине самодельный веб-сервер. Естественно хочется чтобы он не мешал во время работы, а так как сервер самодельный риск всяких утечек памяти и зацикливаний высок — нужно средство слежения которое в критический момент будет убивать мою поделку.
В качестве языка я выбрал bash, т.к. программы на нём жрут очень мало ресурсов.

Пока делал эту прогу, мне показались интересными три момента:
  1. Отлавливание сигналов происходит при помощи команды trap
    trap "echo Hello world" SIGHUP SIGINT SIGTERM
  2. Самым надёжным способом выяснить в какой папке лежит сам скрипт является команда lsof
    LSOF=$(lsof -p $$ | grep -E "/"$(basename $0)"$")
    MY_PATH=$(echo $LSOF\
    | sed -r s/'^([^\/]+)\/'/'\/'/1 2>/dev/null)
    MY_ROOT=$(dirname $MY_PATH)
  3. Судя по всему самый надёжный способ узнать сколько памяти занимает процесс — это сложить значения RSS и Dirty команды pmap
    MEMUSE_RAW=$(pmap -x $TARG_PID 2>/dev/null | grep total\
    | sed 's/-//g' | sed s/[^0-9\ ]*//g);
    RSS=$(echo $MEMUSE_RAW | awk '{print $2}')
    DIRTY=$(echo $MEMUSE_RAW | awk '{print $3}')
    MEMUSE=$(echo $RSS+$DIRTY | bc)
Весь код скрипта:

четверг, 28 октября 2010 г.

Как избавится от ms_server и ms_client в новом RAS-соединении

Если программно создавать Dial-up соединение при помощи RAS API, Windows по умолчанию включает использование клиента и сервера для сетей Samba (возможность расшаривания и просмотра удалённых файлов/папок/принтеров). В результате, как только вы подключаетесь допустим через 3G соединение куча траффика уходит на поддержку этих сомнительных функций. + на моём компьютере из-за этого начинает тормозить connect/disconnect.
В исходном тексте соединения это выглядит так:

....
IpSecFlags=0
IpDnsSuffix=

NETCOMPONENTS=
ms_msclient=0
ms_server=0

MEDIA=serial
Port=COM8
....

Чтобы программно выключить эту опцию, добавьте флаг RASEO_SecureLocalFiles к вашей RASENTRY:

RASENTRY entry = {0};
entry.dwfOptions |= RASEO_SecureLocalFiles;

Описание RASENTRY на MSDN.

понедельник, 16 августа 2010 г.

Аналог питоновского slice в QString

QString QString::mid ( int position, int n = -1 ) const

Returns a string that contains n characters of this string, starting at the specified position index.

Returns a null string if the position index exceeds the length of the string. If there are less than n characters available in the string starting at the given position, or if n is -1 (default), the function returns all characters that are available from the specified position.

Example:

QString x = "Nine pineapples";
QString y = x.mid(5, 4); // y == "pine"
QString z = x.mid(5); // z == "pineapples"

See also left() and right().

понедельник, 19 апреля 2010 г.

Си++: forward declaration of a template


//header.h:
template class QVector;
struct sImage;

QVector * networks;


Используя такой способ, можно избежать включения дополнительных заголовков в header.h (QVector и sImage нужно будет определить в *.cpp)


Статья в Википедии о Forward declarations.

воскресенье, 21 марта 2010 г.

Как запустить процесс с правами текущего пользователя из сервиса

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

Вот этот код решает такую задачу:

//get Active UI session
ulSessionId = WTSGetActiveConsoleSessionId();

WTSQueryUserToken (ulSessionId, &hTokenthis);

DuplicateTokenEx(hTokenthis, TOKEN_ALL_ACCESS|TOKEN_EXECUTE,
NULL, SecurityIdentification, TokenPrimary, &hToken);

// Start the child process.

if ( CreateEnvironmentBlock(&lpEnvironment, hToken, TRUE) )
{
char * path = "C:\\program.exe --run";
// Start the child process.
if( !CreateProcessAsUser( hToken,
NULL,
path, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
NORMAL_PRIORITY_CLASS |CREATE_UNICODE_ENVIRONMENT,
lpEnvironment, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
OutputDebugString( "CreateProcess failed" );
}
}

пятница, 12 марта 2010 г.

WlanConnect + error 1168

Функция WlanConnect возвращает код 1168.
Причина ошибки: неверное имя профиля в структуре WLAN_CONNECTION_PARAMETERS. В системе нету wifi-профиля с таким именем.

Ещё такая ошибка возникает на Windows XP, если пытаться подключится к adhoc-сети используя только её имя без приставки "-adhoc".

четверг, 11 марта 2010 г.

Коды ошибок в windows

Platform_SDK/Include/error.h: