Last active
January 29, 2023 20:20
-
-
Save lpereira/678ee5f38a8facf7ef5b0a93b3304c8b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
struct error_code { | |
int code; | |
}; | |
struct error_context { | |
const struct error_code *code; | |
const char *msg; | |
const char *file; | |
int line; | |
}; | |
#ifndef NDEBUG | |
#define _ERROR_NEW(msg_) \ | |
static struct error_code __attribute__((__used__)) \ | |
__attribute__((__section__("error_code"))) __error_code__ = {.code = 0}; \ | |
static const struct error_context __attribute__((__used__)) \ | |
__attribute__((__section__("error_context"))) \ | |
__error_context__ = {.msg = msg_, \ | |
.file = __FILE__, \ | |
.line = __LINE__, \ | |
.code = &__error_code__}; | |
#else | |
#define _ERROR_NEW(msg_) \ | |
static struct error_code __attribute__((__used__)) \ | |
__attribute__((__section__("error_code"))) __error_code__ = {.code = 0}; | |
#endif | |
#define ERROR_NEW(msg_) \ | |
({ \ | |
_ERROR_NEW(msg_) \ | |
__error_code__.code; \ | |
}) | |
__attribute__((__constructor__)) static void error_init(void) { | |
extern struct error_code __start_error_code[], __stop_error_code[]; | |
struct error_code *c; | |
int counter = 0; | |
for (c = __start_error_code; c < __stop_error_code; c++) { | |
c->code = counter++; | |
} | |
} | |
const struct error_code *error_find(int code) { | |
extern struct error_code __start_error_code[], __stop_error_code[]; | |
const struct error_code *c; | |
for (c = __start_error_code; c < __stop_error_code; c++) { | |
if (c->code == code) | |
return c; | |
} | |
return NULL; | |
} | |
const struct error_context *error_find_context(int code) { | |
extern struct error_context __start_error_context[], __stop_error_context[]; | |
const struct error_context *ctx; | |
const struct error_code *c = error_find(code); | |
if (!c) | |
return NULL; | |
for (ctx = __start_error_context; ctx < __stop_error_context; ctx++) { | |
if (ctx->code == c) | |
return ctx; | |
} | |
return NULL; | |
} | |
int main() { | |
int error_code_1 = ERROR_NEW("foo"); | |
int error_code_2 = ERROR_NEW("bar"); | |
int error_code_3 = ERROR_NEW("baz"); | |
int error_code_4 = ERROR_NEW("aaa"); | |
int error_code_5 = ERROR_NEW("bbb"); | |
int error_code_6 = ERROR_NEW("ccc"); | |
int error_code_7 = ERROR_NEW("ddd"); | |
printf("%d %d\n", error_code_1, error_code_2); | |
printf("%d %d\n", error_code_3, error_code_4); | |
printf("%d %d\n", error_code_5, error_code_6); | |
printf("%d\n", error_code_7); | |
const struct error_context *ctx = error_find_context(error_code_1); | |
if (!ctx) { | |
printf("context not found; maybe it was stripped?\n"); | |
} else { | |
printf("error code %d defined with message '%s' on file '%s' at line %d\n", | |
error_code_1, ctx->msg, ctx->file, ctx->line); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ make error-codes | |
cc error-codes.c -o error-codes | |
$ ./error-codes | |
0 1 | |
2 3 | |
4 5 | |
6 | |
error code 0 defined with message 'foo' on file 'error-codes.c' at line 73 | |
$ objcopy --remove-section error_context ./error-codes | |
$ ./error-codes | |
0 1 | |
2 3 | |
4 5 | |
6 | |
context not found; maybe it was stripped? | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment