Я бы хотел сделать только комментарий, но он слишком длинный ...
Глобальные переменные по определению находятся в исполняемом файле (точнее, в разделе .data или .bss в зависимости от того, являются ли ониинициализирован или нет).Другие переменные размещаются (либо в стеке, либо в куче).
Вам даже не нужны символы, чтобы проверить, находится ли переменная (с учетом ее адреса) в одном из исполняемых разделов или нет: используйте инструментальные функции изображения (IMG_xxx
), зацикливайтесь вокруг разделов (SEC_xxx
) получить основу и конец разделов, проверить, какой это (.data или .bss).Вы можете получить тип раздела с помощью PIN-кода, используя SEC_Type
;если у вас есть адрес, если он находится внутри .bss или .data, то у вас есть глобальная переменная.
Теперь, если вам нужно имя переменной, которая находится по данному адресу, это более сложно икак гласит документация PIN, вам понадобится символическая информация.Я не знаю, может ли libelf сделать это легко, но libdwarf может.Вы также можете проверить код llvm-dwarfdump с открытым исходным кодом, который также может это делать.
note : я провел эксперименты на Windows (раздел .data
)но вывод должен быть несколько похож на Linux.
Вот небольшой пример с одной известной глобальной переменной;скомпилировано без оптимизации:
#include <iostream>
int global_counter; // global
void count(const int i)
{
int local_counter = 0; // local
for(int j = 0; j < i; j++)
{
global_counter += 1;
if(j % 2 == 0) {
local_counter += 1;
}
}
std::cout << "local counter: " << local_counter << std::endl;
}
int main(int argc, char** argv)
{
if(argc < 2) {
return -1;
}
const auto i = std::atoi(argv[1]);
if (i >= 0) {
count(i);
std::cout << "global counter: " << global_counter << std::endl;
}
return 0;
}
Вот разборка части функции count
, в которой используется глобальная переменная:
00007FF7077B10BE | 8B | mov eax,dword ptr ds:[<global_counter>] | PinTestSimpleTarget.cpp:14
00007FF7077B10C4 | FF | inc eax |
00007FF7077B10C6 | 89 | mov dword ptr ds:[<global_counter>],eax |
00007FF7077B10CC | 8B | mov eax,dword ptr ss:[rsp+20] | PinTestSimpleTarget.cpp:15
00007FF7077B10D0 | 99 | cdq |
00007FF7077B10D1 | 83 | and eax,1 |
00007FF7077B10D4 | 33 | xor eax,edx |
00007FF7077B10D6 | 2B | sub eax,edx |
00007FF7077B10D8 | 85 | test eax,eax |
00007FF7077B10DA | 75 | jne pintestsimpletarget.7FF7077B10E6 |
Разборка std :: coutв глобальной переменной:
00007FF7077B117A | 8B | mov edx,dword ptr ds:[<global_counter>] |
00007FF7077B1180 | 48 | mov rcx,rax | rax:$LN23
00007FF7077B1183 | FF | call qword ptr ds:[<&??6?$basic_ostream@DU?$char_traits@D@std |
Обратите внимание на 3 адреса:
- 00007FF7077B10BE (чтение)
- 00007FF7077B10C6 (запись)
- 00007FF7077B117A (std :: cout)
Сама глобальная переменная имеет вид:
Вот источник пинтоин (примечание:по неизвестной причине я не смог заставить CRT правильно инициализироваться при использовании std::cout
, поэтому я прибегнул к использованию printf
вместо этого.
#include "pin.H"
typedef struct _BOUNDARIES
{
ADDRINT lowest_address;
ADDRINT highest_address;
std::string to_str() const
{
std::stringstream stream;
stream << "Low Addr: " << std::hex << lowest_address <<
"; High Addr: " << highest_address;
return std::string(stream.str());
}
bool is_in_bounds(const ADDRINT addr) const
{
return addr >= lowest_address && addr < highest_address;
}
} BOUNDARIES;
/* ================================================================== */
// Global variables
/* ================================================================== */
BOUNDARIES main_executable_boundaries;
BOUNDARIES data_section_boundaries;
/* ===================================================================== */
// Utilities
/* ===================================================================== */
/*!
* Print out help message.
*/
INT32 Usage()
{
//std::cout << "[PINTOOL] This tool display the addresses of global variables in the .data section " << std::endl;
printf("[PINTOOL] This tool display the addresses of global variables in the .data section\n");
return -1;
}
/* ===================================================================== */
// Analysis routines
/* ===================================================================== */
// analysis for memory read
VOID record_mem_read(ADDRINT ip, ADDRINT addr)
{
if(data_section_boundaries.is_in_bounds(addr))
{
printf("[PINTOOL] Read on a global variable (.data); Instruction addr: %p; Read addr: %p\n", ip, addr);
}
}
// analysis for memory write
VOID record_mem_write(VOID* ip, ADDRINT addr)
{
if (data_section_boundaries.is_in_bounds(addr))
{
printf("[PINTOOL] Write on a global variable (.data); Instruction addr: %p; Write addr: %p\n", ip, addr);
}
}
/* ===================================================================== */
// Instrumentation callbacks
/* ===================================================================== */
VOID instrument_instruction(INS ins, VOID *v)
{
// must be valid and within bounds of the main executable.
if(!INS_Valid(ins) || !main_executable_boundaries.is_in_bounds(INS_Address(ins))) {
return;
}
const UINT32 mem_operands = INS_MemoryOperandCount(ins);
// Iterate over each memory operand of the instruction.
for (UINT32 memOp = 0; memOp < mem_operands; memOp++)
{
if (INS_MemoryOperandIsRead(ins, memOp))
{
INS_InsertPredicatedCall(
ins, IPOINT_BEFORE, reinterpret_cast<AFUNPTR>(record_mem_read),
IARG_INST_PTR,
IARG_MEMORYOP_EA, memOp,
IARG_END);
}
if (INS_MemoryOperandIsWritten(ins, memOp))
{
INS_InsertPredicatedCall(
ins, IPOINT_BEFORE, reinterpret_cast<AFUNPTR>(record_mem_write),
IARG_INST_PTR,
IARG_MEMORYOP_EA, memOp,
IARG_END);
}
}
}
VOID image_load(IMG img, VOID* v)
{
printf("[PINTOOL] Loading image: %s; Image ID: %i\n",IMG_Name(img).c_str(), IMG_Id(img));
if(IMG_IsMainExecutable(img)) {
// register lowest and highest addresses to restrict the trace between those addresses.
main_executable_boundaries.lowest_address = IMG_LowAddress(img);
main_executable_boundaries.highest_address = IMG_HighAddress(img);
printf("Main executable boundaries: %s\n", main_executable_boundaries.to_str().c_str());
// cycle through all sections of the main executable.
for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec))
{
// get boundaries of the '.data' section
if(SEC_Name(sec) == ".data") {
const auto sec_address = SEC_Address(sec);
data_section_boundaries.lowest_address = sec_address;
data_section_boundaries.highest_address = sec_address + SEC_Size(sec);
printf("Data section boundaries: %s\n", data_section_boundaries.to_str().c_str());
}
}
}
}
VOID image_unload(IMG img, VOID* v)
{
printf("[PINTOOL] Unloading image: %s\n", IMG_Name(img).c_str());
}
VOID fini(INT32 code, VOID *v)
{
printf("[PINTOOL] Instrumentation tear down.\n");
}
/* ===================================================================== */
// Main
/* ===================================================================== */
int main(int argc, char *argv[])
{
//std::cerr << "[PINTOOL] Loading." << std::endl;
// Initialize PIN library. Print help message if -h(elp) is specified
// in the command line or the command line is invalid
if( PIN_Init(argc,argv) )
{
return Usage();
}
// Register Instruction to be called to instrument instructions
INS_AddInstrumentFunction(instrument_instruction, nullptr);
// Register ImageLoad to be called when an image is loaded
IMG_AddInstrumentFunction(image_load, nullptr);
// Register ImageUnload to be called when an image is unloaded
IMG_AddUnloadFunction(image_unload, nullptr);
// Register function to be called when the application exits
PIN_AddFiniFunction(fini, nullptr);
//std::cerr << "[PINTOOL] Starting instrumentation." << std::endl;
// Start the program, never returns
PIN_StartProgram();
return 0;
}
.\pin.exe -t MyPinTool.dll -- PinTestSimpleTarget.exe 6
output:
[PINTOOL] Loading image: G:\Appdata\CPP\PinTestSimpleTarget\x64\Release\PinTestSimpleTarget.exe; Image ID: 1
Main executable boundaries: Low Addr: 7ff7077b0000; High Addr: 7ff7077b8fff
Data section boundaries: Low Addr: 7ff7077b5000; High Addr: 7ff7077b5640
[PINTOOL] Loading image: C:\WINDOWS\System32\KERNELBASE.dll; Image ID: 2
[PINTOOL] Loading image: C:\WINDOWS\System32\KERNEL32.DLL; Image ID: 3
[PINTOOL] Loading image: C:\WINDOWS\SYSTEM32\ntdll.dll; Image ID: 4
[PINTOOL] Loading image: C:\WINDOWS\System32\ucrtbase.dll; Image ID: 5
[PINTOOL] Loading image: C:\WINDOWS\SYSTEM32\VCRUNTIME140.dll; Image ID: 6
[PINTOOL] Loading image: C:\WINDOWS\SYSTEM32\MSVCP140.dll; Image ID: 7
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1ed1; Read addr: 0x7ff7077b5008
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1f63; Write addr: 0x7ff7077b5000
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1cb6; Read addr: 0x7ff7077b55c0
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1cc7; Write addr: 0x7ff7077b55c0
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b2265; Write addr: 0x7ff7077b501c
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b2271; Write addr: 0x7ff7077b5018
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b22c0; Read addr: 0x7ff7077b5020
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b22c0; Write addr: 0x7ff7077b5020
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b2310; Read addr: 0x7ff7077b5624
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b233f; Write addr: 0x7ff7077b5624
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b234d; Write addr: 0x7ff7077b5018
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b2357; Write addr: 0x7ff7077b501c
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b238b; Read addr: 0x7ff7077b501c
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b2394; Write addr: 0x7ff7077b5018
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b239e; Write addr: 0x7ff7077b501c
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b23ad; Write addr: 0x7ff7077b5018
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b23b7; Write addr: 0x7ff7077b501c
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b23d2; Read addr: 0x7ff7077b5030
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1c97; Read addr: 0x7ff7077b55b8
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1c97; Write addr: 0x7ff7077b55b8
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1998; Read addr: 0x7ff7077b55b0
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b19ab; Write addr: 0x7ff7077b55b0
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1d02; Read addr: 0x7ff7077b55c1
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b23d2; Read addr: 0x7ff7077b5030
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1d4f; Write addr: 0x7ff7077b55c8
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1d57; Write addr: 0x7ff7077b55d8
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1d5e; Write addr: 0x7ff7077b55e0
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1d66; Write addr: 0x7ff7077b55f0
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1d6d; Write addr: 0x7ff7077b55c1
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1e76; Read addr: 0x7ff7077b55c8
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1fca; Read addr: 0x7ff7077b5014
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1fb5; Read addr: 0x7ff7077b5610
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1fb5; Write addr: 0x7ff7077b5610
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1fbe; Read addr: 0x7ff7077b5618
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1fbe; Write addr: 0x7ff7077b5618
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b19e9; Write addr: 0x7ff7077b55b0
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b23d2; Read addr: 0x7ff7077b5030
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1e37; Read addr: 0x7ff7077b55b8
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b1e37; Write addr: 0x7ff7077b55b8
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1a0c; Read addr: 0x7ff7077b5638
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1a38; Read addr: 0x7ff7077b5630
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b10be; Read addr: 0x7ff7077b5628
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b10c6; Write addr: 0x7ff7077b5628
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b10be; Read addr: 0x7ff7077b5628
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b10c6; Write addr: 0x7ff7077b5628
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b10be; Read addr: 0x7ff7077b5628
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b10c6; Write addr: 0x7ff7077b5628
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b10be; Read addr: 0x7ff7077b5628
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b10c6; Write addr: 0x7ff7077b5628
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b10be; Read addr: 0x7ff7077b5628
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b10c6; Write addr: 0x7ff7077b5628
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b10be; Read addr: 0x7ff7077b5628
[PINTOOL] Write on a global variable (.data); Instruction addr: 0x7ff7077b10c6; Write addr: 0x7ff7077b5628
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b143d; Read addr: 0x7ff7077b5008
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1860; Read addr: 0x7ff7077b5008
local counter: 3
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b143d; Read addr: 0x7ff7077b5008
global counter: [PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b1860; Read addr: 0x7ff7077b5008
[PINTOOL] Read on a global variable (.data); Instruction addr: 0x7ff7077b117a; Read addr: 0x7ff7077b5628
6
[PINTOOL] Loading image: C:\WINDOWS\System32\kernel.appcore.dll; Image ID: 8
[PINTOOL] Loading image: C:\WINDOWS\System32\msvcrt.dll; Image ID: 9
[PINTOOL] Loading image: C:\WINDOWS\System32\RPCRT4.dll; Image ID: 10
[PINTOOL] Unloading image: G:\Appdata\CPP\PinTestSimpleTarget\x64\Release\PinTestSimpleTarget.exe
[PINTOOL] Unloading image: C:\WINDOWS\System32\KERNELBASE.dll
[PINTOOL] Unloading image: C:\WINDOWS\System32\KERNEL32.DLL
[PINTOOL] Unloading image: C:\WINDOWS\SYSTEM32\ntdll.dll
[PINTOOL] Unloading image: C:\WINDOWS\System32\ucrtbase.dll
[PINTOOL] Unloading image: C:\WINDOWS\SYSTEM32\VCRUNTIME140.dll
[PINTOOL] Unloading image: C:\WINDOWS\SYSTEM32\MSVCP140.dll
[PINTOOL] Unloading image: C:\WINDOWS\System32\kernel.appcore.dll
[PINTOOL] Unloading image: C:\WINDOWS\System32\msvcrt.dll
[PINTOOL] Unloading image: C:\WINDOWS\System32\RPCRT4.dll
[PINTOOL] Instrumentation tear down.
Очевидно, что есть некоторые другие глобальные переменные, используемые программой для внутренних целей;но по крайней мере это должно дать вам хорошее представление о том, как отслеживать глобальные переменные в вашей программе.