Skip to content

Commit 09f7d94

Browse files
committed
Move and rename several functions out of opcodeswich
Move and rename dump to context_dump Factorize and rename cp_to_mod_lbl_off to module_cp_to_label_offset Move and rename get_catch_label_and_change_module to context_get_catch_label Signed-off-by: Paul Guyot <pguyot@kallisys.net>
1 parent 5790613 commit 09f7d94

File tree

6 files changed

+245
-237
lines changed

6 files changed

+245
-237
lines changed

src/libAtomVM/context.c

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -971,3 +971,175 @@ term context_get_monitor_pid(Context *ctx, uint64_t ref_ticks, bool *is_monitori
971971
}
972972
return term_invalid_term();
973973
}
974+
975+
int context_get_catch_label(Context *ctx, Module **mod)
976+
{
977+
term *ct = ctx->e;
978+
term *last_frame = ctx->e;
979+
980+
while (ct != ctx->heap.heap_end) {
981+
if (term_is_catch_label(*ct)) {
982+
int target_module;
983+
int target_label = term_to_catch_label_and_module(*ct, &target_module);
984+
TRACE("- found catch: label: %i, module: %i\n", target_label, target_module);
985+
*mod = globalcontext_get_module_by_index(ctx->global, target_module);
986+
987+
DEBUG_DUMP_STACK(ctx);
988+
ctx->e = last_frame;
989+
DEBUG_DUMP_STACK(ctx);
990+
991+
return target_label;
992+
993+
} else if (term_is_cp(*ct)) {
994+
last_frame = ct + 1;
995+
}
996+
997+
ct++;
998+
}
999+
1000+
return 0;
1001+
}
1002+
1003+
COLD_FUNC void context_dump(Context *ctx)
1004+
{
1005+
GlobalContext *glb = ctx->global;
1006+
1007+
fprintf(stderr, "CRASH \n======\n");
1008+
1009+
fprintf(stderr, "pid: ");
1010+
term_display(stderr, term_from_local_process_id(ctx->process_id), ctx);
1011+
fprintf(stderr, "\n");
1012+
1013+
fprintf(stderr, "\nStacktrace:\n");
1014+
term_display(stderr, stacktrace_build(ctx, &ctx->x[2], 3), ctx);
1015+
fprintf(stderr, "\n\n");
1016+
1017+
{
1018+
Module *cp_mod;
1019+
int label;
1020+
int offset;
1021+
module_cp_to_label_offset(ctx->cp, &cp_mod, &label, &offset, NULL, ctx->global);
1022+
fprintf(stderr, "cp: #CP<module: %i, label: %i, offset: %i>\n\n",
1023+
cp_mod->module_index, label, offset);
1024+
}
1025+
1026+
fprintf(stderr, "x[0]: ");
1027+
term_display(stderr, ctx->x[0], ctx);
1028+
fprintf(stderr, "\nx[1]: ");
1029+
term_display(stderr, ctx->x[1], ctx);
1030+
fprintf(stderr, "\nx[2]: ");
1031+
term_display(stderr, ctx->x[2], ctx);
1032+
fprintf(stderr, "\n\nStack \n-----\n\n");
1033+
1034+
term *ct = ctx->e;
1035+
1036+
while (ct != ctx->heap.heap_end) {
1037+
if (term_is_catch_label(*ct)) {
1038+
int target_module;
1039+
int target_label = term_to_catch_label_and_module(*ct, &target_module);
1040+
fprintf(stderr, "catch: %i:%i\n", target_label, target_module);
1041+
1042+
} else if (term_is_cp(*ct)) {
1043+
Module *cp_mod;
1044+
int label;
1045+
int offset;
1046+
module_cp_to_label_offset(*ct, &cp_mod, &label, &offset, NULL, ctx->global);
1047+
fprintf(stderr, "#CP<module: %i, label: %i, offset: %i>\n", cp_mod->module_index, label, offset);
1048+
1049+
} else {
1050+
term_display(stderr, *ct, ctx);
1051+
fprintf(stderr, "\n");
1052+
}
1053+
1054+
ct++;
1055+
}
1056+
1057+
fprintf(stderr, "\n\nMailbox\n-------\n");
1058+
mailbox_crashdump(ctx);
1059+
1060+
fprintf(stderr, "\n\nMonitors\n--------\n");
1061+
// Lock processes table to make sure any dying process will not modify monitors
1062+
struct ListHead *processes_table = synclist_rdlock(&glb->processes_table);
1063+
UNUSED(processes_table);
1064+
struct ListHead *item;
1065+
LIST_FOR_EACH (item, &ctx->monitors_head) {
1066+
struct Monitor *monitor = GET_LIST_ENTRY(item, struct Monitor, monitor_list_head);
1067+
switch (monitor->monitor_type) {
1068+
case CONTEXT_MONITOR_LINK_LOCAL: {
1069+
struct LinkLocalMonitor *link_monitor = CONTAINER_OF(monitor, struct LinkLocalMonitor, monitor);
1070+
fprintf(stderr, "link ");
1071+
if (link_monitor->unlink_id) {
1072+
fprintf(stderr, "(inactive) ");
1073+
}
1074+
fprintf(stderr, "to ");
1075+
term_display(stderr, link_monitor->link_local_process_id, ctx);
1076+
fprintf(stderr, "\n");
1077+
break;
1078+
}
1079+
case CONTEXT_MONITOR_LINK_REMOTE: {
1080+
struct LinkRemoteMonitor *link_monitor = CONTAINER_OF(monitor, struct LinkRemoteMonitor, monitor);
1081+
fprintf(stderr, "remote link ");
1082+
if (link_monitor->unlink_id) {
1083+
fprintf(stderr, "(inactive) ");
1084+
}
1085+
fprintf(stderr, "to ");
1086+
term_display(stderr, link_monitor->node, ctx);
1087+
fprintf(stderr, "\n");
1088+
break;
1089+
}
1090+
case CONTEXT_MONITOR_MONITORING_LOCAL: {
1091+
struct MonitorLocalMonitor *monitoring_monitor = CONTAINER_OF(monitor, struct MonitorLocalMonitor, monitor);
1092+
fprintf(stderr, "monitor to ");
1093+
term_display(stderr, monitoring_monitor->monitor_obj, ctx);
1094+
fprintf(stderr, " ref=%lu", (long unsigned) monitoring_monitor->ref_ticks);
1095+
fprintf(stderr, "\n");
1096+
break;
1097+
}
1098+
case CONTEXT_MONITOR_MONITORED_LOCAL: {
1099+
struct MonitorLocalMonitor *monitored_monitor = CONTAINER_OF(monitor, struct MonitorLocalMonitor, monitor);
1100+
fprintf(stderr, "monitored by ");
1101+
term_display(stderr, monitored_monitor->monitor_obj, ctx);
1102+
fprintf(stderr, " ref=%lu", (long unsigned) monitored_monitor->ref_ticks);
1103+
fprintf(stderr, "\n");
1104+
break;
1105+
}
1106+
case CONTEXT_MONITOR_RESOURCE: {
1107+
struct ResourceContextMonitor *resource_monitor = CONTAINER_OF(monitor, struct ResourceContextMonitor, monitor);
1108+
fprintf(stderr, "monitored by resource %p ref=%lu", resource_monitor->resource_obj, (long unsigned) resource_monitor->ref_ticks);
1109+
fprintf(stderr, "\n");
1110+
break;
1111+
}
1112+
}
1113+
}
1114+
synclist_unlock(&glb->processes_table);
1115+
1116+
// If crash is caused by out_of_memory, print more data about memory usage
1117+
if (ctx->x[0] == ERROR_ATOM && ctx->x[1] == OUT_OF_MEMORY_ATOM) {
1118+
fprintf(stderr, "\n\nContext memory info\n-------------------\n");
1119+
fprintf(stderr, "context_size = %zu\n", context_size(ctx));
1120+
fprintf(stderr, "context_avail_free_memory = %zu\n", context_avail_free_memory(ctx));
1121+
fprintf(stderr, "heap_size = %zu\n", memory_heap_youngest_size(&ctx->heap));
1122+
fprintf(stderr, "total_heap_size = %zu\n", memory_heap_memory_size(&ctx->heap));
1123+
fprintf(stderr, "stack_size = %zu\n", context_stack_size(ctx));
1124+
fprintf(stderr, "message_queue_len = %zu\n", context_message_queue_len(ctx));
1125+
fprintf(stderr, "\n\nGlobal memory info\n------------------\n");
1126+
1127+
processes_table = synclist_rdlock(&glb->processes_table);
1128+
size_t process_count = 0;
1129+
size_t ports_count = 0;
1130+
LIST_FOR_EACH (item, processes_table) {
1131+
Context *p = GET_LIST_ENTRY(item, Context, processes_table_head);
1132+
process_count++;
1133+
if (p->native_handler) {
1134+
ports_count++;
1135+
}
1136+
}
1137+
synclist_unlock(&glb->processes_table);
1138+
1139+
fprintf(stderr, "process_count = %zu\n", process_count);
1140+
fprintf(stderr, "ports_count = %zu\n", ports_count);
1141+
fprintf(stderr, "atoms_count = %zu\n", atom_table_count(glb->atom_table));
1142+
fprintf(stderr, "refc_binary_total_size = %zu\n", refc_binary_total_size(ctx));
1143+
}
1144+
fprintf(stderr, "\n\n**End Of Crash Report**\n");
1145+
}

