GNU/Linux >> Belajar Linux >  >> Linux

Mengupas perpustakaan bersama linux

Jika Anda membungkus bagian pribadi Anda dalam ruang nama anonim maka tidak ada std::abs maupun private_function dapat dilihat pada tabel simbol:

namespace{
#include<cmath>
  float private_function(float f)
  {
    return std::abs(f);
  }
}
extern "C" float public_function(float f)
{
        return private_function(f);
}

kompilasi (g++ 4.3.3):

g++ -shared -o libtest.so test.cpp -s

memeriksa:

# nm -DC libtest.so
         w _Jv_RegisterClasses
0000200c A __bss_start
         w __cxa_finalize
         w __gmon_start__
0000200c A _edata
00002014 A _end
000004a8 T _fini
000002f4 T _init
00000445 T public_function

Perlu diketahui bahwa Ulrich Drepper menulis esai tentang (semua?) aspek penulisan pustaka bersama untuk Linux/Unix, yang mencakup kontrol simbol yang diekspor di antara banyak topik lainnya.

Ini sangat berguna untuk memperjelas cara mengekspor hanya fungsi pada daftar putih dari lib bersama.


Penggunaan Anda atas atribut visibilitas default dan -fvisibility=hidden harus ditambah dengan -fvisibility-inlines-hidden.

Anda juga harus melupakan tentang mencoba menyembunyikan ekspor stdlib, lihat bug GCC ini untuk alasannya.

Selain itu, jika Anda memiliki semua simbol publik di header tertentu, Anda dapat membungkusnya dalam #pragma GCC visibility push(default) dan #pragma GCC visibility pop daripada menggunakan atribut. Meskipun jika Anda membuat pustaka lintas platform, lihat Mengontrol Simbol yang Diekspor dari Pustaka Bersama untuk teknik menyatukan strategi ekspor Windows DLL dan Linux DSO.


Jadi solusi yang kami miliki untuk saat ini adalah sebagai berikut:

test.cpp

#include <cmath>
#include <vector>
#include <typeinfo>

struct private_struct
{
    float f;
};

float private_function(float f)
{
    return std::abs(f);
}

void other_private_function()
{
    std::vector<private_struct> f(1);
}

extern "C" void __attribute__ ((visibility ("default"))) public_function2()
{
    other_private_function();
}

extern "C" float __attribute__ ((visibility ("default"))) public_function1(float f)
{
    return private_function(f);
}

ekspor.versi

LIBTEST 
{
global:
    public*;
local:
    *;
};

dikompilasi dengan

g++ -shared test.cpp -o libtest.so -fvisibility=hidden -fvisibility-inlines-hidden -s -Wl,--version-script=exports.version

memberi

00000000 A LIBTEST
         w _Jv_RegisterClasses
         U _Unwind_Resume
         U std::__throw_bad_alloc()
         U operator delete(void*)
         U operator new(unsigned int)
         w __cxa_finalize
         w __gmon_start__
         U __gxx_personality_v0
000005db T public_function1
00000676 T public_function2

Yang cukup dekat dengan apa yang kita cari. Namun ada beberapa gotcha:

  • Kita harus memastikan bahwa kita tidak menggunakan awalan "diekspor" (dalam contoh sederhana ini "publik", tetapi jelas sesuatu yang lebih berguna dalam kasus kita) dalam kode internal.
  • Banyak nama simbol masih berakhir di tabel string, yang tampaknya turun ke RTTI, -fno-rtti membuatnya hilang dalam pengujian sederhana saya, tetapi merupakan solusi yang agak nuklir.

Saya senang menerima solusi yang lebih baik dari siapa pun!


Linux
  1. Bagaimana cara menampilkan semua pustaka bersama yang digunakan oleh executable di Linux?

  2. C++ Dynamic Shared Library di Linux

  3. Kesalahan Linux saat memuat pustaka bersama:tidak dapat membuka file objek bersama:Tidak ada file atau direktori tersebut

  1. Cara menginisialisasi perpustakaan bersama di Linux

  2. Kompatibilitas biner distribusi Linux

  3. Bagaimana cara membuat versi perpustakaan bersama di Linux?

  1. Panduan untuk memahami pustaka perangkat lunak Linux di C

  2. Bagaimana menangani perpustakaan dinamis dan statis di Linux

  3. Kesalahan memuat pustaka bersama libcrypto.so.1.1 – OpenSSL [Perbaiki]