Проверить загруженные общие библиотеки из другой общей библиотеки в Linux/Android

Можно ли проверить, какие разделяемые библиотеки загружаются вызывающим процессом из другой разделяемой библиотеки (.so)? Я знаю, что для этого есть инструменты командной строки, но можно ли выполнить такую ​​проверку в коде C++?

Мне нужно каким-то образом получить список собственных общих библиотек, загруженных приложением Android, но это не представляется возможным из кода Java.


person vitakot    schedule 05.01.2012    source источник


Ответы (2)


Вы можете использовать /proc/<pid>/maps файл или просто /proc/self/maps для вызывающего процесса: строки, которые заканчиваются на «.so», предназначены для связанных общих библиотек. Это хак, но должно работать. Обратите внимание, что одна библиотека может быть отображена несколько раз, поэтому вам нужно пропустить повторения.

И хорошие новости: вы можете сделать это из java. Фрагмент кода ниже выводит общие библиотеки для текущего процесса в logcat.

try {
    Set<String> libs = new HashSet<String>();
    String mapsFile = "/proc/self/maps";
    BufferedReader reader = new BufferedReader(new FileReader(mapsFile));
    String line;
    while ((line = reader.readLine()) != null) {
        if (line.endsWith(".so")) {
            int n = line.lastIndexOf(" ");
            libs.add(line.substring(n + 1));
        }
    }
    Log.d("Ldd", libs.size() + " libraries:");
    for (String lib : libs) {
        Log.d("Ldd", lib);
    }
} catch (FileNotFoundException e) {
    // Do some error handling...
} catch (IOException e) {
    // Do some error handling...
}

Вывод на моем устройстве:

D/Ldd     (11286): 55 libraries:
D/Ldd     (11286): /system/lib/libc.so
D/Ldd     (11286): /system/lib/libdbus.so
D/Ldd     (11286): /system/lib/librpc.so
D/Ldd     (11286): /system/lib/libEGL.so
D/Ldd     (11286): /system/lib/libstagefright_color_conversion.so
D/Ldd     (11286): /system/lib/libmedia.so
D/Ldd     (11286): /system/lib/libemoji.so
D/Ldd     (11286): /system/lib/libcrypto.so
D/Ldd     (11286): /system/lib/libstagefright_avc_common.so
D/Ldd     (11286): /system/lib/libnativehelper.so
D/Ldd     (11286): /system/lib/libskiagl.so
D/Ldd     (11286): /system/lib/libopencore_player.so
D/Ldd     (11286): /system/lib/libjpeg.so
D/Ldd     (11286): /system/lib/libsurfaceflinger_client.so
D/Ldd     (11286): /system/lib/libstagefright.so
D/Ldd     (11286): /system/lib/libdrm1.so
D/Ldd     (11286): /system/lib/libdvm.so
D/Ldd     (11286): /system/lib/libwebcore.so
D/Ldd     (11286): /system/lib/libGLESv1_CM.so
D/Ldd     (11286): /system/lib/libhardware.so
D/Ldd     (11286): /system/lib/libexif.so
D/Ldd     (11286): /system/lib/libgps.so
D/Ldd     (11286): /system/lib/liblog.so
D/Ldd     (11286): /system/lib/libexpat.so
D/Ldd     (11286): /system/lib/libopencore_common.so
D/Ldd     (11286): /system/lib/libbluedroid.so
D/Ldd     (11286): /system/lib/libm.so
D/Ldd     (11286): /system/lib/libicui18n.so
D/Ldd     (11286): /system/lib/libomx_amrenc_sharedlibrary.so
D/Ldd     (11286): /system/lib/libwpa_client.so
D/Ldd     (11286): /system/lib/libstdc++.so
D/Ldd     (11286): /system/lib/libandroid_runtime.so
D/Ldd     (11286): /system/lib/libz.so
D/Ldd     (11286): /system/lib/libETC1.so
D/Ldd     (11286): /system/lib/libsonivox.so
D/Ldd     (11286): /system/lib/libstlport.so
D/Ldd     (11286): /system/lib/libutils.so
D/Ldd     (11286): /system/lib/libicudata.so
D/Ldd     (11286): /system/lib/libsqlite.so
D/Ldd     (11286): /system/lib/libhardware_legacy.so
D/Ldd     (11286): /system/lib/libpixelflinger.so
D/Ldd     (11286): /system/lib/libvorbisidec.so
D/Ldd     (11286): /system/lib/libstagefright_amrnb_common.so
D/Ldd     (11286): /system/lib/libcutils.so
D/Ldd     (11286): /system/lib/libui.so
D/Ldd     (11286): /system/lib/libmedia_jni.so
D/Ldd     (11286): /system/lib/libomx_sharedlibrary.so
D/Ldd     (11286): /system/lib/libcamera_client.so
D/Ldd     (11286): /system/lib/libskia.so
D/Ldd     (11286): /system/lib/libopencore_net_support.so
D/Ldd     (11286): /system/lib/libnetutils.so
D/Ldd     (11286): /system/lib/libbinder.so
D/Ldd     (11286): /system/lib/libssl.so
D/Ldd     (11286): /system/lib/libicuuc.so
D/Ldd     (11286): /system/lib/libGLESv2.so

Также при необходимости pid можно получить по android.os.Process.myPid().

person praetorian droid    schedule 05.01.2012
comment
Нет, для этого вам не нужен какой-либо инструмент командной строки. Я обновил свой ответ. - person praetorian droid; 05.01.2012
comment
Отличный пример! Но он показывает мне ошибку: метод myPid() не определен для типа Process... - person vitakot; 05.01.2012
comment
ОК, я понял, просто нужно вызвать android.os.Process.myPid() - person vitakot; 05.01.2012
comment
Да, вы правы насчет Process. Я обновил ответ (для других), чтобы не путать с java.lang.Process. - person praetorian droid; 05.01.2012
comment
Вы также можете просто использовать /proc/self вместо того, чтобы возиться с Process.myPid(); self — символическая ссылка на текущий PID - person Michael Mrozek; 29.05.2015
comment
Это правда, спасибо. Я пропустил это. Обновил ответ. - person praetorian droid; 30.05.2015

WRT java, запустите процесс вызова ldd для рассматриваемого .so. Захватите вывод из stdout и обработайте вывод:

Process process = Runtime.getRuntime().exec("ldd a.so");  
StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream());  
outputGobbler.start();  
process.waitFor();  
String result = outputGobbler.buffer;  

Обратитесь к основному сообщению на StreamGobbler для определения класса. Я добавил переменную String buffer и заменил эту строку System.out.println(type + ">" + line); на эту buffer = buffer + line+"\n"; в определении класса из предыдущей ссылки. Я также, очевидно, отказался от второго аргумента конструктора.

class StreamGobbler extends Thread
{
    InputStream is;
    String buffer;

    StreamGobbler(InputStream is)
    {
        this.is = is;
        this.buffer = "";
    }

    public void run()
    {
        try
        {
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line=null;
            while ( (line = br.readLine()) != null)
                buffer += line+"\n";    
            } catch (IOException ioe)
              {
                ioe.printStackTrace();  
              }
    }
}
person ajshower    schedule 05.01.2012
comment
К сожалению, в стандартной (немодифицированной) системе Android нет команды ldd. - person praetorian droid; 05.01.2012
comment
nm тоже нет. Нет даже grep или find или большинства других стандартных инструментов UNIX. Вы можете проверить это в эмуляторе. - person praetorian droid; 05.01.2012
comment
Извините, я основывал свои ответы на теге linux. У меня нет никакого опыта Android или эмулятора. - person ajshower; 05.01.2012