src/libAtomVM/context.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,22 @@ term context_get_monitor_pid(Context *ctx, uint64_t ref_ticks, bool *is_monitori
563563
*/
564564
bool context_add_monitor(Context *ctx, struct Monitor *new_monitor);
565565

566+
/**
567+
* @brief Get catch label from stack
568+
*
569+
* @param ctx the context being executed
570+
* @param mod on output, the module
571+
* @return the found label or 0 if no catch label was found in the stack
572+
*/
573+
int context_get_catch_label(Context *ctx, Module **mod);
574+
575+
/**
576+
* @brief Dump context to stderr
577+
*
578+
* @param ctx context to dump
579+
*/
580+
void context_dump(Context *ctx);
581+
566582
#ifdef __cplusplus
567583
}
568584
#endif

src/libAtomVM/module.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,3 +828,43 @@ bool module_find_line(Module *mod, unsigned int offset, uint32_t *line, size_t *
828828
DECODE_LITERAL(line_ref, ref_pc);
829829
return module_find_line_ref(mod, line_ref, line, filename_len, filename);
830830
}
831+
832+
COLD_FUNC void module_cp_to_label_offset(term cp, Module **cp_mod, int *label, int *l_off, long *out_mod_offset, GlobalContext *global)
833+
{
834+
Module *mod = globalcontext_get_module_by_index(global, ((uintptr_t) cp) >> 24);
835+
long mod_offset = (cp & 0xFFFFFF) >> 2;
836+
if (out_mod_offset) {
837+
*out_mod_offset = mod_offset;
838+
}
839+
840+
if (cp_mod) {
841+
*cp_mod = mod;
842+
}
843+
844+
uint8_t *code = &mod->code->code[0];
845+
int labels_count = ENDIAN_SWAP_32(mod->code->labels);
846+
847+
int i = 1;
848+
const uint8_t *l = mod->labels[1];
849+
while (mod_offset > l - code) {
850+
i++;
851+
if (i >= labels_count) {
852+
// last label + 1 is reserved for end of module.
853+
if (label) {
854+
*label = i;
855+
}
856+
if (l_off) {
857+
*l_off = 0;
858+
}
859+
return;
860+
}
861+
l = mod->labels[i];
862+
}
863+
864+
if (label) {
865+
*label = i - 1;
866+
}
867+
if (l_off) {
868+
*l_off = mod_offset - (mod->labels[*label] - code);
869+
}
870+
}

src/libAtomVM/module.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,18 @@ static inline bool module_has_line_chunk(Module *mod)
396396
return mod->line_refs_table != NULL;
397397
}
398398

399+
/*
400+
* @brief Get the module, offset, label and label offset from module start from a continuation pointer.
401+
*
402+
* @param cp continuation pointer to parse
403+
* @param cp_mod if not null, set to found module
404+
* @param label if not null, set to found label
405+
* @param l_off if not null, set to offset of label from module start
406+
* @param mod_offset if not null, set to offset of cp from module start
407+
* @param global the global context
408+
*/
409+
void module_cp_to_label_offset(term cp, Module **cp_mod, int *label, int *l_off, long *mod_offset, GlobalContext *global);
410+
399411
#ifdef __cplusplus
400412
}
401413
#endif

0 commit comments

Comments
 (0)