section: introspect sections without linker extensions. Fixes #91

This commit is contained in:
Snaipe 2016-09-03 20:25:32 +02:00
parent 8882c7d9cc
commit a3df2ab9a4
12 changed files with 407 additions and 164 deletions

View file

@ -56,15 +56,11 @@
# endif
# ifdef __APPLE__
# define CR_SECTION_START_PREFIX __first
# define CR_SECTION_END_PREFIX __last
# define CR_SECTION_START_SUFFIX(Name) __asm("section$start$__DATA$" Name)
# define CR_SECTION_END_SUFFIX(Name) __asm("section$end$__DATA$" Name)
# define CR_SECTION_(Name) CR_ATTRIBUTE(section("__DATA," Name))
# define CR_SECTION_SUFFIX_
# elif CR_IS_MSVC
# define CR_SECTION_START_PREFIX __start
# define CR_SECTION_END_PREFIX __stop
# define CR_SECTION_START_SUFFIX(Name)
# define CR_SECTION_END_SUFFIX(Name)
# define CR_SECTION_(Name) \
@ -74,8 +70,6 @@
# define CR_SECTION_SUFFIX_ \
__pragma(data_seg(pop))
# else
# define CR_SECTION_START_PREFIX __start
# define CR_SECTION_END_PREFIX __stop
# define CR_SECTION_START_SUFFIX(Name)
# define CR_SECTION_END_SUFFIX(Name)
# define CR_SECTION_(Name) CR_ATTRIBUTE(section(Name))
@ -85,21 +79,6 @@
# define CR_MAKE_IDENTIFIER_(Prefix, Id) CR_MAKE_IDENTIFIER__(Prefix, Id)
# define CR_MAKE_IDENTIFIER__(Prefix, Id) Prefix ## _ ## Id
# define CR_SECTION_START_(Name) CR_MAKE_IDENTIFIER_(CR_SECTION_START_PREFIX, Name)
# define CR_SECTION_END_(Name) CR_MAKE_IDENTIFIER_(CR_SECTION_END_PREFIX, Name)
# define CR_SECTION_START(Name) g_ ## Name ## _section_start
# define CR_SECTION_END(Name) g_ ## Name ## _section_end
# define CR_DECL_SECTION_LIMITS(Type, Name) CR_DECL_SECTION_LIMITS_(Type, Name)
# define CR_DECL_SECTION_LIMITS_(Type, Name) \
extern Type CR_SECTION_START_(Name) CR_SECTION_START_SUFFIX(#Name); \
extern Type CR_SECTION_END_(Name) CR_SECTION_END_SUFFIX(#Name)
# define CR_IMPL_SECTION_LIMITS(Type, Name) \
Type *const CR_SECTION_START(Name) = &CR_SECTION_START_(Name); \
Type *const CR_SECTION_END(Name) = &CR_SECTION_END_(Name)
# ifdef __GNUC__
# define CR_UNUSED CR_ATTRIBUTE(unused)
# define CR_NORETURN CR_ATTRIBUTE(noreturn)

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Criterion \n"
"Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n"
"POT-Creation-Date: 2016-08-08 15:38+0200\n"
"POT-Creation-Date: 2016-09-03 20:06+0200\n"
"PO-Revision-Date: 2016-02-12 11:12+0100\n"
"Last-Translator: <a1lu@arcor.de>\n"
"Language-Team: German\n"
@ -181,7 +181,7 @@ msgstr "Die Anweisung `%1$s` hat eine Instanz der Ausname `%2$s` geworfen."
msgid "The statement `%1$s` did not throw an instance of the `%2$s` exception."
msgstr "Die Anweisung `%1$s` hat keine Instanz der Ausname `%2$s` geworfen."
#: src/core/runner.c:62
#: src/core/runner.c:68
#, c-format
msgid ""
"%1$sWarning! Criterion has detected that it is running under valgrind, but "

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: criterion 2.0.0\n"
"Report-Msgid-Bugs-To: franklinmathieu+criterion@gmail.com\n"
"POT-Creation-Date: 2016-08-08 15:38+0200\n"
"POT-Creation-Date: 2016-09-03 20:06+0200\n"
"PO-Revision-Date: 2015-04-03 17:58+0200\n"
"Last-Translator: <franklinmathieu@gmail.com>\n"
"Language-Team: French\n"
@ -183,7 +183,7 @@ msgstr "L'instruction `%1$s` a levé une instance de l'exception `%2$s`."
msgid "The statement `%1$s` did not throw an instance of the `%2$s` exception."
msgstr "L'instruction `%1$s` n'a pas levé d'instance de l'exception `%2$s`."
#: src/core/runner.c:62
#: src/core/runner.c:68
#, c-format
msgid ""
"%1$sWarning! Criterion has detected that it is running under valgrind, but "

167
src/compat/section-elf.c Normal file
View file

@ -0,0 +1,167 @@
/*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu <http://snai.pe/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
# include "section.h"
# include <string.h>
# include <sys/mman.h>
# include <fcntl.h>
# include <unistd.h>
static int open_self(void) {
#if defined __linux__
return open("/proc/self/exe", O_RDONLY);
#elif defined __NetBSD__
return open("/proc/curproc/exe", O_RDONLY)
#elif defined __FreeBSD__
int fd = open("/proc/curproc/file", O_RDONLY);
/* Fallback */
if (fd == -1 && errno == ENOENT) {
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
char path[PATH_MAX];
size_t cb = sizeof (path);
sysctl(mib, sizeof (mib) / sizeof (int), path, &cb, NULL, 0);
fd = open(path, O_RDONLY);
}
return fd;
#elif defined __OpenBSD__ || defined __DragonFly__
return open("/proc/curproc/file", O_RDONLY)
#else
return -1;
#endif
}
static int open_module_map(mod_handle *mod)
{
/* Load the ELF header and the section header table */
const ElfW(Ehdr) *elf = mmap(NULL, sizeof (ElfW(Ehdr)),
PROT_READ, MAP_PRIVATE, mod->fd, 0);
const void *oldm = elf;
if (elf == MAP_FAILED)
goto fail;
if (memcmp(elf->e_ident, (char [4]) { 0x7f, 'E', 'L', 'F' }, 4))
goto fail;
size_t new_map_len = elf->e_shoff + elf->e_shnum * elf->e_shentsize;
#ifdef HAVE_MREMAP
elf = mremap((void*) elf, sizeof (ElfW(Ehdr)), new_map_len, MREMAP_MAYMOVE);
#else
elf = mmap(NULL, new_map_len, PROT_READ, MAP_PRIVATE, mod->fd, 0);
#endif
if (elf == MAP_FAILED)
goto fail;
#ifndef HAVE_MREMAP
munmap((void *) oldm, sizeof (ElfW(Ehdr)));
#else
(void) oldm;
#endif
mod->len = new_map_len;
mod->map = elf;
return 1;
fail:
munmap((void *) elf, sizeof (ElfW(Ehdr)));
return 0;
}
static void close_module_map(mod_handle *mod)
{
munmap((void *) mod->map, mod->len);
}
int open_module_self(mod_handle *mod)
{
int fd = open_self();
if (fd == -1)
return 0;
mod->fd = fd;
return open_module_map(mod);
}
void close_module(mod_handle *mod)
{
close_module_map(mod);
close(mod->fd);
}
static const void *map_shdr(int fd, const ElfW(Shdr) *shdr, struct section_mapping *out)
{
size_t shdr_map_off = shdr->sh_offset & ~0xfffllu;
size_t shdr_map_len = shdr->sh_size + (shdr->sh_offset - shdr_map_off);
const uint8_t *shdr_map = mmap(NULL, shdr_map_len,
PROT_READ, MAP_PRIVATE, fd, shdr_map_off);
if (shdr_map == MAP_FAILED)
return NULL;
*out = (struct section_mapping) {
.map = shdr_map,
.len = shdr_map_len
};
return shdr_map + (shdr->sh_offset - shdr_map_off);
}
static void unmap_shdr(struct section_mapping *map)
{
munmap((void*) map->map, map->len);
}
void *map_section_data(mod_handle *mod, const char *name,
struct section_mapping *map)
{
const ElfW(Shdr) *shdr = (void *) ((char *) mod->map + mod->map->e_shoff);
const ElfW(Shdr) *shstr_shdr = shdr + mod->map->e_shstrndx;
struct section_mapping shstr_map;
const char *shstr = map_shdr(mod->fd, shstr_shdr, &shstr_map);
const void *ptr = NULL;
for (size_t i = 0; i < mod->map->e_shnum; i++) {
const char *section_name = shstr + shdr[i].sh_name;
if (!strcmp(section_name, name)) {
const ElfW(Shdr) *hdr = shdr + i;
ptr = map_shdr(mod->fd, hdr, map);
map->sec_len = hdr->sh_size;
break;
}
}
unmap_shdr(&shstr_map);
return (void *)ptr;
}
void unmap_section_data(struct section_mapping *map)
{
unmap_shdr(map);
}

104
src/compat/section-mach-o.c Normal file
View file

@ -0,0 +1,104 @@
/*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu <http://snai.pe/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include <mach-o/dyld.h>
#include <mach-o/getsect.h>
#include <mach-o/loader.h>
#include "section.h"
#ifdef __LP64__
typedef struct mach_header_64 mach_hdr;
typedef struct section_64 section;
#else
typedef struct mach_header mach_hdr;
typedef struct section section;
#endif
static inline void *get_real_address(int lib, void *addr) {
if (!addr)
return NULL;
// We need to slide the section address to get a valid pointer
// because ASLR will shift the image by a random offset
return addr + _dyld_get_image_vmaddr_slide(lib);
}
static inline void *ptr_add(const void *ptr, size_t off)
{
return (char *) ptr + off;
}
int open_module_self(mod_handle *mod)
{
*mod = 0;
return 1;
}
void close_module(mod_handle *mod)
{
(void) mod;
}
void *map_section_data(mod_handle *mod, const char *name,
struct section_mapping *map)
{
(void) map;
const struct mach_header *hdr = _dyld_get_image_header(*mod);
const struct load_command *lc = ptr_add(hdr, sizeof (mach_hdr));
for (size_t i = 0; i < hdr->ncmds; ++i, lc = ptr_add(lc, lc->cmdsize)) {
if (lc->cmd == LC_SEGMENT) {
const struct segment_command *sc = (void *) lc;
if (strncmp("__DATA", sc->segname, 16))
continue;
const struct section *s = ptr_add(sc, sizeof (*sc));
for (size_t j = 0; j < sc->nsects; ++j, ++s) {
if (strncmp(name, s->sectname, 16))
continue;
map->sec_len = s->size;
return get_real_address(*mod, (void *)(uintptr_t) s->addr);
}
} else if (lc->cmd == LC_SEGMENT_64) {
const struct segment_command_64 *sc = (void *) lc;
if (strncmp("__DATA", sc->segname, 16))
continue;
const struct section_64 *s = ptr_add(sc, sizeof (*sc));
for (size_t j = 0; j < sc->nsects; ++j, ++s) {
if (strncmp(name, s->sectname, 16))
continue;
map->sec_len = s->size;
return get_real_address(*mod, (void *)(uintptr_t) s->addr);
}
}
}
return NULL;
}
void unmap_section_data(struct section_mapping *map)
{
(void) map;
}

58
src/compat/section-pe.c Normal file
View file

@ -0,0 +1,58 @@
/*
* The MIT License (MIT)
*
* Copyright © 2016 Franklin "Snaipe" Mathieu <http://snai.pe/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "section.h"
#include <windows.h>
int open_module_self(mod_handle *mod)
{
*mod = GetModuleHandle(NULL);
return 1;
}
void close_module(mod_handle *mod)
{
(void) mod;
}
void *map_section_data(mod_handle *mod, const char *name,
struct section_mapping *map)
{
PIMAGE_DOS_HEADER dos_hdr = (PIMAGE_DOS_HEADER) *mod;
PIMAGE_NT_HEADERS nt_hdr = (PIMAGE_NT_HEADERS) ((uintptr_t) dos_hdr
+ dos_hdr->e_lfanew);
PIMAGE_SECTION_HEADER sec_hdr = IMAGE_FIRST_SECTION(nt_hdr);
for(int i = 0; i < nt_hdr->FileHeader.NumberOfSections; i++, sec_hdr++) {
if (!strncmp((char *) sec_hdr->Name, name, IMAGE_SIZEOF_SHORT_NAME)) {
map->sec_len = sec_hdr->SizeOfRawData;
return (char *) dos_hdr + sec_hdr->VirtualAddress;
}
}
return NULL;
}
void unmap_section_data(struct section_mapping *map)
{
(void) map;
}

View file

@ -21,69 +21,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <assert.h>
#include <stdint.h>
#include "section.h"
#include "internal.h"
#ifdef _WIN32
void *get_win_section_start(const char *section) {
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER) GetModuleHandle(NULL);
PIMAGE_NT_HEADERS ntHeader = ntHeader = (PIMAGE_NT_HEADERS) ((uintptr_t)(dosHeader) + (dosHeader->e_lfanew));
assert(dosHeader->e_magic == IMAGE_DOS_SIGNATURE);
assert(ntHeader->Signature == IMAGE_NT_SIGNATURE);
PIMAGE_SECTION_HEADER pSecHeader = IMAGE_FIRST_SECTION(ntHeader);
for(int i = 0; i < ntHeader->FileHeader.NumberOfSections; i++, pSecHeader++) {
if (!strncmp((char*) pSecHeader->Name, section, 8)) {
return (char*) dosHeader + pSecHeader->VirtualAddress;
}
}
return NULL;
}
void *get_win_section_end(const char *section) {
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER) GetModuleHandle(NULL);
PIMAGE_NT_HEADERS ntHeader = ntHeader = (PIMAGE_NT_HEADERS) ((uintptr_t)(dosHeader) + (dosHeader->e_lfanew));
assert(dosHeader->e_magic == IMAGE_DOS_SIGNATURE);
assert(ntHeader->Signature == IMAGE_NT_SIGNATURE);
PIMAGE_SECTION_HEADER pSecHeader = IMAGE_FIRST_SECTION(ntHeader);
for(int i = 0; i < ntHeader->FileHeader.NumberOfSections; i++, pSecHeader++) {
if (!strncmp((char*) pSecHeader->Name, section, 8)) {
return (char*) dosHeader + (size_t) pSecHeader->VirtualAddress + pSecHeader->SizeOfRawData;
}
}
return NULL;
}
#if defined (__ELF__)
# include "section-elf.c"
#elif defined (__APPLE__)
# include "section-mach-o.c"
#elif defined (_WIN32)
# include "section-pe.c"
#else
# error Unsupported executable format
#endif
#ifdef __APPLE__
# include <mach-o/getsect.h>
# include <mach-o/dyld.h>
# define BASE_IMAGE_INDEX 0
static inline void *get_real_address(void *addr) {
if (!addr)
return NULL;
// We need to slide the section address to get a valid pointer
// because ASLR will shift the image by a random offset
return addr + _dyld_get_image_vmaddr_slide(BASE_IMAGE_INDEX);
}
void *get_osx_section_start(const char *section) {
unsigned long secsize;
return get_real_address(getsectdata("__DATA", section, &secsize));
}
void *get_osx_section_end(const char *section) {
unsigned long secsize;
char *section_start = getsectdata("__DATA", section, &secsize);
return get_real_address(section_start) + secsize;
}
#endif

View file

@ -24,25 +24,36 @@
#ifndef SECTION_H_
# define SECTION_H_
# include "criterion/internal/common.h"
# include "config.h"
# ifdef _WIN32
void *get_win_section_start(const char *section);
void *get_win_section_end(const char *section);
# define CR_STRINGIFY_(Param) #Param
# define CR_STRINGIFY(Param) CR_STRINGIFY_(Param)
# define GET_SECTION_START(Name) get_win_section_start(CR_STRINGIFY(Name))
# define GET_SECTION_END(Name) get_win_section_end(CR_STRINGIFY(Name))
# elif defined(__APPLE__)
void *get_osx_section_start(const char *section);
void *get_osx_section_end(const char *section);
# define CR_STRINGIFY_(Param) #Param
# define CR_STRINGIFY(Param) CR_STRINGIFY_(Param)
# define GET_SECTION_START(Name) get_osx_section_start(CR_STRINGIFY(Name))
# define GET_SECTION_END(Name) get_osx_section_end(CR_STRINGIFY(Name))
# else
# define GET_SECTION_START(Name) CR_SECTION_START(Name)
# define GET_SECTION_END(Name) CR_SECTION_END(Name)
# if defined (__ELF__)
# define MODULE_INVALID NULL
# include <link.h>
typedef struct mod_handle {
int fd;
const ElfW(Ehdr) *map;
size_t len;
} mod_handle;
# elif defined (__APPLE__)
# define MODULE_INVALID -1
typedef int mod_handle;
# elif defined (_WIN32)
# include <windows.h>
# define MODULE_INVALID NULL
typedef HMODULE mod_handle;
# endif
struct section_mapping {
const void *map;
size_t len;
size_t sec_len;
};
int open_module_self(mod_handle *mod);
void close_module(mod_handle *mod);
void *map_section_data(mod_handle *mod, const char *name,
struct section_mapping *map);
void unmap_section_data(struct section_mapping *map);
#endif /* !SECTION_H_ */

View file

@ -33,42 +33,24 @@
#include "config.h"
#include "compat/posix.h"
#define IMPL_CALL_REPORT_HOOKS(Kind) \
CR_IMPL_SECTION_LIMITS(f_report_hook, CR_HOOK_SECTION(Kind)); \
void call_report_hooks_##Kind(void *data) { \
for (f_report_hook *hook = GET_SECTION_START(CR_HOOK_SECTION(Kind)); \
hook < (f_report_hook*) GET_SECTION_END(CR_HOOK_SECTION(Kind)); \
++hook) { \
(*hook ? *hook : nothing)(data); \
} \
#define CR_HSEC_STR(Kind) CR_HSEC_STR_(CR_HOOK_SECTION(Kind))
#define CR_HSEC_STR_(S) CR_HSEC_STR__(S)
#define CR_HSEC_STR__(S) #S
#define IMPL_CALL_REPORT_HOOKS(Kind) \
void call_report_hooks_##Kind(void *data) { \
mod_handle self; \
struct section_mapping sect; \
if (!open_module_self(&self)) \
abort(); \
void *start = map_section_data(&self, CR_HSEC_STR(Kind), &sect); \
if (!start) \
return; \
void *end = (char *)start + sect.sec_len; \
for (f_report_hook *hook = start; hook < (f_report_hook*) end; ++hook) \
(*hook ? *hook : nothing)(data); \
}
#ifdef _MSC_VER
f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(PRE_ALL));
f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(PRE_SUITE));
f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(PRE_INIT));
f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(PRE_TEST));
f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(ASSERT));
f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(THEORY_FAIL));
f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(TEST_CRASH));
f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(POST_TEST));
f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(POST_FINI));
f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(POST_SUITE));
f_report_hook CR_SECTION_START_(CR_HOOK_SECTION(POST_ALL));
f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(PRE_ALL));
f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(PRE_SUITE));
f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(PRE_INIT));
f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(PRE_TEST));
f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(ASSERT));
f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(THEORY_FAIL));
f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(TEST_CRASH));
f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(POST_TEST));
f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(POST_FINI));
f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(POST_SUITE));
f_report_hook CR_SECTION_END_(CR_HOOK_SECTION(POST_ALL));
#endif
IMPL_CALL_REPORT_HOOKS(PRE_ALL)
IMPL_CALL_REPORT_HOOKS(PRE_SUITE)
IMPL_CALL_REPORT_HOOKS(PRE_INIT)

