Encontrando deslocamentos de símbolos locais em bibliotecas compartilhadas programaticamente no OS X
Eu preciso encontrar o deslocamento de um símbolo local em uma biblioteca compartilhada no OS X. Símbolo local como no símbolo não exportado. Assim sendodyld("symbol_name")
não funciona.
Eu posso no entanto usarnm
para encontrar esses offsets, por exemplo
$ nm /System/Library/PrivateFrameworks/DesktopServicesPriv.framework/DesktopServicesPriv | grep -e ChildSetLabel -e NodeVolumeEject
000000000006cccd T _NodeVolumeEject
000000000009dbd7 t __ChildSetLabel
Lá vemos o exportado (T
) símboloNodeVolumeEject
qual é o offset0x6cccd
Eu posso facilmente revelar usandodyld("NodeVolumeEject")
. dyld()
revelará o endereço no espaço de endereço atual, mas estou satisfeito com o deslocamento na biblioteca compartilhada ou com o endereço absoluto no espaço de endereço. Além disso, há o local (t
) símbolo_ChildSetLabel
qual é compensado (0x9dbd7
) Não posso revelar usandodyld()
.
Eu gostaria de poder fazer essa resolução programaticamente (semgobjdump
, nm
, otool
, ou qualquer outro programa externo). Existe uma maneira "fácil" de conseguir isso? O código fonte das ferramentas mencionadas acima contém o código necessário, mas me pergunto se não há algo mais direto.
Domínio: A solução tem apenas que funcionar no OS X 10.8 ou melhor para binários x86_64 do MachO.
Esclarecimento: Eu ficaria feliz em descobrir o deslocamento absoluto no deslocamento atual (que devido a ASLR) não é estático, obviamente. Mas também fico feliz em descobrir o deslocamento em relação ao início dessa biblioteca, que permanece estática (até a recompilação). A parte de "endereço na biblioteca" para "endereço no espaço de endereço" é bastante fácil:
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 */
}
Isto é, desde que_ChildSetLabel
eNodeVolumeEject
estão na mesma biblioteca compartilhada o suficiente. Portanto, o ASLR não é um problema aqui.