Qual é o formato dos logs do Android?

8

Estou tentando coletar dados sobre o meu telefone analisando os arquivos de log /dev/log. Eu estou olhando especificamente /dev/log/main. Eu sempre pensei que qualquer formato de log sadio seria texto sem formatação, mas esses arquivos parecem ser binários ou com algum conjunto de caracteres que nem eu nem meus editores de texto do Linux podemos identificar.

Qual é o formato?

Aqui estão algumas capturas de tela:

  • Primeiro, aqui está um trecho do log, interpretado por vim( ^@refere-se ao byte nulo; não tenho certeza sobre as outras sequências de controle coloridas): vim

  • A seguir, é assim que o log se parece em um editor hexadecimal: editor hexadecimal

Estou usando um Galaxy Nexus executando o Jelly Bean. Os logs foram coletados usando o root e um emulador de terminal, pois o aLogcat parece não usar o root e, portanto, não pode acessar todas as informações de log.

Scott Severance
fonte

Respostas:

6

Se você quiser informações sensatas, recomendo comandos sensatos :) (sem ofensa, apenas brincando). Portanto, a pergunta deve ser:

Como obter informações de log de um dispositivo Android?

E agora estamos do lado melhor. Existem várias abordagens que podem ser usadas:

  • utilize aplicativos para exibir informações de log (codificadas por cores)
  • utilize o ADB (parte do Android SDK) para extrair remotamente as mesmas informações
  • use ssh do controle remoto (ou de um aplicativo de terminal local) para obter as informações diretamente do dispositivo

Para lidar completamente com esse tópico, é preciso mais do que esta resposta simples (se estiver interessado, você pode, por exemplo, encontrar informações mais detalhadas em muitos sites, ou no livro Android Forensics: Investigação, Análise e Segurança Móvel para Andrew Android, de Andrew Hoog , que eu tinha o honra de traduzir para o alemão.Há provavelmente muitas outras fontes também.

Então, apenas darei alguns exemplos aqui para você começar:

Utilizando aplicativos

O aplicativo provavelmente mais conhecido nesse contexto é o aLogcat , disponível gratuitamente no playstore (e o desenvolvedor aceitará com prazer sua doação para a outra variante do mesmo aplicativo). Você encontrará uma captura de tela abaixo 1 . O aplicativo permite filtrar os logs, iniciar / parar a gravação de mensagens de log e até armazenar os trechos gravados no seu cartão SD - é claro em texto simples, conforme solicitado.

Outro aplicativo nesta seção é o Log Collector , que simplesmente tenta pegar todo o log disponível e enviá-lo pelo menu de compartilhamento 2 .

aLogCat Coletor de Log

A ponte de depuração do Android (ADB)

O Android Software Development Kit (SDK) inclui o adbcomando para várias tarefas. Entre muitos outros, oferece o adb shellcomando para executar no dispositivo. Usando isso, você também pode coletar as informações de log desejadas: basta prefixar os comandos abaixo com adb shell.

Prompt de comando no dispositivo

Usando um aplicativo de terminal (por exemplo, Android Emulator Terminal ou Terminal IDE ), você pode acessar os logs diretamente no prompt de comando, localmente no seu dispositivo. Um pouco mais confortável, isso pode ser feito com um servidor ssh (por exemplo, DroidSSHd ou DropBear SSH Server ) no seu dispositivo e acessá-lo no seu computador. Dessa forma, você pode trabalhar em uma tela grande enquanto investiga seus logs.

Comandos para acessar suas informações de log

Existem muitos comandos poderosos que você pode usar para acessar suas informações de log na linha de comando, e apenas darei alguns exemplos aqui.

dmesg

O dmesgcomando extrai o log do kernel:

$ dmesg
<6>[82839.126586] PM: Syncing filesystems ... done.
<7>[82839.189056] PM: Preparing system for mem sleep
<4>[82839.189361] Freezing user space processes ... (elapsed 0.05 seconds) done.
<4>[82839.240661] Freezing remaining freezable tasks ... (elapsed 0.00 seconds) done.
<7>[82839.242279] PM: Entering mem sleep
<4>[82839.242889] Suspending console(s) (use no_console_suspend to debug)
<7>[82839.252410] vfp_pm_save_context: saving vfp state
<6>[82839.252716] PM: Resume timer in 26 secs (864747 ticks at 32768 ticks/sec.)
<6>[82842.091369] Successfully put all powerdomains to target state
<6>[82842.092468] wakeup wake lock: wifi_wake

logcat

Com logcat, você pode acessar muitas informações de log - mas, na maioria das vezes, isso exige raiz. Possui alguns parâmetros para filtrar as informações, por exemplo, selecionando o buffer de log para leitura -b. Leia as informações fornecidas na página de desenvolvedores no logcat para obter detalhes. Para dar dois exemplos: você listaria logcat -b eventseventos ou logcat -b radioinformações no módulo de rádio do seu dispositivo.

dumpsys e dumpstate

Os dois comandos dumpsyse dumpstatefornecem informações detalhadas do sistema:

$ dumpsys
Currently running services:
    LocationProxyService
    SurfaceFlinger
    accessibility
    account
    activity
<snip>
DUMP OF SERVICE account:
Accounts: 1
    Account {[email protected], type=com.google}
<snip>
DUMP OF SERVICE alarm:

$ dumpstate
========================================================
== dumpstate: 2012-08-18 23:39:53
========================================================
Build: Gingerbread GWK74 - CyanogenMilestone2
Bootloader: 0x0000
Radio: unknown
<snip>
------ MEMORY INFO (/proc/meminfo) ------
MemTotal: 487344 kB
MemFree:   10436 kB
Buffers:   14136 kB
Cached:    145460 kB
<snip>

relatório de erro

E se você estiver com preguiça de se lembrar de todos, basta usar o bugreportcomando - que chama todos os itens acima e o agrupa para um desenvolvedor, humm, bom relatório de bug ao desenvolvedor ...

Obviamente, você pode redirecionar a saída de todos esses comandos para um arquivo para copiar para o seu computador e, na maioria dos casos, você deve fazê-lo - pois o buffer da tela seria muito pequeno para lidar com tudo: bugreport > /mnt/sdcard/bugreport.txtseria um exemplo para aquela parte.

Izzy
fonte
$ dmesgou dmsg? Deve haver um erro de digitação em um destes :)
jadkik94
@ jadkik94 esse é o meu favorito para verificar se alguém percebe ... Não, esqueça a segunda parte - e obrigado por perceber :) Corrigido.
Izzy
Eu sempre esqueço qual é o correto :) e sempre com preguiça de procurá-lo ...: P
jadkik94 1/12
3
Todos saem da conclusão do bash-auto :) Além disso: copiei os exemplos do meu livro, onde os copiei de um exemplo da vida real, então sabia qual deveria ser a versão correta. ..
Izzy
2
A mudança teve a ver com uma nova permissão necessária para ler logs de outros aplicativos. Atualmente, o aLogcat pode apenas ler seus próprios logs. A fim de obter-lo para ler os logs de outros aplicativos, você precisa dar-lhe manualmente este novas permissões assim:adb shell pm grant com.nolanlawson.logcat android.permission.READ_LOGS
Chahk
4