View file

@ -31,7 +31,6 @@
# define report_(Kind, Data) call_report_hooks_##Kind(Data)
# define DECL_CALL_REPORT_HOOKS(Kind) \
CR_DECL_SECTION_LIMITS(f_report_hook, CR_HOOK_SECTION(Kind)); \
void call_report_hooks_##Kind(void *data)
DECL_CALL_REPORT_HOOKS(PRE_ALL);

View file

@ -74,17 +74,6 @@ static msg_t msg_valgrind_jobs = "%sWarning! Criterion has detected "
"explicitely set. Reports might appear confusing!%s\n";
#endif
#ifdef _MSC_VER
struct criterion_test *CR_SECTION_START_(cr_tst);
struct criterion_suite *CR_SECTION_START_(cr_sts);
struct criterion_test *CR_SECTION_END_(cr_tst);
struct criterion_suite *CR_SECTION_END_(cr_sts);
#endif
CR_IMPL_SECTION_LIMITS(struct criterion_test*, cr_tst);
CR_IMPL_SECTION_LIMITS(struct criterion_suite*, cr_sts);
// This is here to make the test suite & test sections non-empty
CR_SECTION_("cr_sts") struct criterion_suite *dummy_suite = NULL;
CR_SECTION_("cr_tst") struct criterion_test *dummy_test = NULL;
@ -131,7 +120,16 @@ CR_API void criterion_register_test(struct criterion_test_set *set,
struct criterion_test_set *criterion_init(void) {
struct criterion_ordered_set *suites = new_ordered_set(cmp_suite, dtor_suite_set);
FOREACH_SUITE_SEC(s) {
mod_handle self;
if (!open_module_self(&self))
cr_panic("Could not open self executable file");
struct section_mapping suite_sect = { .sec_len = 0 };
void *suite_start = map_section_data(&self, "cr_sts", &suite_sect);
void *suite_end = (char *) suite_start + suite_sect.sec_len;
FOREACH_SUITE_SEC(s, suite_start, suite_end) {
if (!*s || !*(*s)->name)
continue;
@ -151,7 +149,11 @@ struct criterion_test_set *criterion_init(void) {
0,
};
FOREACH_TEST_SEC(test) {
struct section_mapping test_sect = { .sec_len = 0 };
void *test_start = map_section_data(&self, "cr_tst", &test_sect);
void *test_end = (char *) test_start + test_sect.sec_len;
FOREACH_TEST_SEC(test, test_start, test_end) {
if (!*test)
continue;

View file

@ -27,19 +27,16 @@
# include "criterion/types.h"
# include "compat/pipe.h"
CR_DECL_SECTION_LIMITS(struct criterion_test*, cr_tst);
CR_DECL_SECTION_LIMITS(struct criterion_suite*, cr_sts);
struct criterion_test_set *criterion_init(void);
# define FOREACH_TEST_SEC(Test) \
for (struct criterion_test **Test = GET_SECTION_START(cr_tst); \
Test < (struct criterion_test**) GET_SECTION_END(cr_tst); \
# define FOREACH_TEST_SEC(Test, Start, End) \
for (struct criterion_test **Test = Start; \
Test < (struct criterion_test**) End; \
++Test)
# define FOREACH_SUITE_SEC(Suite) \
for (struct criterion_suite **Suite = GET_SECTION_START(cr_sts); \
Suite < (struct criterion_suite**) GET_SECTION_END(cr_sts); \
# define FOREACH_SUITE_SEC(Suite, Start, End) \
for (struct criterion_suite **Suite = Start; \
Suite < (struct criterion_suite**) End; \
++Suite)
#endif /* !CRITERION_RUNNER_H_ */