2010-08-01 1 views
2

C 프로그램에서 테스트를 시작할 때 전역 변수를 다시 초기화해야합니다.전문가 - GCC 및 ld 링커 : .data 섹션에 포함 된 변수를 다시 초기화 하시겠습니까?

데이터 복사를로드 메모리 주소, LMA에서 VMA (런타임 주소)로 재생성하려면 재 초기화 기능이있는 GCC 라이브러리가 필요합니다. 예를 들어, foo 변수가 전역 변수로 선언되고 초기화되면. 그리고 내 재 초기화 기능) (re_init 경우 :

#include <stdio.h> 
int foo1 = 42; 
int foo2 = 777; 

int main(){ 
    foo1 = 0; 
    foo2 = 0; 
    re_init(); 
    printf("foo1:%d and foo2:%d",foo1,foo2); 
    return 0; 
} 

그때 내가 출력으로 갖고 싶어 :

foo1:42 and foo2:777 

나는이 작업을 수행하는 올바른 방법은 기본 링커 파일이라고 생각 시작 값을 RAM에 복사하는 시작 코드 일 수 있습니다. 그래서 GCC (cygwin)에서이 작업을 수행하려면 어떻게해야합니까?

편집 :이 페이지는 O가 더 많은 정밀도가 보인다 http://sources.redhat.com/binutils/docs-2.12/ld.info/Output-Section-LMA.html#Output%20Section%20LMA

답변

3

내가 정확히 모르는 Cygwin에서이 작업을 수행하는 방법, 그러나 일반적으로, 데이터 섹션의 VMA과의 LMA에서 복사되지 않습니다; 대신 실행 파일의 관련 청크는 커널이 원하는 VMA에서 RAM으로 메모리 매핑 한 다음 동적 링커가 데이터 섹션을 가리키는 재배치를 실행합니다.

따라서 실행 파일의 내용에서 데이터 섹션을 다시 초기화하려면 동적 링커와 커널 측 실행 로더를 충분히 복제해야합니다. 실행 파일을 찾습니다 (반드시 argv [ 0]); 헤더를 파싱하고 데이터 섹션을 찾습니다. 이전 맵핑을 제거하고 적절한 VMA에서 다시 작성하십시오. 모든 재배치를 다시 수행하십시오. 그런 다음 C 라이브러리의 런타임 상태를 그 아래에서 꺼내서 발생하는 모든 악영향을 처리합니다. 데이터 섹션에는 사용자 자신의 전역 변수뿐만 아니라 stdout 및 malloc의 마스터 할당 테이블도 있습니다.

"unexec"및 "undump"에 대한 일부 검색을 수행하여 비슷한 문제는 해결하지만 재활용 할 수있는 코드를 얻을 수 있습니다.

+0

잭이 더 많은 투표를 가졌습니다. 대답을 수락했습니다. 나는 Steven Schlansker만큼 확실한 답을 고맙게 생각합니다. – djondal

2

이동 경로는 이식성 문제, 버그 및 슬픔이 가득합니다.

가장 좋은 방법은이 문제를 해결하는 것입니다. 내가 주위에 전달되는 "컨텍스트"구조체에 상태를 저장하기 위해 모든 코드를 작성합니다. 그런 식으로 "상태"를 재설정하는 것은 새로운 "컨텍스트"구조체를 만드는 것입니다.

+0

그리고 슬픔 ... 재미 있습니다! – djondal

+0

나는 그것에 대해 생각하고 슬퍼지고있다! :-p –

0

솔루션에 대한 또 다른 아이디어입니다. 글로벌 상태를 제거하는 것이 더 좋습니다.

매크로를 통해 헤더 파일에있는 모든 전역을 정의

globals.h :

DEFINE_GLOBAL(int, foo, 5); 
DEFINE_GLOBAL(char, bar, 'x'); 

을 main.c :

#include <stdio.h> 

#define DEFINE_GLOBAL(type, name, initialvalue) type name = initialvalue 
#include "globals.h" 
#undef DEFINE_GLOBAL 

void resetState() { 
    #define DEFINE_GLOBAL(type, name, initialvalue) name = initialvalue 
    #include "globals.h" 
    #undef DEFINE_GLOBAL 
} 

나는이 테스트를하지 않은, 그것 때문에 일부 구문 수정이 필요할 수도 있습니다.하지만 개념은 건전하다고 생각합니다.

+0

나는 글로벌 상태가 코드 품질 수준에서 고통과 고통의 또 다른 이름이라는 데 동의합니다. 안티 캡슐화 개념입니다. 하지만 여기서 다른 사람의 디자인을 다루지는 않겠지 만 불행히도 나는 다시 초기화 할 수있는 수백 개의 전역 변수가 있습니다. – djondal

+0

아마도 파일을 읽고 적절한 재 초기화 명령을 내뱉기 위해 빠른 스크립트를 작성할 수 있습니까? 즉 모든 전역을 검색하고 모두를 재설정하는 함수를 생성합니까? –