Ukrywanie symboli w bibliotekach statycznych zbudowanych z Xcode

Próbuję się dowiedzieć, czy mogę zbudować statyczną bibliotekę, która ukrywa wszystkie wewnętrzne obiekty i funkcje, itp., z wyjątkiem interfejsów, które chcę wyeksportować. Eksperymentuję z Xcode (gcc 4.2).

Użyłem atrybutu {[0] } w niektórych klasach C++ na tej dokumentacji . Zdefiniowałem też małe pomocnicze funkcje C jako plik-lokalny (statyczny), itp.

Jednak, gdy uruchamiam strings na wynikowym .pliku bibliotecznego, nawet po skompilowaniu w Release configuration, nadal widzę nazwy moich pozornie ukrytych klas, z ich nazwami metod, a nawet nazwy lokalnych funkcji plików rozrzuconych tam również.

Dodałem -fvisibility=hidden a nawet -fno-rtti do FLAG gcc. Chociaż zmniejsza to niektóre ciągi znaków, nazwy klas, metod i statyczne nazwy funkcji są nadal tam w postaci zwykłej lub zniekształconej, ale czytelnej.

Czy istnieje niezawodny sposób, aby kompilator zbudował te rzeczy bez konieczności ciągi znaków wszystkich wewnętrznych rzeczy emitowanych do binarnych? Nie powinno być konieczne, aby mieć dla żadnych zewnętrznych klientów łączących się.

(dla wyjaśnienia: pytam o zaciemnienie nazewnictwa wewnętrznego, a dosłowne potrzeby związane z eksportem. Jestem zaniepokojony, że wszystkie wewnętrzne działania są widoczne za pomocą polecenia strings, niezależnie od tego, czy te symbole są formalnie eksportowane, czy nie.)

Dzięki.
Author: jww, 2010-07-18

3 answers

Ukrywanie nazw wewnętrznych wymaga kilku prostych ustawień kompilacji Xcode i generalnie nie jest konieczne modyfikowanie źródła lub zmiana typu budowanego produktu.

  1. wyeliminuj wszelkie symbole wewnętrzne wymagane między modułami, wykonując prelink pojedynczego obiektu. Ustaw ustawienie kompilacji Xcode o nazwie "Perform Single-Object Prelink" na yes (GENERATE_MASTER_OBJECT_FILE=Yes). Powoduje to uruchomienie ld z flagą "- r".
  2. Upewnij się, że ustawienie "Styl paska" jest ustawione na "Non-Global symbols "(STRIP_STYLE = non-global), to przechodzi "-x" do ld.
  3. Stripping jest faktycznie wykonywany tylko na bibliotekach statycznych, jeśli włączone jest przetwarzanie końcowe (i nie jest to domyślne). Ustaw Xcode build setting "Deployment Postprocessing" na tak. (DEPLOYMENT_POSTPROCESSING = YES). Upewnij się również, że "użyj oddzielnego paska" jest ustawione na Yes (nie zawsze domyślne) (SEPARATE_STRIP=YES).
  4. Jeśli oprócz symboli lokalnych, musisz usunąć niektóre z symboli globalnych, możesz dostarczyć dodatkowe opcje do polecenia strip, pod Xcode build ustawienie "dodatkowe flagi strip". Na przykład często używam opcji strip "- r somefile", aby dostarczyć Plik z dodatkową listą symboli, które chcę usunąć z globalnej tabeli symboli.
 54
Author: bleater,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-19 23:48:42

Główną sztuczką w ukrywaniu symboli w bibliotekach statycznych jest wygenerowanie pliku Obiektowego, który można przenieść (w przeciwieństwie do archiwum biblioteki statycznej, które składa się po prostu ze zbioru pojedynczych .o pliki). Aby zbudować relokowalny plik obiektowy, musisz wybrać cel w XCode jako pakiet (w przeciwieństwie do "Cocoa Touch Static Library"). Obiekt docelowy w pakiecie jest wyświetlany pod szablonami systemu OS X, a w Ustawieniach budowania dla systemu iOS można ustawić jego cel na iOS.

