elf, gcc - .got vs constant strings - jeśli znasz format ELF/skrypty linkera, to jesteś koksu i pomóż! :)

0

Czesc,

Pracuję nad obsługą elfa w swoim systemie i mam napotkałem na pewien problem, który liczę że może ktoś już spotkał, lub może ma jakiś pomysł z czym to może być związane. Mi przychodzi aktualnie do głowy tylko, że to może jakiś bug w gcc, ale mam nadzieję, że się mylę...

Jako, że nie mam MMU, to wykorzystuję fPICa do shakowania adresów (aktualizuję je w .got). Generalnie wygląda na to, że to działa i to całkiem przyzwoicie, tylko jest jeden problem...

#include <oc_stdio.h>
#include <oc_stdtypes.h>

static char *       SomeString = "Hue hue, it is my string!\n";
static uint32_t     Variable   = 0xDEADBEEF;
static uint32_t *   Pointer    = NULL;
static uint32_t     Variable2  = 0xBEEFBABA;

//=========================================
/**
 * The main entry of the application
 *
 * @param Argc      Argument counter
 * @param Argv      Arguments array
 *
 * @return result
 */
//=========================================
int main( int Argc , char ** Argv )
{
    printf("Hello ChocoOS - userspace World!\n");
    printf("It is very nice to be here!\n");

    printf("Here is string from data section: '%s'\n", SomeString);
    printf("And here variable from data section: 0x%08X\n", Variable);

    Pointer = &Variable2;

    printf("Variable2 = 0x%08X\n", Variable2);
    printf("Pointer to Variable2 = 0x%08X\n", Pointer);
    printf("Value from pointer = 0x%08X\n", *Pointer);
    printf("String pointer = 0x%08X\n", SomeString);

    return 0;
}

title

Jak widać wszystkie pointery zostały zaktualizowane oprócz referencji do .rodata (jego offset to 0x00000CB8) ... Temat jest dosyć niszowy i ciężko informacje po googlach znaleźć. Miał ktoś może z tym do czynienia, albo ma pomysł jak by można było to zaktualizować?

0

To spróbuję trochę bardziej przybliżyć temat stosując się do zaleceniea kq:

Targetem jest mikrokontroler oparty na ARMie. Środowisko budujące to arm-none-eabi. Celem jest odpalenie programu, który nie musi być wkompilowany w system. Program jest kompilowany z flagą -fPIC do pliku w formacie ELF (dla niezaznajomionych specyfikacja tutaj: http://www.skyfree.org/linux/references/ELF_Format.pdf). Plik jest wrzucany na kartę SD, lub coś podobnego i dostarczony do systemu. System go interpretuje, wczytuje sekcje w nim zawarte, aktualizuje tablice GOT (Global Offset Table) i wykonuje.

Aktualny efekt jest taki, że to działa, za wyjątkiem sytuacji, gdy używamy pointera wskazującego na sekcję .rodata. Z jakiegoś powodu odwołanie się do niej nie wykorzystuje .got. I moje pytanie jest - jak ten cholerny pointer zaktualizować (oczywiście w grę nie wchodzi opcja parsowania całej sekcji .text :P) ?

0

Dziwne jest to, że printf też korzysta ze stringów zaalokowanych w rodata i je widać na zamieszczonym screenie, co sugeruje, że wszystko działa, a mimo to adres pointera zawiera jego sam offset, co jest dziwne, bo powien mieć dodany do offsetu adress pod jaki została załadowana binarka.

Czyli wszystko działa i nie działa jednocześnie.

1

Takie pytanie, a jakby ten string nie był static to działa?
Robiłeś objdump/readelf by sprawdzić gdzie ten string został umieszczony w elfie?
Rozumiem, że samemu ładujesz kod i wtedy uaktualniasz got. Na pewno dobrze ją uaktualniłeś?
Skąd wiesz, że nie wykorzystuje got? Sprawdzałeś asemblera?

1

Nie trzymaj nas w niepewności tylko odpisz coś, cała armia się zebrała ludzi żeby to rozwiązać.

2

No ale czekaj, tak mnie teraz naszło... skoro to jest arm-none-eabi architektura docelowa to jest jakiś Cortex pewnie, tak? Wobec tego .rodata defaultowo będzie we flashu i możliwe, że tego nie przeskoczysz raczej. Utworzenie customowej sekcji nie będzie rozwiązaniem?
https://stackoverflow.com/questions/7090791/rodata-relocation-related-question

0

@Psychopata: Haha Sorry, przeprowadzam się aktuaalnie i mam urwanie głowy dzisiaj :D

@nalik: Ciekawy pomysł, ale sprawdziłem i jest to samo dokładnie jeśli usunę statica... :/

@alagner: Masz rację, to cortex, ale docelowo nie będzie ta sekcja we flashu, tylko całość w ramie :) Chodzi o to, aby odpalać programy np z karty SD - po prostu ładujesz plik to RAMu, aktualizujesz parę rzeczy (offsety sekcji, stack itd) i potem skaczesz do maina. Customową sekcję mogę stworzyć, tylko w jaki sposób zmusić kompilator, aby do niej się odwoływał? No i nie jestem pewien, czym by mogło to się różnić :/

