I have a small C program:
#include <stdio.h>
struct foo {
int x;
struct foo *next;
};
#define CONST __attribute__((used, section("const_heap")))
struct foo f CONST = { 1, 0 };
struct foo g CONST = { 2, &g };
extern char *__start_const_heap;
extern char *__stop_const_heap;
int main() {
printf("f: %p, g: %p\n", &f, &g);
printf("start: %p, end %p\n", &__start_const_heap, &__stop_const_heap);
}
and I want to be able to check if a pointer is within a section const_heap
. GCC and Clang compile and run this fine; TCC has a linker error for the __start
and __stop
symbols.
hickory% gcc const.c && ./a.out
f: 0x5c97a966d020, g: 0x5c97a966d030
start: 0x5c97a966d048, end 0x5c97a966d050
hickory% clang const.c && ./a.out
f: 0x574924409030, g: 0x574924409040
start: 0x574924409068, end 0x574924409070
hickory% tcc const.c
tcc: error: undefined symbol '__stop_const_heap'
tcc: error: undefined symbol '__start_const_heap'
hickory%
(the exact numbers don't matter; just that the program runs and prints a pointer)
I checked with readelf
on the (unlinked) object file and sure enough, no const_heap
section is present.
TCC apparently supports this as of 0.9.9 and I am using 0.9.27 (20-some years newer). Even the TCC code looks like this should work. What am I doing wrong?
EDIT: Just downloaded and compiled the latest commit and it still fails with the same error.
preprocessor makes attributes disappear:
Yes, you stumbled over an artifact of the glibc standard headers. If used with a compiler that doesn't claim to be GCC (e.g. with TCC), you'll hit this snippet in /usr/include/sys/cdefs.h:
#if !defined __GNUC__ || __GNUC__ < 2
# define __attribute__(xyz) /* Ignore */
#endif
With this tweak it works on all 3 compilers:
#include <stdio.h>
#if !defined __GNUC__ || __GNUC__ < 2
#undef __attribute__
#endif
struct foo {
int x;
struct foo *next;
};
#define CONST __attribute__((section("const_heap")))
struct foo f CONST = { 1, 0 };
struct foo g CONST = { 2, &g };
extern char *__start_const_heap;
extern char *__stop_const_heap;
int main() {
printf("f: %p, g: %p\n", &f, &g);
printf("start: %p, end %p\n", &__start_const_heap, &__stop_const_heap);
}