В общем случае правильно, что статическая глобальная переменная недоступна. Он даже может быть оптимизирован при некоторых обстоятельствах, так что фиксированной области памяти вообще не существует.
Но если он не оптимизирован, то, конечно, всегда есть «хакерские» способы получить к нему доступ. Сканирование таблицы символов, однако, не вариант, так как символ обычно там не указан. Вы должны копать глубже в коде сборки. Этот пример для linux с процессором gcc и x86_64. Предполагается, что источник доступен для идентификации доступа к переменной в коде сборки.
Представьте себе следующий исходный файл общего объекта:
static int bar = 31337;
int foo (void) {
bar = getpid();
}
bar
- ваша статическая переменная. Теперь вы можете узнать смещение bar
из функции foo
, которая всегда постоянна, несмотря на перемещение всей библиотеки, изучив разобранный источник:
objdump -x shared.so
00000000000006a0 <foo>:
6a0: 48 83 ec 08 sub $0x8,%rsp
6a4: 31 c0 xor %eax,%eax
6a6: e8 c5 fe ff ff callq 570 <getpid@plt>
6ab: 89 05 c7 02 20 00 mov %eax,0x2002c7(%rip) # 200978 <_fini+0x2002c0>
6b1: 48 83 c4 08 add $0x8,%rsp
6b5: c3 retq
Здесь вы видите, что функция foo
имеет адрес 6a0
(подлежит перемещению позже), а статическая глобальная переменная bar
доступна по адресу 200978
, что дает общее смещение 200978-6a0 = 2002D8
. Так что если вы откроете общую библиотеку
void *h = dlopen("shared.so", RTLD_LAZY);
и поиск символа foo
void *foo = dlsym(h, "foo");
Вы можете рассчитать адрес bar
, добавив вычисленное смещение:
int *a = foo + 0x2002D8;
printf("%d\n", *a);
Хакерский путь, как и просили;)