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, otoollub 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.

questionAnswers(1)

yourAnswerToTheQuestion