2010-07-07 7 views
5

Я изо всех сил пытаюсь преобразовать C-программу, связанную с ld, из цепочки инструментов gnu , чтобы она была скомпилирована как проект visual-studio (2005). Программа помещает .data-символы в разные сегменты и на этапе инициализации копирует данные между сегментами. Указатели на начало и конец сегмента определены в сценарии компоновщика ld.Как обратиться к началу пользовательского сегмента в проекте Visual Studio?

Я понимаю, как найти переменную в различные, определяемом пользователе сегментов, но я гавань был в состоянии выяснить, как определить компоновщик константу , такие как _start_of_my_segment или если есть что-то похожее на сценарий линкера в Визуальном Студия.

Моя цель состоит в том, чтобы быть в состоянии составить программу с, prefferably нет изменений в исходном код, который относится к компоновщику определенного символов, но с моей собственной пользовательской компоновкой данных в визуальном проекте студии ,

Ниже приведены примеры, C-кода, который иллюстрирует то, что я хотел бы сделать и (урезанная, возможно, синтаксически неправильно) версия из косметики скрипт, используемый при соединении с GCC/LD.

Любые советы были бы очень признательны!

#pragma data_seg("MY_DATA_FOO") 
#pragma data_seg("MY_DATA_BAR") 
#pragma comment(linker, "/section:MY_DATA_BAR,R") 

__declspec(allocate("MY_DATA_FOO")) int foo1; 
__declspec(allocate("MY_DATA_FOO")) int foo2; 

__declspec(allocate("MY_DATA_BAR")) int bar1 = 1; 
__declspec(allocate("MY_DATA_BAR")) int bar2 = 2; 

#pragma data_seg() 
void test() { 
    foo1 = bar1; 
    foo2 = bar2; 

    // i would rather do this as 
    //extern unsigned int __start_of_MY_DATA_FOO; 
    //extern unsigned int __start_of_MY_DATA_BAR; 
    //extern unsigned int __size_of_MY_DATA_BAR; 
    //memcpy(__start_of_MY_DATA_FOO, _start_of_MY_DATA_BAR, _size_of_MY_DATA_BAR); 
} 

Псевдо ссылка-скрипт (что будет эквивалентно для Visual Studio

MEMORY 
{ 
    foo: org=0x1000, len=0x100 
    bar: org=0x2000, len=0x100 
} 

SECTIONS 
{ 
    GROUP: 
    { 
     MY_DATA_FOO : {} 
     __start_of_MY_DATA_FOO = ADDR(MY_DATA_FOO); 
     __end_of_MY_DATA_FOO = .; 
     __size_of_MY_DATA_FOO = SIZEOF(MY_DATA_FOO); 
    } > foo 

    GROUP: 
    { 
     MY_DATA_BAR : {} 
     __start_of_MY_DATA_BAR = ADDR(MY_DATA_BAR); 
     __end_of_MY_DATA_BAR = .; 
     __size_of_MY_DATA_BAR = SIZEOF(MY_DATA_BAR); 
    } > bar 
} 
+0

Это действительно то, что не должно быть сделано. Разумеется, есть способы записи одной и той же программы. Похоже, что кто-то думал, что они умны, обманывая внутреннюю структуру внутренней сборки, вместо того, чтобы правильно использовать C ... Это примерно на один шаг выше, предполагая, что вы можете получить доступ к локальным переменным из вызываемой функции в своем вызывающем абоненте после того, как он вернется ... –

+0

@ R .: Есть редкие, но иногда достойные причины использовать этот шаблон. Я использовал его для добавления проверок отладки. В версиях релиза мои объекты независимы и не знают друг о друге. Но для отладки они это делают. «Законный C/C++» способ является центральным регистром для отслеживания этого, сделанного только для отладки, на самом деле намного больше обслуживания для 200+ вещей, чем этот подход (этот подход является автоматическим). С другой стороны, импортная стоимость - это разные затраты, которые это приносит. – VoidStar

ответ

0

Создание дополнительных сегментов (они помещаются в памяти в алфавитном порядке):

#pragma data_seg("MY_DATA_FOO__a") 
#pragma data_seg("MY_DATA_FOO__z") 
#pragma data_seg("MY_DATA_FOO__m") 

__declspec(allocate("MY_DATA_FOO__a")) int fooFirst; 
__declspec(allocate("MY_DATA_FOO__z")) int fooLast; 
__declspec(allocate("MY_DATA_FOO__m")) int foo1; 
__declspec(allocate("MY_DATA_FOO__m")) int foo2; 

Затем скопируйте все между & fooFirst и & fooLast.

+0

Спасибо за предложение. Однако, когда я пытаюсь это сделать, адрес fooFirst не меньше, чем fooLast, а & foo1 больше, чем & fooLast. Также кажется, что есть отступы, чтобы выровнять сегменты даже с блоками 0x1000. Это может быть изменено некоторыми настройками компилятора и компоновщика. Любые подсказки о том, какие настройки вы использовали? – ara

+0

Еще раз спасибо! Я нашел пример трюка, который вы предлагаете в документе для #pragma init_seg (здесь http://msdn.microsoft.com/en-us/library/7977wcck.aspx). Он говорит: «Имена разделов должны быть не более 8 символов.Секции с таким же именем до $ объединены в один раздел. Порядок их объединения определяется путем сортировки символов после $. « И когда я изменил имена разделов на« MY_DATA_FOO $ a »и т. Д., Они оказались правильно отсортированы. Однако каждый размер раздела по-прежнему равен нулю - помещается до примерно 0x100 байт, что затрудняет определение «правильного» конца сегмента. – ara

+0

Вот пример из источников ATL: #pragma section («ATL $ __ a», чтение, общий) #pragma section («ATL $ __ z», read, shared) #pragma section («ATL $ __ m», read, shared) Попробуйте раздел вместо data_seg. –

3

обивка может быть удалена с помощью сегментов сливаясь

, например

#pragma data_seg(".foo_begin") 
#pragma data_seg(".foo_data") 
#pragma data_seg(".foo_end") 

#pragma comment(linker, "/merge:.foo_begin=.foo") 
#pragma comment(linker, "/merge:.foo_data=.foo") 
#pragma comment(linker, "/merge:.foo_end=.foo") 

__declspec(allocate(".foo_begin")) int foo_begin_marker; 
__declspec(allocate(".foo_end")) int foo_end_marker; 

__declspec(allocate(".foo_data")) int foo_data; 
+1

Спасибо! Тем не менее, я все еще получаю заполнение 0x100 байт между переменными (не так ли?). Без команды merge padding составляет 0x1000 байт, а сегменты оказываются в неправильном порядке, поэтому команда слияния имеет некоторый эффект и кажется столь же полезной, как и другой подход (используя $ в именах разделов). – ara