2013-02-11 11 views
5

Mam program C++, który zawiera zewnętrzną zależność od pustego pliku Xlsx. Aby usunąć tę zależność konwertowane ten plik do obiektu binarnego z uwagi na powiązanie go bezpośrednio, przy użyciu:ld pliku danych powoduje, że rozmiar danych jest * ABS *, a nie liczbą całkowitą

ld -r -b binary -o template.o template.xlsx 

następnie

objcopy --rename-section .data=.rodata,alloc,load,readonly,data,contents template.o template.o 

Korzystanie objdump, widzę trzy zmienne zadeklarowane:

$ objdump -x template.o 

template.o:  file format elf64-x86-64 
template.o 
architecture: i386:x86-64, flags 0x00000010: 
HAS_SYMS 
start address 0x0000000000000000 

Sections: 
Idx Name   Size  VMA    LMA    File off Algn 
    0 .rodata  00000fd1 0000000000000000 0000000000000000 00000040 2**0 
        CONTENTS, ALLOC, LOAD, READONLY, DATA 
SYMBOL TABLE: 
0000000000000000 l d .rodata  0000000000000000 .rodata 
0000000000000fd1 g  *ABS* 0000000000000000 _binary_template_xlsx_size 
0000000000000000 g  .rodata  0000000000000000 _binary_template_xlsx_start 
0000000000000fd1 g  .rodata  0000000000000000 _binary_template_xlsx_end 

I wtedy powiedzieć mój program o tym dane:

template.h: 
#ifndef TEMPLATE_H 
#define TEMPLATE_H 

#include <cstddef> 
extern "C" { 
    extern const char _binary_template_xlsx_start[]; 
    extern const char _binary_template_xlsx_end[]; 
    extern const int _binary_template_xlsx_size; 
} 
#endif 

To kompiluje i łączy w porządku (chociaż mam pewne kłopoty automatyzującego go z cmake, zobacz tutaj: compile and add object file from binary with cmake)

Jednak kiedy używam _binary_template_xlsx_size w moim kodu, jest interpretowany jako wskaźnik do adresu, który nie istnieje. Tak, aby uzyskać rozmiar moich danych, muszę zdać (int)&_binary_template_xlsx_size (lub (int)(_binary_template_xlsx_end - _binary_template_xlsx_start))

Niektóre badania mówi mi, że *ABS* w objdump powyżej oznacza „wartość bezwzględną”, ale nie rozumiem dlaczego. Jak mogę uzyskać program C++ (lub c), aby zobaczyć zmienną jako int, a nie jako wskaźnik?

+0

myślę, że może być kilka wskazówek zawartych w dokumentacji, dlaczego i jak tego uniknąć. Dlaczego po prostu nie napisać prostego skryptu, aby przekonwertować plik na definicję tablicy włączalnej? –

+0

Plik jest plikiem xlsx: skompresowaną kolekcją plików xml. Powodem, dla którego to zrobiłem, było to, że poświęciłem trochę czasu na napisanie kodu w celu rozpakowania, iteracji po plikach i przeanalizowania xml i nie chcę tego ponownie. Poza tym jest fajnie. –

+0

Mam również dostęp do danych. Próbuję dowiedzieć się, co się tutaj dzieje, ponieważ jestem zaintrygowany tym zachowaniem. –

Odpowiedz

3

Symbol *ABS* jest adresem bezwzględnym; częściej jest tworzony przez przekazanie --defsym foo=0x1234 do ld.

--defsym symbol=expression 

Tworzenie globalny symbol w pliku wyjściowego, zawierająca bezwzględną adres podany przez ekspresję. [...]

Ponieważ symbol bezwzględny jest stałą, nie można jej powiązać z plikiem źródłowym C jako zmienną; wszystkie zmienne obiektowe C mają adres, ale stała nie.

Aby upewnić się, że nie nieprawidłowego adresu (tzn odczytu zmiennej) przez przypadek, to najlepiej określić jako const char [] jak masz z innymi symbolami:

extern const char _binary_template_xlsx_size[]; 

Jeśli chcesz, aby czy używasz go jako int, można użyć makra:

extern const char _abs_binary_template_xlsx_size[] asm("_binary_template_xlsx_size"); 
    #define _binary_template_xlsx_size ((int) (intptr_t) _abs_binary_template_xlsx_size) 
Powiązane problemy