2010-07-07 2 views
5

lnd와 연결된 C 프로그램을 gnu 도구 체인 으로 변환하여 Visual Studio (2005) 프로젝트로 컴파일하는 데 어려움을 겪고 있습니다. 프로그램은 .data-symbols을 다른 세그먼트에 넣고 초기화 단계 동안 세그먼트간에 데이터를 복사합니다. 세그먼트의 시작과 끝 포인터는 ld 링커 스크립트에 정의되어 있습니다.Visual Studio 프로젝트에서 사용자 정의 세그먼트 시작을 참조하는 방법은 무엇입니까?

나는 다른 사용자 정의 세그먼트로 변수를 찾는 방법을 이해하지만, 나는 그런 _start_of_my_segment 같은 링커 상수를 정의하거나하는 방법을 알아낼 수 있었다를 havent 시각에 링커 스크립트와 비슷한 뭔가가있는 경우 사진관.

내 목표는 을 휘젓고와 링커 정의 기호를 참조하는 소스 코드에는 수정 프로그램을 컴파일하지 할 수있을 것입니다,하지만 비주얼 스튜디오 프로젝트에서 데이터를 내 자신의 사용자 정의 레이아웃 .

아래와 같은 코드 예는 을 수행하고 gcc/ld와 링크 할 때 사용되는 make- 스크립트 버전 (버전 - 구문 오류)을 보여줍니다.

모든 힌트를 크게 높이세요! 비주얼 스튜디오의 상응하는 것입니다 무슨

#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); 
} 

의사 링크 스크립트 (

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 "등으로 변경했을 때 올바르게 정렬되었습니다. 그러나 각 섹션 크기는 여전히 0입니다. - 최대 0x100 바이트까지 채워져 세그먼트의 "적절한"끝 부분을 알기 어렵게 만듭니다. – ara

+0

다음은 ATL 소스의 예입니다. #pragma section ("ATL $ __ a", 읽기, 공유) #pragma section ("ATL $ __ z", 읽기, 공유) #pragma section ("ATL $ __ m"읽기, 공유) 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 바이트가 채워집니다 (안 그렇습니까?). 병합 명령이 없으면 패딩은 0x1000 바이트이고 세그먼트는 잘못된 순서로 끝나기 때문에 병합 명령은 일부 효과가 있으며 다른 방법 (섹션 이름에 $ 사용)과 마찬가지로 유용합니다. – ara

관련 문제