Ответ 1
Мой вопрос в том, как я могу получить адрес, который вызвал основной дамп в C?
Краткий ответ:
Есть два способа интерпретировать этот вопрос.
-
Каков был адрес инструкции о неисправности?
-
Каким был адрес, который был за пределами границ?
Откидные отвалы эльфов хранят всю метаинформацию в заметках, которые сохраненный в сегменте примечаний. Примечания имеют разные типы.
Чтобы ответить на # 1, нам нужно захватить регистры. Посмотрите на заголовок эльфа, чтобы
найдите таблицу заголовков программ. Пройдите таблицу заголовков программ, чтобы найти
таблица примечаний (тип PT_NOTE). Пройдите стол для заметок, чтобы найти примечание
тип NT_PRSTATUS. Полезная нагрузка этой заметки - struct
elf_prstatus
, которую можно найти в linux/elfcore.h. Один из
поля этой структуры - все регистры общего назначения. грейфер
% rip, и все готово.
Для # 2 мы делаем что-то подобное. На этот раз мы ищем записку типа NT_SIGINFO. Полезной нагрузкой этой заметки является структура siginfo_t определенный в сигнале .h. Для применимых сигналов (SIGILL, SIGFPE, SIGSEGV, SIGBUS), поле si_addr будет содержать адрес, который вы пытались доступ, но не мог.
Более подробная информация приведена ниже. В примере core dump, rip - 0x400560, адрес инструкции, который пытался сделать незаконный доступ. Это отображается вместе с остальными регистрами общего назначения.
Память, которую программа пыталась получить, равна 0x03. Это отображается вместе с остальной информацией о сигнале.
Длинный ответ:
Я думаю, что BFD имеет 25-летнюю рывку, поэтому я бы не использовал его просто для того, чтобы сбрасывать содержимое основного файла в ящик Linux. Возможно, если бы вам пришлось написать какой-то код общего назначения, который должен работать с кучей форматов, но даже тогда я не уверен, что сегодня я пойду.
эльф spec довольно хорошо написан, и нетрудно просто пройти через таблицы заголовков программ или заголовков разделов по мере необходимости. Вся метаинформация процесса в основном файле содержится в наборе заметок в сегменте программы PT_NOTE, который может быть проанализирован всего несколькими строками прямого кода C.
Я написал небольшую программу для захвата регистров из основного файла x86_68 и печати некоторых метаданных. Я положил его на github. Логика получения полезной нагрузки примечания находится в этой функции:
void *get_note(void *vp, int nt_type){
Elf64_Ehdr *eh=vp;
for(int i=0; i<eh->e_phnum; ++i){
Elf64_Phdr *ph=(vp+eh->e_phoff+i*eh->e_phentsize);
if(ph->p_type!=PT_NOTE){
continue;
}
void *note_table=(vp + ph->p_offset);
void *note_table_end=(note_table+ph->p_filesz);
Elf64_Nhdr *current_note=note_table;
while(current_note<(Elf64_Nhdr *)note_table_end){
void *note_end=current_note;
note_end += 3*sizeof(Elf64_Word);
note_end += roundup8(current_note->n_namesz);
if(current_note->n_type==nt_type){
return note_end;
}
note_end += roundup8(current_note->n_descsz);
current_note=note_end;
}
}
return 0;
}
Функция передается указателем на файл elf и тип заметки и возвращает указатель на полезную нагрузку связанной ноты, если она существует. Различные возможные типы нот находятся в elf.h. Типы заметки, которые я фактически вижу в основных файлах на моей машине:
#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
#define NT_FPREGSET 2 /* Contains copy of fpregset struct */
#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */
#define NT_AUXV 6 /* Contains copy of auxv array */
#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */
#define NT_SIGINFO 0x53494749 /* Contains copy of siginfo_t,
size might increase */
#define NT_FILE 0x46494c45 /* Contains information about mapped
files */
Большинство этих структур находятся в заголовках под /usr/include/linux. Структура xsave представляет собой пару КБ информации с плавающей точкой, описанную в Ch 13 руководства intel. В нем записаны SSE, AVX и MPX.
Полезная нагрузка NT_FILE, похоже, не имеет связанной структуры в заголовке, но она описана в комментарии ядра (fs/binfmt_elf.c):
/*
* Format of NT_FILE note:
*
* long count -- how many files are mapped
* long page_size -- units for file_ofs
* array of [COUNT] elements of
* long start
* long end
* long file_ofs
* followed by COUNT filenames in ASCII: "FILE1" NUL "FILE2" NUL...
*/
Изменения для анализа файла эльфа для 32-битной системы довольно тривиальны. Используйте соответствующие структуры Elf32_XXX и округлите до 4 вместо 8 для полей с переменным размером.
Я добавлял материал этой маленькой программе последние пару дней. В настоящее время он содержит заголовок файла, заголовки сегментов, общие регистры, статус программы, информацию о программе и обратную трассировку. Я добавлю поддержку для остальных заметок, когда получаю время. Вот текущий вывод:
$ ./read_pc -biprst core
General Registers:
r15 0x000000000000000000 r14 0x000000000000000000
r13 0x0000007ffc20d36a50 r12 0x000000000000400430
rbp 0x0000007ffc20d36950 rbx 0x000000000000000000
r11 0x000000000000000246 r10 0x000000000000000000
r9 0x000000000000000002 r8 0x000000000000000000
rax 0x000000000000000003 rcx 0x00000000007ffffffe
rdx 0x0000007f5817523780 rsi 0x000000000000000001
rdi 0x000000000000000001 ss 0x00000000000000002b
rip 0x000000000000400560 cs 0x000000000000000033
eflags 0x000000000000010246 rsp 0x0000007ffc20d36950
fs_base 0x0000007f5817723700 gs_base 0x000000000000000000
ds 0x000000000000000000 es 0x000000000000000000
fs 0x000000000000000000 gs 0x000000000000000000
orig_rax 0x00ffffffffffffffff
Program status:
signo 11 signal code 0 errno 0
cursig 11 sigpend 000000000000000000 sigheld 000000000000000000
pid 27547 ppid 26600 pgrp 27547 sid 26600
utime: 0.000000 stime 0.000000
cutime: 0.000000 cstime 0.000000
fpvalid: 1
Signal Information:
signo: 11 errno 0 code 1
addr 0x3 addr_lsb 0 addr_bnd ((nil), (nil))
Process Information:
state 0 (R) zombie 0 nice 0 flags 0x400600
uid 1000 gid 1000 pid 27547 ppid 26600 pgrp 27547 sid 26600
fname: foo
args: ./foo
Backtrace:
rip = 0x000000000000400560
rip = 0x000000000000400591
rip = 0x0000000000004005a1
Program Headers:
Type Offset Virt Addr PhysAddr
FileSiz MemSize Flags Align
NOTE 0x00000000000004a0 0x0000000000000000 0000000000000000
0x0000000000000b98 0x0000000000000000 0x000000
LOAD 0x0000000000002000 0x0000000000400000 0000000000000000
0x0000000000001000 0x0000000000001000 R X 0x001000
LOAD 0x0000000000003000 0x0000000000600000 0000000000000000
0x0000000000001000 0x0000000000001000 X 0x001000
LOAD 0x0000000000004000 0x0000000000601000 0000000000000000
0x0000000000001000 0x0000000000001000 WX 0x001000
LOAD 0x0000000000005000 0x00000000018bf000 0000000000000000
0x0000000000021000 0x0000000000021000 WX 0x001000
LOAD 0x0000000000026000 0x00007f581715e000 0000000000000000
0x0000000000001000 0x00000000001c0000 R X 0x001000
LOAD 0x0000000000027000 0x00007f581731e000 0000000000000000
0x0000000000000000 0x00000000001ff000 0x001000
LOAD 0x0000000000027000 0x00007f581751d000 0000000000000000
0x0000000000004000 0x0000000000004000 X 0x001000
LOAD 0x000000000002b000 0x00007f5817521000 0000000000000000
0x0000000000002000 0x0000000000002000 WX 0x001000
LOAD 0x000000000002d000 0x00007f5817523000 0000000000000000
0x0000000000004000 0x0000000000004000 WX 0x001000
LOAD 0x0000000000031000 0x00007f5817527000 0000000000000000
0x0000000000001000 0x0000000000026000 R X 0x001000
LOAD 0x0000000000032000 0x00007f5817722000 0000000000000000
0x0000000000003000 0x0000000000003000 WX 0x001000
LOAD 0x0000000000035000 0x00007f581774a000 0000000000000000
0x0000000000002000 0x0000000000002000 WX 0x001000
LOAD 0x0000000000037000 0x00007f581774c000 0000000000000000
0x0000000000001000 0x0000000000001000 X 0x001000
LOAD 0x0000000000038000 0x00007f581774d000 0000000000000000
0x0000000000001000 0x0000000000001000 WX 0x001000
LOAD 0x0000000000039000 0x00007f581774e000 0000000000000000
0x0000000000001000 0x0000000000001000 WX 0x001000
LOAD 0x000000000003a000 0x00007ffc20d16000 0000000000000000
0x0000000000022000 0x0000000000022000 WX 0x001000
LOAD 0x000000000005c000 0x00007ffc20d9c000 0000000000000000
0x0000000000002000 0x0000000000002000 X 0x001000
LOAD 0x000000000005e000 0x00007ffc20d9e000 0000000000000000
0x0000000000002000 0x0000000000002000 R X 0x001000
LOAD 0x0000000000060000 0xffffffffff600000 0000000000000000
0x0000000000001000 0x0000000000001000 R X 0x001000
All worked