2016-09-15 2 views
4

Возможно ли узнать аргументы функции и типы имен переменных во время выполнения в программе C? Например, если у меня есть функция:имя переменной, аргументы функции во время выполнения в C

int abc(int x, float y , somestruct z){ 
    char a; 
    int b ; 
} 

Могу ли я знать, внутри этой функции abc(), какие имена аргументов и переменных т.е. в этом случае его x, y, z, a, b и они имеют тип int, float, somestruct, char, int.

Скажем, если есть еще одна функция:

float some_func(specialstruct my_struct, int index){ 

} 

я должен знать, что имя аргументы my_struct, index и типы specialstruct, int.

Мне нужна эта информация во время выполнения?

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

Мне удалось извлечь имя функции, используя обратный адрес и dladdr() функция.

Я вижу GDB делает это, поэтому должна быть возможность извлечь эту информацию?

+7

Зачем вам эти имена во время выполнения? Что вы можете с ними сделать? – Mat

+2

C - это скомпилированный язык. Как только программа была скомпилирована (или, другими словами, после ее преобразования в машинный код), все имена переменных, имена функций и т. Д. Исчезли. Итак, ответ: Нет. С другой стороны, GDB знает имена переменных и функций, потому что программа была скомпилирована со специальными параметрами, но это полезно только для отладки. –

+0

'gdb' использует отладочную информацию, которая генерируется компилятором. См. Http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information/ – purplepsycho

ответ

1

В C. нет такого отражения или подобных вещей. Если вы хотите такой объект, вы должны разработать некоторые утилиты, макросы для этой цели и использовать специальные правила кодирования для достижения желаемого эффекта. Но ИМО - это не будет читаемым и понятным C-кодом.

1

На самом деле не существует родного способа сделать это в C. На других языках то, что вы искали бы, было бы отражением. Вы можете использовать его с макросами и некоторыми трюками, но по основному принципу вам нужно знать имена переменных и аргументы во время компиляции.

+0

@Mat Видимо, я сделал там мозговой штурм. Я имел в виду аргументы, с которыми запускается _program_. Исправление. – Magisch

0

Существует ограниченный способ интроспекции, предоставляемый совместно библиотечными функциями dlsym и dladdr, предоставляющий имя-на-адрес и наоборот. Это, однако, не является частью языка C, а скорее функцией, предоставляемой динамическим загрузчиком ОС. Вы, однако, можете не вычесть, например, какой именно символ, который вы нашли, является переменной или функцией.

backtrace и др. Составляют расширение GNU для стандарта, которое позволяет анализировать стек вызовов функции (историю вызовов). Если в двоичном файле все еще присутствуют символы (имена функций), то backtrace_symbols позволит вам их восстановить.

Предопределенные макросы __LINE__ и __FILE__ обеспечивают способ сброса, где вы также находитесь, и могут быть основой некоторых очень полезных макросов для трассировки.

И вот оно. C не дает больше интроспекции, чем это. Имена и типы параметров исчезают в двоичном формате, сигнатуры функций также исчезают, а также отображаются типы результатов.

0

Как уже отмечалось, отражение не встроено в язык C или C++.Существует множество идей. here

Однако отражение возможно в C/C++ с помощью сторонней библиотеки и отладки символов в исполняемом файле или внешнем файле.

dwarfdump исполняемый файл более или менее делает то, на что вы надеетесь. С данными DWARF доступны сведения о функциях, переменных, типах и т. Д. Аналогичным образом, функция libdwarfdump может использоваться процессом для проверки самого себя.

Вот простой ручной пример:

typedef struct somestruct 
{ 
    int i; 
    int j; 
} somestruct ; 

int abc(int x, float y , struct somestruct z){ 
    char a; 
    int b ; 
} 


int main(int argc, char* argv[]) 
{ 

    struct somestruct z; 
    abc(1,1.0f,z); 
    return 0; 
} 

и частичный выход из dwarfdump

< 1><0x00000055> DW_TAG_subprogram 
         DW_AT_external    yes(1) 
         DW_AT_name     "abc" 
         DW_AT_decl_file    0x00000001 /tmp/dwarf.c 
         DW_AT_decl_line    0x00000009 
         DW_AT_prototyped   yes(1) 
         DW_AT_type     <0x0000004e> 
         DW_AT_low_pc    0x004004ed 
         DW_AT_high_pc    <offset-from-lowpc>18 
         DW_AT_frame_base   len 0x0001: 9c: DW_OP_call_frame_cfa 
         DW_AT_GNU_all_call_sites yes(1) 
         DW_AT_sibling    <0x000000ad> 
< 2><0x00000076>  DW_TAG_formal_parameter 
         DW_AT_name     "x" 
         DW_AT_decl_file    0x00000001 /tmp/dwarf.c 
         DW_AT_decl_line    0x00000009 
         DW_AT_type     <0x0000004e> 
         DW_AT_location    len 0x0002: 916c: DW_OP_fbreg -20 
< 2><0x00000082>  DW_TAG_formal_parameter 
         DW_AT_name     "y" 
         DW_AT_decl_file    0x00000001 /tmp/dwarf.c 
         DW_AT_decl_line    0x00000009 
         DW_AT_type     <0x000000ad> 
         DW_AT_location    len 0x0002: 9168: DW_OP_fbreg -24 
< 2><0x0000008e>  DW_TAG_formal_parameter 
         DW_AT_name     "z" 
         DW_AT_decl_file    0x00000001 /tmp/dwarf.c 
         DW_AT_decl_line    0x00000009 
         DW_AT_type     <0x0000002d> 
         DW_AT_location    len 0x0002: 9160:  DW_OP_fbreg -32 

При тщательном исследовании, мы можем увидеть фрагмент определяет функцию «ABC» с заданы параметры х, y и z.

Тип параметра x является ссылкой на таблицу типов с ключом 0x4e.

Если посмотреть в другом месте на выходе, мы можем увидеть определение типа 0x4e. Тип 0x2d - это somestruct, связанный назад с параметром z.

< 1><0x0000002d> DW_TAG_structure_type 
         DW_AT_name     "somestruct" 
         DW_AT_byte_size    0x00000008 
         DW_AT_decl_file    0x00000001 /tmp/dwarf.c 
         DW_AT_decl_line    0x00000003 
         DW_AT_sibling    <0x0000004e> 

< 1><0x0000004e> DW_TAG_base_type 
         DW_AT_byte_size    0x00000004 
         DW_AT_encoding    DW_ATE_signed 
         DW_AT_name     "int" 

Сочетание ptrace, ELF, DWARF и/Proc файловая система позволяют GDB читать статическую и динамическую информацию для процесса. Другой процесс может использовать аналогичную функциональность для создания функциональности Reflection.

Я использовал варианты этой стратегии для создания пользовательских отладчиков и детекторов утечки памяти. Однако я никогда не видел эту стратегию, используемую для бизнес-логики.

Смежные вопросы