GCC C attribute--packed
GCC allows you to specify attributes of variables, types and functions using the keyword __attribute__, the syntax of which is
__attribute__((attribute-list)).
One such attribute is __packed__, which specifies from GCC Mauual that
a variable or structure field should have the smallest possible alignment--one byte for a variable, and one bit
for a field, unless you specify a larger value with the aligned attribute.
That means GCC will not add any of the zero's for padding(for memory alignment) and make variables or fields immediately next
to each other. For example, here are some things i tried out--I created a C source file named attribute_unpacked.c
struct test_t {
int a;
char b;
int c;
};
struct test_t test = {10, 20, 30};
And compiled it with the -S option
$ gcc -c attribute_unpacked.c -S -o attribute_unpacked.s
Then I open the .s file
.file "attribute_unpacked.c"
.globl test
.data
.align 4
.type test, @object
.size test, 12
test:
.long 10
.byte 20
.zero 3
.long 30
.ident "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-48)"
.section .note.GNU-stack,"",@progbits
Notice the code above, hum. You can see the structure "test" is 4-byte alignment, and has a 12-byte size. First the field "a"(int)
as .long 10 followed by field "b"(char) as .byte 20. To keep the fields' 4-byte alignment, that GCC has added 3 zero bytes(.zero 3)
before field "c"(int) which is declared as .long 30.This makes sizeof struct test_t as 12 instead of th expected 9.
OK. Let's create another C source file named attribute_packed.c
struct test_t {
int a;
char b;
int c;
} __attribute__((__packed__));
struct test_t test = {10, 20, 30};
And the -S output file I got after compiling was
.file "attribute_packed.c"
.globl test
.data
.type test, @object
.size test, 9
test:
.long 10
.byte 20
.long 30
.ident "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-48)"
.section .note.GNU-stack,"",@progbits
in which the zeros are missing, and the sizeof structure test_t is 9-byte. Always remember that memory alignment is GOOD
even if it compromises space, so think twice before using this kind attribute.
GCC C attribute--weak
One of GCC attribtes is __weak__, which we call weak symbol specifies from GCC Manual that
The weak attribute causes the declaration to be emitted as a weak symbol rather than a global. This is primarily useful
in defining library functions which can be overridden in user code, though it can also be used with non-function declarations.
Weak symbols are supported for ELF targets, and also for a.out targets when using the GNU assembler and linker.
For example, I created a C source file named weak.c like
extern void foo() __attribute__((__weak__));
main()
{
if (foo)
foo();
}
a C source file named strong.c like
extern void foo();
main()
{
if (foo)
foo();
}
and a C source file named foo.c like
#include
void foo()
{
printf("in foo.\n");
}
Now, if I compile file weak.c and run it
$ gcc -static -o weak weak.c
$ ./weak
$
That means the linker will fill in 0 for undefined weak symbols.
when I compile file strong.c
$ gcc -static -o strong strong.c
strong.c: In function ‘main’:
strong.c:5: warning: the address of ‘foo’, will always evaluate as ‘true’
/tmp/ccCTkWl9.o: In function `main':
strong.c:(.text+0x12): undefined reference to `foo'
collect2: ld returned 1 exit status
It means the linker can not find the strong symbol. So when the "foo" is declared to be weak, its definition can be emitted,
or replaced by different libraries, featuring kind of "link-time binding".
At last, I combined files weak.c, foo.c and strong.c, foo.c respectively
$gcc -static -o weak_foo weak.c foo.c
$ ./weak_foo
in foo.
$ gcc -static -o strong_foo strong.c foo.c
$ ./strong_foo
in foo.
GCC C attribute--packed
As to GCC, you can place a function or varible in a special section. It defines the __section__ attribute from GCC Manual that
Normally, the compiler places the code it generates in thte text section. Sometimes, however, you need additional sections,
or you need certain particular functions to appear in special sections. The section attribute specifies that a function lives
in a particular section. For example, the declaration:
extern void foobar (void) __attribute__ ((section("bar")));
puts the function foobar in the bar section.
And we have an example in the Linux kernel where it defines __init, __initdata etc.
#define __init __section(.init.text) __cold notrace
#define __initdata __section(.init.data)
#define __section(S) __attribute__((__section__(#S)))
It puts initial function in .init.text section and initial data in .init.data section respectively.
阅读(1256) | 评论(0) | 转发(0) |