@Psychopata ma rację, że stringi do printfa też są przekazane z .rodata. Tam gdzieś musi być ten offset do tej sekcji w .got, tylko nie wiem dlaczego w przypadku odwoływania się do stringów z niej nie korzysta... Tak jakby miał tam na sztywno wpisany ten address :/

Edit:
@nalik: Tak, sprawdziłem asemblera. Jeszcze nie przeportowałem serwera gdb na swój system, więc niestety to jest jedyna metoda, aby dowiedzieć się, co tam się dzieje :) No i w readelf widzę, że właśnie w tym miejscu się zaczyna ta sekcja
title

0
JohnAmadis napisał(a):

@nalik: Tak, sprawdziłem asemblera. Jeszcze nie przeportowałem serwera gdb na swój system, więc niestety to jest jedyna metoda, aby dowiedzieć się, co tam się dzieje :) No i w readelf widzę, że właśnie w tym miejscu się zaczyna ta sekcja

Bardziej chodziło mi o sprawdzenie jak oblicza adres pointera. Wtedy byś wiedział, czy dodał zero z got czy nic nie dodał.

0

@nalik: Tak, też to miałem na myśli :P ASM tego programu to już bym chyba z pamięci mógł Ci recytować xD Sam adres zmiennej, gdzie jest przechowywany pointer jest obliczany z użyciem .got, ale już zawartość nie jest w żaden sposób modyfikowana - jest żywcem pozostawiona w rejestrze r2...
title

1

Strzelam, opcja -mno-pic-data-is-text-relative ?

0

@nalik ++ to może być dobry trop;) W linku poniżej przydatne info;
https://answers.launchpad.net/gcc-arm-embedded/+question/236744

Ponawiam prośbę o mwce, albo chociaż skrypt linkera i startup.

0

Source code masz tutaj:
https://bitbucket.org/chocos/chocos/src/16e64246c33058fda9d7b4af85ba53d07ba4b8c1/?at=feature%2Felf_support

Widziałem właśnie też ten wątek z -mno-pic-data-is-text-relative i wygląda jakby to było to, ale w praktyce w ogóle gcc nie reaguje na tą opcję.. (gcc version 5.4.1 20160609) wiec chyba juz powinna byc dostepna... Nie wiem, moze jeszcze sprobuje dzisiaj w ogole wymienic gcc?

0

Niestety nic nie pomogło. Rozwiązałem aktualnie to tak, że po prostu wymuszam przesunięcie pointerów do sekcji .got. Może kiedyś mi się uda wymyślić coś lepszego:

#define POINTER          __attribute__((__section__(".got")))

static char *       SomeString POINTER  = "Hue hue, it is my string!";

Dziękuję wszystkim za zaangażowanie!

1 użytkowników online, w tym zalogowanych: 0, gości: 1