2013-06-11 4 views
3

У меня есть проблема, которую я не могу решить за несколько недель. Я уверен, что есть решение, и, возможно, у него есть идея.Перезаписать c статической функцией позади указателя функции

Там это общая библиотека называется libaudio.so который выглядит следующим образом:

static ssize_t out_write(..) 
{ 
    // /!\ I need to overwrite/extend this function 
    return 0; 
} 

static int adev_open_output_stream(struct audio_stream_out **stream_out) 
{ 
    struct stream_out *out; 
    out = (struct stream_out *)calloc(1, sizeof(struct stream_out)); 
    if (!out) 
      return -ENOMEM; 

    out->stream.write = out_write; // pointer to static function above 

    *stream_out = &out->stream; 
    return 0; 
} 

static int adev_open(hw_device_t** device) 
{ 
    struct audio_device *adev; 
    adev = calloc(1, sizeof(struct audio_device)); 
    if (!adev) 
      return -ENOMEM; 

    adev->hw_device.open_output_stream = adev_open_output_stream; // pointer to static function above 

    *device = &adev->hw_device.common;  
    return 0; 
} 

static struct hw_module_methods_t hal_module_methods = { 
    .open = adev_open, // this function can be called after obtained via dlsym() below 
}; 

struct audio_module HAL_MODULE_INFO_SYM = { 
     .methods = &hal_module_methods, // this field is public available and can be called via dlsym() 
}; 

Мой код (также общая библиотека имени libplugin.so) ниже работает как плагин под процесс.

Этот процесс ранее открытый libaudio.so (выше), получают * * HAL_MODULE_INFO_SYM и называется

HAL_MODULE_INFO_SYM->methods->open(device) 

я не имеют доступа к устройства -instance процесса, так что я не могу просто перезаписывать записи с функцией

struct audio_stream_out **stream_out 
device->open_output_stream(stream_out) 
stream_out.write = MY_WRITE_FUNCTION 

Но вот моя надежда:

Как я работаю в том же самом процессе, который ранее dlopen'd libaudio.so, я также могу назвать dlopen («libaudio.so») и получит такую ​​же ссылку на эту библиотеку, как и раньше.

Я также могу вызвать dlsym (HAL_MODULE_INFO_SYM) и затем получить ту же публичную структуру. Тогда я мог позвонить open и * open_output_stream *, а затем теоретически изменить указатель на написать -функция.

Но, с моим началом C-знанием, это не повлияет на экземпляр процесса, а только на мой собственный экземпляр.

Это означает: процесс все еще имеет оригинальную запись -функция за его примером, и только мой экземпляр будет вызывать MY_WRITE_FUNCTION.

Я не знаю, как заставить процесс перезагрузить HAL_MODULE_INFO_SYM и вспомнить HAL_MODULE_INFO_SYM-> methods-> открытое (устройство) - поэтому изменение этот символ не будет работать.

Я не могу изменить внешний код и не изменять libaudio.so. У меня есть только доступ к моему собственному маленькому libplugin.so.

Я был бы очень благодарен, если кто-то может мне помочь.

+0

Вы хотите переписать функцию _pointer_, а не фактический код функции, правильно? Кроме того, я думаю, что символ, который вы используете, не экспортируется из библиотеки? Как структура libaudio.so структурирована и построена? – idoby

+0

Как я уже сказал, я относительно новичок в C, поэтому не понимаю все, что вы просили. Но я знаю, что процесс, называемый моим libplugin.so, ранее назывался ** handle = dlopen ('libaudio.so', RTLD_NOW); dlsym (handle, HAL_MODULE_INFO_SYM) -> методы-> открыть (устройство); ** и ** device-> open_output_stream (..) **. Весь код, кроме libplugin.so, вышел из моей области действия и на запущенной системе, которая не под моим контролем. –

+0

'out-> stream.write' и т. Д. Вы знаете, что переменная' out' неинициализирована, указывая на la-la land? Он не указывает на выделенную память. Конечно, это не может быть реальный код, пожалуйста, опубликуйте его. Если этот _is_ реальный код, предмет указателя функции является наименьшим из ваших многочисленных, серьезных проблем ... – Lundin

ответ

1

Я думаю, что это можно сделать, но только если вы вмешались в до процесс звонков libaudio.so.

В то время, вы можете получить адрес HAL_MODULE_INFO_SYM в libaudio.so (с использованием dlopen, как вы предложили), скопировать methods указатель где-то и заменить его с указателем на вашу собственную структуру методов. Методы в этой структуре просто вызывают исходные методы из сохраненного указателя.
Само по себе это ничего не достигает, но ваш метод open может, после вызова реального open, увидеть возвращенный dev и манипулировать им.

Если вы не сделали это вовремя, у процесса уже есть указатель dev, и я не вижу способа его изменить.

Но я хочу предупредить вас, что все это кажется хрупким и зависит от деталей реализации libaudio.so. Это очень легко приведет к неприятностям, особенно если библиотека будет изменена в будущем.

+0

Да, это работает, но, к сожалению, мой плагин загружен после libaudio.so, порядок не может быть изменен :) Я почти не ищу способ заставить перезагрузить эту часть. –

Смежные вопросы