Код:
// test.c
#include <stdint.h>
typedef struct cgi
{
const char *cgi_name;
void *data;
uint32_t flags;
} cgi_t;
static cgi_t a, b, c;
скомпилируйте его:
$ cc -c test.c
readelf
$ readelf -a test.o
5: 0000000000000000 24 OBJECT LOCAL DEFAULT 3 a
6: 0000000000000020 24 OBJECT LOCAL DEFAULT 3 b
7: 0000000000000040 24 OBJECT LOCAL DEFAULT 3 c
настолько странно, что эти 3 переменные размещены по адресу, выровненному по 0x20 , это приводит к сбою следующего кода:
extern cgi_t __start_cgicalls, __stop_cgicalls;
cgi_t * lookup_cgi(const char *name) {
cgi_t *cgi_entry;
for (cgi_entry = &__start_cgicalls;
cgi_entry < &__stop_cgicalls; cgi_entry++) {
if (!strcmp(name, cgi_entry->cgi_name))
return cgi_entry;
}
return NULL;
}
Я помещаю зарегистрированную запись CGI в раздел CGI и просматриваю их, потому что они расположены с неправильным смещением, поэтому я ищу их при сбое программы.
==============
Я исправляю это с помощью принудительного выравнивания структуры до 16 байтов. Я обнаружил, что материал говорит, что
, когда структура больше 16 байтов, переменная будет преобразована в 16 байтов
typedef int (* cgicb_t)(struct http_req *req, struct http_res *res);
/* note: because we look up cgi entry based on array align (8 bytes in 64bits system)
but the variable may be put in section with different align (big struct is aligned to 16 bytes)
so, here we force the align to 16 bytes !!!
*/
typedef struct cgi
{
const char *cgi_name;
cgicb_t fn;
uint32_t flags;
} __attribute__ ((aligned (16))) cgi_t;
#define REGISTER_CGI(name, cb, flag) \
static cgi_t __cgicall##cb \
__attribute__((__section__("cgicalls"))) __attribute__((used)) \
= { \
.cgi_name = name, \
.fn = cb, \
.flags = flag, \
}
#define REG_CGI(cb) REGISTER_CGI(CGI_PATH #cb, cb, CGI_FLAG_PERM)