2017-12-16 3 views
0

각 변수에 __attribute__((aligned(1)))을 지정하지 않고도 GCC에서 모든 전역 변수에 대한 정렬을 없애려면 어떻게합니까 (기본값 : .align 4)?gcc의 기본 전역 변수 정렬을 지정하는 방법은 무엇입니까?

일부 아키텍처에서는 1의 배 열이 작동하지 않기 때문에 제가 요구하는 것은 보편적으로 적용하는 것이 좋습니다. CPU는 정렬되지 않은 포인터를 역 참조 할 수 없습니다. 내 경우에는 비트 i386 부트 로더를 쓰고 있고, 정렬되지 않은 포인터는 괜찮지 만 (느리지 만) 거기에있다.

소스 코드 (a.c) : gcc -m32 -Os -S a.c

총회 출력 (a.s) : 플래그 gcc -fpack-struct=1 모든 구조체 멤버 및 구조체의 정렬을 변경

.file "a.c" 
    .globl answer 
    .data 
    .align 4 
    .type answer, @object 
    .size answer, 4 
answer: 
    .long 42 
    .globl answer0 
    .type answer0, @object 
    .size answer0, 4 
answer0: 
    .long 41 
    .ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4" 
    .section  .note.GNU-stack,"",@progbits 

__attribute__((aligned(1))) int answer0 = 41; 
int answer = 42; 

함께 컴파일 예를 들어, 해당 플래그가있는 경우

,515,
struct x { char a; int b; }; 
struct y { int v : sizeof(char) + sizeof(int) == sizeof(struct x); }; 
struct z { int b; }; 
struct x x = { 1, 1 }; 
int i = 42; 
struct z z = { 2 }; 

변수 x' and Z '에 대한 정렬을 컴파일하지만 여전히 변수 i (int의 종류)에 대한 .align 4있다. 나는 또한 각각의 변수에 대해 무언가를 지정할 필요없이 int i = 42;을 정렬하지 않는 해결책이 필요하다.

+0

프로젝트의 링커 지시문 파일을 옵션으로 편집하고 있습니까? – Yunnosch

+0

@Yunnosch : 예, 링커 스크립트 편집 (예 :'-Wl, -T, foo.scr')이 가능합니다. – pts

+0

나는 무엇을하고 싶은지 잘 모르겠다. 그러나 여기서 너는 평범한 사람이다. C는 변수를 자유롭게 정렬 할 수 없습니다. '__attribute __ ((aligned (1)))'은 망가진 해킹 일 뿐이며, GCC 버그 추적기조차도이를 인정합니다. –

답변

0

대부분의 아마 GCC는 글로벌 변수의 기본 정렬을 변경할 수 있습니다 이러한 플래그를 가지고 있지 않습니다.

gcc -fpack-struct=1은 해결 방법이 될 수 있지만, 발생하는 전역 변수는 struct 유형입니다.

또한 .s 출력을 gcc로 후 처리하고 .align 행을 제거하면 (일부) 문제를 해결할 수 있습니다.

0

압축 된 구조체를 사용하여 공간을 절약하기위한 IMO 패킹 변수가 가장 쉽고 안전합니다.

예 :

#include <stdio.h> 
#include <stdint.h> 

#define _packed __attribute__((packed)) 


_packed struct 
{ 
    uint8_t x1; 
    _packed int x2; 
    _packed uint8_t x3[2]; 
    _packed int x4; 

}byte_int; 

int main(void) { 
    printf("%p %p %p %p\n", &byte_int.x1, &byte_int.x2, &byte_int.x3, &byte_int.x4); 
    printf("%u %u %u %u\n", (unsigned int)&byte_int.x1, (unsigned int)&byte_int.x2, (unsigned int)&byte_int.x3, (unsigned int)&byte_int.x4); // I know it is an UB just to show the op in dec - easier to spot the odd and the even addresses 

    return 0; 
} 

https://ideone.com/bY1soH

+0

답변 해 주셔서 감사합니다. 이것은 정렬되지 않은'int'를 갖는 한가지 방법입니다. 또 다른 방법은 각 int를'__attribute __ ((aligned (1)))'로 선언하고 링커 스크립트의 각 섹션에': ALIGN (1) SUBALIGN (1)'을 추가하는 것입니다. 이 두 가지 모두 C 코드베이스의 모든 전역 변수를 수동으로 열거하고 각 선언을 수동으로 변경해야합니다. 이 질문에 나는 그것을 피하고 싶다. 나는 모든 글로벌 C 변수를 기본적으로 정렬되지 않도록하고 싶다 *. 최종 결과는 gcc가 기본적으로 어셈블리 출력 *에서'.align 4' 라인을 생성하지 않는다는 것입니다. 이 대답은 내 질문에 대답하지 않습니다. – pts

+0

아키텍처가 정의되어 있습니다. 모든 섹션을 올바르게 정렬하지 않으면 매우 위험하고 부적절한 방법입니다. 그러나 그것은 당신의 선택입니다. –

+0

i386 부트 로더에서 왜 매우 위험하다고 생각합니까? 부적절한 이유는 무엇입니까? – pts

관련 문제