Para desenvolvedores (ou outras partes interessadas) que precisam analisar esse arquivo bruto, aqui estão alguns recursos:

O formato real do formato de log é detalhado em:

Uma cópia das partes relevantes, ligeiramente anotada e reordenada para sua conveniência:

#define LOGGER_ENTRY_MAX_LEN (5*1024)

struct log_msg {
    union {
        /* Maximum size of entry: 5121 bytes */
        unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1];

        struct logger_entry_v3 entry;
        struct logger_entry_v3 entry_v3;
        struct logger_entry_v2 entry_v2;
        struct logger_entry entry_v1;
    } __attribute__((aligned(4)));
}
/*
 * The userspace structure for version 1 of the logger_entry ABI.
 * This structure is returned to userspace by the kernel logger
 * driver unless an upgrade to a newer ABI version is requested.
 */
struct logger_entry {
    uint16_t    len;    /* length of the payload */
    uint16_t    __pad;  /* no matter what, we get 2 bytes of padding */
    int32_t     pid;    /* generating process's pid */
    int32_t     tid;    /* generating process's tid */
    int32_t     sec;    /* seconds since Epoch */
    int32_t     nsec;   /* nanoseconds */
    char        msg[0]; /* the entry's payload */
} __attribute__((__packed__));

/*
 * The userspace structure for version 2 of the logger_entry ABI.
 * This structure is returned to userspace if ioctl(LOGGER_SET_VERSION)
 * is called with version==2; or used with the user space log daemon.
 */
struct logger_entry_v2 {
    uint16_t    len;    /* length of the payload */
    uint16_t    hdr_size; /* sizeof(struct logger_entry_v2) */
    int32_t     pid;    /* generating process's pid */
    int32_t     tid;    /* generating process's tid */
    int32_t     sec;    /* seconds since Epoch */
    int32_t     nsec;   /* nanoseconds */
    uint32_t    euid;   /* effective UID of logger */
    char        msg[0]; /* the entry's payload */
} __attribute__((__packed__));

struct logger_entry_v3 {
    uint16_t    len;    /* length of the payload */
    uint16_t    hdr_size; /* sizeof(struct logger_entry_v3) */
    int32_t     pid;    /* generating process's pid */
    int32_t     tid;    /* generating process's tid */
    int32_t     sec;    /* seconds since Epoch */
    int32_t     nsec;   /* nanoseconds */
    uint32_t    lid;    /* log id of the payload */
    char        msg[0]; /* the entry's payload */
} __attribute__((__packed__));

Você pode diferenciar as versões das diferenças observando o terceiro e o quatro bytes. Aparentemente, o formato também depende da capacidade de endereçamento da sua plataforma. Para mensagens v1, __padé igual a 0. As mensagens v2 (e v3) usam 24 ( 0x18).

Para main, radioe systemregistros de msgcampo é interpretado da seguinte forma ( fonte ):

  • prioridade: 1 byte
  • tag: 0 ou mais bytes
  • literal \0como separador
  • mensagem: 0 ou mais bytes
  • literal \0como terminador

Se esta mensagem estiver truncada, o final \0pode estar faltando.

Para o eventsregistro, no entanto, o msgcampo contém os seguintes dados binários:

  • Etiqueta: chave inteira de 4 bytes do arquivo "/ system / etc / event-log-tags".
  • Mensagem: árvore serializada iniciando no nó raiz. Cada nó da árvore começa com um valor de 1 byte da enumeração AndroidEventLogType:
    • EVENT_TYPE_INT - o valor do nó é 4 bytes inteiros
    • EVENT_TYPE_LONG - o valor do nó é 8 bytes inteiros
    • EVENT_TYPE_STRING - o valor do nó é um número inteiro de 4 bytes length, seguido pelos lengthbytes que contêm uma sequência codificada em UTF8
    • EVENT_TYPE_LIST - o valor do nó é um byte único length, seguido pelos lengthnós da árvore, cada um por si AndroidEventLogType.
Lekensteyn
fonte