Programowe znajdowanie przesunięć symboli lokalnych we wspólnych bibliotekach w systemie OS X
Muszę znaleźć przesunięcie symbolu lokalnego w bibliotece współdzielonej w OS X. Symbol lokalny jak w nieeksportowanym symbolu. W związku z tymdyld("symbol_name")
nie będzie działać.
Mogę jednak użyćnm
na przykład znaleźć te przesunięcia
$ nm /System/Library/PrivateFrameworks/DesktopServicesPriv.framework/DesktopServicesPriv | grep -e ChildSetLabel -e NodeVolumeEject
000000000006cccd T _NodeVolumeEject
000000000009dbd7 t __ChildSetLabel
Widzimy wyeksportowane (T
) symbolNodeVolumeEject
który jest offset0x6cccd
Mogę z łatwością odkryć, jak to zrobićdyld("NodeVolumeEject")
. dyld()
ujawni adres w bieżącej przestrzeni adresowej, ale jestem zadowolony z przesunięcia w bibliotece współdzielonej lub adresu bezwzględnego w przestrzeni adresowej. Dodatkowo jest lokalny (t
) symbol_ChildSetLabel
który offset (0x9dbd7
) Nie mogę ujawnić używaniadyld()
.
Chciałbym móc programowo wykonać tę rozdzielczość (bezgobjdump
, nm
, otool
lub dowolny inny program zewnętrzny). Czy istnieje „łatwy” sposób na osiągnięcie tego? Kod źródłowy wyżej wymienionych narzędzi zawiera potrzebny kod, ale zastanawiam się, czy nie ma czegoś prostszego.
Domena: Rozwiązanie musi działać tylko na OS X 10.8 lub nowszym dla plików binarnych MachO x86_64.
Wyjaśnienie: Byłbym szczęśliwy, gdybym odkrył, że absolutne przesunięcie w bieżącym przesunięciu (które z powodu ASLR) nie jest oczywiście statyczne. Ale cieszę się również, że mogę znaleźć przesunięcie względem początku tej biblioteki, która pozostaje statyczna (aż do rekompilacji). Część od „adresu w bibliotece” do „adresu w przestrzeni adresowej” jest całkiem prosta:
off_t sym_offset_child_set_label = ANSWER_TO_THIS_QUESTION("_ChildSetLabel");
Dl_info info;
void *abs_volume_eject = dlsym(RTLD_DEFAULT, "NodeVolumeEject");
void *abs_child_set_label = NULL;
if (dladdr(abs_volume_eject, &info)) {
abs_child_set_label = (void *)((char *)info.dli_fbase + sym_offset_child_set_label);
/* abs_child_set_label now points to the function in question */
}
To tak długo, jak_ChildSetLabel
iNodeVolumeEject
są w tej samej bibliotece współdzielonej. Dlatego ASLR nie stanowi tutaj problemu.