Once you po poprawnym skonfigurowaniu celu, następujące kroki pomogą w poprawnym ukryciu symbolu:

  1. Ustaw opcję "Symbole Ukryte domyślnie" na tak w Ustawieniach kompilacji. Dzięki temu wszystkie symbole skompilowane w plikach są oznaczone jako prywatne.

  2. Ponieważ jest to biblioteka, musisz zachować niektóre symbole publiczne. Należy umieścić kod dla funkcji, które mają być publicznie widoczne w oddzielnych plikach, i skompilować te pliki z flagą -fvisibility=default (można ustaw tę flagę dla poszczególnych plików "fazy kompilacji > Źródła kompilacji > -- flagi kompilatora" w Xcode). Alternatywnie, możesz przedrostek nazwy funkcji / klasy, którą chcesz widzieć za pomocą dyrektywy __attribute__((visibility("default"))).

  3. W Ustawieniach łączenia w projekcie X-code Ustaw typ Mach-O na "Relocatable Object File". Oznacza to, że wszystkie .o pliki zostaną ponownie połączone, aby wygenerować pojedynczy plik obiektowy. To jest ten krok, który pomaga oznaczyć wszystkie symbole jako prywatne, gdy .o pliki są połączone w jeden plik. Jeśli zbudujesz statyczną bibliotekę (np. plik .a), ten krok ponownego łączenia się nie nastąpi, więc symbole nigdy nie zostaną ukryte. Decydujące znaczenie ma więc wybór Pliku obiektowego, który można przenosić jako obiekt docelowy.

  4. Nawet po oznaczeniu symboli jako prywatnych nadal pojawiają się w .plik o. Musisz włączyć stripping, aby pozbyć się prywatnych symboli. Można to zrobić, ustawiając ustawienie" Stripped Linked Product " na tak w Ustawieniach kompilacji. Ustawienie tej opcji uruchamia polecenie strip -x na pliku obiektowym, które usuwa prywatne symbole z pliku obiektowego.

  5. Sprawdź dokładnie, czy wszystkie symbole wewnętrzne zniknęły, uruchamiając polecenie nm na ostatecznym pliku obiektu, który można przenosić, wygenerowanym przez proces budowania.

Powyższe kroki pomogą Ci pozbyć się nazw symboli z polecenia nm. Niektóre nazwy funkcji i plików będą nadal widoczne, jeśli uruchomisz polecenie strings na pliku OBIEKTU (ze względu na niektóre ciągi znaków i nazwy obiektów kompilacji poprzez wyjątki). Jeden z moich kolegów ma skrypt, który zmienia nazwy niektórych z tych symboli, przeglądając sekcje binarne i zmieniając nazwy tych łańcuchów. Zamieściłem go tutaj do wykorzystania: https://gist.github.com/varungulshan/6198167 . możesz dodać ten skrypt jako dodatkowy krok budowania w Xcode.

 17
Author: Varun Gulshan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:17:42

Jest dla mnie nieco niejasne, jak ukryć symbole w statycznych bibliotekach ze środowiska linuksowego w oparciu o poprzednie odpowiedzi, więc po prostu opublikuję moje rozwiązanie tutaj dla potomności (biorąc pod uwagę, że jest to jeden z najlepszych wyników w google dla tego pytania).

Powiedzmy, że masz te dwie .pliki c:
// f1.c
const char *get_english_greeting(void)
{
  return "hello";
}

__attribute__((visibility("default")))
const char *get_greeting(void)
{
  return get_english_greeting();
}

I

// f2.c
#include <stdio.h>
const char *get_english_greeting(void);

__attribute__((visibility("default")))
void print_greeting(void)
{
  puts(get_english_greeting());
}

Chcesz przekonwertować te dwa pliki do statycznej biblioteki eksportującej zarówno get_greeting jak i print_greeting, ale nie get_english_greeting, której nie chcesz robić statycznie jak chcesz go używać w całej bibliotece.

Oto kroki, aby to osiągnąć:

gcc -fvisibility=hidden -c f1.c f2.c
ld -r f1.o f2.o -o libf.o
objcopy --localize-hidden libf.o
ar rcs libf.a libf.o

Teraz to działa:

// gcc -L. main.c -lf
void get_greeting(void);
void print_greeting(void);
int main(void)
{
  get_greeting();
  print_greeting();
  return 0;
}

A to nie:

// gcc -L. main.c -lf
const char *get_english_greeting(void);
int main(void)
{
  get_english_greeting();
  return 0;
}

Dla tego drugiego dostajesz ten błąd:

/tmp/ccmfg54F.o: In function `main':
main.c:(.text+0x8): undefined reference to `get_english_greeting'
collect2: error: ld returned 1 exit status
Tego właśnie chcemy.

Zauważ, że ukryte nazwy symboli są nadal widoczne w bibliotece statycznej, ale łącznik odmówi połączenia z nimi poza wspomnianą biblioteką statyczną. Aby całkowicie usunąć nazwy symboli musisz rozebrać i zaciemnić.

 3
Author: ypsu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-04 11:24:14