gcc의 __attribute__((bitwise))에 관한 질문

시로코의 이미지

리눅스 커널 소스(2.6.21.x)의 include/linux/types.h에 보면

#ifdef __CHECKER__
#define __bitwise__ __attribute__((bitwise))
#else
#define __bitwise__
#endif
#ifdef __CHECK_ENDIAN__
#define __bitwise __bitwise__
#else
#define __bitwise
#endif
 
typedef __u16 __bitwise __le16;
typedef __u16 __bitwise __be16;
typedef __u32 __bitwise __le32;
typedef __u32 __bitwise __be32;
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
typedef __u64 __bitwise __le64;
typedef __u64 __bitwise __be64;
#endif
typedef __u16 __bitwise __sum16;
typedef __u32 __bitwise __wsum;

이렇게 __attribute__((bitwise))로 자료형이 정의된 것을 볼 수 가 있습니다.
__le16, __be16의 이름으로 봐서는 16비트 리틀 엔디안, 16비트 빅 엔디안 변수라는 것 같은데.

리눅스 커널 내에서도 대부분 코드들이 uint32_t를 사용하지 않고 __le16, __be16을 쓰고 있었습니다.

실제로 __attribute__((bitwise))는 어떤 효과를 가지는지 궁금합니다.

wariua의 이미지

GCC 속성 확장 중의 하나이겠거니 생각했는데 아니로군요. "__attbibute__((bitwise))"로 검색한 결과 중 하나를 따라가다 보니 다음과 같은 내용들을 알 수 있었습니다.

리눅스 소스에 ~linux/Documentations/sparse.txt라는 파일이 있습니다. 문서 제목은 "Using sparse for typechecking"입니다. sparse는 "semantic parser"에서 따온 이름으로, 그 패키지 안에 들어있는 sparse라는 이름의 프로그램은 static analyzer라고 합니다.

sparse.txt 문서의 내용처럼, 커널 소스에서 "make C=1"이나 "make C=2"라고 명령을 주면 C 소스 파일에 대해 sparse 프로그램을 실행합니다. 그 때 "CHECKFLAGS=-D__CHECKER__ -D__CHECK_ENDIAN__" 옵션을 함께 주면 소스 코드에서 "__attribute__((bitwise))"가 활성화 된 상태로 sparse 프로그램이 이를 분석하게 됩니다. 그래서 "__attribute__((bitwise))" 속성이 일치하지 않는 변수 할당 등을 발견하면 다음과 같은 식의 메시지를 출력합니다.

validation/foul-bitwise.c:9:9: warning: restricted degrades to integer
validation/foul-bitwise.c:9:15: warning: restricted degrades to integer
validation/foul-bitwise.c:19:9: error: incompatible types for operation (-)
validation/foul-bitwise.c:19:9:    argument has type restricted unsigned short [usertype] a

리누스가 sparse를 작성하기 시작한 건 소스 내에서 사용자 메모리 공간에 대한 포인터와 커널 메모리 공간에 대한 포인터가 섞여 쓰이는 문제를 해결하기 위해서였다고 합니다. 컴파일러로는 탐지하기 힘든 코딩 상의 오류이죠. ~linux/include/linux/compiler.h에 그 내용이 들어가 있습니다. 그리고 이후 그걸 확장해서 엔디안 검사까지 하도록 확장된 듯 합니다.
----
$PWD `date`

$PWD `date`

시로코의 이미지

답변 감사드립니다.

그러면 엔디안 검사까지 한다면 __be64에 값을 넣으면 메모리에도 빅 엔디안 형식으로 들어간다는 것인가요? 현재 인텔 프로세서는 변수에 값을 넣으면 모두 리틀 엔디안으로 들어가는데, __be64, __le64가 이해가 잘 안됩니다.

wariua의 이미지

__be64라고 타입을 선언했다고 해서 그 변수에는 알아서 빅엔디안으로 들어가는 건 아닙니다. 당연히 cpu_to_xxx() 등을 통해 적절히 변환을 해줘야 합니다. 말씀드린 '엔디안 검사'라는 건 그렇게 적절히 변환하는 과정을 실수로 빠뜨린 경우를 잡아주는 거라고 할 수 있습니다. 가령 다음과 같은 경우이죠.

void foo(__u64 hostbyte_value)
{
    /* __be64 bigendian_value = cpu_to_be64(hostbyte_value); */ /* CORRECT */
    __be64 bigendian_value = hostbyte_value; /* INCORRECT */
    ...
}

----
$PWD `date`

$PWD `date`

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.